00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 #include "postgres.h"
00059
00060 #include "access/sysattr.h"
00061 #include "access/tuptoaster.h"
00062 #include "executor/tuptable.h"
00063
00064
00065
00066 #define ATT_IS_PACKABLE(att) \
00067 ((att)->attlen == -1 && (att)->attstorage != 'p')
00068
00069 #define VARLENA_ATT_IS_PACKABLE(att) \
00070 ((att)->attstorage != 'p')
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 Size
00084 heap_compute_data_size(TupleDesc tupleDesc,
00085 Datum *values,
00086 bool *isnull)
00087 {
00088 Size data_length = 0;
00089 int i;
00090 int numberOfAttributes = tupleDesc->natts;
00091 Form_pg_attribute *att = tupleDesc->attrs;
00092
00093 for (i = 0; i < numberOfAttributes; i++)
00094 {
00095 Datum val;
00096
00097 if (isnull[i])
00098 continue;
00099
00100 val = values[i];
00101
00102 if (ATT_IS_PACKABLE(att[i]) &&
00103 VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
00104 {
00105
00106
00107
00108
00109 data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
00110 }
00111 else
00112 {
00113 data_length = att_align_datum(data_length, att[i]->attalign,
00114 att[i]->attlen, val);
00115 data_length = att_addlength_datum(data_length, att[i]->attlen,
00116 val);
00117 }
00118 }
00119
00120 return data_length;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 void
00133 heap_fill_tuple(TupleDesc tupleDesc,
00134 Datum *values, bool *isnull,
00135 char *data, Size data_size,
00136 uint16 *infomask, bits8 *bit)
00137 {
00138 bits8 *bitP;
00139 int bitmask;
00140 int i;
00141 int numberOfAttributes = tupleDesc->natts;
00142 Form_pg_attribute *att = tupleDesc->attrs;
00143
00144 #ifdef USE_ASSERT_CHECKING
00145 char *start = data;
00146 #endif
00147
00148 if (bit != NULL)
00149 {
00150 bitP = &bit[-1];
00151 bitmask = HIGHBIT;
00152 }
00153 else
00154 {
00155
00156 bitP = NULL;
00157 bitmask = 0;
00158 }
00159
00160 *infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTERNAL);
00161
00162 for (i = 0; i < numberOfAttributes; i++)
00163 {
00164 Size data_length;
00165
00166 if (bit != NULL)
00167 {
00168 if (bitmask != HIGHBIT)
00169 bitmask <<= 1;
00170 else
00171 {
00172 bitP += 1;
00173 *bitP = 0x0;
00174 bitmask = 1;
00175 }
00176
00177 if (isnull[i])
00178 {
00179 *infomask |= HEAP_HASNULL;
00180 continue;
00181 }
00182
00183 *bitP |= bitmask;
00184 }
00185
00186
00187
00188
00189
00190
00191 if (att[i]->attbyval)
00192 {
00193
00194 data = (char *) att_align_nominal(data, att[i]->attalign);
00195 store_att_byval(data, values[i], att[i]->attlen);
00196 data_length = att[i]->attlen;
00197 }
00198 else if (att[i]->attlen == -1)
00199 {
00200
00201 Pointer val = DatumGetPointer(values[i]);
00202
00203 *infomask |= HEAP_HASVARWIDTH;
00204 if (VARATT_IS_EXTERNAL(val))
00205 {
00206 *infomask |= HEAP_HASEXTERNAL;
00207
00208 data_length = VARSIZE_EXTERNAL(val);
00209 memcpy(data, val, data_length);
00210 }
00211 else if (VARATT_IS_SHORT(val))
00212 {
00213
00214 data_length = VARSIZE_SHORT(val);
00215 memcpy(data, val, data_length);
00216 }
00217 else if (VARLENA_ATT_IS_PACKABLE(att[i]) &&
00218 VARATT_CAN_MAKE_SHORT(val))
00219 {
00220
00221 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
00222 SET_VARSIZE_SHORT(data, data_length);
00223 memcpy(data + 1, VARDATA(val), data_length - 1);
00224 }
00225 else
00226 {
00227
00228 data = (char *) att_align_nominal(data,
00229 att[i]->attalign);
00230 data_length = VARSIZE(val);
00231 memcpy(data, val, data_length);
00232 }
00233 }
00234 else if (att[i]->attlen == -2)
00235 {
00236
00237 *infomask |= HEAP_HASVARWIDTH;
00238 Assert(att[i]->attalign == 'c');
00239 data_length = strlen(DatumGetCString(values[i])) + 1;
00240 memcpy(data, DatumGetPointer(values[i]), data_length);
00241 }
00242 else
00243 {
00244
00245 data = (char *) att_align_nominal(data, att[i]->attalign);
00246 Assert(att[i]->attlen > 0);
00247 data_length = att[i]->attlen;
00248 memcpy(data, DatumGetPointer(values[i]), data_length);
00249 }
00250
00251 data += data_length;
00252 }
00253
00254 Assert((data - start) == data_size);
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 bool
00268 heap_attisnull(HeapTuple tup, int attnum)
00269 {
00270 if (attnum > (int) HeapTupleHeaderGetNatts(tup->t_data))
00271 return true;
00272
00273 if (attnum > 0)
00274 {
00275 if (HeapTupleNoNulls(tup))
00276 return false;
00277 return att_isnull(attnum - 1, tup->t_data->t_bits);
00278 }
00279
00280 switch (attnum)
00281 {
00282 case TableOidAttributeNumber:
00283 case SelfItemPointerAttributeNumber:
00284 case ObjectIdAttributeNumber:
00285 case MinTransactionIdAttributeNumber:
00286 case MinCommandIdAttributeNumber:
00287 case MaxTransactionIdAttributeNumber:
00288 case MaxCommandIdAttributeNumber:
00289
00290 break;
00291
00292 default:
00293 elog(ERROR, "invalid attnum: %d", attnum);
00294 }
00295
00296 return false;
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 Datum
00323 nocachegetattr(HeapTuple tuple,
00324 int attnum,
00325 TupleDesc tupleDesc)
00326 {
00327 HeapTupleHeader tup = tuple->t_data;
00328 Form_pg_attribute *att = tupleDesc->attrs;
00329 char *tp;
00330 bits8 *bp = tup->t_bits;
00331 bool slow = false;
00332 int off;
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343 attnum--;
00344
00345 if (!HeapTupleNoNulls(tuple))
00346 {
00347
00348
00349
00350
00351
00352 int byte = attnum >> 3;
00353 int finalbit = attnum & 0x07;
00354
00355
00356 if ((~bp[byte]) & ((1 << finalbit) - 1))
00357 slow = true;
00358 else
00359 {
00360
00361 int i;
00362
00363 for (i = 0; i < byte; i++)
00364 {
00365 if (bp[i] != 0xFF)
00366 {
00367 slow = true;
00368 break;
00369 }
00370 }
00371 }
00372 }
00373
00374 tp = (char *) tup + tup->t_hoff;
00375
00376 if (!slow)
00377 {
00378
00379
00380
00381
00382 if (att[attnum]->attcacheoff >= 0)
00383 {
00384 return fetchatt(att[attnum],
00385 tp + att[attnum]->attcacheoff);
00386 }
00387
00388
00389
00390
00391
00392
00393 if (HeapTupleHasVarWidth(tuple))
00394 {
00395 int j;
00396
00397 for (j = 0; j <= attnum; j++)
00398 {
00399 if (att[j]->attlen <= 0)
00400 {
00401 slow = true;
00402 break;
00403 }
00404 }
00405 }
00406 }
00407
00408 if (!slow)
00409 {
00410 int natts = tupleDesc->natts;
00411 int j = 1;
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 att[0]->attcacheoff = 0;
00423
00424
00425 while (j < natts && att[j]->attcacheoff > 0)
00426 j++;
00427
00428 off = att[j - 1]->attcacheoff + att[j - 1]->attlen;
00429
00430 for (; j < natts; j++)
00431 {
00432 if (att[j]->attlen <= 0)
00433 break;
00434
00435 off = att_align_nominal(off, att[j]->attalign);
00436
00437 att[j]->attcacheoff = off;
00438
00439 off += att[j]->attlen;
00440 }
00441
00442 Assert(j > attnum);
00443
00444 off = att[attnum]->attcacheoff;
00445 }
00446 else
00447 {
00448 bool usecache = true;
00449 int i;
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 off = 0;
00462 for (i = 0;; i++)
00463 {
00464 if (HeapTupleHasNulls(tuple) && att_isnull(i, bp))
00465 {
00466 usecache = false;
00467 continue;
00468 }
00469
00470
00471 if (usecache && att[i]->attcacheoff >= 0)
00472 off = att[i]->attcacheoff;
00473 else if (att[i]->attlen == -1)
00474 {
00475
00476
00477
00478
00479
00480
00481 if (usecache &&
00482 off == att_align_nominal(off, att[i]->attalign))
00483 att[i]->attcacheoff = off;
00484 else
00485 {
00486 off = att_align_pointer(off, att[i]->attalign, -1,
00487 tp + off);
00488 usecache = false;
00489 }
00490 }
00491 else
00492 {
00493
00494 off = att_align_nominal(off, att[i]->attalign);
00495
00496 if (usecache)
00497 att[i]->attcacheoff = off;
00498 }
00499
00500 if (i == attnum)
00501 break;
00502
00503 off = att_addlength_pointer(off, att[i]->attlen, tp + off);
00504
00505 if (usecache && att[i]->attlen <= 0)
00506 usecache = false;
00507 }
00508 }
00509
00510 return fetchatt(att[attnum], tp + off);
00511 }
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522 Datum
00523 heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
00524 {
00525 Datum result;
00526
00527 Assert(tup);
00528
00529
00530 *isnull = false;
00531
00532 switch (attnum)
00533 {
00534 case SelfItemPointerAttributeNumber:
00535
00536 result = PointerGetDatum(&(tup->t_self));
00537 break;
00538 case ObjectIdAttributeNumber:
00539 result = ObjectIdGetDatum(HeapTupleGetOid(tup));
00540 break;
00541 case MinTransactionIdAttributeNumber:
00542 result = TransactionIdGetDatum(HeapTupleHeaderGetXmin(tup->t_data));
00543 break;
00544 case MaxTransactionIdAttributeNumber:
00545 result = TransactionIdGetDatum(HeapTupleHeaderGetRawXmax(tup->t_data));
00546 break;
00547 case MinCommandIdAttributeNumber:
00548 case MaxCommandIdAttributeNumber:
00549
00550
00551
00552
00553
00554
00555
00556 result = CommandIdGetDatum(HeapTupleHeaderGetRawCommandId(tup->t_data));
00557 break;
00558 case TableOidAttributeNumber:
00559 result = ObjectIdGetDatum(tup->t_tableOid);
00560 break;
00561 default:
00562 elog(ERROR, "invalid attnum: %d", attnum);
00563 result = 0;
00564 break;
00565 }
00566 return result;
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 HeapTuple
00579 heap_copytuple(HeapTuple tuple)
00580 {
00581 HeapTuple newTuple;
00582
00583 if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
00584 return NULL;
00585
00586 newTuple = (HeapTuple) palloc(HEAPTUPLESIZE + tuple->t_len);
00587 newTuple->t_len = tuple->t_len;
00588 newTuple->t_self = tuple->t_self;
00589 newTuple->t_tableOid = tuple->t_tableOid;
00590 newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
00591 memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_len);
00592 return newTuple;
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 void
00605 heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
00606 {
00607 if (!HeapTupleIsValid(src) || src->t_data == NULL)
00608 {
00609 dest->t_data = NULL;
00610 return;
00611 }
00612
00613 dest->t_len = src->t_len;
00614 dest->t_self = src->t_self;
00615 dest->t_tableOid = src->t_tableOid;
00616 dest->t_data = (HeapTupleHeader) palloc(src->t_len);
00617 memcpy((char *) dest->t_data, (char *) src->t_data, src->t_len);
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627 HeapTuple
00628 heap_form_tuple(TupleDesc tupleDescriptor,
00629 Datum *values,
00630 bool *isnull)
00631 {
00632 HeapTuple tuple;
00633 HeapTupleHeader td;
00634 Size len,
00635 data_len;
00636 int hoff;
00637 bool hasnull = false;
00638 Form_pg_attribute *att = tupleDescriptor->attrs;
00639 int numberOfAttributes = tupleDescriptor->natts;
00640 int i;
00641
00642 if (numberOfAttributes > MaxTupleAttributeNumber)
00643 ereport(ERROR,
00644 (errcode(ERRCODE_TOO_MANY_COLUMNS),
00645 errmsg("number of columns (%d) exceeds limit (%d)",
00646 numberOfAttributes, MaxTupleAttributeNumber)));
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 for (i = 0; i < numberOfAttributes; i++)
00660 {
00661 if (isnull[i])
00662 hasnull = true;
00663 else if (att[i]->attlen == -1 &&
00664 att[i]->attalign == 'd' &&
00665 att[i]->attndims == 0 &&
00666 !VARATT_IS_EXTENDED(DatumGetPointer(values[i])))
00667 {
00668 values[i] = toast_flatten_tuple_attribute(values[i],
00669 att[i]->atttypid,
00670 att[i]->atttypmod);
00671 }
00672 }
00673
00674
00675
00676
00677 len = offsetof(HeapTupleHeaderData, t_bits);
00678
00679 if (hasnull)
00680 len += BITMAPLEN(numberOfAttributes);
00681
00682 if (tupleDescriptor->tdhasoid)
00683 len += sizeof(Oid);
00684
00685 hoff = len = MAXALIGN(len);
00686
00687 data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
00688
00689 len += data_len;
00690
00691
00692
00693
00694
00695 tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
00696 tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
00697
00698
00699
00700
00701
00702 tuple->t_len = len;
00703 ItemPointerSetInvalid(&(tuple->t_self));
00704 tuple->t_tableOid = InvalidOid;
00705
00706 HeapTupleHeaderSetDatumLength(td, len);
00707 HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
00708 HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
00709
00710 HeapTupleHeaderSetNatts(td, numberOfAttributes);
00711 td->t_hoff = hoff;
00712
00713 if (tupleDescriptor->tdhasoid)
00714 td->t_infomask = HEAP_HASOID;
00715
00716 heap_fill_tuple(tupleDescriptor,
00717 values,
00718 isnull,
00719 (char *) td + hoff,
00720 data_len,
00721 &td->t_infomask,
00722 (hasnull ? td->t_bits : NULL));
00723
00724 return tuple;
00725 }
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739 HeapTuple
00740 heap_formtuple(TupleDesc tupleDescriptor,
00741 Datum *values,
00742 char *nulls)
00743 {
00744 HeapTuple tuple;
00745 int numberOfAttributes = tupleDescriptor->natts;
00746 bool *boolNulls = (bool *) palloc(numberOfAttributes * sizeof(bool));
00747 int i;
00748
00749 for (i = 0; i < numberOfAttributes; i++)
00750 boolNulls[i] = (nulls[i] == 'n');
00751
00752 tuple = heap_form_tuple(tupleDescriptor, values, boolNulls);
00753
00754 pfree(boolNulls);
00755
00756 return tuple;
00757 }
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771 HeapTuple
00772 heap_modify_tuple(HeapTuple tuple,
00773 TupleDesc tupleDesc,
00774 Datum *replValues,
00775 bool *replIsnull,
00776 bool *doReplace)
00777 {
00778 int numberOfAttributes = tupleDesc->natts;
00779 int attoff;
00780 Datum *values;
00781 bool *isnull;
00782 HeapTuple newTuple;
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
00796 isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
00797
00798 heap_deform_tuple(tuple, tupleDesc, values, isnull);
00799
00800 for (attoff = 0; attoff < numberOfAttributes; attoff++)
00801 {
00802 if (doReplace[attoff])
00803 {
00804 values[attoff] = replValues[attoff];
00805 isnull[attoff] = replIsnull[attoff];
00806 }
00807 }
00808
00809
00810
00811
00812 newTuple = heap_form_tuple(tupleDesc, values, isnull);
00813
00814 pfree(values);
00815 pfree(isnull);
00816
00817
00818
00819
00820
00821 newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
00822 newTuple->t_self = tuple->t_self;
00823 newTuple->t_tableOid = tuple->t_tableOid;
00824 if (tupleDesc->tdhasoid)
00825 HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
00826
00827 return newTuple;
00828 }
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841 HeapTuple
00842 heap_modifytuple(HeapTuple tuple,
00843 TupleDesc tupleDesc,
00844 Datum *replValues,
00845 char *replNulls,
00846 char *replActions)
00847 {
00848 HeapTuple result;
00849 int numberOfAttributes = tupleDesc->natts;
00850 bool *boolNulls = (bool *) palloc(numberOfAttributes * sizeof(bool));
00851 bool *boolActions = (bool *) palloc(numberOfAttributes * sizeof(bool));
00852 int attnum;
00853
00854 for (attnum = 0; attnum < numberOfAttributes; attnum++)
00855 {
00856 boolNulls[attnum] = (replNulls[attnum] == 'n');
00857 boolActions[attnum] = (replActions[attnum] == 'r');
00858 }
00859
00860 result = heap_modify_tuple(tuple, tupleDesc, replValues, boolNulls, boolActions);
00861
00862 pfree(boolNulls);
00863 pfree(boolActions);
00864
00865 return result;
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885 void
00886 heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
00887 Datum *values, bool *isnull)
00888 {
00889 HeapTupleHeader tup = tuple->t_data;
00890 bool hasnulls = HeapTupleHasNulls(tuple);
00891 Form_pg_attribute *att = tupleDesc->attrs;
00892 int tdesc_natts = tupleDesc->natts;
00893 int natts;
00894 int attnum;
00895 char *tp;
00896 long off;
00897 bits8 *bp = tup->t_bits;
00898 bool slow = false;
00899
00900 natts = HeapTupleHeaderGetNatts(tup);
00901
00902
00903
00904
00905
00906
00907 natts = Min(natts, tdesc_natts);
00908
00909 tp = (char *) tup + tup->t_hoff;
00910
00911 off = 0;
00912
00913 for (attnum = 0; attnum < natts; attnum++)
00914 {
00915 Form_pg_attribute thisatt = att[attnum];
00916
00917 if (hasnulls && att_isnull(attnum, bp))
00918 {
00919 values[attnum] = (Datum) 0;
00920 isnull[attnum] = true;
00921 slow = true;
00922 continue;
00923 }
00924
00925 isnull[attnum] = false;
00926
00927 if (!slow && thisatt->attcacheoff >= 0)
00928 off = thisatt->attcacheoff;
00929 else if (thisatt->attlen == -1)
00930 {
00931
00932
00933
00934
00935
00936
00937 if (!slow &&
00938 off == att_align_nominal(off, thisatt->attalign))
00939 thisatt->attcacheoff = off;
00940 else
00941 {
00942 off = att_align_pointer(off, thisatt->attalign, -1,
00943 tp + off);
00944 slow = true;
00945 }
00946 }
00947 else
00948 {
00949
00950 off = att_align_nominal(off, thisatt->attalign);
00951
00952 if (!slow)
00953 thisatt->attcacheoff = off;
00954 }
00955
00956 values[attnum] = fetchatt(thisatt, tp + off);
00957
00958 off = att_addlength_pointer(off, thisatt->attlen, tp + off);
00959
00960 if (thisatt->attlen <= 0)
00961 slow = true;
00962 }
00963
00964
00965
00966
00967
00968 for (; attnum < tdesc_natts; attnum++)
00969 {
00970 values[attnum] = (Datum) 0;
00971 isnull[attnum] = true;
00972 }
00973 }
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997 void
00998 heap_deformtuple(HeapTuple tuple,
00999 TupleDesc tupleDesc,
01000 Datum *values,
01001 char *nulls)
01002 {
01003 int natts = tupleDesc->natts;
01004 bool *boolNulls = (bool *) palloc(natts * sizeof(bool));
01005 int attnum;
01006
01007 heap_deform_tuple(tuple, tupleDesc, values, boolNulls);
01008
01009 for (attnum = 0; attnum < natts; attnum++)
01010 nulls[attnum] = (boolNulls[attnum] ? 'n' : ' ');
01011
01012 pfree(boolNulls);
01013 }
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026 static void
01027 slot_deform_tuple(TupleTableSlot *slot, int natts)
01028 {
01029 HeapTuple tuple = slot->tts_tuple;
01030 TupleDesc tupleDesc = slot->tts_tupleDescriptor;
01031 Datum *values = slot->tts_values;
01032 bool *isnull = slot->tts_isnull;
01033 HeapTupleHeader tup = tuple->t_data;
01034 bool hasnulls = HeapTupleHasNulls(tuple);
01035 Form_pg_attribute *att = tupleDesc->attrs;
01036 int attnum;
01037 char *tp;
01038 long off;
01039 bits8 *bp = tup->t_bits;
01040 bool slow;
01041
01042
01043
01044
01045
01046 attnum = slot->tts_nvalid;
01047 if (attnum == 0)
01048 {
01049
01050 off = 0;
01051 slow = false;
01052 }
01053 else
01054 {
01055
01056 off = slot->tts_off;
01057 slow = slot->tts_slow;
01058 }
01059
01060 tp = (char *) tup + tup->t_hoff;
01061
01062 for (; attnum < natts; attnum++)
01063 {
01064 Form_pg_attribute thisatt = att[attnum];
01065
01066 if (hasnulls && att_isnull(attnum, bp))
01067 {
01068 values[attnum] = (Datum) 0;
01069 isnull[attnum] = true;
01070 slow = true;
01071 continue;
01072 }
01073
01074 isnull[attnum] = false;
01075
01076 if (!slow && thisatt->attcacheoff >= 0)
01077 off = thisatt->attcacheoff;
01078 else if (thisatt->attlen == -1)
01079 {
01080
01081
01082
01083
01084
01085
01086 if (!slow &&
01087 off == att_align_nominal(off, thisatt->attalign))
01088 thisatt->attcacheoff = off;
01089 else
01090 {
01091 off = att_align_pointer(off, thisatt->attalign, -1,
01092 tp + off);
01093 slow = true;
01094 }
01095 }
01096 else
01097 {
01098
01099 off = att_align_nominal(off, thisatt->attalign);
01100
01101 if (!slow)
01102 thisatt->attcacheoff = off;
01103 }
01104
01105 values[attnum] = fetchatt(thisatt, tp + off);
01106
01107 off = att_addlength_pointer(off, thisatt->attlen, tp + off);
01108
01109 if (thisatt->attlen <= 0)
01110 slow = true;
01111 }
01112
01113
01114
01115
01116 slot->tts_nvalid = attnum;
01117 slot->tts_off = off;
01118 slot->tts_slow = slow;
01119 }
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133 Datum
01134 slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
01135 {
01136 HeapTuple tuple = slot->tts_tuple;
01137 TupleDesc tupleDesc = slot->tts_tupleDescriptor;
01138 HeapTupleHeader tup;
01139
01140
01141
01142
01143 if (attnum <= 0)
01144 {
01145 if (tuple == NULL)
01146 elog(ERROR, "cannot extract system attribute from virtual tuple");
01147 if (tuple == &(slot->tts_minhdr))
01148 elog(ERROR, "cannot extract system attribute from minimal tuple");
01149 return heap_getsysattr(tuple, attnum, tupleDesc, isnull);
01150 }
01151
01152
01153
01154
01155 if (attnum <= slot->tts_nvalid)
01156 {
01157 *isnull = slot->tts_isnull[attnum - 1];
01158 return slot->tts_values[attnum - 1];
01159 }
01160
01161
01162
01163
01164 if (attnum > tupleDesc->natts)
01165 {
01166 *isnull = true;
01167 return (Datum) 0;
01168 }
01169
01170
01171
01172
01173
01174 if (tuple == NULL)
01175 elog(ERROR, "cannot extract attribute from empty tuple slot");
01176
01177
01178
01179
01180
01181
01182
01183
01184 tup = tuple->t_data;
01185 if (attnum > HeapTupleHeaderGetNatts(tup))
01186 {
01187 *isnull = true;
01188 return (Datum) 0;
01189 }
01190
01191
01192
01193
01194 if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
01195 {
01196 *isnull = true;
01197 return (Datum) 0;
01198 }
01199
01200
01201
01202
01203
01204
01205 if (tupleDesc->attrs[attnum - 1]->attisdropped)
01206 {
01207 *isnull = true;
01208 return (Datum) 0;
01209 }
01210
01211
01212
01213
01214 slot_deform_tuple(slot, attnum);
01215
01216
01217
01218
01219 *isnull = slot->tts_isnull[attnum - 1];
01220 return slot->tts_values[attnum - 1];
01221 }
01222
01223
01224
01225
01226
01227
01228
01229 void
01230 slot_getallattrs(TupleTableSlot *slot)
01231 {
01232 int tdesc_natts = slot->tts_tupleDescriptor->natts;
01233 int attnum;
01234 HeapTuple tuple;
01235
01236
01237 if (slot->tts_nvalid == tdesc_natts)
01238 return;
01239
01240
01241
01242
01243
01244 tuple = slot->tts_tuple;
01245 if (tuple == NULL)
01246 elog(ERROR, "cannot extract attribute from empty tuple slot");
01247
01248
01249
01250
01251 attnum = HeapTupleHeaderGetNatts(tuple->t_data);
01252 attnum = Min(attnum, tdesc_natts);
01253
01254 slot_deform_tuple(slot, attnum);
01255
01256
01257
01258
01259
01260 for (; attnum < tdesc_natts; attnum++)
01261 {
01262 slot->tts_values[attnum] = (Datum) 0;
01263 slot->tts_isnull[attnum] = true;
01264 }
01265 slot->tts_nvalid = tdesc_natts;
01266 }
01267
01268
01269
01270
01271
01272
01273 void
01274 slot_getsomeattrs(TupleTableSlot *slot, int attnum)
01275 {
01276 HeapTuple tuple;
01277 int attno;
01278
01279
01280 if (slot->tts_nvalid >= attnum)
01281 return;
01282
01283
01284 if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts)
01285 elog(ERROR, "invalid attribute number %d", attnum);
01286
01287
01288
01289
01290
01291 tuple = slot->tts_tuple;
01292 if (tuple == NULL)
01293 elog(ERROR, "cannot extract attribute from empty tuple slot");
01294
01295
01296
01297
01298 attno = HeapTupleHeaderGetNatts(tuple->t_data);
01299 attno = Min(attno, attnum);
01300
01301 slot_deform_tuple(slot, attno);
01302
01303
01304
01305
01306
01307 for (; attno < attnum; attno++)
01308 {
01309 slot->tts_values[attno] = (Datum) 0;
01310 slot->tts_isnull[attno] = true;
01311 }
01312 slot->tts_nvalid = attnum;
01313 }
01314
01315
01316
01317
01318
01319
01320 bool
01321 slot_attisnull(TupleTableSlot *slot, int attnum)
01322 {
01323 HeapTuple tuple = slot->tts_tuple;
01324 TupleDesc tupleDesc = slot->tts_tupleDescriptor;
01325
01326
01327
01328
01329 if (attnum <= 0)
01330 {
01331 if (tuple == NULL)
01332 elog(ERROR, "cannot extract system attribute from virtual tuple");
01333 if (tuple == &(slot->tts_minhdr))
01334 elog(ERROR, "cannot extract system attribute from minimal tuple");
01335 return heap_attisnull(tuple, attnum);
01336 }
01337
01338
01339
01340
01341 if (attnum <= slot->tts_nvalid)
01342 return slot->tts_isnull[attnum - 1];
01343
01344
01345
01346
01347 if (attnum > tupleDesc->natts)
01348 return true;
01349
01350
01351
01352
01353
01354 if (tuple == NULL)
01355 elog(ERROR, "cannot extract attribute from empty tuple slot");
01356
01357
01358 return heap_attisnull(tuple, attnum);
01359 }
01360
01361
01362
01363
01364 void
01365 heap_freetuple(HeapTuple htup)
01366 {
01367 pfree(htup);
01368 }
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382 MinimalTuple
01383 heap_form_minimal_tuple(TupleDesc tupleDescriptor,
01384 Datum *values,
01385 bool *isnull)
01386 {
01387 MinimalTuple tuple;
01388 Size len,
01389 data_len;
01390 int hoff;
01391 bool hasnull = false;
01392 Form_pg_attribute *att = tupleDescriptor->attrs;
01393 int numberOfAttributes = tupleDescriptor->natts;
01394 int i;
01395
01396 if (numberOfAttributes > MaxTupleAttributeNumber)
01397 ereport(ERROR,
01398 (errcode(ERRCODE_TOO_MANY_COLUMNS),
01399 errmsg("number of columns (%d) exceeds limit (%d)",
01400 numberOfAttributes, MaxTupleAttributeNumber)));
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413 for (i = 0; i < numberOfAttributes; i++)
01414 {
01415 if (isnull[i])
01416 hasnull = true;
01417 else if (att[i]->attlen == -1 &&
01418 att[i]->attalign == 'd' &&
01419 att[i]->attndims == 0 &&
01420 !VARATT_IS_EXTENDED(values[i]))
01421 {
01422 values[i] = toast_flatten_tuple_attribute(values[i],
01423 att[i]->atttypid,
01424 att[i]->atttypmod);
01425 }
01426 }
01427
01428
01429
01430
01431 len = offsetof(MinimalTupleData, t_bits);
01432
01433 if (hasnull)
01434 len += BITMAPLEN(numberOfAttributes);
01435
01436 if (tupleDescriptor->tdhasoid)
01437 len += sizeof(Oid);
01438
01439 hoff = len = MAXALIGN(len);
01440
01441 data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
01442
01443 len += data_len;
01444
01445
01446
01447
01448 tuple = (MinimalTuple) palloc0(len);
01449
01450
01451
01452
01453 tuple->t_len = len;
01454 HeapTupleHeaderSetNatts(tuple, numberOfAttributes);
01455 tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
01456
01457 if (tupleDescriptor->tdhasoid)
01458 tuple->t_infomask = HEAP_HASOID;
01459
01460 heap_fill_tuple(tupleDescriptor,
01461 values,
01462 isnull,
01463 (char *) tuple + hoff,
01464 data_len,
01465 &tuple->t_infomask,
01466 (hasnull ? tuple->t_bits : NULL));
01467
01468 return tuple;
01469 }
01470
01471
01472
01473
01474 void
01475 heap_free_minimal_tuple(MinimalTuple mtup)
01476 {
01477 pfree(mtup);
01478 }
01479
01480
01481
01482
01483
01484
01485
01486 MinimalTuple
01487 heap_copy_minimal_tuple(MinimalTuple mtup)
01488 {
01489 MinimalTuple result;
01490
01491 result = (MinimalTuple) palloc(mtup->t_len);
01492 memcpy(result, mtup, mtup->t_len);
01493 return result;
01494 }
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505 HeapTuple
01506 heap_tuple_from_minimal_tuple(MinimalTuple mtup)
01507 {
01508 HeapTuple result;
01509 uint32 len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
01510
01511 result = (HeapTuple) palloc(HEAPTUPLESIZE + len);
01512 result->t_len = len;
01513 ItemPointerSetInvalid(&(result->t_self));
01514 result->t_tableOid = InvalidOid;
01515 result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
01516 memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len);
01517 memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_infomask2));
01518 return result;
01519 }
01520
01521
01522
01523
01524
01525
01526
01527 MinimalTuple
01528 minimal_tuple_from_heap_tuple(HeapTuple htup)
01529 {
01530 MinimalTuple result;
01531 uint32 len;
01532
01533 Assert(htup->t_len > MINIMAL_TUPLE_OFFSET);
01534 len = htup->t_len - MINIMAL_TUPLE_OFFSET;
01535 result = (MinimalTuple) palloc(len);
01536 memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len);
01537 result->t_len = len;
01538 return result;
01539 }