91
91
* Portions Copyright (c) 1994, Regents of the University of California
92
92
*
93
93
* IDENTIFICATION
94
- * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.65 2006/03/10 23:19:00 tgl Exp $
94
+ * $PostgreSQL: pgsql/src/backend/utils/sort/tuplesort.c,v 1.66 2006/05/23 21:37:59 tgl Exp $
95
95
*
96
96
*-------------------------------------------------------------------------
97
97
*/
@@ -2329,23 +2329,53 @@ copytup_heap(Tuplesortstate *state, SortTuple *stup, void *tup)
2329
2329
}
2330
2330
2331
2331
/*
2332
- * We don't bother to write the HeapTupleData part of the tuple.
2332
+ * When writing HeapTuples to tape, we strip off all tuple identity and
2333
+ * transaction visibility information, because those fields aren't really
2334
+ * interesting for in-memory tuples (they may or may not be valid in the
2335
+ * incoming tuples, depending on the plan that's feeding the sort). We
2336
+ * only need to store t_natts, t_infomask, the nulls bitmap if any, and
2337
+ * the user data.
2338
+ *
2339
+ * You might think that we could omit storing t_natts, but you'd be wrong:
2340
+ * the incoming tuple might be a physical disk tuple with fewer columns
2341
+ * than the table's current logical tupdesc.
2333
2342
*/
2343
+ typedef struct TapeTupleHeader
2344
+ {
2345
+ unsigned int tuplen ; /* required header of a tape item */
2346
+ int16 natts ; /* number of attributes */
2347
+ uint16 infomask ; /* various flag bits */
2348
+ /* nulls bitmap follows if HEAP_HASNULL, then actual tuple data */
2349
+ } TapeTupleHeader ;
2334
2350
2335
2351
static void
2336
2352
writetup_heap (Tuplesortstate * state , int tapenum , SortTuple * stup )
2337
2353
{
2338
2354
HeapTuple tuple = (HeapTuple ) stup -> tuple ;
2339
- unsigned int tuplen ;
2340
-
2341
- tuplen = tuple -> t_len + sizeof (tuplen );
2355
+ HeapTupleHeader t_data = tuple -> t_data ;
2356
+ TapeTupleHeader tapehdr ;
2357
+ unsigned int datalen ;
2358
+ unsigned int nullslen ;
2359
+
2360
+ Assert (tuple -> t_len >= t_data -> t_hoff );
2361
+ datalen = tuple -> t_len - t_data -> t_hoff ;
2362
+ if (HeapTupleHasNulls (tuple ))
2363
+ nullslen = BITMAPLEN (t_data -> t_natts );
2364
+ else
2365
+ nullslen = 0 ;
2366
+ tapehdr .tuplen = sizeof (TapeTupleHeader ) + nullslen + datalen ;
2367
+ tapehdr .natts = t_data -> t_natts ;
2368
+ tapehdr .infomask = t_data -> t_infomask ;
2342
2369
LogicalTapeWrite (state -> tapeset , tapenum ,
2343
- (void * ) & tuplen , sizeof (tuplen ));
2370
+ (void * ) & tapehdr , sizeof (tapehdr ));
2371
+ if (nullslen )
2372
+ LogicalTapeWrite (state -> tapeset , tapenum ,
2373
+ (void * ) t_data -> t_bits , nullslen );
2344
2374
LogicalTapeWrite (state -> tapeset , tapenum ,
2345
- (void * ) tuple -> t_data , tuple -> t_len );
2375
+ (char * ) t_data + t_data -> t_hoff , datalen );
2346
2376
if (state -> randomAccess ) /* need trailing length word? */
2347
2377
LogicalTapeWrite (state -> tapeset , tapenum ,
2348
- (void * ) & tuplen , sizeof (tuplen ));
2378
+ (void * ) & tapehdr . tuplen , sizeof (tapehdr . tuplen ));
2349
2379
2350
2380
FREEMEM (state , GetMemoryChunkSpace (tuple ));
2351
2381
heap_freetuple (tuple );
@@ -2355,22 +2385,59 @@ static void
2355
2385
readtup_heap (Tuplesortstate * state , SortTuple * stup ,
2356
2386
int tapenum , unsigned int len )
2357
2387
{
2358
- unsigned int tuplen = len - sizeof (unsigned int ) + HEAPTUPLESIZE ;
2359
- HeapTuple tuple = (HeapTuple ) palloc (tuplen );
2388
+ TapeTupleHeader tapehdr ;
2389
+ unsigned int datalen ;
2390
+ unsigned int nullslen ;
2391
+ unsigned int hoff ;
2392
+ HeapTuple tuple ;
2393
+ HeapTupleHeader t_data ;
2360
2394
2395
+ /* read in the rest of the header */
2396
+ if (LogicalTapeRead (state -> tapeset , tapenum ,
2397
+ (char * ) & tapehdr + sizeof (unsigned int ),
2398
+ sizeof (tapehdr ) - sizeof (unsigned int )) !=
2399
+ sizeof (tapehdr ) - sizeof (unsigned int ))
2400
+ elog (ERROR , "unexpected end of data" );
2401
+ /* reconstruct lengths of null bitmap and data part */
2402
+ if (tapehdr .infomask & HEAP_HASNULL )
2403
+ nullslen = BITMAPLEN (tapehdr .natts );
2404
+ else
2405
+ nullslen = 0 ;
2406
+ datalen = len - sizeof (TapeTupleHeader ) - nullslen ;
2407
+ /* determine overhead size of tuple (should match heap_form_tuple) */
2408
+ hoff = offsetof(HeapTupleHeaderData , t_bits ) + nullslen ;
2409
+ if (tapehdr .infomask & HEAP_HASOID )
2410
+ hoff += sizeof (Oid );
2411
+ hoff = MAXALIGN (hoff );
2412
+ /* Allocate the space in one chunk, like heap_form_tuple */
2413
+ tuple = (HeapTuple ) palloc (HEAPTUPLESIZE + hoff + datalen );
2361
2414
USEMEM (state , GetMemoryChunkSpace (tuple ));
2362
- /* reconstruct the HeapTupleData portion */
2363
- tuple -> t_len = len - sizeof (unsigned int );
2415
+ t_data = (HeapTupleHeader ) ((char * ) tuple + HEAPTUPLESIZE );
2416
+ /* make sure unused header fields are zeroed */
2417
+ MemSetAligned (t_data , 0 , hoff );
2418
+ /* reconstruct the HeapTupleData fields */
2419
+ tuple -> t_len = hoff + datalen ;
2364
2420
ItemPointerSetInvalid (& (tuple -> t_self ));
2365
2421
tuple -> t_tableOid = InvalidOid ;
2366
- tuple -> t_data = (HeapTupleHeader ) (((char * ) tuple ) + HEAPTUPLESIZE );
2367
- /* read in the tuple proper */
2368
- if (LogicalTapeRead (state -> tapeset , tapenum , (void * ) tuple -> t_data ,
2369
- tuple -> t_len ) != tuple -> t_len )
2422
+ tuple -> t_data = t_data ;
2423
+ /* reconstruct the HeapTupleHeaderData fields */
2424
+ ItemPointerSetInvalid (& (t_data -> t_ctid ));
2425
+ t_data -> t_natts = tapehdr .natts ;
2426
+ t_data -> t_infomask = (tapehdr .infomask & ~HEAP_XACT_MASK )
2427
+ | (HEAP_XMIN_INVALID | HEAP_XMAX_INVALID );
2428
+ t_data -> t_hoff = hoff ;
2429
+ /* read in the null bitmap if any */
2430
+ if (nullslen )
2431
+ if (LogicalTapeRead (state -> tapeset , tapenum ,
2432
+ (void * ) t_data -> t_bits , nullslen ) != nullslen )
2433
+ elog (ERROR , "unexpected end of data" );
2434
+ /* and the data proper */
2435
+ if (LogicalTapeRead (state -> tapeset , tapenum ,
2436
+ (char * ) t_data + hoff , datalen ) != datalen )
2370
2437
elog (ERROR , "unexpected end of data" );
2371
2438
if (state -> randomAccess ) /* need trailing length word? */
2372
- if (LogicalTapeRead (state -> tapeset , tapenum , (void * ) & tuplen ,
2373
- sizeof (tuplen )) != sizeof (tuplen ))
2439
+ if (LogicalTapeRead (state -> tapeset , tapenum , (void * ) & tapehdr . tuplen ,
2440
+ sizeof (tapehdr . tuplen )) != sizeof (tapehdr . tuplen ))
2374
2441
elog (ERROR , "unexpected end of data" );
2375
2442
stup -> tuple = (void * ) tuple ;
2376
2443
/* set up first-column key value */
0 commit comments