53
53
# We choose to read and write binary copies of our table's tuples, using perl's
54
54
# pack() and unpack() functions. Perl uses a packing code system in which:
55
55
#
56
+ # l = "signed 32-bit Long",
56
57
# L = "Unsigned 32-bit Long",
57
58
# S = "Unsigned 16-bit Short",
58
59
# C = "Unsigned 8-bit Octet",
59
- # c = "signed 8-bit octet",
60
60
# q = "signed 64-bit quadword"
61
61
#
62
62
# Each tuple in our table has a layout as follows:
72
72
# xx t_hoff: x offset = 22 C
73
73
# xx t_bits: x offset = 23 C
74
74
# xx xx xx xx xx xx xx xx 'a': xxxxxxxx offset = 24 q
75
- # xx xx xx xx xx xx xx xx 'b': xxxxxxxx offset = 32 Cccccccc
76
- # xx xx xx xx xx xx xx xx 'c': xxxxxxxx offset = 40 SSSS
77
- # xx xx xx xx xx xx xx xx : xxxxxxxx ...continued SSSS
78
- # xx xx : xx ...continued S
75
+ # xx xx xx xx xx xx xx xx 'b': xxxxxxxx offset = 32 CCCCCCCC
76
+ # xx xx xx xx xx xx xx xx 'c': xxxxxxxx offset = 40 CCllLL
77
+ # xx xx xx xx xx xx xx xx : xxxxxxxx ...continued
78
+ # xx xx : xx ...continued
79
79
#
80
80
# We could choose to read and write columns 'b' and 'c' in other ways, but
81
81
# it is convenient enough to do it this way. We define packing code
82
82
# constants here, where they can be compared easily against the layout.
83
83
84
- use constant HEAPTUPLE_PACK_CODE => ' LLLSSSSSCCqCcccccccSSSSSSSSS ' ;
84
+ use constant HEAPTUPLE_PACK_CODE => ' LLLSSSSSCCqCCCCCCCCCCllLL ' ;
85
85
use constant HEAPTUPLE_PACK_LENGTH => 58; # Total size
86
86
87
87
# Read a tuple of our table from a heap page.
@@ -121,15 +121,12 @@ sub read_tuple
121
121
b_body5 => shift ,
122
122
b_body6 => shift ,
123
123
b_body7 => shift ,
124
- c1 => shift ,
125
- c2 => shift ,
126
- c3 => shift ,
127
- c4 => shift ,
128
- c5 => shift ,
129
- c6 => shift ,
130
- c7 => shift ,
131
- c8 => shift ,
132
- c9 => shift );
124
+ c_va_header => shift ,
125
+ c_va_vartag => shift ,
126
+ c_va_rawsize => shift ,
127
+ c_va_extsize => shift ,
128
+ c_va_valueid => shift ,
129
+ c_va_toastrelid => shift );
133
130
# Stitch together the text for column 'b'
134
131
$tup {b } = join (' ' , map { chr ($tup {" b_body$_ " }) } (1..7));
135
132
return \%tup ;
@@ -168,15 +165,12 @@ sub write_tuple
168
165
$tup -> {b_body5 },
169
166
$tup -> {b_body6 },
170
167
$tup -> {b_body7 },
171
- $tup -> {c1 },
172
- $tup -> {c2 },
173
- $tup -> {c3 },
174
- $tup -> {c4 },
175
- $tup -> {c5 },
176
- $tup -> {c6 },
177
- $tup -> {c7 },
178
- $tup -> {c8 },
179
- $tup -> {c9 });
168
+ $tup -> {c_va_header },
169
+ $tup -> {c_va_vartag },
170
+ $tup -> {c_va_rawsize },
171
+ $tup -> {c_va_extsize },
172
+ $tup -> {c_va_valueid },
173
+ $tup -> {c_va_toastrelid });
180
174
seek ($fh , $offset , 0)
181
175
or BAIL_OUT(" seek failed: $! " );
182
176
defined (syswrite ($fh , $buffer , HEAPTUPLE_PACK_LENGTH))
@@ -273,6 +267,7 @@ sub write_tuple
273
267
or BAIL_OUT(" open failed: $! " );
274
268
binmode $file ;
275
269
270
+ my $ENDIANNESS ;
276
271
for (my $tupidx = 0; $tupidx < ROWCOUNT; $tupidx ++)
277
272
{
278
273
my $offnum = $tupidx + 1; # offnum is 1-based, not zero-based
@@ -289,6 +284,9 @@ sub write_tuple
289
284
plan skip_all => qq( Page layout differs from our expectations: expected (12345678, "abcdefg"), got ($a , "$b ")) ;
290
285
exit ;
291
286
}
287
+
288
+ # Determine endianness of current platform from the 1-byte varlena header
289
+ $ENDIANNESS = $tup -> {b_header } == 0x11 ? " little" : " big" ;
292
290
}
293
291
close ($file )
294
292
or BAIL_OUT(" close failed: $! " );
@@ -459,22 +457,36 @@ sub header
459
457
}
460
458
elsif ($offnum == 12)
461
459
{
462
- # Corrupt the bits in column 'b' 1-byte varlena header
463
- $tup -> {b_header } = 0x80;
460
+ # Overwrite column 'b' 1-byte varlena header and initial characters to
461
+ # look like a long 4-byte varlena
462
+ #
463
+ # On little endian machines, bytes ending in two zero bits (xxxxxx00 bytes)
464
+ # are 4-byte length word, aligned, uncompressed data (up to 1G). We set the
465
+ # high six bits to 111111 and the lower two bits to 00, then the next three
466
+ # bytes with 0xFF using 0xFCFFFFFF.
467
+ #
468
+ # On big endian machines, bytes starting in two zero bits (00xxxxxx bytes)
469
+ # are 4-byte length word, aligned, uncompressed data (up to 1G). We set the
470
+ # low six bits to 111111 and the high two bits to 00, then the next three
471
+ # bytes with 0xFF using 0x3FFFFFFF.
472
+ #
473
+ $tup -> {b_header } = $ENDIANNESS eq ' little' ? 0xFC : 0x3F;
474
+ $tup -> {b_body1 } = 0xFF;
475
+ $tup -> {b_body2 } = 0xFF;
476
+ $tup -> {b_body3 } = 0xFF;
464
477
465
478
$header = header(0, $offnum , 1);
466
479
push @expected ,
467
- qr /${header} attribute 1 with length 4294967295 ends at offset 416848000 beyond total tuple length 58 / ;
480
+ qr /${header} attribute \d + with length \d + ends at offset \d + beyond total tuple length \d + / ;
468
481
}
469
482
elsif ($offnum == 13)
470
483
{
471
484
# Corrupt the bits in column 'c' toast pointer
472
- $tup -> {c6 } = 41;
473
- $tup -> {c7 } = 41;
485
+ $tup -> {c_va_valueid } = 0xFFFFFFFF;
474
486
475
487
$header = header(0, $offnum , 2);
476
488
push @expected ,
477
- qr /${header} final toast chunk number 0 differs from expected value 6 / ,
489
+ qr /${header} final toast chunk number 0 differs from expected value \d + / ,
478
490
qr /${header} toasted value for attribute 2 missing from toast table/ ;
479
491
}
480
492
elsif ($offnum == 14)
0 commit comments