5353# We choose to read and write binary copies of our table's tuples, using perl's
5454# pack() and unpack() functions. Perl uses a packing code system in which:
5555#
56+ # l = "signed 32-bit Long",
5657# L = "Unsigned 32-bit Long",
5758# S = "Unsigned 16-bit Short",
5859# C = "Unsigned 8-bit Octet",
59- # c = "signed 8-bit octet",
6060# q = "signed 64-bit quadword"
6161#
6262# Each tuple in our table has a layout as follows:
7272# xx t_hoff: x offset = 22 C
7373# xx t_bits: x offset = 23 C
7474# 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
7979#
8080# We could choose to read and write columns 'b' and 'c' in other ways, but
8181# it is convenient enough to do it this way. We define packing code
8282# constants here, where they can be compared easily against the layout.
8383
84- use constant HEAPTUPLE_PACK_CODE => ' LLLSSSSSCCqCcccccccSSSSSSSSS ' ;
84+ use constant HEAPTUPLE_PACK_CODE => ' LLLSSSSSCCqCCCCCCCCCCllLL ' ;
8585use constant HEAPTUPLE_PACK_LENGTH => 58; # Total size
8686
8787# Read a tuple of our table from a heap page.
@@ -121,15 +121,12 @@ sub read_tuple
121121 b_body5 => shift ,
122122 b_body6 => shift ,
123123 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 );
133130 # Stitch together the text for column 'b'
134131 $tup {b } = join (' ' , map { chr ($tup {" b_body$_ " }) } (1..7));
135132 return \%tup ;
@@ -168,15 +165,12 @@ sub write_tuple
168165 $tup -> {b_body5 },
169166 $tup -> {b_body6 },
170167 $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 });
180174 seek ($fh , $offset , 0)
181175 or BAIL_OUT(" seek failed: $! " );
182176 defined (syswrite ($fh , $buffer , HEAPTUPLE_PACK_LENGTH))
@@ -273,6 +267,7 @@ sub write_tuple
273267 or BAIL_OUT(" open failed: $! " );
274268binmode $file ;
275269
270+ my $ENDIANNESS ;
276271for (my $tupidx = 0; $tupidx < ROWCOUNT; $tupidx ++)
277272{
278273 my $offnum = $tupidx + 1; # offnum is 1-based, not zero-based
@@ -289,6 +284,9 @@ sub write_tuple
289284 plan skip_all => qq( Page layout differs from our expectations: expected (12345678, "abcdefg"), got ($a , "$b ")) ;
290285 exit ;
291286 }
287+
288+ # Determine endianness of current platform from the 1-byte varlena header
289+ $ENDIANNESS = $tup -> {b_header } == 0x11 ? " little" : " big" ;
292290}
293291close ($file )
294292 or BAIL_OUT(" close failed: $! " );
@@ -459,22 +457,36 @@ sub header
459457 }
460458 elsif ($offnum == 12)
461459 {
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;
464477
465478 $header = header(0, $offnum , 1);
466479 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 + / ;
468481 }
469482 elsif ($offnum == 13)
470483 {
471484 # Corrupt the bits in column 'c' toast pointer
472- $tup -> {c6 } = 41;
473- $tup -> {c7 } = 41;
485+ $tup -> {c_va_valueid } = 0xFFFFFFFF;
474486
475487 $header = header(0, $offnum , 2);
476488 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 + / ,
478490 qr /${header} toasted value for attribute 2 missing from toast table/ ;
479491 }
480492 elsif ($offnum == 14)
0 commit comments