PostgreSQL Source Code: src/backend/access/common/heaptuple.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
59
68
69
70
71
72
73
74
75
76
77
78
79
80#define ATT_IS_PACKABLE(att) \
81 ((att)->attlen == -1 && (att)->attstorage != TYPSTORAGE_PLAIN)
82
83#define VARLENA_ATT_IS_PACKABLE(att) \
84 ((att)->attstorage != TYPSTORAGE_PLAIN)
85
86
87#define COMPACT_ATTR_IS_PACKABLE(att) \
88 ((att)->attlen == -1 && (att)->attispackable)
89
90
91
92
93
94
95typedef struct
96{
100
102
105{
107
109}
110
111static int
113{
116
117 if (entry1->len != entry2->len)
118 return entry1->len > entry2->len ? 1 : -1;
119
122 entry1->len);
123}
124
125static void
127{
129
137 32,
138 &hash_ctl,
140}
141
142
143
144
145
146
147
148
149
152 int attnum, bool *isnull)
153{
155
156 Assert(attnum <= tupleDesc->natts);
158
160
162 {
164
167
169
171 {
174 bool found;
176
177 *isnull = false;
178
179
182
183
186
187
191 else
194
196
197 if (!found)
198 {
199
204 }
205
206 return entry->value;
207 }
208 }
209
210 *isnull = true;
212}
213
214
215
216
217
221 const bool *isnull)
222{
223 Size data_length = 0;
224 int i;
225 int numberOfAttributes = tupleDesc->natts;
226
227 for (i = 0; i < numberOfAttributes; i++)
228 {
231
232 if (isnull[i])
233 continue;
234
237
240 {
241
242
243
244
246 }
247 else if (atti->attlen == -1 &&
249 {
250
251
252
253
256 }
257 else
258 {
263 }
264 }
265
266 return data_length;
267}
268
269
270
271
272
273
274static inline void
277 int *bitmask,
278 char **dataP,
281 bool isnull)
282{
283 Size data_length;
284 char *data = *dataP;
285
286
287
288
289
290 if (bit != NULL)
291 {
293 *bitmask <<= 1;
294 else
295 {
296 *bit += 1;
297 **bit = 0x0;
298 *bitmask = 1;
299 }
300
301 if (isnull)
302 {
304 return;
305 }
306
307 **bit |= *bitmask;
308 }
309
310
311
312
313
315 {
316
319 data_length = att->attlen;
320 }
321 else if (att->attlen == -1)
322 {
323
325
328 {
330 {
331
332
333
334
336
340 }
341 else
342 {
344
346 memcpy(data, val, data_length);
347 }
348 }
350 {
351
353 memcpy(data, val, data_length);
354 }
356 {
357
361 }
362 else
363 {
364
367 memcpy(data, val, data_length);
368 }
369 }
370 else if (att->attlen == -2)
371 {
372
377 }
378 else
379 {
380
383 data_length = att->attlen;
385 }
386
387 data += data_length;
388 *dataP = data;
389}
390
391
392
393
394
395
396
397
398
399
400void
405{
407 int bitmask;
408 int i;
409 int numberOfAttributes = tupleDesc->natts;
410
411#ifdef USE_ASSERT_CHECKING
413#endif
414
415 if (bit != NULL)
416 {
417 bitP = &bit[-1];
419 }
420 else
421 {
422
423 bitP = NULL;
424 bitmask = 0;
425 }
426
428
429 for (i = 0; i < numberOfAttributes; i++)
430 {
432
434 bitP ? &bitP : NULL,
435 &bitmask,
437 infomask,
439 isnull ? isnull[i] : true);
440 }
441
443}
444
445
446
447
448
449
450
451
452
453
454
455bool
457{
458
459
460
461
462 Assert(!tupleDesc || attnum <= tupleDesc->natts);
464 {
465 if (tupleDesc &&
467 return false;
468 else
469 return true;
470 }
471
473 {
475 return false;
477 }
478
480 {
487
488 break;
489
490 default:
492 }
493
494 return false;
495}
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
524{
526 char *tp;
528 bool slow = false;
529 int off;
530
531
532
533
534
535
536
537
538
539
541
543 {
544
545
546
547
548
549 int byte = attnum >> 3;
550 int finalbit = attnum & 0x07;
551
552
553 if ((~bp[byte]) & ((1 << finalbit) - 1))
554 slow = true;
555 else
556 {
557
558 int i;
559
560 for (i = 0; i < byte; i++)
561 {
562 if (bp[i] != 0xFF)
563 {
564 slow = true;
565 break;
566 }
567 }
568 }
569 }
570
571 tp = (char *) td + td->t_hoff;
572
573 if (!slow)
574 {
576
577
578
579
580
584
585
586
587
588
589
591 {
592 int j;
593
595 {
597 {
598 slow = true;
599 break;
600 }
601 }
602 }
603 }
604
605 if (!slow)
606 {
607 int natts = tupleDesc->natts;
608 int j = 1;
609
610
611
612
613
614
615
616
617
618
620
621
623 j++;
624
627
629 {
631
632 if (att->attlen <= 0)
633 break;
634
636
638
640 }
641
643
645 }
646 else
647 {
648 bool usecache = true;
649 int i;
650
651
652
653
654
655
656
657
658
659
660
661 off = 0;
663 {
665
667 {
668 usecache = false;
669 continue;
670 }
671
672
675 else if (att->attlen == -1)
676 {
677
678
679
680
681
682
683 if (usecache &&
686 else
687 {
689 tp + off);
690 usecache = false;
691 }
692 }
693 else
694 {
695
697
698 if (usecache)
700 }
701
703 break;
704
706
707 if (usecache && att->attlen <= 0)
708 usecache = false;
709 }
710 }
711
713}
714
715
716
717
718
719
720
721
722
723
726{
728
730
731
732 *isnull = false;
733
735 {
737
739 break;
742 break;
745 break;
748
749
750
751
752
753
754
756 break;
759 break;
760 default:
762 result = 0;
763 break;
764 }
765 return result;
766}
767
768
769
770
771
772
773
774
775
776
779{
781
783 return NULL;
784
791 return newTuple;
792}
793
794
795
796
797
798
799
800
801
802
803void
805{
807 {
808 dest->t_data = NULL;
809 return;
810 }
811
817}
818
819
820
821
822
823
824
825
826
827
828
829static void
834{
837 int firstmissingnum;
842 int natts = tupleDesc->natts;
843 int sourceNullLen;
844 int targetNullLen;
845 Size sourceDataLen = sourceTuple->t_len - sourceTHeader->t_hoff;
846 Size targetDataLen;
848 int hoff;
849 bits8 *nullBits = NULL;
850 int bitMask = 0;
851 char *targetData;
853
854 Assert((targetHeapTuple && !targetMinimalTuple)
855 || (!targetHeapTuple && targetMinimalTuple));
856
857 Assert(sourceNatts < natts);
858
859 sourceNullLen = (hasNulls ? BITMAPLEN(sourceNatts) : 0);
860
861 targetDataLen = sourceDataLen;
862
863 if (tupleDesc->constr &&
865 {
866
867
868
869
870
872
873
874
875
876
877 for (firstmissingnum = sourceNatts;
878 firstmissingnum < natts;
879 firstmissingnum++)
880 {
881 if (attrmiss[firstmissingnum].am_present)
882 break;
883 else
884 hasNulls = true;
885 }
886
887
888
889
890
891 for (attnum = firstmissingnum;
894 {
895 if (attrmiss[attnum].am_present)
896 {
898
903
907 }
908 else
909 {
910
911 hasNulls = true;
912 }
913 }
914 }
915 else
916 {
917
918
919
920
921 hasNulls = true;
922 }
923
925
926 if (hasNulls)
927 {
928 targetNullLen = BITMAPLEN(natts);
929 len += targetNullLen;
930 }
931 else
932 targetNullLen = 0;
933
934
935
936
937
938 if (targetHeapTuple)
939 {
941 hoff = len = MAXALIGN(len);
942 len += targetDataLen;
943
945 (*targetHeapTuple)->t_data
946 = targetTHeader
948 (*targetHeapTuple)->t_len = len;
949 (*targetHeapTuple)->t_tableOid = sourceTuple->t_tableOid;
950 (*targetHeapTuple)->t_self = sourceTuple->t_self;
951
953 targetTHeader->t_hoff = hoff;
958
960 if (targetNullLen > 0)
961 nullBits = (bits8 *) ((char *) (*targetHeapTuple)->t_data
963 targetData = (char *) (*targetHeapTuple)->t_data + hoff;
964 infoMask = &(targetTHeader->t_infomask);
965 }
966 else
967 {
969 hoff = len = MAXALIGN(len);
970 len += targetDataLen;
971
973 (*targetMinimalTuple)->t_len = len;
975 (*targetMinimalTuple)->t_infomask = sourceTHeader->t_infomask;
976
978 if (targetNullLen > 0)
979 nullBits = (bits8 *) ((char *) *targetMinimalTuple
981 targetData = (char *) *targetMinimalTuple + hoff;
982 infoMask = &((*targetMinimalTuple)->t_infomask);
983 }
984
985 if (targetNullLen > 0)
986 {
987 if (sourceNullLen > 0)
988 {
989
990 memcpy(nullBits,
991 ((char *) sourceTHeader)
993 sourceNullLen);
994 nullBits += sourceNullLen - 1;
995 }
996 else
997 {
998 sourceNullLen = BITMAPLEN(sourceNatts);
999
1000 memset(nullBits, 0xff, sourceNullLen);
1001
1002 nullBits += sourceNullLen - 1;
1003
1004 if (sourceNatts & 0x07)
1005 {
1006
1007 bitMask = 0xff << (sourceNatts & 0x07);
1008
1009 *nullBits = ~bitMask;
1010 }
1011 }
1012
1013 bitMask = (1 << ((sourceNatts - 1) & 0x07));
1014 }
1015
1016 memcpy(targetData,
1017 ((char *) sourceTuple->t_data) + sourceTHeader->t_hoff,
1018 sourceDataLen);
1019
1020 targetData += sourceDataLen;
1021
1022
1024 {
1026
1027 if (attrmiss && attrmiss[attnum].am_present)
1028 {
1030 nullBits ? &nullBits : NULL,
1031 &bitMask,
1032 &targetData,
1033 infoMask,
1034 attrmiss[attnum].am_value,
1035 false);
1036 }
1037 else
1038 {
1040 &nullBits,
1041 &bitMask,
1042 &targetData,
1043 infoMask,
1045 true);
1046 }
1047 }
1048}
1049
1050
1051
1052
1055{
1057
1058 expand_tuple(NULL, &minimalTuple, sourceTuple, tupleDesc);
1059 return minimalTuple;
1060}
1061
1062
1063
1064
1067{
1069
1070 expand_tuple(&heapTuple, NULL, sourceTuple, tupleDesc);
1071 return heapTuple;
1072}
1073
1074
1075
1076
1077
1078
1079
1082{
1084
1085
1086
1087
1088
1092 tupleDesc);
1093
1094
1095
1096
1097
1098
1100 memcpy(td, tuple->t_data, tuple->t_len);
1101
1105
1107}
1108
1109
1110
1111
1112
1113
1114
1115
1119 const bool *isnull)
1120{
1121 HeapTuple tuple;
1124 data_len;
1125 int hoff;
1126 bool hasnull = false;
1127 int numberOfAttributes = tupleDescriptor->natts;
1128 int i;
1129
1132 (errcode(ERRCODE_TOO_MANY_COLUMNS),
1133 errmsg("number of columns (%d) exceeds limit (%d)",
1135
1136
1137
1138
1139 for (i = 0; i < numberOfAttributes; i++)
1140 {
1141 if (isnull[i])
1142 {
1143 hasnull = true;
1144 break;
1145 }
1146 }
1147
1148
1149
1150
1152
1153 if (hasnull)
1155
1156 hoff = len = MAXALIGN(len);
1157
1159
1160 len += data_len;
1161
1162
1163
1164
1165
1168
1169
1170
1171
1172
1173
1177
1181
1183
1186
1189 isnull,
1190 (char *) td + hoff,
1191 data_len,
1193 (hasnull ? td->t_bits : NULL));
1194
1195 return tuple;
1196}
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1212 const Datum *replValues,
1213 const bool *replIsnull,
1214 const bool *doReplace)
1215{
1216 int numberOfAttributes = tupleDesc->natts;
1217 int attoff;
1219 bool *isnull;
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1234 isnull = palloc_array(bool, numberOfAttributes);
1235
1237
1238 for (attoff = 0; attoff < numberOfAttributes; attoff++)
1239 {
1240 if (doReplace[attoff])
1241 {
1242 values[attoff] = replValues[attoff];
1243 isnull[attoff] = replIsnull[attoff];
1244 }
1245 }
1246
1247
1248
1249
1251
1254
1255
1256
1257
1261
1262 return newTuple;
1263}
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1280 int nCols,
1281 const int *replCols,
1282 const Datum *replValues,
1283 const bool *replIsnull)
1284{
1285 int numberOfAttributes = tupleDesc->natts;
1287 bool *isnull;
1289 int i;
1290
1291
1292
1293
1294
1296 isnull = palloc_array(bool, numberOfAttributes);
1297
1299
1300 for (i = 0; i < nCols; i++)
1301 {
1302 int attnum = replCols[i];
1303
1304 if (attnum <= 0 || attnum > numberOfAttributes)
1307 isnull[attnum - 1] = replIsnull[i];
1308 }
1309
1310
1311
1312
1314
1317
1318
1319
1320
1324
1325 return newTuple;
1326}
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345void
1348{
1351 int tdesc_natts = tupleDesc->natts;
1352 int natts;
1354 char *tp;
1355 uint32 off;
1357 bool slow = false;
1358
1360
1361
1362
1363
1364
1365
1366 natts = Min(natts, tdesc_natts);
1367
1368 tp = (char *) tup + tup->t_hoff;
1369
1370 off = 0;
1371
1373 {
1375
1377 {
1379 isnull[attnum] = true;
1380 slow = true;
1381 continue;
1382 }
1383
1384 isnull[attnum] = false;
1385
1388 else if (thisatt->attlen == -1)
1389 {
1390
1391
1392
1393
1394
1395
1396 if (!slow &&
1399 else
1400 {
1402 tp + off);
1403 slow = true;
1404 }
1405 }
1406 else
1407 {
1408
1410
1411 if (!slow)
1412 thisatt->attcacheoff = off;
1413 }
1414
1416
1418
1419 if (thisatt->attlen <= 0)
1420 slow = true;
1421 }
1422
1423
1424
1425
1426
1429}
1430
1431
1432
1433
1434void
1436{
1438}
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1455 const bool *isnull,
1457{
1459 char *mem;
1461 data_len;
1462 int hoff;
1463 bool hasnull = false;
1464 int numberOfAttributes = tupleDescriptor->natts;
1465 int i;
1466
1468
1471 (errcode(ERRCODE_TOO_MANY_COLUMNS),
1472 errmsg("number of columns (%d) exceeds limit (%d)",
1474
1475
1476
1477
1478 for (i = 0; i < numberOfAttributes; i++)
1479 {
1480 if (isnull[i])
1481 {
1482 hasnull = true;
1483 break;
1484 }
1485 }
1486
1487
1488
1489
1491
1492 if (hasnull)
1494
1495 hoff = len = MAXALIGN(len);
1496
1498
1499 len += data_len;
1500
1501
1502
1503
1506
1507
1508
1509
1513
1516 isnull,
1517 (char *) tuple + hoff,
1518 data_len,
1520 (hasnull ? tuple->t_bits : NULL));
1521
1522 return tuple;
1523}
1524
1525
1526
1527
1528void
1530{
1532}
1533
1534
1535
1536
1537
1538
1539
1542{
1544 char *mem;
1545
1548 memset(mem, 0, extra);
1550 memcpy(result, mtup, mtup->t_len);
1551 return result;
1552}
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1565{
1568
1576 return result;
1577}
1578
1579
1580
1581
1582
1583
1584
1587{
1589 char *mem;
1591
1596 memset(mem, 0, extra);
1599
1601 return result;
1602}
1603
1604
1605
1606
1607
1608size_t
1610{
1612}
static Datum values[MAXATTR]
Datum datumCopy(Datum value, bool typByVal, int typLen)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
ExpandedObjectHeader * DatumGetEOHP(Datum d)
void EOH_flatten_into(ExpandedObjectHeader *eohptr, void *result, Size allocated_size)
Size EOH_get_flat_size(ExpandedObjectHeader *eohptr)
#define palloc_array(type, count)
uint32 hash_bytes(const unsigned char *k, int keylen)
Assert(PointerIsAligned(start, uint64))
Datum toast_flatten_tuple_to_datum(HeapTupleHeader tup, uint32 tup_len, TupleDesc tupleDesc)
Size heap_compute_data_size(TupleDesc tupleDesc, const Datum *values, const bool *isnull)
static uint32 missing_hash(const void *key, Size keysize)
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
void heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
HeapTuple heap_copytuple(HeapTuple tuple)
size_t varsize_any(void *p)
MinimalTuple heap_copy_minimal_tuple(MinimalTuple mtup, Size extra)
Datum heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
MinimalTuple heap_form_minimal_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull, Size extra)
HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple, TupleDesc tupleDesc, int nCols, const int *replCols, const Datum *replValues, const bool *replIsnull)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_free_minimal_tuple(MinimalTuple mtup)
bool heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Datum nocachegetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc)
Datum getmissingattr(TupleDesc tupleDesc, int attnum, bool *isnull)
MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup, Size extra)
HeapTuple heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
static void fill_val(CompactAttribute *att, bits8 **bit, int *bitmask, char **dataP, uint16 *infomask, Datum datum, bool isnull)
void heap_fill_tuple(TupleDesc tupleDesc, const Datum *values, const bool *isnull, char *data, Size data_size, uint16 *infomask, bits8 *bit)
#define COMPACT_ATTR_IS_PACKABLE(att)
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
static void init_missing_cache(void)
static int missing_match(const void *key1, const void *key2, Size keysize)
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
static HTAB * missing_cache
static void expand_tuple(HeapTuple *targetHeapTuple, MinimalTuple *targetMinimalTuple, HeapTuple sourceTuple, TupleDesc tupleDesc)
HeapTuple heap_tuple_from_minimal_tuple(MinimalTuple mtup)
MinimalTuple minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
void heap_freetuple(HeapTuple htup)
HeapTupleData * HeapTuple
MinimalTupleData * MinimalTuple
HeapTupleHeaderData * HeapTupleHeader
#define HeapTupleIsValid(tuple)
#define MINIMAL_TUPLE_OFFSET
#define HeapTupleHeaderGetNatts(tup)
static void HeapTupleHeaderSetTypMod(HeapTupleHeaderData *tup, int32 typmod)
static bool HeapTupleHasNulls(const HeapTupleData *tuple)
static int BITMAPLEN(int NATTS)
static bool HeapTupleHasExternal(const HeapTupleData *tuple)
#define SizeofMinimalTupleHeader
static void HeapTupleHeaderSetTypeId(HeapTupleHeaderData *tup, Oid datum_typeid)
static CommandId HeapTupleHeaderGetRawCommandId(const HeapTupleHeaderData *tup)
static TransactionId HeapTupleHeaderGetRawXmax(const HeapTupleHeaderData *tup)
#define MaxTupleAttributeNumber
static bool HeapTupleNoNulls(const HeapTupleData *tuple)
static void HeapTupleHeaderSetDatumLength(HeapTupleHeaderData *tup, uint32 len)
static TransactionId HeapTupleHeaderGetRawXmin(const HeapTupleHeaderData *tup)
#define HeapTupleHeaderSetNatts(tup, natts)
static bool HeapTupleHasVarWidth(const HeapTupleData *tuple)
if(TABLE==NULL||TABLE_index==NULL)
static void ItemPointerSetInvalid(ItemPointerData *pointer)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext TopMemoryContext
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
static Datum PointerGetDatum(const void *X)
static Datum TransactionIdGetDatum(TransactionId X)
static Datum CommandIdGetDatum(CommandId X)
static Datum ObjectIdGetDatum(Oid X)
static char * DatumGetCString(Datum X)
static Pointer DatumGetPointer(Datum X)
bits8 t_bits[FLEXIBLE_ARRAY_MEMBER]
struct AttrMissing * missing
#define MinTransactionIdAttributeNumber
#define MaxCommandIdAttributeNumber
#define MaxTransactionIdAttributeNumber
#define TableOidAttributeNumber
#define SelfItemPointerAttributeNumber
#define MinCommandIdAttributeNumber
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
#define att_nominal_alignby(cur_offset, attalignby)
#define att_datum_alignby(cur_offset, attalignby, attlen, attdatum)
static bool att_isnull(int ATT, const bits8 *BITS)
#define att_addlength_pointer(cur_offset, attlen, attptr)
#define att_pointer_alignby(cur_offset, attalignby, attlen, attptr)
#define att_addlength_datum(cur_offset, attlen, attdatum)
static void store_att_byval(void *T, Datum newdatum, int attlen)
static bool VARATT_IS_SHORT(const void *PTR)
static Size VARSIZE_ANY(const void *PTR)
static bool VARATT_CAN_MAKE_SHORT(const void *PTR)
static bool VARATT_IS_EXTERNAL(const void *PTR)
static Size VARSIZE(const void *PTR)
static char * VARDATA(const void *PTR)
static Size VARATT_CONVERTED_SHORT_SIZE(const void *PTR)
static Size VARSIZE_EXTERNAL(const void *PTR)
static bool VARATT_IS_EXTERNAL_EXPANDED(const void *PTR)
static void SET_VARSIZE_SHORT(void *PTR, Size len)
static Size VARSIZE_SHORT(const void *PTR)
Datum bit(PG_FUNCTION_ARGS)