PostgreSQL Source Code: src/backend/utils/adt/rowtypes.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
16
17#include <ctype.h>
18
29
30
31
32
33
35{
42
44{
50
51
52
53
55{
58
60{
68
69
70
71
72
75{
79 Node *escontext = fcinfo->context;
84 bool needComma = false;
85 int ncolumns;
86 int i;
87 char *ptr;
89 bool *nulls;
91
93
94
95
96
97
98
99
100
101
102 if (tupType == RECORDOID && tupTypmod < 0)
104 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
105 errmsg("input of anonymous composite types is not implemented")));
106
107
108
109
110
111
113 ncolumns = tupdesc->natts;
114
115
116
117
118
119 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
120 if (my_extra == NULL ||
121 my_extra->ncolumns != ncolumns)
122 {
123 fcinfo->flinfo->fn_extra =
127 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
130 }
131
134 {
140 my_extra->ncolumns = ncolumns;
141 }
142
144 nulls = (bool *) palloc(ncolumns * sizeof(bool));
145
146
147
148
149
151
152 while (*ptr && isspace((unsigned char) *ptr))
153 ptr++;
154 if (*ptr++ != '(')
155 {
157 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
158 errmsg("malformed record literal: \"%s\"", string),
159 errdetail("Missing left parenthesis.")));
160 goto fail;
161 }
162
164
165 for (i = 0; i < ncolumns; i++)
166 {
169 Oid column_type = att->atttypid;
170 char *column_data;
171
172
173 if (att->attisdropped)
174 {
176 nulls[i] = true;
177 continue;
178 }
179
180 if (needComma)
181 {
182
183 if (*ptr == ',')
184 ptr++;
185 else
186
187 {
189 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
190 errmsg("malformed record literal: \"%s\"", string),
192 goto fail;
193 }
194 }
195
196
197 if (*ptr == ',' || *ptr == ')')
198 {
199 column_data = NULL;
200 nulls[i] = true;
201 }
202 else
203 {
204
205 bool inquote = false;
206
208 while (inquote || !(*ptr == ',' || *ptr == ')'))
209 {
210 char ch = *ptr++;
211
212 if (ch == '\0')
213 {
215 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
216 errmsg("malformed record literal: \"%s\"",
217 string),
218 errdetail("Unexpected end of input.")));
219 goto fail;
220 }
221 if (ch == '\\')
222 {
223 if (*ptr == '\0')
224 {
226 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
227 errmsg("malformed record literal: \"%s\"",
228 string),
229 errdetail("Unexpected end of input.")));
230 goto fail;
231 }
233 }
234 else if (ch == '"')
235 {
236 if (!inquote)
237 inquote = true;
238 else if (*ptr == '"')
239 {
240
242 }
243 else
244 inquote = false;
245 }
246 else
248 }
249
250 column_data = buf.data;
251 nulls[i] = false;
252 }
253
254
255
256
257 if (column_info->column_type != column_type)
258 {
263 fcinfo->flinfo->fn_mcxt);
265 }
266
268 column_data,
270 att->atttypmod,
271 escontext,
273 goto fail;
274
275
276
277
278 needComma = true;
279 }
280
281 if (*ptr++ != ')')
282 {
284 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
285 errmsg("malformed record literal: \"%s\"", string),
286 errdetail("Too many columns.")));
287 goto fail;
288 }
289
290 while (*ptr && isspace((unsigned char) *ptr))
291 ptr++;
292 if (*ptr)
293 {
295 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
296 errmsg("malformed record literal: \"%s\"", string),
297 errdetail("Junk after right parenthesis.")));
298 goto fail;
299 }
300
302
303
304
305
306
307
309 memcpy(result, tuple->t_data, tuple->t_len);
310
316
318
319
320fail:
323}
324
325
326
327
330{
332 Oid tupType;
337 bool needComma = false;
338 int ncolumns;
339 int i;
341 bool *nulls;
343
345
346
350 ncolumns = tupdesc->natts;
351
352
357
358
359
360
361
362 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
363 if (my_extra == NULL ||
364 my_extra->ncolumns != ncolumns)
365 {
366 fcinfo->flinfo->fn_extra =
370 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
373 }
374
377 {
383 my_extra->ncolumns = ncolumns;
384 }
385
387 nulls = (bool *) palloc(ncolumns * sizeof(bool));
388
389
391
392
394
396
397 for (i = 0; i < ncolumns; i++)
398 {
401 Oid column_type = att->atttypid;
404 char *tmp;
405 bool nq;
406
407
408 if (att->attisdropped)
409 continue;
410
411 if (needComma)
413 needComma = true;
414
415 if (nulls[i])
416 {
417
418 continue;
419 }
420
421
422
423
424 if (column_info->column_type != column_type)
425 {
430 fcinfo->flinfo->fn_mcxt);
432 }
433
436
437
438 nq = (value[0] == '\0');
439 for (tmp = value; *tmp; tmp++)
440 {
441 char ch = *tmp;
442
443 if (ch == '"' || ch == '\\' ||
444 ch == '(' || ch == ')' || ch == ',' ||
445 isspace((unsigned char) ch))
446 {
447 nq = true;
448 break;
449 }
450 }
451
452
453 if (nq)
455 for (tmp = value; *tmp; tmp++)
456 {
457 char ch = *tmp;
458
459 if (ch == '"' || ch == '\\')
462 }
463 if (nq)
465 }
466
468
472
474}
475
476
477
478
481{
489 int ncolumns;
490 int usercols;
491 int validcols;
492 int i;
494 bool *nulls;
495
497
498
499
500
501
502
503
504
505
506 if (tupType == RECORDOID && tupTypmod < 0)
508 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
509 errmsg("input of anonymous composite types is not implemented")));
510
512 ncolumns = tupdesc->natts;
513
514
515
516
517
518 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
519 if (my_extra == NULL ||
520 my_extra->ncolumns != ncolumns)
521 {
522 fcinfo->flinfo->fn_extra =
526 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
529 }
530
533 {
539 my_extra->ncolumns = ncolumns;
540 }
541
543 nulls = (bool *) palloc(ncolumns * sizeof(bool));
544
545
547
548
549 validcols = 0;
550 for (i = 0; i < ncolumns; i++)
551 {
553 validcols++;
554 }
555 if (usercols != validcols)
557 (errcode(ERRCODE_DATATYPE_MISMATCH),
558 errmsg("wrong number of columns: %d, expected %d",
559 usercols, validcols)));
560
561
562 for (i = 0; i < ncolumns; i++)
563 {
566 Oid column_type = att->atttypid;
567 Oid coltypoid;
568 int itemlen;
571
572
573 if (att->attisdropped)
574 {
576 nulls[i] = true;
577 continue;
578 }
579
580
582
583
584
585
586
587
588
589
590
591
592
593
594 if (coltypoid != column_type &&
598 (errcode(ERRCODE_DATATYPE_MISMATCH),
599 errmsg("binary data has type %u (%s) instead of expected %u (%s) in record column %d",
600 coltypoid,
603 column_type,
606 i + 1)));
607
608
610 if (itemlen < -1 || itemlen > (buf->len - buf->cursor))
612 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
613 errmsg("insufficient data left in message")));
614
615 if (itemlen == -1)
616 {
617
618 bufptr = NULL;
619 nulls[i] = true;
620 }
621 else
622 {
623 char *strbuff;
624
625
626
627
628
629
630 strbuff = &buf->data[buf->cursor];
631 buf->cursor += itemlen;
633
634 bufptr = &item_buf;
635 nulls[i] = false;
636 }
637
638
639 if (column_info->column_type != column_type)
640 {
645 fcinfo->flinfo->fn_mcxt);
647 }
648
650 bufptr,
652 att->atttypmod);
653
654 if (bufptr)
655 {
656
657 if (item_buf.cursor != itemlen)
659 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
660 errmsg("improper binary format in record column %d",
661 i + 1)));
662 }
663 }
664
666
667
668
669
670
671
673 memcpy(result, tuple->t_data, tuple->t_len);
674
679
681}
682
683
684
685
688{
690 Oid tupType;
695 int ncolumns;
696 int validcols;
697 int i;
699 bool *nulls;
701
703
704
708 ncolumns = tupdesc->natts;
709
710
715
716
717
718
719
720 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
721 if (my_extra == NULL ||
722 my_extra->ncolumns != ncolumns)
723 {
724 fcinfo->flinfo->fn_extra =
728 my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
731 }
732
735 {
741 my_extra->ncolumns = ncolumns;
742 }
743
745 nulls = (bool *) palloc(ncolumns * sizeof(bool));
746
747
749
750
752
753
754 validcols = 0;
755 for (i = 0; i < ncolumns; i++)
756 {
758 validcols++;
759 }
761
762 for (i = 0; i < ncolumns; i++)
763 {
766 Oid column_type = att->atttypid;
768 bytea *outputbytes;
769
770
771 if (att->attisdropped)
772 continue;
773
775
776 if (nulls[i])
777 {
778
780 continue;
781 }
782
783
784
785
786 if (column_info->column_type != column_type)
787 {
792 fcinfo->flinfo->fn_mcxt);
794 }
795
801 }
802
806
808}
809
810
811
812
813
814
815
816
817
818
819
820
821
822static int
824{
827 int result = 0;
828 Oid tupType1;
829 Oid tupType2;
830 int32 tupTypmod1;
831 int32 tupTypmod2;
836 int ncolumns1;
837 int ncolumns2;
839 int ncols;
842 bool *nulls1;
843 bool *nulls2;
844 int i1;
845 int i2;
846 int j;
847
849
850
854 ncolumns1 = tupdesc1->natts;
858 ncolumns2 = tupdesc2->natts;
859
860
864 tuple1.t_data = record1;
868 tuple2.t_data = record2;
869
870
871
872
873
874 ncols = Max(ncolumns1, ncolumns2);
876 if (my_extra == NULL ||
878 {
889 }
890
895 {
901 }
902
903
905 nulls1 = (bool *) palloc(ncolumns1 * sizeof(bool));
908 nulls2 = (bool *) palloc(ncolumns2 * sizeof(bool));
910
911
912
913
914
915
916 i1 = i2 = j = 0;
917 while (i1 < ncolumns1 || i2 < ncolumns2)
918 {
922 Oid collation;
923
924
925
926
927 if (i1 < ncolumns1 && TupleDescAttr(tupdesc1, i1)->attisdropped)
928 {
929 i1++;
930 continue;
931 }
932 if (i2 < ncolumns2 && TupleDescAttr(tupdesc2, i2)->attisdropped)
933 {
934 i2++;
935 continue;
936 }
937 if (i1 >= ncolumns1 || i2 >= ncolumns2)
938 break;
939
942
943
944
945
946 if (att1->atttypid != att2->atttypid)
948 (errcode(ERRCODE_DATATYPE_MISMATCH),
949 errmsg("cannot compare dissimilar column types %s and %s at record column %d",
952 j + 1)));
953
954
955
956
957
958 collation = att1->attcollation;
959 if (collation != att2->attcollation)
961
962
963
964
966 if (typentry == NULL ||
967 typentry->type_id != att1->atttypid)
968 {
973 (errcode(ERRCODE_UNDEFINED_FUNCTION),
974 errmsg("could not identify a comparison function for type %s",
977 }
978
979
980
981
982 if (!nulls1[i1] || !nulls2[i2])
983 {
986
987 if (nulls1[i1])
988 {
989
990 result = 1;
991 break;
992 }
993 if (nulls2[i2])
994 {
995
996 result = -1;
997 break;
998 }
999
1000
1002 collation, NULL, NULL);
1003 locfcinfo->args[0].value = values1[i1];
1004 locfcinfo->args[0].isnull = false;
1005 locfcinfo->args[1].value = values2[i2];
1006 locfcinfo->args[1].isnull = false;
1008
1009
1010 Assert(!locfcinfo->isnull);
1011
1012 if (cmpresult < 0)
1013 {
1014
1015 result = -1;
1016 break;
1017 }
1018 else if (cmpresult > 0)
1019 {
1020
1021 result = 1;
1022 break;
1023 }
1024 }
1025
1026
1027 i1++, i2++, j++;
1028 }
1029
1030
1031
1032
1033
1034
1035 if (result == 0)
1036 {
1037 if (i1 != ncolumns1 || i2 != ncolumns2)
1039 (errcode(ERRCODE_DATATYPE_MISMATCH),
1040 errmsg("cannot compare record types with different numbers of columns")));
1041 }
1042
1049
1050
1053
1054 return result;
1055}
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1068{
1071 bool result = true;
1072 Oid tupType1;
1073 Oid tupType2;
1074 int32 tupTypmod1;
1075 int32 tupTypmod2;
1080 int ncolumns1;
1081 int ncolumns2;
1083 int ncols;
1086 bool *nulls1;
1087 bool *nulls2;
1088 int i1;
1089 int i2;
1090 int j;
1091
1093
1094
1098 ncolumns1 = tupdesc1->natts;
1102 ncolumns2 = tupdesc2->natts;
1103
1104
1108 tuple1.t_data = record1;
1112 tuple2.t_data = record2;
1113
1114
1115
1116
1117
1118 ncols = Max(ncolumns1, ncolumns2);
1120 if (my_extra == NULL ||
1122 {
1123 fcinfo->flinfo->fn_extra =
1133 }
1134
1139 {
1145 }
1146
1147
1149 nulls1 = (bool *) palloc(ncolumns1 * sizeof(bool));
1152 nulls2 = (bool *) palloc(ncolumns2 * sizeof(bool));
1154
1155
1156
1157
1158
1159
1160 i1 = i2 = j = 0;
1161 while (i1 < ncolumns1 || i2 < ncolumns2)
1162 {
1167 Oid collation;
1168 bool oprresult;
1169
1170
1171
1172
1173 if (i1 < ncolumns1 && TupleDescAttr(tupdesc1, i1)->attisdropped)
1174 {
1175 i1++;
1176 continue;
1177 }
1178 if (i2 < ncolumns2 && TupleDescAttr(tupdesc2, i2)->attisdropped)
1179 {
1180 i2++;
1181 continue;
1182 }
1183 if (i1 >= ncolumns1 || i2 >= ncolumns2)
1184 break;
1185
1188
1189
1190
1191
1192 if (att1->atttypid != att2->atttypid)
1194 (errcode(ERRCODE_DATATYPE_MISMATCH),
1195 errmsg("cannot compare dissimilar column types %s and %s at record column %d",
1198 j + 1)));
1199
1200
1201
1202
1203
1204 collation = att1->attcollation;
1205 if (collation != att2->attcollation)
1207
1208
1209
1210
1212 if (typentry == NULL ||
1213 typentry->type_id != att1->atttypid)
1214 {
1219 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1220 errmsg("could not identify an equality operator for type %s",
1223 }
1224
1225
1226
1227
1228 if (!nulls1[i1] || !nulls2[i2])
1229 {
1230 if (nulls1[i1] || nulls2[i2])
1231 {
1232 result = false;
1233 break;
1234 }
1235
1236
1238 collation, NULL, NULL);
1239 locfcinfo->args[0].value = values1[i1];
1240 locfcinfo->args[0].isnull = false;
1241 locfcinfo->args[1].value = values2[i2];
1242 locfcinfo->args[1].isnull = false;
1244 if (locfcinfo->isnull || !oprresult)
1245 {
1246 result = false;
1247 break;
1248 }
1249 }
1250
1251
1252 i1++, i2++, j++;
1253 }
1254
1255
1256
1257
1258
1259
1260 if (result)
1261 {
1262 if (i1 != ncolumns1 || i2 != ncolumns2)
1264 (errcode(ERRCODE_DATATYPE_MISMATCH),
1265 errmsg("cannot compare record types with different numbers of columns")));
1266 }
1267
1274
1275
1278
1280}
1281
1284{
1286}
1287
1290{
1292}
1293
1296{
1298}
1299
1302{
1304}
1305
1308{
1310}
1311
1314{
1316}
1317
1320{
1323 else
1325}
1326
1329{
1332 else
1334}
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348static int
1350{
1353 int result = 0;
1354 Oid tupType1;
1355 Oid tupType2;
1356 int32 tupTypmod1;
1357 int32 tupTypmod2;
1362 int ncolumns1;
1363 int ncolumns2;
1365 int ncols;
1368 bool *nulls1;
1369 bool *nulls2;
1370 int i1;
1371 int i2;
1372 int j;
1373
1374
1378 ncolumns1 = tupdesc1->natts;
1382 ncolumns2 = tupdesc2->natts;
1383
1384
1388 tuple1.t_data = record1;
1392 tuple2.t_data = record2;
1393
1394
1395
1396
1397
1398 ncols = Max(ncolumns1, ncolumns2);
1400 if (my_extra == NULL ||
1402 {
1413 }
1414
1419 {
1425 }
1426
1427
1429 nulls1 = (bool *) palloc(ncolumns1 * sizeof(bool));
1432 nulls2 = (bool *) palloc(ncolumns2 * sizeof(bool));
1434
1435
1436
1437
1438
1439
1440 i1 = i2 = j = 0;
1441 while (i1 < ncolumns1 || i2 < ncolumns2)
1442 {
1445
1446
1447
1448
1449 if (i1 < ncolumns1 && TupleDescAttr(tupdesc1, i1)->attisdropped)
1450 {
1451 i1++;
1452 continue;
1453 }
1454 if (i2 < ncolumns2 && TupleDescAttr(tupdesc2, i2)->attisdropped)
1455 {
1456 i2++;
1457 continue;
1458 }
1459 if (i1 >= ncolumns1 || i2 >= ncolumns2)
1460 break;
1461
1464
1465
1466
1467
1468 if (att1->atttypid != att2->atttypid)
1470 (errcode(ERRCODE_DATATYPE_MISMATCH),
1471 errmsg("cannot compare dissimilar column types %s and %s at record column %d",
1474 j + 1)));
1475
1476
1477
1478
1479
1480 Assert(att1->attlen == att2->attlen);
1481
1482
1483
1484
1485 if (!nulls1[i1] || !nulls2[i2])
1486 {
1487 int cmpresult = 0;
1488
1489 if (nulls1[i1])
1490 {
1491
1492 result = 1;
1493 break;
1494 }
1495 if (nulls2[i2])
1496 {
1497
1498 result = -1;
1499 break;
1500 }
1501
1502
1503 if (att1->attbyval)
1504 {
1505 if (values1[i1] != values2[i2])
1506 cmpresult = (values1[i1] < values2[i2]) ? -1 : 1;
1507 }
1508 else if (att1->attlen > 0)
1509 {
1512 att1->attlen);
1513 }
1514 else if (att1->attlen == -1)
1515 {
1517 len2;
1518 struct varlena *arg1val;
1519 struct varlena *arg2val;
1520
1525
1526 cmpresult = memcmp(VARDATA_ANY(arg1val),
1529 if ((cmpresult == 0) && (len1 != len2))
1530 cmpresult = (len1 < len2) ? -1 : 1;
1531
1536 }
1537 else
1538 elog(ERROR, "unexpected attlen: %d", att1->attlen);
1539
1540 if (cmpresult < 0)
1541 {
1542
1543 result = -1;
1544 break;
1545 }
1546 else if (cmpresult > 0)
1547 {
1548
1549 result = 1;
1550 break;
1551 }
1552 }
1553
1554
1555 i1++, i2++, j++;
1556 }
1557
1558
1559
1560
1561
1562
1563 if (result == 0)
1564 {
1565 if (i1 != ncolumns1 || i2 != ncolumns2)
1567 (errcode(ERRCODE_DATATYPE_MISMATCH),
1568 errmsg("cannot compare record types with different numbers of columns")));
1569 }
1570
1577
1578
1581
1582 return result;
1583}
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1596{
1599 bool result = true;
1600 Oid tupType1;
1601 Oid tupType2;
1602 int32 tupTypmod1;
1603 int32 tupTypmod2;
1608 int ncolumns1;
1609 int ncolumns2;
1611 int ncols;
1614 bool *nulls1;
1615 bool *nulls2;
1616 int i1;
1617 int i2;
1618 int j;
1619
1620
1624 ncolumns1 = tupdesc1->natts;
1628 ncolumns2 = tupdesc2->natts;
1629
1630
1634 tuple1.t_data = record1;
1638 tuple2.t_data = record2;
1639
1640
1641
1642
1643
1644 ncols = Max(ncolumns1, ncolumns2);
1646 if (my_extra == NULL ||
1648 {
1649 fcinfo->flinfo->fn_extra =
1659 }
1660
1665 {
1671 }
1672
1673
1675 nulls1 = (bool *) palloc(ncolumns1 * sizeof(bool));
1678 nulls2 = (bool *) palloc(ncolumns2 * sizeof(bool));
1680
1681
1682
1683
1684
1685
1686 i1 = i2 = j = 0;
1687 while (i1 < ncolumns1 || i2 < ncolumns2)
1688 {
1691
1692
1693
1694
1695 if (i1 < ncolumns1 && TupleDescAttr(tupdesc1, i1)->attisdropped)
1696 {
1697 i1++;
1698 continue;
1699 }
1700 if (i2 < ncolumns2 && TupleDescAttr(tupdesc2, i2)->attisdropped)
1701 {
1702 i2++;
1703 continue;
1704 }
1705 if (i1 >= ncolumns1 || i2 >= ncolumns2)
1706 break;
1707
1710
1711
1712
1713
1714 if (att1->atttypid != att2->atttypid)
1716 (errcode(ERRCODE_DATATYPE_MISMATCH),
1717 errmsg("cannot compare dissimilar column types %s and %s at record column %d",
1720 j + 1)));
1721
1722
1723
1724
1725 if (!nulls1[i1] || !nulls2[i2])
1726 {
1727 if (nulls1[i1] || nulls2[i2])
1728 {
1729 result = false;
1730 break;
1731 }
1732
1733
1734 result = datum_image_eq(values1[i1], values2[i2], att1->attbyval, att2->attlen);
1735 if (!result)
1736 break;
1737 }
1738
1739
1740 i1++, i2++, j++;
1741 }
1742
1743
1744
1745
1746
1747
1748 if (result)
1749 {
1750 if (i1 != ncolumns1 || i2 != ncolumns2)
1752 (errcode(ERRCODE_DATATYPE_MISMATCH),
1753 errmsg("cannot compare record types with different numbers of columns")));
1754 }
1755
1762
1763
1766
1768}
1769
1772{
1774}
1775
1778{
1780}
1781
1784{
1786}
1787
1790{
1792}
1793
1796{
1798}
1799
1802{
1804}
1805
1806
1807
1808
1809
1810
1813{
1816 Oid tupType;
1817 int32 tupTypmod;
1820 int ncolumns;
1823 bool *nulls;
1824
1826
1827
1831 ncolumns = tupdesc->natts;
1832
1833
1837 tuple.t_data = record;
1838
1839
1840
1841
1842
1844 if (my_extra == NULL ||
1845 my_extra->ncolumns < ncolumns)
1846 {
1847 fcinfo->flinfo->fn_extra =
1852 my_extra->ncolumns = ncolumns;
1855 }
1856
1859 {
1863 }
1864
1865
1867 nulls = (bool *) palloc(ncolumns * sizeof(bool));
1869
1870 for (int i = 0; i < ncolumns; i++)
1871 {
1875
1877
1878 if (att->attisdropped)
1879 continue;
1880
1881
1882
1883
1885 if (typentry == NULL ||
1886 typentry->type_id != att->atttypid)
1887 {
1892 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1893 errmsg("could not identify a hash function for type %s",
1896 }
1897
1898
1899 if (nulls[i])
1900 {
1902 }
1903 else
1904 {
1906
1908 att->attcollation, NULL, NULL);
1909 locfcinfo->args[0].value = values[i];
1910 locfcinfo->args[0].isnull = false;
1912
1913
1914 Assert(!locfcinfo->isnull);
1915 }
1916
1917
1918 result = (result << 5) - result + element_hash;
1919 }
1920
1924
1925
1927
1929}
1930
1933{
1937 Oid tupType;
1938 int32 tupTypmod;
1941 int ncolumns;
1944 bool *nulls;
1945
1947
1948
1952 ncolumns = tupdesc->natts;
1953
1954
1958 tuple.t_data = record;
1959
1960
1961
1962
1963
1965 if (my_extra == NULL ||
1966 my_extra->ncolumns < ncolumns)
1967 {
1968 fcinfo->flinfo->fn_extra =
1973 my_extra->ncolumns = ncolumns;
1976 }
1977
1980 {
1984 }
1985
1986
1988 nulls = (bool *) palloc(ncolumns * sizeof(bool));
1990
1991 for (int i = 0; i < ncolumns; i++)
1992 {
1996
1998
1999 if (att->attisdropped)
2000 continue;
2001
2002
2003
2004
2006 if (typentry == NULL ||
2007 typentry->type_id != att->atttypid)
2008 {
2013 (errcode(ERRCODE_UNDEFINED_FUNCTION),
2014 errmsg("could not identify an extended hash function for type %s",
2017 }
2018
2019
2020 if (nulls[i])
2021 {
2023 }
2024 else
2025 {
2027
2029 att->attcollation, NULL, NULL);
2030 locfcinfo->args[0].value = values[i];
2031 locfcinfo->args[0].isnull = false;
2033 locfcinfo->args[0].isnull = false;
2035
2036
2037 Assert(!locfcinfo->isnull);
2038 }
2039
2040
2041 result = (result << 5) - result + element_hash;
2042 }
2043
2047
2048
2050
2052}
static uint32 element_hash(const void *key, Size keysize)
static Datum values[MAXATTR]
#define FORMAT_TYPE_ALLOW_INVALID
#define FLEXIBLE_ARRAY_MEMBER
#define MemSet(start, val, len)
#define OidIsValid(objectId)
bool datum_image_eq(Datum value1, Datum value2, bool typByVal, int typLen)
Size toast_raw_datum_size(Datum value)
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereturn(context, dummy_value,...)
#define errsave(context,...)
#define ereport(elevel,...)
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Datum Int64GetDatum(int64 X)
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, fmNodePtr escontext, Datum *result)
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Datum ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, Oid typioparam, int32 typmod)
#define PG_FREE_IF_COPY(ptr, n)
#define PG_RETURN_UINT32(x)
#define PG_RETURN_BYTEA_P(x)
#define PG_GETARG_POINTER(n)
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
#define PG_RETURN_CSTRING(x)
#define PG_GETARG_DATUM(n)
#define LOCAL_FCINFO(name, nargs)
#define PG_GETARG_CSTRING(n)
#define PG_GETARG_INT64(n)
#define PG_DETOAST_DATUM_PACKED(datum)
#define PG_RETURN_UINT64(x)
#define PG_GETARG_HEAPTUPLEHEADER(n)
#define FunctionCallInvoke(fcinfo)
#define PG_RETURN_INT32(x)
#define PG_RETURN_HEAPTUPLEHEADER(x)
#define PG_GETARG_INT32(n)
#define PG_RETURN_DATUM(x)
#define PG_RETURN_BOOL(x)
char * format_type_extended(Oid type_oid, int32 typemod, bits16 flags)
char * format_type_be(Oid type_oid)
Assert(PointerIsAligned(start, uint64))
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
void heap_freetuple(HeapTuple htup)
HeapTupleHeaderData * HeapTupleHeader
static int32 HeapTupleHeaderGetTypMod(const HeapTupleHeaderData *tup)
static uint32 HeapTupleHeaderGetDatumLength(const HeapTupleHeaderData *tup)
static Oid HeapTupleHeaderGetTypeId(const HeapTupleHeaderData *tup)
if(TABLE==NULL||TABLE_index==NULL)
static void ItemPointerSetInvalid(ItemPointerData *pointer)
void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
void * MemoryContextAlloc(MemoryContext context, Size size)
void pfree(void *pointer)
FormData_pg_attribute * Form_pg_attribute
static uint32 DatumGetUInt32(Datum X)
static uint64 DatumGetUInt64(Datum X)
static bool DatumGetBool(Datum X)
static Pointer DatumGetPointer(Datum X)
static int32 DatumGetInt32(Datum X)
unsigned int pq_getmsgint(StringInfo msg, int b)
void pq_sendbytes(StringInfo buf, const void *data, int datalen)
void pq_begintypsend(StringInfo buf)
bytea * pq_endtypsend(StringInfo buf)
static void pq_sendint32(StringInfo buf, uint32 i)
Datum record_eq(PG_FUNCTION_ARGS)
static int record_cmp(FunctionCallInfo fcinfo)
Datum record_image_ne(PG_FUNCTION_ARGS)
Datum record_image_ge(PG_FUNCTION_ARGS)
Datum hash_record_extended(PG_FUNCTION_ARGS)
Datum record_larger(PG_FUNCTION_ARGS)
Datum record_out(PG_FUNCTION_ARGS)
Datum record_ge(PG_FUNCTION_ARGS)
Datum btrecordcmp(PG_FUNCTION_ARGS)
Datum record_recv(PG_FUNCTION_ARGS)
Datum record_image_lt(PG_FUNCTION_ARGS)
struct ColumnIOData ColumnIOData
Datum hash_record(PG_FUNCTION_ARGS)
Datum record_image_gt(PG_FUNCTION_ARGS)
Datum btrecordimagecmp(PG_FUNCTION_ARGS)
Datum record_in(PG_FUNCTION_ARGS)
Datum record_send(PG_FUNCTION_ARGS)
Datum record_image_le(PG_FUNCTION_ARGS)
Datum record_ne(PG_FUNCTION_ARGS)
struct RecordCompareData RecordCompareData
struct ColumnCompareData ColumnCompareData
Datum record_le(PG_FUNCTION_ARGS)
Datum record_smaller(PG_FUNCTION_ARGS)
Datum record_image_eq(PG_FUNCTION_ARGS)
static int record_image_cmp(FunctionCallInfo fcinfo)
struct RecordIOData RecordIOData
Datum record_lt(PG_FUNCTION_ARGS)
Datum record_gt(PG_FUNCTION_ARGS)
void check_stack_depth(void)
void resetStringInfo(StringInfo str)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
StringInfoData * StringInfo
#define appendStringInfoCharMacro(str, ch)
static void initReadOnlyStringInfo(StringInfo str, char *data, int len)
TypeCacheEntry * typentry
ColumnCompareData columns[FLEXIBLE_ARRAY_MEMBER]
ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER]
FmgrInfo hash_extended_proc_finfo
#define FirstGenbkiObjectId
#define ReleaseTupleDesc(tupdesc)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
#define TYPECACHE_HASH_PROC_FINFO
#define TYPECACHE_EQ_OPR_FINFO
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
#define TYPECACHE_CMP_PROC_FINFO