~ubuntu-branches/ubuntu/hardy/postgresql-8.4/hardy-backports

« back to all changes in this revision

Viewing changes to src/backend/access/common/heaptuple.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-03-20 12:00:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090320120013-hogj7egc5mjncc5g
Tags: upstream-8.4~0cvs20090328
ImportĀ upstreamĀ versionĀ 8.4~0cvs20090328

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * heaptuple.c
 
4
 *        This file contains heap tuple accessor and mutator routines, as well
 
5
 *        as various tuple utilities.
 
6
 *
 
7
 * Some notes about varlenas and this code:
 
8
 *
 
9
 * Before Postgres 8.3 varlenas always had a 4-byte length header, and
 
10
 * therefore always needed 4-byte alignment (at least).  This wasted space
 
11
 * for short varlenas, for example CHAR(1) took 5 bytes and could need up to
 
12
 * 3 additional padding bytes for alignment.
 
13
 *
 
14
 * Now, a short varlena (up to 126 data bytes) is reduced to a 1-byte header
 
15
 * and we don't align it.  To hide this from datatype-specific functions that
 
16
 * don't want to deal with it, such a datum is considered "toasted" and will
 
17
 * be expanded back to the normal 4-byte-header format by pg_detoast_datum.
 
18
 * (In performance-critical code paths we can use pg_detoast_datum_packed
 
19
 * and the appropriate access macros to avoid that overhead.)  Note that this
 
20
 * conversion is performed directly in heap_form_tuple, without invoking
 
21
 * tuptoaster.c.
 
22
 *
 
23
 * This change will break any code that assumes it needn't detoast values
 
24
 * that have been put into a tuple but never sent to disk.      Hopefully there
 
25
 * are few such places.
 
26
 *
 
27
 * Varlenas still have alignment 'i' (or 'd') in pg_type/pg_attribute, since
 
28
 * that's the normal requirement for the untoasted format.  But we ignore that
 
29
 * for the 1-byte-header format.  This means that the actual start position
 
30
 * of a varlena datum may vary depending on which format it has.  To determine
 
31
 * what is stored, we have to require that alignment padding bytes be zero.
 
32
 * (Postgres actually has always zeroed them, but now it's required!)  Since
 
33
 * the first byte of a 1-byte-header varlena can never be zero, we can examine
 
34
 * the first byte after the previous datum to tell if it's a pad byte or the
 
35
 * start of a 1-byte-header varlena.
 
36
 *
 
37
 * Note that while formerly we could rely on the first varlena column of a
 
38
 * system catalog to be at the offset suggested by the C struct for the
 
39
 * catalog, this is now risky: it's only safe if the preceding field is
 
40
 * word-aligned, so that there will never be any padding.
 
41
 *
 
42
 * We don't pack varlenas whose attstorage is 'p', since the data type
 
43
 * isn't expecting to have to detoast values.  This is used in particular
 
44
 * by oidvector and int2vector, which are used in the system catalogs
 
45
 * and we'd like to still refer to them via C struct offsets.
 
46
 *
 
47
 *
 
48
 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
 
49
 * Portions Copyright (c) 1994, Regents of the University of California
 
50
 *
 
51
 *
 
52
 * IDENTIFICATION
 
53
 *        $PostgreSQL$
 
54
 *
 
55
 *-------------------------------------------------------------------------
 
56
 */
 
57
 
 
58
#include "postgres.h"
 
59
 
 
60
#include "access/heapam.h"
 
61
#include "access/sysattr.h"
 
62
#include "access/tuptoaster.h"
 
63
#include "executor/tuptable.h"
 
64
 
 
65
 
 
66
/* Does att's datatype allow packing into the 1-byte-header varlena format? */
 
67
#define ATT_IS_PACKABLE(att) \
 
68
        ((att)->attlen == -1 && (att)->attstorage != 'p')
 
69
/* Use this if it's already known varlena */
 
70
#define VARLENA_ATT_IS_PACKABLE(att) \
 
71
        ((att)->attstorage != 'p')
 
72
 
 
73
 
 
74
/* ----------------------------------------------------------------
 
75
 *                                              misc support routines
 
76
 * ----------------------------------------------------------------
 
77
 */
 
78
 
 
79
 
 
80
/*
 
81
 * heap_compute_data_size
 
82
 *              Determine size of the data area of a tuple to be constructed
 
83
 */
 
84
Size
 
85
heap_compute_data_size(TupleDesc tupleDesc,
 
86
                                           Datum *values,
 
87
                                           bool *isnull)
 
88
{
 
89
        Size            data_length = 0;
 
90
        int                     i;
 
91
        int                     numberOfAttributes = tupleDesc->natts;
 
92
        Form_pg_attribute *att = tupleDesc->attrs;
 
93
 
 
94
        for (i = 0; i < numberOfAttributes; i++)
 
95
        {
 
96
                Datum           val;
 
97
 
 
98
                if (isnull[i])
 
99
                        continue;
 
100
 
 
101
                val = values[i];
 
102
 
 
103
                if (ATT_IS_PACKABLE(att[i]) &&
 
104
                        VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
 
105
                {
 
106
                        /*
 
107
                         * we're anticipating converting to a short varlena header, so
 
108
                         * adjust length and don't count any alignment
 
109
                         */
 
110
                        data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
 
111
                }
 
112
                else
 
113
                {
 
114
                        data_length = att_align_datum(data_length, att[i]->attalign,
 
115
                                                                                  att[i]->attlen, val);
 
116
                        data_length = att_addlength_datum(data_length, att[i]->attlen,
 
117
                                                                                          val);
 
118
                }
 
119
        }
 
120
 
 
121
        return data_length;
 
122
}
 
123
 
 
124
/*
 
125
 * heap_fill_tuple
 
126
 *              Load data portion of a tuple from values/isnull arrays
 
127
 *
 
128
 * We also fill the null bitmap (if any) and set the infomask bits
 
129
 * that reflect the tuple's data contents.
 
130
 *
 
131
 * NOTE: it is now REQUIRED that the caller have pre-zeroed the data area.
 
132
 */
 
133
void
 
134
heap_fill_tuple(TupleDesc tupleDesc,
 
135
                                Datum *values, bool *isnull,
 
136
                                char *data, Size data_size,
 
137
                                uint16 *infomask, bits8 *bit)
 
138
{
 
139
        bits8      *bitP;
 
140
        int                     bitmask;
 
141
        int                     i;
 
142
        int                     numberOfAttributes = tupleDesc->natts;
 
143
        Form_pg_attribute *att = tupleDesc->attrs;
 
144
 
 
145
#ifdef USE_ASSERT_CHECKING
 
146
        char       *start = data;
 
147
#endif
 
148
 
 
149
        if (bit != NULL)
 
150
        {
 
151
                bitP = &bit[-1];
 
152
                bitmask = HIGHBIT;
 
153
        }
 
154
        else
 
155
        {
 
156
                /* just to keep compiler quiet */
 
157
                bitP = NULL;
 
158
                bitmask = 0;
 
159
        }
 
160
 
 
161
        *infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTERNAL);
 
162
 
 
163
        for (i = 0; i < numberOfAttributes; i++)
 
164
        {
 
165
                Size            data_length;
 
166
 
 
167
                if (bit != NULL)
 
168
                {
 
169
                        if (bitmask != HIGHBIT)
 
170
                                bitmask <<= 1;
 
171
                        else
 
172
                        {
 
173
                                bitP += 1;
 
174
                                *bitP = 0x0;
 
175
                                bitmask = 1;
 
176
                        }
 
177
 
 
178
                        if (isnull[i])
 
179
                        {
 
180
                                *infomask |= HEAP_HASNULL;
 
181
                                continue;
 
182
                        }
 
183
 
 
184
                        *bitP |= bitmask;
 
185
                }
 
186
 
 
187
                /*
 
188
                 * XXX we use the att_align macros on the pointer value itself, not on
 
189
                 * an offset.  This is a bit of a hack.
 
190
                 */
 
191
 
 
192
                if (att[i]->attbyval)
 
193
                {
 
194
                        /* pass-by-value */
 
195
                        data = (char *) att_align_nominal((long) data, att[i]->attalign);
 
196
                        store_att_byval(data, values[i], att[i]->attlen);
 
197
                        data_length = att[i]->attlen;
 
198
                }
 
199
                else if (att[i]->attlen == -1)
 
200
                {
 
201
                        /* varlena */
 
202
                        Pointer         val = DatumGetPointer(values[i]);
 
203
 
 
204
                        *infomask |= HEAP_HASVARWIDTH;
 
205
                        if (VARATT_IS_EXTERNAL(val))
 
206
                        {
 
207
                                *infomask |= HEAP_HASEXTERNAL;
 
208
                                /* no alignment, since it's short by definition */
 
209
                                data_length = VARSIZE_EXTERNAL(val);
 
210
                                memcpy(data, val, data_length);
 
211
                        }
 
212
                        else if (VARATT_IS_SHORT(val))
 
213
                        {
 
214
                                /* no alignment for short varlenas */
 
215
                                data_length = VARSIZE_SHORT(val);
 
216
                                memcpy(data, val, data_length);
 
217
                        }
 
218
                        else if (VARLENA_ATT_IS_PACKABLE(att[i]) &&
 
219
                                         VARATT_CAN_MAKE_SHORT(val))
 
220
                        {
 
221
                                /* convert to short varlena -- no alignment */
 
222
                                data_length = VARATT_CONVERTED_SHORT_SIZE(val);
 
223
                                SET_VARSIZE_SHORT(data, data_length);
 
224
                                memcpy(data + 1, VARDATA(val), data_length - 1);
 
225
                        }
 
226
                        else
 
227
                        {
 
228
                                /* full 4-byte header varlena */
 
229
                                data = (char *) att_align_nominal((long) data,
 
230
                                                                                                  att[i]->attalign);
 
231
                                data_length = VARSIZE(val);
 
232
                                memcpy(data, val, data_length);
 
233
                        }
 
234
                }
 
235
                else if (att[i]->attlen == -2)
 
236
                {
 
237
                        /* cstring ... never needs alignment */
 
238
                        *infomask |= HEAP_HASVARWIDTH;
 
239
                        Assert(att[i]->attalign == 'c');
 
240
                        data_length = strlen(DatumGetCString(values[i])) + 1;
 
241
                        memcpy(data, DatumGetPointer(values[i]), data_length);
 
242
                }
 
243
                else
 
244
                {
 
245
                        /* fixed-length pass-by-reference */
 
246
                        data = (char *) att_align_nominal((long) data, att[i]->attalign);
 
247
                        Assert(att[i]->attlen > 0);
 
248
                        data_length = att[i]->attlen;
 
249
                        memcpy(data, DatumGetPointer(values[i]), data_length);
 
250
                }
 
251
 
 
252
                data += data_length;
 
253
        }
 
254
 
 
255
        Assert((data - start) == data_size);
 
256
}
 
257
 
 
258
 
 
259
/* ----------------------------------------------------------------
 
260
 *                                              heap tuple interface
 
261
 * ----------------------------------------------------------------
 
262
 */
 
263
 
 
264
/* ----------------
 
265
 *              heap_attisnull  - returns TRUE iff tuple attribute is not present
 
266
 * ----------------
 
267
 */
 
268
bool
 
269
heap_attisnull(HeapTuple tup, int attnum)
 
270
{
 
271
        if (attnum > (int) HeapTupleHeaderGetNatts(tup->t_data))
 
272
                return true;
 
273
 
 
274
        if (attnum > 0)
 
275
        {
 
276
                if (HeapTupleNoNulls(tup))
 
277
                        return false;
 
278
                return att_isnull(attnum - 1, tup->t_data->t_bits);
 
279
        }
 
280
 
 
281
        switch (attnum)
 
282
        {
 
283
                case TableOidAttributeNumber:
 
284
                case SelfItemPointerAttributeNumber:
 
285
                case ObjectIdAttributeNumber:
 
286
                case MinTransactionIdAttributeNumber:
 
287
                case MinCommandIdAttributeNumber:
 
288
                case MaxTransactionIdAttributeNumber:
 
289
                case MaxCommandIdAttributeNumber:
 
290
                        /* these are never null */
 
291
                        break;
 
292
 
 
293
                default:
 
294
                        elog(ERROR, "invalid attnum: %d", attnum);
 
295
        }
 
296
 
 
297
        return false;
 
298
}
 
299
 
 
300
/* ----------------
 
301
 *              nocachegetattr
 
302
 *
 
303
 *              This only gets called from fastgetattr() macro, in cases where
 
304
 *              we can't use a cacheoffset and the value is not null.
 
305
 *
 
306
 *              This caches attribute offsets in the attribute descriptor.
 
307
 *
 
308
 *              An alternative way to speed things up would be to cache offsets
 
309
 *              with the tuple, but that seems more difficult unless you take
 
310
 *              the storage hit of actually putting those offsets into the
 
311
 *              tuple you send to disk.  Yuck.
 
312
 *
 
313
 *              This scheme will be slightly slower than that, but should
 
314
 *              perform well for queries which hit large #'s of tuples.  After
 
315
 *              you cache the offsets once, examining all the other tuples using
 
316
 *              the same attribute descriptor will go much quicker. -cim 5/4/91
 
317
 *
 
318
 *              NOTE: if you need to change this code, see also heap_deform_tuple.
 
319
 *              Also see nocache_index_getattr, which is the same code for index
 
320
 *              tuples.
 
321
 * ----------------
 
322
 */
 
323
Datum
 
324
nocachegetattr(HeapTuple tuple,
 
325
                           int attnum,
 
326
                           TupleDesc tupleDesc,
 
327
                           bool *isnull)
 
328
{
 
329
        HeapTupleHeader tup = tuple->t_data;
 
330
        Form_pg_attribute *att = tupleDesc->attrs;
 
331
        char       *tp;                         /* ptr to data part of tuple */
 
332
        bits8      *bp = tup->t_bits;           /* ptr to null bitmap in tuple */
 
333
        bool            slow = false;   /* do we have to walk attrs? */
 
334
        int                     off;                    /* current offset within data */
 
335
 
 
336
        (void) isnull;                          /* not used */
 
337
 
 
338
        /* ----------------
 
339
         *       Three cases:
 
340
         *
 
341
         *       1: No nulls and no variable-width attributes.
 
342
         *       2: Has a null or a var-width AFTER att.
 
343
         *       3: Has nulls or var-widths BEFORE att.
 
344
         * ----------------
 
345
         */
 
346
 
 
347
#ifdef IN_MACRO
 
348
/* This is handled in the macro */
 
349
        Assert(attnum > 0);
 
350
 
 
351
        if (isnull)
 
352
                *isnull = false;
 
353
#endif
 
354
 
 
355
        attnum--;
 
356
 
 
357
        if (HeapTupleNoNulls(tuple))
 
358
        {
 
359
#ifdef IN_MACRO
 
360
/* This is handled in the macro */
 
361
                if (att[attnum]->attcacheoff >= 0)
 
362
                {
 
363
                        return fetchatt(att[attnum],
 
364
                                                        (char *) tup + tup->t_hoff +
 
365
                                                        att[attnum]->attcacheoff);
 
366
                }
 
367
#endif
 
368
        }
 
369
        else
 
370
        {
 
371
                /*
 
372
                 * there's a null somewhere in the tuple
 
373
                 *
 
374
                 * check to see if desired att is null
 
375
                 */
 
376
 
 
377
#ifdef IN_MACRO
 
378
/* This is handled in the macro */
 
379
                if (att_isnull(attnum, bp))
 
380
                {
 
381
                        if (isnull)
 
382
                                *isnull = true;
 
383
                        return (Datum) NULL;
 
384
                }
 
385
#endif
 
386
 
 
387
                /*
 
388
                 * Now check to see if any preceding bits are null...
 
389
                 */
 
390
                {
 
391
                        int                     byte = attnum >> 3;
 
392
                        int                     finalbit = attnum & 0x07;
 
393
 
 
394
                        /* check for nulls "before" final bit of last byte */
 
395
                        if ((~bp[byte]) & ((1 << finalbit) - 1))
 
396
                                slow = true;
 
397
                        else
 
398
                        {
 
399
                                /* check for nulls in any "earlier" bytes */
 
400
                                int                     i;
 
401
 
 
402
                                for (i = 0; i < byte; i++)
 
403
                                {
 
404
                                        if (bp[i] != 0xFF)
 
405
                                        {
 
406
                                                slow = true;
 
407
                                                break;
 
408
                                        }
 
409
                                }
 
410
                        }
 
411
                }
 
412
        }
 
413
 
 
414
        tp = (char *) tup + tup->t_hoff;
 
415
 
 
416
        if (!slow)
 
417
        {
 
418
                /*
 
419
                 * If we get here, there are no nulls up to and including the target
 
420
                 * attribute.  If we have a cached offset, we can use it.
 
421
                 */
 
422
                if (att[attnum]->attcacheoff >= 0)
 
423
                {
 
424
                        return fetchatt(att[attnum],
 
425
                                                        tp + att[attnum]->attcacheoff);
 
426
                }
 
427
 
 
428
                /*
 
429
                 * Otherwise, check for non-fixed-length attrs up to and including
 
430
                 * target.      If there aren't any, it's safe to cheaply initialize the
 
431
                 * cached offsets for these attrs.
 
432
                 */
 
433
                if (HeapTupleHasVarWidth(tuple))
 
434
                {
 
435
                        int                     j;
 
436
 
 
437
                        for (j = 0; j <= attnum; j++)
 
438
                        {
 
439
                                if (att[j]->attlen <= 0)
 
440
                                {
 
441
                                        slow = true;
 
442
                                        break;
 
443
                                }
 
444
                        }
 
445
                }
 
446
        }
 
447
 
 
448
        if (!slow)
 
449
        {
 
450
                int                     natts = tupleDesc->natts;
 
451
                int                     j = 1;
 
452
 
 
453
                /*
 
454
                 * If we get here, we have a tuple with no nulls or var-widths up to
 
455
                 * and including the target attribute, so we can use the cached offset
 
456
                 * ... only we don't have it yet, or we'd not have got here.  Since
 
457
                 * it's cheap to compute offsets for fixed-width columns, we take the
 
458
                 * opportunity to initialize the cached offsets for *all* the leading
 
459
                 * fixed-width columns, in hope of avoiding future visits to this
 
460
                 * routine.
 
461
                 */
 
462
                att[0]->attcacheoff = 0;
 
463
 
 
464
                /* we might have set some offsets in the slow path previously */
 
465
                while (j < natts && att[j]->attcacheoff > 0)
 
466
                        j++;
 
467
 
 
468
                off = att[j - 1]->attcacheoff + att[j - 1]->attlen;
 
469
 
 
470
                for (; j < natts; j++)
 
471
                {
 
472
                        if (att[j]->attlen <= 0)
 
473
                                break;
 
474
 
 
475
                        off = att_align_nominal(off, att[j]->attalign);
 
476
 
 
477
                        att[j]->attcacheoff = off;
 
478
 
 
479
                        off += att[j]->attlen;
 
480
                }
 
481
 
 
482
                Assert(j > attnum);
 
483
 
 
484
                off = att[attnum]->attcacheoff;
 
485
        }
 
486
        else
 
487
        {
 
488
                bool            usecache = true;
 
489
                int                     i;
 
490
 
 
491
                /*
 
492
                 * Now we know that we have to walk the tuple CAREFULLY.  But we still
 
493
                 * might be able to cache some offsets for next time.
 
494
                 *
 
495
                 * Note - This loop is a little tricky.  For each non-null attribute,
 
496
                 * we have to first account for alignment padding before the attr,
 
497
                 * then advance over the attr based on its length.      Nulls have no
 
498
                 * storage and no alignment padding either.  We can use/set
 
499
                 * attcacheoff until we reach either a null or a var-width attribute.
 
500
                 */
 
501
                off = 0;
 
502
                for (i = 0;; i++)               /* loop exit is at "break" */
 
503
                {
 
504
                        if (HeapTupleHasNulls(tuple) && att_isnull(i, bp))
 
505
                        {
 
506
                                usecache = false;
 
507
                                continue;               /* this cannot be the target att */
 
508
                        }
 
509
 
 
510
                        /* If we know the next offset, we can skip the rest */
 
511
                        if (usecache && att[i]->attcacheoff >= 0)
 
512
                                off = att[i]->attcacheoff;
 
513
                        else if (att[i]->attlen == -1)
 
514
                        {
 
515
                                /*
 
516
                                 * We can only cache the offset for a varlena attribute if the
 
517
                                 * offset is already suitably aligned, so that there would be
 
518
                                 * no pad bytes in any case: then the offset will be valid for
 
519
                                 * either an aligned or unaligned value.
 
520
                                 */
 
521
                                if (usecache &&
 
522
                                        off == att_align_nominal(off, att[i]->attalign))
 
523
                                        att[i]->attcacheoff = off;
 
524
                                else
 
525
                                {
 
526
                                        off = att_align_pointer(off, att[i]->attalign, -1,
 
527
                                                                                        tp + off);
 
528
                                        usecache = false;
 
529
                                }
 
530
                        }
 
531
                        else
 
532
                        {
 
533
                                /* not varlena, so safe to use att_align_nominal */
 
534
                                off = att_align_nominal(off, att[i]->attalign);
 
535
 
 
536
                                if (usecache)
 
537
                                        att[i]->attcacheoff = off;
 
538
                        }
 
539
 
 
540
                        if (i == attnum)
 
541
                                break;
 
542
 
 
543
                        off = att_addlength_pointer(off, att[i]->attlen, tp + off);
 
544
 
 
545
                        if (usecache && att[i]->attlen <= 0)
 
546
                                usecache = false;
 
547
                }
 
548
        }
 
549
 
 
550
        return fetchatt(att[attnum], tp + off);
 
551
}
 
552
 
 
553
/* ----------------
 
554
 *              heap_getsysattr
 
555
 *
 
556
 *              Fetch the value of a system attribute for a tuple.
 
557
 *
 
558
 * This is a support routine for the heap_getattr macro.  The macro
 
559
 * has already determined that the attnum refers to a system attribute.
 
560
 * ----------------
 
561
 */
 
562
Datum
 
563
heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
 
564
{
 
565
        Datum           result;
 
566
 
 
567
        Assert(tup);
 
568
 
 
569
        /* Currently, no sys attribute ever reads as NULL. */
 
570
        if (isnull)
 
571
                *isnull = false;
 
572
 
 
573
        switch (attnum)
 
574
        {
 
575
                case SelfItemPointerAttributeNumber:
 
576
                        /* pass-by-reference datatype */
 
577
                        result = PointerGetDatum(&(tup->t_self));
 
578
                        break;
 
579
                case ObjectIdAttributeNumber:
 
580
                        result = ObjectIdGetDatum(HeapTupleGetOid(tup));
 
581
                        break;
 
582
                case MinTransactionIdAttributeNumber:
 
583
                        result = TransactionIdGetDatum(HeapTupleHeaderGetXmin(tup->t_data));
 
584
                        break;
 
585
                case MaxTransactionIdAttributeNumber:
 
586
                        result = TransactionIdGetDatum(HeapTupleHeaderGetXmax(tup->t_data));
 
587
                        break;
 
588
                case MinCommandIdAttributeNumber:
 
589
                case MaxCommandIdAttributeNumber:
 
590
 
 
591
                        /*
 
592
                         * cmin and cmax are now both aliases for the same field, which
 
593
                         * can in fact also be a combo command id.      XXX perhaps we should
 
594
                         * return the "real" cmin or cmax if possible, that is if we are
 
595
                         * inside the originating transaction?
 
596
                         */
 
597
                        result = CommandIdGetDatum(HeapTupleHeaderGetRawCommandId(tup->t_data));
 
598
                        break;
 
599
                case TableOidAttributeNumber:
 
600
                        result = ObjectIdGetDatum(tup->t_tableOid);
 
601
                        break;
 
602
                default:
 
603
                        elog(ERROR, "invalid attnum: %d", attnum);
 
604
                        result = 0;                     /* keep compiler quiet */
 
605
                        break;
 
606
        }
 
607
        return result;
 
608
}
 
609
 
 
610
/* ----------------
 
611
 *              heap_copytuple
 
612
 *
 
613
 *              returns a copy of an entire tuple
 
614
 *
 
615
 * The HeapTuple struct, tuple header, and tuple data are all allocated
 
616
 * as a single palloc() block.
 
617
 * ----------------
 
618
 */
 
619
HeapTuple
 
620
heap_copytuple(HeapTuple tuple)
 
621
{
 
622
        HeapTuple       newTuple;
 
623
 
 
624
        if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
 
625
                return NULL;
 
626
 
 
627
        newTuple = (HeapTuple) palloc(HEAPTUPLESIZE + tuple->t_len);
 
628
        newTuple->t_len = tuple->t_len;
 
629
        newTuple->t_self = tuple->t_self;
 
630
        newTuple->t_tableOid = tuple->t_tableOid;
 
631
        newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
 
632
        memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_len);
 
633
        return newTuple;
 
634
}
 
635
 
 
636
/* ----------------
 
637
 *              heap_copytuple_with_tuple
 
638
 *
 
639
 *              copy a tuple into a caller-supplied HeapTuple management struct
 
640
 *
 
641
 * Note that after calling this function, the "dest" HeapTuple will not be
 
642
 * allocated as a single palloc() block (unlike with heap_copytuple()).
 
643
 * ----------------
 
644
 */
 
645
void
 
646
heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
 
647
{
 
648
        if (!HeapTupleIsValid(src) || src->t_data == NULL)
 
649
        {
 
650
                dest->t_data = NULL;
 
651
                return;
 
652
        }
 
653
 
 
654
        dest->t_len = src->t_len;
 
655
        dest->t_self = src->t_self;
 
656
        dest->t_tableOid = src->t_tableOid;
 
657
        dest->t_data = (HeapTupleHeader) palloc(src->t_len);
 
658
        memcpy((char *) dest->t_data, (char *) src->t_data, src->t_len);
 
659
}
 
660
 
 
661
/*
 
662
 * heap_form_tuple
 
663
 *              construct a tuple from the given values[] and isnull[] arrays,
 
664
 *              which are of the length indicated by tupleDescriptor->natts
 
665
 *
 
666
 * The result is allocated in the current memory context.
 
667
 */
 
668
HeapTuple
 
669
heap_form_tuple(TupleDesc tupleDescriptor,
 
670
                                Datum *values,
 
671
                                bool *isnull)
 
672
{
 
673
        HeapTuple       tuple;                  /* return tuple */
 
674
        HeapTupleHeader td;                     /* tuple data */
 
675
        Size            len,
 
676
                                data_len;
 
677
        int                     hoff;
 
678
        bool            hasnull = false;
 
679
        Form_pg_attribute *att = tupleDescriptor->attrs;
 
680
        int                     numberOfAttributes = tupleDescriptor->natts;
 
681
        int                     i;
 
682
 
 
683
        if (numberOfAttributes > MaxTupleAttributeNumber)
 
684
                ereport(ERROR,
 
685
                                (errcode(ERRCODE_TOO_MANY_COLUMNS),
 
686
                                 errmsg("number of columns (%d) exceeds limit (%d)",
 
687
                                                numberOfAttributes, MaxTupleAttributeNumber)));
 
688
 
 
689
        /*
 
690
         * Check for nulls and embedded tuples; expand any toasted attributes in
 
691
         * embedded tuples.  This preserves the invariant that toasting can only
 
692
         * go one level deep.
 
693
         *
 
694
         * We can skip calling toast_flatten_tuple_attribute() if the attribute
 
695
         * couldn't possibly be of composite type.  All composite datums are
 
696
         * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
 
697
         * if an attribute is already toasted, it must have been sent to disk
 
698
         * already and so cannot contain toasted attributes.
 
699
         */
 
700
        for (i = 0; i < numberOfAttributes; i++)
 
701
        {
 
702
                if (isnull[i])
 
703
                        hasnull = true;
 
704
                else if (att[i]->attlen == -1 &&
 
705
                                 att[i]->attalign == 'd' &&
 
706
                                 att[i]->attndims == 0 &&
 
707
                                 !VARATT_IS_EXTENDED(DatumGetPointer(values[i])))
 
708
                {
 
709
                        values[i] = toast_flatten_tuple_attribute(values[i],
 
710
                                                                                                          att[i]->atttypid,
 
711
                                                                                                          att[i]->atttypmod);
 
712
                }
 
713
        }
 
714
 
 
715
        /*
 
716
         * Determine total space needed
 
717
         */
 
718
        len = offsetof(HeapTupleHeaderData, t_bits);
 
719
 
 
720
        if (hasnull)
 
721
                len += BITMAPLEN(numberOfAttributes);
 
722
 
 
723
        if (tupleDescriptor->tdhasoid)
 
724
                len += sizeof(Oid);
 
725
 
 
726
        hoff = len = MAXALIGN(len); /* align user data safely */
 
727
 
 
728
        data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
 
729
 
 
730
        len += data_len;
 
731
 
 
732
        /*
 
733
         * Allocate and zero the space needed.  Note that the tuple body and
 
734
         * HeapTupleData management structure are allocated in one chunk.
 
735
         */
 
736
        tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
 
737
        tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
 
738
 
 
739
        /*
 
740
         * And fill in the information.  Note we fill the Datum fields even though
 
741
         * this tuple may never become a Datum.
 
742
         */
 
743
        tuple->t_len = len;
 
744
        ItemPointerSetInvalid(&(tuple->t_self));
 
745
        tuple->t_tableOid = InvalidOid;
 
746
 
 
747
        HeapTupleHeaderSetDatumLength(td, len);
 
748
        HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
 
749
        HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
 
750
 
 
751
        HeapTupleHeaderSetNatts(td, numberOfAttributes);
 
752
        td->t_hoff = hoff;
 
753
 
 
754
        if (tupleDescriptor->tdhasoid)          /* else leave infomask = 0 */
 
755
                td->t_infomask = HEAP_HASOID;
 
756
 
 
757
        heap_fill_tuple(tupleDescriptor,
 
758
                                        values,
 
759
                                        isnull,
 
760
                                        (char *) td + hoff,
 
761
                                        data_len,
 
762
                                        &td->t_infomask,
 
763
                                        (hasnull ? td->t_bits : NULL));
 
764
 
 
765
        return tuple;
 
766
}
 
767
 
 
768
/*
 
769
 *              heap_formtuple
 
770
 *
 
771
 *              construct a tuple from the given values[] and nulls[] arrays
 
772
 *
 
773
 *              Null attributes are indicated by a 'n' in the appropriate byte
 
774
 *              of nulls[]. Non-null attributes are indicated by a ' ' (space).
 
775
 *
 
776
 * OLD API with char 'n'/' ' convention for indicating nulls.
 
777
 * This is deprecated and should not be used in new code, but we keep it
 
778
 * around for use by old add-on modules.
 
779
 */
 
780
HeapTuple
 
781
heap_formtuple(TupleDesc tupleDescriptor,
 
782
                           Datum *values,
 
783
                           char *nulls)
 
784
{
 
785
        HeapTuple       tuple;                  /* return tuple */
 
786
        int                     numberOfAttributes = tupleDescriptor->natts;
 
787
        bool       *boolNulls = (bool *) palloc(numberOfAttributes * sizeof(bool));
 
788
        int                     i;
 
789
 
 
790
        for (i = 0; i < numberOfAttributes; i++)
 
791
                boolNulls[i] = (nulls[i] == 'n');
 
792
 
 
793
        tuple = heap_form_tuple(tupleDescriptor, values, boolNulls);
 
794
 
 
795
        pfree(boolNulls);
 
796
 
 
797
        return tuple;
 
798
}
 
799
 
 
800
 
 
801
/*
 
802
 * heap_modify_tuple
 
803
 *              form a new tuple from an old tuple and a set of replacement values.
 
804
 *
 
805
 * The replValues, replIsnull, and doReplace arrays must be of the length
 
806
 * indicated by tupleDesc->natts.  The new tuple is constructed using the data
 
807
 * from replValues/replIsnull at columns where doReplace is true, and using
 
808
 * the data from the old tuple at columns where doReplace is false.
 
809
 *
 
810
 * The result is allocated in the current memory context.
 
811
 */
 
812
HeapTuple
 
813
heap_modify_tuple(HeapTuple tuple,
 
814
                                  TupleDesc tupleDesc,
 
815
                                  Datum *replValues,
 
816
                                  bool *replIsnull,
 
817
                                  bool *doReplace)
 
818
{
 
819
        int                     numberOfAttributes = tupleDesc->natts;
 
820
        int                     attoff;
 
821
        Datum      *values;
 
822
        bool       *isnull;
 
823
        HeapTuple       newTuple;
 
824
 
 
825
        /*
 
826
         * allocate and fill values and isnull arrays from either the tuple or the
 
827
         * repl information, as appropriate.
 
828
         *
 
829
         * NOTE: it's debatable whether to use heap_deform_tuple() here or just
 
830
         * heap_getattr() only the non-replaced colums.  The latter could win if
 
831
         * there are many replaced columns and few non-replaced ones. However,
 
832
         * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
 
833
         * O(N^2) if there are many non-replaced columns, so it seems better to
 
834
         * err on the side of linear cost.
 
835
         */
 
836
        values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
 
837
        isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
 
838
 
 
839
        heap_deform_tuple(tuple, tupleDesc, values, isnull);
 
840
 
 
841
        for (attoff = 0; attoff < numberOfAttributes; attoff++)
 
842
        {
 
843
                if (doReplace[attoff])
 
844
                {
 
845
                        values[attoff] = replValues[attoff];
 
846
                        isnull[attoff] = replIsnull[attoff];
 
847
                }
 
848
        }
 
849
 
 
850
        /*
 
851
         * create a new tuple from the values and isnull arrays
 
852
         */
 
853
        newTuple = heap_form_tuple(tupleDesc, values, isnull);
 
854
 
 
855
        pfree(values);
 
856
        pfree(isnull);
 
857
 
 
858
        /*
 
859
         * copy the identification info of the old tuple: t_ctid, t_self, and OID
 
860
         * (if any)
 
861
         */
 
862
        newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
 
863
        newTuple->t_self = tuple->t_self;
 
864
        newTuple->t_tableOid = tuple->t_tableOid;
 
865
        if (tupleDesc->tdhasoid)
 
866
                HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
 
867
 
 
868
        return newTuple;
 
869
}
 
870
 
 
871
/*
 
872
 *              heap_modifytuple
 
873
 *
 
874
 *              forms a new tuple from an old tuple and a set of replacement values.
 
875
 *              returns a new palloc'ed tuple.
 
876
 *
 
877
 * OLD API with char 'n'/' ' convention for indicating nulls, and
 
878
 * char 'r'/' ' convention for indicating whether to replace columns.
 
879
 * This is deprecated and should not be used in new code, but we keep it
 
880
 * around for use by old add-on modules.
 
881
 */
 
882
HeapTuple
 
883
heap_modifytuple(HeapTuple tuple,
 
884
                                 TupleDesc tupleDesc,
 
885
                                 Datum *replValues,
 
886
                                 char *replNulls,
 
887
                                 char *replActions)
 
888
{
 
889
        HeapTuple       result;
 
890
        int                     numberOfAttributes = tupleDesc->natts;
 
891
        bool       *boolNulls = (bool *) palloc(numberOfAttributes * sizeof(bool));
 
892
        bool       *boolActions = (bool *) palloc(numberOfAttributes * sizeof(bool));
 
893
        int                     attnum;
 
894
 
 
895
        for (attnum = 0; attnum < numberOfAttributes; attnum++)
 
896
        {
 
897
                boolNulls[attnum] = (replNulls[attnum] == 'n');
 
898
                boolActions[attnum] = (replActions[attnum] == 'r');
 
899
        }
 
900
 
 
901
        result = heap_modify_tuple(tuple, tupleDesc, replValues, boolNulls, boolActions);
 
902
 
 
903
        pfree(boolNulls);
 
904
        pfree(boolActions);
 
905
 
 
906
        return result;
 
907
}
 
908
 
 
909
/*
 
910
 * heap_deform_tuple
 
911
 *              Given a tuple, extract data into values/isnull arrays; this is
 
912
 *              the inverse of heap_form_tuple.
 
913
 *
 
914
 *              Storage for the values/isnull arrays is provided by the caller;
 
915
 *              it should be sized according to tupleDesc->natts not tuple->t_natts.
 
916
 *
 
917
 *              Note that for pass-by-reference datatypes, the pointer placed
 
918
 *              in the Datum will point into the given tuple.
 
919
 *
 
920
 *              When all or most of a tuple's fields need to be extracted,
 
921
 *              this routine will be significantly quicker than a loop around
 
922
 *              heap_getattr; the loop will become O(N^2) as soon as any
 
923
 *              noncacheable attribute offsets are involved.
 
924
 */
 
925
void
 
926
heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
 
927
                                  Datum *values, bool *isnull)
 
928
{
 
929
        HeapTupleHeader tup = tuple->t_data;
 
930
        bool            hasnulls = HeapTupleHasNulls(tuple);
 
931
        Form_pg_attribute *att = tupleDesc->attrs;
 
932
        int                     tdesc_natts = tupleDesc->natts;
 
933
        int                     natts;                  /* number of atts to extract */
 
934
        int                     attnum;
 
935
        char       *tp;                         /* ptr to tuple data */
 
936
        long            off;                    /* offset in tuple data */
 
937
        bits8      *bp = tup->t_bits;           /* ptr to null bitmap in tuple */
 
938
        bool            slow = false;   /* can we use/set attcacheoff? */
 
939
 
 
940
        natts = HeapTupleHeaderGetNatts(tup);
 
941
 
 
942
        /*
 
943
         * In inheritance situations, it is possible that the given tuple actually
 
944
         * has more fields than the caller is expecting.  Don't run off the end of
 
945
         * the caller's arrays.
 
946
         */
 
947
        natts = Min(natts, tdesc_natts);
 
948
 
 
949
        tp = (char *) tup + tup->t_hoff;
 
950
 
 
951
        off = 0;
 
952
 
 
953
        for (attnum = 0; attnum < natts; attnum++)
 
954
        {
 
955
                Form_pg_attribute thisatt = att[attnum];
 
956
 
 
957
                if (hasnulls && att_isnull(attnum, bp))
 
958
                {
 
959
                        values[attnum] = (Datum) 0;
 
960
                        isnull[attnum] = true;
 
961
                        slow = true;            /* can't use attcacheoff anymore */
 
962
                        continue;
 
963
                }
 
964
 
 
965
                isnull[attnum] = false;
 
966
 
 
967
                if (!slow && thisatt->attcacheoff >= 0)
 
968
                        off = thisatt->attcacheoff;
 
969
                else if (thisatt->attlen == -1)
 
970
                {
 
971
                        /*
 
972
                         * We can only cache the offset for a varlena attribute if the
 
973
                         * offset is already suitably aligned, so that there would be no
 
974
                         * pad bytes in any case: then the offset will be valid for either
 
975
                         * an aligned or unaligned value.
 
976
                         */
 
977
                        if (!slow &&
 
978
                                off == att_align_nominal(off, thisatt->attalign))
 
979
                                thisatt->attcacheoff = off;
 
980
                        else
 
981
                        {
 
982
                                off = att_align_pointer(off, thisatt->attalign, -1,
 
983
                                                                                tp + off);
 
984
                                slow = true;
 
985
                        }
 
986
                }
 
987
                else
 
988
                {
 
989
                        /* not varlena, so safe to use att_align_nominal */
 
990
                        off = att_align_nominal(off, thisatt->attalign);
 
991
 
 
992
                        if (!slow)
 
993
                                thisatt->attcacheoff = off;
 
994
                }
 
995
 
 
996
                values[attnum] = fetchatt(thisatt, tp + off);
 
997
 
 
998
                off = att_addlength_pointer(off, thisatt->attlen, tp + off);
 
999
 
 
1000
                if (thisatt->attlen <= 0)
 
1001
                        slow = true;            /* can't use attcacheoff anymore */
 
1002
        }
 
1003
 
 
1004
        /*
 
1005
         * If tuple doesn't have all the atts indicated by tupleDesc, read the
 
1006
         * rest as null
 
1007
         */
 
1008
        for (; attnum < tdesc_natts; attnum++)
 
1009
        {
 
1010
                values[attnum] = (Datum) 0;
 
1011
                isnull[attnum] = true;
 
1012
        }
 
1013
}
 
1014
 
 
1015
/*
 
1016
 *              heap_deformtuple
 
1017
 *
 
1018
 *              Given a tuple, extract data into values/nulls arrays; this is
 
1019
 *              the inverse of heap_formtuple.
 
1020
 *
 
1021
 *              Storage for the values/nulls arrays is provided by the caller;
 
1022
 *              it should be sized according to tupleDesc->natts not tuple->t_natts.
 
1023
 *
 
1024
 *              Note that for pass-by-reference datatypes, the pointer placed
 
1025
 *              in the Datum will point into the given tuple.
 
1026
 *
 
1027
 *              When all or most of a tuple's fields need to be extracted,
 
1028
 *              this routine will be significantly quicker than a loop around
 
1029
 *              heap_getattr; the loop will become O(N^2) as soon as any
 
1030
 *              noncacheable attribute offsets are involved.
 
1031
 *
 
1032
 * OLD API with char 'n'/' ' convention for indicating nulls.
 
1033
 * This is deprecated and should not be used in new code, but we keep it
 
1034
 * around for use by old add-on modules.
 
1035
 */
 
1036
void
 
1037
heap_deformtuple(HeapTuple tuple,
 
1038
                                 TupleDesc tupleDesc,
 
1039
                                 Datum *values,
 
1040
                                 char *nulls)
 
1041
{
 
1042
        int                     natts = tupleDesc->natts;
 
1043
        bool       *boolNulls = (bool *) palloc(natts * sizeof(bool));
 
1044
        int                     attnum;
 
1045
 
 
1046
        heap_deform_tuple(tuple, tupleDesc, values, boolNulls);
 
1047
 
 
1048
        for (attnum = 0; attnum < natts; attnum++)
 
1049
                nulls[attnum] = (boolNulls[attnum] ? 'n' : ' ');
 
1050
 
 
1051
        pfree(boolNulls);
 
1052
}
 
1053
 
 
1054
/*
 
1055
 * slot_deform_tuple
 
1056
 *              Given a TupleTableSlot, extract data from the slot's physical tuple
 
1057
 *              into its Datum/isnull arrays.  Data is extracted up through the
 
1058
 *              natts'th column (caller must ensure this is a legal column number).
 
1059
 *
 
1060
 *              This is essentially an incremental version of heap_deform_tuple:
 
1061
 *              on each call we extract attributes up to the one needed, without
 
1062
 *              re-computing information about previously extracted attributes.
 
1063
 *              slot->tts_nvalid is the number of attributes already extracted.
 
1064
 */
 
1065
static void
 
1066
slot_deform_tuple(TupleTableSlot *slot, int natts)
 
1067
{
 
1068
        HeapTuple       tuple = slot->tts_tuple;
 
1069
        TupleDesc       tupleDesc = slot->tts_tupleDescriptor;
 
1070
        Datum      *values = slot->tts_values;
 
1071
        bool       *isnull = slot->tts_isnull;
 
1072
        HeapTupleHeader tup = tuple->t_data;
 
1073
        bool            hasnulls = HeapTupleHasNulls(tuple);
 
1074
        Form_pg_attribute *att = tupleDesc->attrs;
 
1075
        int                     attnum;
 
1076
        char       *tp;                         /* ptr to tuple data */
 
1077
        long            off;                    /* offset in tuple data */
 
1078
        bits8      *bp = tup->t_bits;           /* ptr to null bitmap in tuple */
 
1079
        bool            slow;                   /* can we use/set attcacheoff? */
 
1080
 
 
1081
        /*
 
1082
         * Check whether the first call for this tuple, and initialize or restore
 
1083
         * loop state.
 
1084
         */
 
1085
        attnum = slot->tts_nvalid;
 
1086
        if (attnum == 0)
 
1087
        {
 
1088
                /* Start from the first attribute */
 
1089
                off = 0;
 
1090
                slow = false;
 
1091
        }
 
1092
        else
 
1093
        {
 
1094
                /* Restore state from previous execution */
 
1095
                off = slot->tts_off;
 
1096
                slow = slot->tts_slow;
 
1097
        }
 
1098
 
 
1099
        tp = (char *) tup + tup->t_hoff;
 
1100
 
 
1101
        for (; attnum < natts; attnum++)
 
1102
        {
 
1103
                Form_pg_attribute thisatt = att[attnum];
 
1104
 
 
1105
                if (hasnulls && att_isnull(attnum, bp))
 
1106
                {
 
1107
                        values[attnum] = (Datum) 0;
 
1108
                        isnull[attnum] = true;
 
1109
                        slow = true;            /* can't use attcacheoff anymore */
 
1110
                        continue;
 
1111
                }
 
1112
 
 
1113
                isnull[attnum] = false;
 
1114
 
 
1115
                if (!slow && thisatt->attcacheoff >= 0)
 
1116
                        off = thisatt->attcacheoff;
 
1117
                else if (thisatt->attlen == -1)
 
1118
                {
 
1119
                        /*
 
1120
                         * We can only cache the offset for a varlena attribute if the
 
1121
                         * offset is already suitably aligned, so that there would be no
 
1122
                         * pad bytes in any case: then the offset will be valid for either
 
1123
                         * an aligned or unaligned value.
 
1124
                         */
 
1125
                        if (!slow &&
 
1126
                                off == att_align_nominal(off, thisatt->attalign))
 
1127
                                thisatt->attcacheoff = off;
 
1128
                        else
 
1129
                        {
 
1130
                                off = att_align_pointer(off, thisatt->attalign, -1,
 
1131
                                                                                tp + off);
 
1132
                                slow = true;
 
1133
                        }
 
1134
                }
 
1135
                else
 
1136
                {
 
1137
                        /* not varlena, so safe to use att_align_nominal */
 
1138
                        off = att_align_nominal(off, thisatt->attalign);
 
1139
 
 
1140
                        if (!slow)
 
1141
                                thisatt->attcacheoff = off;
 
1142
                }
 
1143
 
 
1144
                values[attnum] = fetchatt(thisatt, tp + off);
 
1145
 
 
1146
                off = att_addlength_pointer(off, thisatt->attlen, tp + off);
 
1147
 
 
1148
                if (thisatt->attlen <= 0)
 
1149
                        slow = true;            /* can't use attcacheoff anymore */
 
1150
        }
 
1151
 
 
1152
        /*
 
1153
         * Save state for next execution
 
1154
         */
 
1155
        slot->tts_nvalid = attnum;
 
1156
        slot->tts_off = off;
 
1157
        slot->tts_slow = slow;
 
1158
}
 
1159
 
 
1160
/*
 
1161
 * slot_getattr
 
1162
 *              This function fetches an attribute of the slot's current tuple.
 
1163
 *              It is functionally equivalent to heap_getattr, but fetches of
 
1164
 *              multiple attributes of the same tuple will be optimized better,
 
1165
 *              because we avoid O(N^2) behavior from multiple calls of
 
1166
 *              nocachegetattr(), even when attcacheoff isn't usable.
 
1167
 *
 
1168
 *              A difference from raw heap_getattr is that attnums beyond the
 
1169
 *              slot's tupdesc's last attribute will be considered NULL even
 
1170
 *              when the physical tuple is longer than the tupdesc.
 
1171
 */
 
1172
Datum
 
1173
slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
 
1174
{
 
1175
        HeapTuple       tuple = slot->tts_tuple;
 
1176
        TupleDesc       tupleDesc = slot->tts_tupleDescriptor;
 
1177
        HeapTupleHeader tup;
 
1178
 
 
1179
        /*
 
1180
         * system attributes are handled by heap_getsysattr
 
1181
         */
 
1182
        if (attnum <= 0)
 
1183
        {
 
1184
                if (tuple == NULL)              /* internal error */
 
1185
                        elog(ERROR, "cannot extract system attribute from virtual tuple");
 
1186
                if (slot->tts_mintuple) /* internal error */
 
1187
                        elog(ERROR, "cannot extract system attribute from minimal tuple");
 
1188
                return heap_getsysattr(tuple, attnum, tupleDesc, isnull);
 
1189
        }
 
1190
 
 
1191
        /*
 
1192
         * fast path if desired attribute already cached
 
1193
         */
 
1194
        if (attnum <= slot->tts_nvalid)
 
1195
        {
 
1196
                *isnull = slot->tts_isnull[attnum - 1];
 
1197
                return slot->tts_values[attnum - 1];
 
1198
        }
 
1199
 
 
1200
        /*
 
1201
         * return NULL if attnum is out of range according to the tupdesc
 
1202
         */
 
1203
        if (attnum > tupleDesc->natts)
 
1204
        {
 
1205
                *isnull = true;
 
1206
                return (Datum) 0;
 
1207
        }
 
1208
 
 
1209
        /*
 
1210
         * otherwise we had better have a physical tuple (tts_nvalid should equal
 
1211
         * natts in all virtual-tuple cases)
 
1212
         */
 
1213
        if (tuple == NULL)                      /* internal error */
 
1214
                elog(ERROR, "cannot extract attribute from empty tuple slot");
 
1215
 
 
1216
        /*
 
1217
         * return NULL if attnum is out of range according to the tuple
 
1218
         *
 
1219
         * (We have to check this separately because of various inheritance and
 
1220
         * table-alteration scenarios: the tuple could be either longer or shorter
 
1221
         * than the tupdesc.)
 
1222
         */
 
1223
        tup = tuple->t_data;
 
1224
        if (attnum > HeapTupleHeaderGetNatts(tup))
 
1225
        {
 
1226
                *isnull = true;
 
1227
                return (Datum) 0;
 
1228
        }
 
1229
 
 
1230
        /*
 
1231
         * check if target attribute is null: no point in groveling through tuple
 
1232
         */
 
1233
        if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
 
1234
        {
 
1235
                *isnull = true;
 
1236
                return (Datum) 0;
 
1237
        }
 
1238
 
 
1239
        /*
 
1240
         * If the attribute's column has been dropped, we force a NULL result.
 
1241
         * This case should not happen in normal use, but it could happen if we
 
1242
         * are executing a plan cached before the column was dropped.
 
1243
         */
 
1244
        if (tupleDesc->attrs[attnum - 1]->attisdropped)
 
1245
        {
 
1246
                *isnull = true;
 
1247
                return (Datum) 0;
 
1248
        }
 
1249
 
 
1250
        /*
 
1251
         * Extract the attribute, along with any preceding attributes.
 
1252
         */
 
1253
        slot_deform_tuple(slot, attnum);
 
1254
 
 
1255
        /*
 
1256
         * The result is acquired from tts_values array.
 
1257
         */
 
1258
        *isnull = slot->tts_isnull[attnum - 1];
 
1259
        return slot->tts_values[attnum - 1];
 
1260
}
 
1261
 
 
1262
/*
 
1263
 * slot_getallattrs
 
1264
 *              This function forces all the entries of the slot's Datum/isnull
 
1265
 *              arrays to be valid.  The caller may then extract data directly
 
1266
 *              from those arrays instead of using slot_getattr.
 
1267
 */
 
1268
void
 
1269
slot_getallattrs(TupleTableSlot *slot)
 
1270
{
 
1271
        int                     tdesc_natts = slot->tts_tupleDescriptor->natts;
 
1272
        int                     attnum;
 
1273
        HeapTuple       tuple;
 
1274
 
 
1275
        /* Quick out if we have 'em all already */
 
1276
        if (slot->tts_nvalid == tdesc_natts)
 
1277
                return;
 
1278
 
 
1279
        /*
 
1280
         * otherwise we had better have a physical tuple (tts_nvalid should equal
 
1281
         * natts in all virtual-tuple cases)
 
1282
         */
 
1283
        tuple = slot->tts_tuple;
 
1284
        if (tuple == NULL)                      /* internal error */
 
1285
                elog(ERROR, "cannot extract attribute from empty tuple slot");
 
1286
 
 
1287
        /*
 
1288
         * load up any slots available from physical tuple
 
1289
         */
 
1290
        attnum = HeapTupleHeaderGetNatts(tuple->t_data);
 
1291
        attnum = Min(attnum, tdesc_natts);
 
1292
 
 
1293
        slot_deform_tuple(slot, attnum);
 
1294
 
 
1295
        /*
 
1296
         * If tuple doesn't have all the atts indicated by tupleDesc, read the
 
1297
         * rest as null
 
1298
         */
 
1299
        for (; attnum < tdesc_natts; attnum++)
 
1300
        {
 
1301
                slot->tts_values[attnum] = (Datum) 0;
 
1302
                slot->tts_isnull[attnum] = true;
 
1303
        }
 
1304
        slot->tts_nvalid = tdesc_natts;
 
1305
}
 
1306
 
 
1307
/*
 
1308
 * slot_getsomeattrs
 
1309
 *              This function forces the entries of the slot's Datum/isnull
 
1310
 *              arrays to be valid at least up through the attnum'th entry.
 
1311
 */
 
1312
void
 
1313
slot_getsomeattrs(TupleTableSlot *slot, int attnum)
 
1314
{
 
1315
        HeapTuple       tuple;
 
1316
        int                     attno;
 
1317
 
 
1318
        /* Quick out if we have 'em all already */
 
1319
        if (slot->tts_nvalid >= attnum)
 
1320
                return;
 
1321
 
 
1322
        /* Check for caller error */
 
1323
        if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts)
 
1324
                elog(ERROR, "invalid attribute number %d", attnum);
 
1325
 
 
1326
        /*
 
1327
         * otherwise we had better have a physical tuple (tts_nvalid should equal
 
1328
         * natts in all virtual-tuple cases)
 
1329
         */
 
1330
        tuple = slot->tts_tuple;
 
1331
        if (tuple == NULL)                      /* internal error */
 
1332
                elog(ERROR, "cannot extract attribute from empty tuple slot");
 
1333
 
 
1334
        /*
 
1335
         * load up any slots available from physical tuple
 
1336
         */
 
1337
        attno = HeapTupleHeaderGetNatts(tuple->t_data);
 
1338
        attno = Min(attno, attnum);
 
1339
 
 
1340
        slot_deform_tuple(slot, attno);
 
1341
 
 
1342
        /*
 
1343
         * If tuple doesn't have all the atts indicated by tupleDesc, read the
 
1344
         * rest as null
 
1345
         */
 
1346
        for (; attno < attnum; attno++)
 
1347
        {
 
1348
                slot->tts_values[attno] = (Datum) 0;
 
1349
                slot->tts_isnull[attno] = true;
 
1350
        }
 
1351
        slot->tts_nvalid = attnum;
 
1352
}
 
1353
 
 
1354
/*
 
1355
 * slot_attisnull
 
1356
 *              Detect whether an attribute of the slot is null, without
 
1357
 *              actually fetching it.
 
1358
 */
 
1359
bool
 
1360
slot_attisnull(TupleTableSlot *slot, int attnum)
 
1361
{
 
1362
        HeapTuple       tuple = slot->tts_tuple;
 
1363
        TupleDesc       tupleDesc = slot->tts_tupleDescriptor;
 
1364
 
 
1365
        /*
 
1366
         * system attributes are handled by heap_attisnull
 
1367
         */
 
1368
        if (attnum <= 0)
 
1369
        {
 
1370
                if (tuple == NULL)              /* internal error */
 
1371
                        elog(ERROR, "cannot extract system attribute from virtual tuple");
 
1372
                if (slot->tts_mintuple) /* internal error */
 
1373
                        elog(ERROR, "cannot extract system attribute from minimal tuple");
 
1374
                return heap_attisnull(tuple, attnum);
 
1375
        }
 
1376
 
 
1377
        /*
 
1378
         * fast path if desired attribute already cached
 
1379
         */
 
1380
        if (attnum <= slot->tts_nvalid)
 
1381
                return slot->tts_isnull[attnum - 1];
 
1382
 
 
1383
        /*
 
1384
         * return NULL if attnum is out of range according to the tupdesc
 
1385
         */
 
1386
        if (attnum > tupleDesc->natts)
 
1387
                return true;
 
1388
 
 
1389
        /*
 
1390
         * otherwise we had better have a physical tuple (tts_nvalid should equal
 
1391
         * natts in all virtual-tuple cases)
 
1392
         */
 
1393
        if (tuple == NULL)                      /* internal error */
 
1394
                elog(ERROR, "cannot extract attribute from empty tuple slot");
 
1395
 
 
1396
        /* and let the tuple tell it */
 
1397
        return heap_attisnull(tuple, attnum);
 
1398
}
 
1399
 
 
1400
/*
 
1401
 * heap_freetuple
 
1402
 */
 
1403
void
 
1404
heap_freetuple(HeapTuple htup)
 
1405
{
 
1406
        pfree(htup);
 
1407
}
 
1408
 
 
1409
 
 
1410
/*
 
1411
 * heap_form_minimal_tuple
 
1412
 *              construct a MinimalTuple from the given values[] and isnull[] arrays,
 
1413
 *              which are of the length indicated by tupleDescriptor->natts
 
1414
 *
 
1415
 * This is exactly like heap_form_tuple() except that the result is a
 
1416
 * "minimal" tuple lacking a HeapTupleData header as well as room for system
 
1417
 * columns.
 
1418
 *
 
1419
 * The result is allocated in the current memory context.
 
1420
 */
 
1421
MinimalTuple
 
1422
heap_form_minimal_tuple(TupleDesc tupleDescriptor,
 
1423
                                                Datum *values,
 
1424
                                                bool *isnull)
 
1425
{
 
1426
        MinimalTuple tuple;                     /* return tuple */
 
1427
        Size            len,
 
1428
                                data_len;
 
1429
        int                     hoff;
 
1430
        bool            hasnull = false;
 
1431
        Form_pg_attribute *att = tupleDescriptor->attrs;
 
1432
        int                     numberOfAttributes = tupleDescriptor->natts;
 
1433
        int                     i;
 
1434
 
 
1435
        if (numberOfAttributes > MaxTupleAttributeNumber)
 
1436
                ereport(ERROR,
 
1437
                                (errcode(ERRCODE_TOO_MANY_COLUMNS),
 
1438
                                 errmsg("number of columns (%d) exceeds limit (%d)",
 
1439
                                                numberOfAttributes, MaxTupleAttributeNumber)));
 
1440
 
 
1441
        /*
 
1442
         * Check for nulls and embedded tuples; expand any toasted attributes in
 
1443
         * embedded tuples.  This preserves the invariant that toasting can only
 
1444
         * go one level deep.
 
1445
         *
 
1446
         * We can skip calling toast_flatten_tuple_attribute() if the attribute
 
1447
         * couldn't possibly be of composite type.  All composite datums are
 
1448
         * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
 
1449
         * if an attribute is already toasted, it must have been sent to disk
 
1450
         * already and so cannot contain toasted attributes.
 
1451
         */
 
1452
        for (i = 0; i < numberOfAttributes; i++)
 
1453
        {
 
1454
                if (isnull[i])
 
1455
                        hasnull = true;
 
1456
                else if (att[i]->attlen == -1 &&
 
1457
                                 att[i]->attalign == 'd' &&
 
1458
                                 att[i]->attndims == 0 &&
 
1459
                                 !VARATT_IS_EXTENDED(values[i]))
 
1460
                {
 
1461
                        values[i] = toast_flatten_tuple_attribute(values[i],
 
1462
                                                                                                          att[i]->atttypid,
 
1463
                                                                                                          att[i]->atttypmod);
 
1464
                }
 
1465
        }
 
1466
 
 
1467
        /*
 
1468
         * Determine total space needed
 
1469
         */
 
1470
        len = offsetof(MinimalTupleData, t_bits);
 
1471
 
 
1472
        if (hasnull)
 
1473
                len += BITMAPLEN(numberOfAttributes);
 
1474
 
 
1475
        if (tupleDescriptor->tdhasoid)
 
1476
                len += sizeof(Oid);
 
1477
 
 
1478
        hoff = len = MAXALIGN(len); /* align user data safely */
 
1479
 
 
1480
        data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
 
1481
 
 
1482
        len += data_len;
 
1483
 
 
1484
        /*
 
1485
         * Allocate and zero the space needed.
 
1486
         */
 
1487
        tuple = (MinimalTuple) palloc0(len);
 
1488
 
 
1489
        /*
 
1490
         * And fill in the information.
 
1491
         */
 
1492
        tuple->t_len = len;
 
1493
        HeapTupleHeaderSetNatts(tuple, numberOfAttributes);
 
1494
        tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
 
1495
 
 
1496
        if (tupleDescriptor->tdhasoid)          /* else leave infomask = 0 */
 
1497
                tuple->t_infomask = HEAP_HASOID;
 
1498
 
 
1499
        heap_fill_tuple(tupleDescriptor,
 
1500
                                        values,
 
1501
                                        isnull,
 
1502
                                        (char *) tuple + hoff,
 
1503
                                        data_len,
 
1504
                                        &tuple->t_infomask,
 
1505
                                        (hasnull ? tuple->t_bits : NULL));
 
1506
 
 
1507
        return tuple;
 
1508
}
 
1509
 
 
1510
/*
 
1511
 * heap_free_minimal_tuple
 
1512
 */
 
1513
void
 
1514
heap_free_minimal_tuple(MinimalTuple mtup)
 
1515
{
 
1516
        pfree(mtup);
 
1517
}
 
1518
 
 
1519
/*
 
1520
 * heap_copy_minimal_tuple
 
1521
 *              copy a MinimalTuple
 
1522
 *
 
1523
 * The result is allocated in the current memory context.
 
1524
 */
 
1525
MinimalTuple
 
1526
heap_copy_minimal_tuple(MinimalTuple mtup)
 
1527
{
 
1528
        MinimalTuple result;
 
1529
 
 
1530
        result = (MinimalTuple) palloc(mtup->t_len);
 
1531
        memcpy(result, mtup, mtup->t_len);
 
1532
        return result;
 
1533
}
 
1534
 
 
1535
/*
 
1536
 * heap_tuple_from_minimal_tuple
 
1537
 *              create a HeapTuple by copying from a MinimalTuple;
 
1538
 *              system columns are filled with zeroes
 
1539
 *
 
1540
 * The result is allocated in the current memory context.
 
1541
 * The HeapTuple struct, tuple header, and tuple data are all allocated
 
1542
 * as a single palloc() block.
 
1543
 */
 
1544
HeapTuple
 
1545
heap_tuple_from_minimal_tuple(MinimalTuple mtup)
 
1546
{
 
1547
        HeapTuple       result;
 
1548
        uint32          len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
 
1549
 
 
1550
        result = (HeapTuple) palloc(HEAPTUPLESIZE + len);
 
1551
        result->t_len = len;
 
1552
        ItemPointerSetInvalid(&(result->t_self));
 
1553
        result->t_tableOid = InvalidOid;
 
1554
        result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
 
1555
        memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len);
 
1556
        memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_infomask2));
 
1557
        return result;
 
1558
}
 
1559
 
 
1560
/*
 
1561
 * minimal_tuple_from_heap_tuple
 
1562
 *              create a MinimalTuple by copying from a HeapTuple
 
1563
 *
 
1564
 * The result is allocated in the current memory context.
 
1565
 */
 
1566
MinimalTuple
 
1567
minimal_tuple_from_heap_tuple(HeapTuple htup)
 
1568
{
 
1569
        MinimalTuple result;
 
1570
        uint32          len;
 
1571
 
 
1572
        Assert(htup->t_len > MINIMAL_TUPLE_OFFSET);
 
1573
        len = htup->t_len - MINIMAL_TUPLE_OFFSET;
 
1574
        result = (MinimalTuple) palloc(len);
 
1575
        memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len);
 
1576
        result->t_len = len;
 
1577
        return result;
 
1578
}