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{

61 int ncolumns;

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