PostgreSQL Source Code: src/backend/utils/adt/tsvector_op.c Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

15

16#include <limits.h>

17

34

35

36typedef struct

37{

41 char *operand;

43

44

46{

47 uint32 ndoc;

48

55

56#define STATENTRYHDRSZ (offsetof(StatEntry, lexeme))

57

58typedef struct

59{

61

63

66

69

70

75 void *arg,

77 List **locations);

80

81

82

83

84

85static int

87{

89 return -1;

91 return 1;

92 else if (a->size < b->size)

93 return -1;

94 else if (a->size > b->size)

95 return 1;

96 else

97 {

100 int i = 0;

101 int res;

102

103

104 for (i = 0; i < a->size; i++)

105 {

107 {

108 return (aptr->haspos > bptr->haspos) ? -1 : 1;

109 }

111 {

112 return res;

113 }

114 else if (aptr->haspos)

115 {

118 int j;

119

122

124 {

126 {

128 }

130 {

132 }

133 ap++, bp++;

134 }

135 }

136

137 aptr++;

138 bptr++;

139 }

140 }

141

142 return 0;

143}

144

145#define TSVECTORCMPFUNC( type, action, ret ) \

146Datum \

147tsvector_##type(PG_FUNCTION_ARGS) \

148{ \

149 TSVector a = PG_GETARG_TSVECTOR(0); \

150 TSVector b = PG_GETARG_TSVECTOR(1); \

151 int res = silly_cmp_tsvector(a, b); \

152 PG_FREE_IF_COPY(a,0); \

153 PG_FREE_IF_COPY(b,1); \

154 PG_RETURN_##ret( res action 0 ); \

155} \

156 \

157extern int no_such_variable

158

166

169{

172 int i,

175 *arrout;

176 char *cur;

177

178 for (i = 0; i < in->size; i++)

180

185 arrout = ARRPTR(out);

187 for (i = 0; i < in->size; i++)

188 {

189 memcpy(cur, STRPTR(in) + arrin[i].pos, arrin[i].len);

190 arrout[i].haspos = 0;

191 arrout[i].len = arrin[i].len;

193 cur += arrout[i].len;

194 }

195

198}

199

202{

205

208}

209

212{

216 int i,

217 j;

220 int w = 0;

221

222 switch (cw)

223 {

224 case 'A':

225 case 'a':

226 w = 3;

227 break;

228 case 'B':

229 case 'b':

230 w = 2;

231 break;

232 case 'C':

233 case 'c':

234 w = 1;

235 break;

236 case 'D':

237 case 'd':

238 w = 0;

239 break;

240 default:

241

242 elog(ERROR, "unrecognized weight: %d", cw);

243 }

244

246 memcpy(out, in, VARSIZE(in));

249 while (i--)

250 {

252 {

254 while (j--)

255 {

257 p++;

258 }

259 }

260 entry++;

261 }

262

265}

266

267

268

269

270

271

274{

278

280 int i,

281 j,

282 nlexemes,

283 weight;

286 bool *nulls;

287

288 switch (char_weight)

289 {

290 case 'A':

291 case 'a':

292 weight = 3;

293 break;

294 case 'B':

295 case 'b':

296 weight = 2;

297 break;

298 case 'C':

299 case 'c':

300 weight = 1;

301 break;

302 case 'D':

303 case 'd':

304 weight = 0;

305 break;

306 default:

307

308 elog(ERROR, "unrecognized weight: %c", char_weight);

309 }

310

312 memcpy(tsout, tsin, VARSIZE(tsin));

313 entry = ARRPTR(tsout);

314

316

317

318

319

320

321

322 for (i = 0; i < nlexemes; i++)

323 {

324 char *lex;

325 int lex_len,

326 lex_pos;

327

328

329 if (nulls[i])

330 continue;

331

335

336 if (lex_pos >= 0 && (j = POSDATALEN(tsout, entry + lex_pos)) != 0)

337 {

339

340 while (j--)

341 {

343 p++;

344 }

345 }

346 }

347

350

352}

353

354#define compareEntry(pa, a, pb, b) \

355 tsCompareString((pa) + (a)->pos, (a)->len, \

356 (pb) + (b)->pos, (b)->len, \

357 false)

358

359

360

361

362

367{

369 int i;

371 startlen;

374

375 if (!destptr->haspos)

376 *clen = 0;

377

378 startlen = *clen;

379 for (i = 0;

382 i++)

383 {

386 (*clen)++;

387 }

388

389 if (*clen != startlen)

391 return *clen - startlen;

392}

393

394

395

396

397

398

399static int

401{

403 int StopLow = 0,

404 StopHigh = tsv->size,

405 StopMiddle,

407

408 while (StopLow < StopHigh)

409 {

410 StopMiddle = (StopLow + StopHigh) / 2;

411

413 STRPTR(tsv) + arrin[StopMiddle].pos,

414 arrin[StopMiddle].len,

415 false);

416

417 if (cmp < 0)

418 StopHigh = StopMiddle;

419 else if (cmp > 0)

420 StopLow = StopMiddle + 1;

421 else

422 return StopMiddle;

423 }

424

425 return -1;

426}

427

428

429

430

431

432static int

434{

435 int a = *((const int *) va);

436 int b = *((const int *) vb);

437

439}

440

441static int

443{

450

451 return tsCompareString(alex, alex_len, blex, blex_len, false);

452}

453

454

455

456

457

458

459

460

461

462

465 int indices_count)

466{

469 *arrout;

471 *dataout;

472 int i,

473 j,

474 k,

475 curoff;

476

477

478

479

480

481

482 if (indices_count > 1)

483 {

484 qsort(indices_to_delete, indices_count, sizeof(int), compare_int);

485 indices_count = qunique(indices_to_delete, indices_count, sizeof(int),

487 }

488

489

490

491

492

494

495

496 tsout->size = tsv->size - indices_count;

497

498

499

500

501 arrout = ARRPTR(tsout);

502 dataout = STRPTR(tsout);

503 curoff = 0;

504 for (i = j = k = 0; i < tsv->size; i++)

505 {

506

507

508

509

510

511 if (k < indices_count && i == indices_to_delete[k])

512 {

513 k++;

514 continue;

515 }

516

517

518 memcpy(dataout + curoff, data + arrin[i].pos, arrin[i].len);

519 arrout[j].haspos = arrin[i].haspos;

520 arrout[j].len = arrin[i].len;

521 arrout[j].pos = curoff;

522 curoff += arrin[i].len;

523 if (arrin[i].haspos)

524 {

527

529 memcpy(dataout + curoff,

532 curoff += len;

533 }

534

535 j++;

536 }

537

538

539

540

541

542

543 Assert(k == indices_count);

544

546 return tsout;

547}

548

549

550

551

552

555{

557 tsout;

561 skip_index;

562

565

567

571}

572

573

574

575

576

579{

581 tsout;

583 int i,

584 nlex,

585 skip_count,

586 *skip_indices;

588 bool *nulls;

589

591

592

593

594

595

596

597 skip_indices = palloc0(nlex * sizeof(int));

598 for (i = skip_count = 0; i < nlex; i++)

599 {

600 char *lex;

601 int lex_len,

602 lex_pos;

603

604

605 if (nulls[i])

606 continue;

607

611

612 if (lex_pos >= 0)

613 skip_indices[skip_count++] = lex_pos;

614 }

615

617

618 pfree(skip_indices);

621

623}

624

625

626

627

628

629

630

633{

636

638 {

641

644

647 TEXTOID, -1, 0);

649 INT2ARRAYOID, -1, 0);

651 TEXTARRAYOID, -1, 0);

653 elog(ERROR, "return type must be a row type");

655

657

659 }

660

663

665 {

669 int j,

671 bool nulls[] = {false, false, false};

673

675

676 if (arrin[i].haspos)

677 {

679 Datum *positions;

681 char weight;

682

683

684

685

686

687

691 for (j = 0; j < posv->npos; j++)

692 {

696 1));

697 }

698

701 }

702 else

703 {

704 nulls[1] = nulls[2] = true;

705 }

706

709 }

710 else

711 {

713 }

714}

715

716

717

718

721{

725 int i;

727

729

730 for (i = 0; i < tsin->size; i++)

731 {

733 arrin[i].len));

734 }

735

737

741}

742

743

744

745

748{

753 bool *nulls;

755 i,

756 tslen,

757 datalen = 0;

758 char *cur;

759

761

762

763

764

765

767 {

768 if (nulls[i])

770 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),

771 errmsg("lexeme array may not contain nulls")));

772

775 (errcode(ERRCODE_ZERO_LENGTH_CHARACTER_STRING),

776 errmsg("lexeme array may not contain empty strings")));

777 }

778

779

781 {

785 }

786

787

791

792

796

797 arrout = ARRPTR(tsout);

800 {

803

804 memcpy(cur, lex, lex_len);

806 arrout[i].len = lex_len;

808 cur += lex_len;

809 }

810

813}

814

815

816

817

820{

822 tsout;

825 *arrout;

826 char *datain = STRPTR(tsin),

827 *dataout;

829 bool *nulls;

830 int nweights;

831 int i,

832 j;

833 int cur_pos = 0;

834 char mask = 0;

835

837

838 for (i = 0; i < nweights; i++)

839 {

840 char char_weight;

841

842 if (nulls[i])

844 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),

845 errmsg("weight array may not contain nulls")));

846

848 switch (char_weight)

849 {

850 case 'A':

851 case 'a':

852 mask = mask | 8;

853 break;

854 case 'B':

855 case 'b':

856 mask = mask | 4;

857 break;

858 case 'C':

859 case 'c':

860 mask = mask | 2;

861 break;

862 case 'D':

863 case 'd':

864 mask = mask | 1;

865 break;

866 default:

868 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),

869 errmsg("unrecognized weight: \"%c\"", char_weight)));

870 }

871 }

872

874 tsout->size = tsin->size;

875 arrout = ARRPTR(tsout);

876 dataout = STRPTR(tsout);

877

878 for (i = j = 0; i < tsin->size; i++)

879 {

881 *posvout;

882 int npos = 0;

883 int k;

884

885 if (!arrin[i].haspos)

886 continue;

887

891

892 for (k = 0; k < posvin->npos; k++)

893 {

895 posvout->pos[npos++] = posvin->pos[k];

896 }

897

898

899 if (!npos)

900 continue;

901

902 arrout[j].haspos = true;

903 arrout[j].len = arrin[i].len;

904 arrout[j].pos = cur_pos;

905

906 memcpy(dataout + cur_pos, datain + arrin[i].pos, arrin[i].len);

907 posvout->npos = npos;

911 j++;

912 }

913

914 tsout->size = j;

915 if (dataout != STRPTR(tsout))

916 memmove(STRPTR(tsout), dataout, cur_pos);

917

919

922}

923

926{

932 *ptr2;

934 int maxpos = 0,

935 i,

936 j,

937 i1,

938 i2,

939 dataoff,

940 output_bytes,

941 output_size;

943 *data1,

944 *data2;

945

946

949 while (i--)

950 {

952 {

954 while (j--)

955 {

958 p++;

959 }

960 }

961 ptr++;

962 }

963

968 i1 = in1->size;

969 i2 = in2->size;

970

971

972

973

974

975

976 output_bytes = VARSIZE(in1) + VARSIZE(in2) + i1 + i2;

977

980

981

982

983

984

986

989 dataoff = 0;

990 while (i1 && i2)

991 {

993

994 if (cmp < 0)

995 {

997 ptr->len = ptr1->len;

998 memcpy(data + dataoff, data1 + ptr1->pos, ptr1->len);

999 ptr->pos = dataoff;

1000 dataoff += ptr1->len;

1002 {

1006 }

1007

1008 ptr++;

1009 ptr1++;

1010 i1--;

1011 }

1012 else if (cmp > 0)

1013 {

1015 ptr->len = ptr2->len;

1016 memcpy(data + dataoff, data2 + ptr2->pos, ptr2->len);

1017 ptr->pos = dataoff;

1018 dataoff += ptr2->len;

1020 {

1021 int addlen = add_pos(in2, ptr2, out, ptr, maxpos);

1022

1023 if (addlen == 0)

1025 else

1026 {

1029 }

1030 }

1031

1032 ptr++;

1033 ptr2++;

1034 i2--;

1035 }

1036 else

1037 {

1039 ptr->len = ptr1->len;

1040 memcpy(data + dataoff, data1 + ptr1->pos, ptr1->len);

1041 ptr->pos = dataoff;

1042 dataoff += ptr1->len;

1044 {

1046 {

1052 }

1053 else

1054 {

1055 int addlen = add_pos(in2, ptr2, out, ptr, maxpos);

1056

1057 if (addlen == 0)

1059 else

1060 {

1063 }

1064 }

1065 }

1066

1067 ptr++;

1068 ptr1++;

1069 ptr2++;

1070 i1--;

1071 i2--;

1072 }

1073 }

1074

1075 while (i1)

1076 {

1078 ptr->len = ptr1->len;

1079 memcpy(data + dataoff, data1 + ptr1->pos, ptr1->len);

1080 ptr->pos = dataoff;

1081 dataoff += ptr1->len;

1083 {

1087 }

1088

1089 ptr++;

1090 ptr1++;

1091 i1--;

1092 }

1093

1094 while (i2)

1095 {

1097 ptr->len = ptr2->len;

1098 memcpy(data + dataoff, data2 + ptr2->pos, ptr2->len);

1099 ptr->pos = dataoff;

1100 dataoff += ptr2->len;

1102 {

1103 int addlen = add_pos(in2, ptr2, out, ptr, maxpos);

1104

1105 if (addlen == 0)

1107 else

1108 {

1111 }

1112 }

1113

1114 ptr++;

1115 ptr2++;

1116 i2--;

1117 }

1118

1119

1120

1121

1122

1125 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),

1126 errmsg("string is too long for tsvector (%d bytes, max %d bytes)", dataoff, MAXSTRPOS)));

1127

1128

1129

1130

1131

1132 output_size = ptr - ARRPTR(out);

1133 Assert(output_size <= out->size);

1134 out->size = output_size;

1136 memmove(STRPTR(out), data, dataoff);

1140

1144}

1145

1146

1147

1148

1149

1150

1153{

1154 int cmp;

1155

1156 if (lena == 0)

1157 {

1158 if (prefix)

1159 cmp = 0;

1160 else

1161 cmp = (lenb > 0) ? -1 : 0;

1162 }

1163 else if (lenb == 0)

1164 {

1165 cmp = (lena > 0) ? 1 : 0;

1166 }

1167 else

1168 {

1169 cmp = memcmp(a, b, Min((unsigned int) lena, (unsigned int) lenb));

1170

1171 if (prefix)

1172 {

1173 if (cmp == 0 && lena > lenb)

1174 cmp = 1;

1175 }

1176 else if (cmp == 0 && lena != lenb)

1177 {

1178 cmp = (lena < lenb) ? -1 : 1;

1179 }

1180 }

1181

1182 return cmp;

1183}

1184

1185

1186

1187

1191{

1193

1195

1197 {

1199

1200

1201

1202

1203

1206

1207 if (val->weight && data)

1208 {

1211

1212

1213

1214

1216 data->allocated = true;

1217

1218

1219 while (posvec_iter < posvec->pos + posvec->npos)

1220 {

1221

1223 {

1225 dptr++;

1226 }

1227

1228 posvec_iter++;

1229 }

1230

1231 data->npos = dptr - data->pos;

1232

1233 if (data->npos > 0)

1235 else

1236 {

1238 data->pos = NULL;

1239 data->allocated = false;

1240 }

1241 }

1242 else if (val->weight)

1243 {

1245

1246

1247 while (posvec_iter < posvec->pos + posvec->npos)

1248 {

1250 {

1252 break;

1253 }

1254

1255 posvec_iter++;

1256 }

1257 }

1258 else if (data)

1259 {

1261 data->pos = posvec->pos;

1262 data->allocated = false;

1264 }

1265 else

1266 {

1267

1269 }

1270 }

1271 else

1272 {

1273

1274

1275

1276

1277

1278

1279

1280

1281

1284 else

1286 }

1287

1288 return result;

1289}

1290

1291

1292

1293

1296{

1300 WordEntry *StopMiddle = StopHigh;

1302

1303

1304 while (StopLow < StopHigh)

1305 {

1307

1308 StopMiddle = StopLow + (StopHigh - StopLow) / 2;

1310 val->length,

1311 chkval->values + StopMiddle->pos,

1312 StopMiddle->len,

1313 false);

1314

1316 {

1317

1319 break;

1320 }

1322 StopLow = StopMiddle + 1;

1323 else

1324 StopHigh = StopMiddle;

1325 }

1326

1327

1328

1329

1330

1331

1332

1333

1335 {

1337 int npos = 0,

1338 totalpos = 0;

1339

1340

1341 if (StopLow >= StopHigh)

1342 StopMiddle = StopHigh;

1343

1344

1346 {

1347 if (data->allocated)

1349 data->pos = NULL;

1350 data->allocated = false;

1351 data->npos = 0;

1352 }

1354

1356 StopMiddle < chkval->arre &&

1358 val->length,

1359 chkval->values + StopMiddle->pos,

1360 StopMiddle->len,

1361 true) == 0)

1362 {

1364

1366

1367 if (subres != TS_NO)

1368 {

1370 {

1371

1372

1373

1375 {

1376

1377

1378

1379

1381

1382 npos = 0;

1383

1384 if (allpos)

1386 break;

1387 }

1388

1389 while (npos + data->npos > totalpos)

1390 {

1391 if (totalpos == 0)

1392 {

1393 totalpos = 256;

1395 }

1396 else

1397 {

1398 totalpos *= 2;

1400 }

1401 }

1402

1404 npos += data->npos;

1405

1406

1407 if (data->allocated)

1409 data->pos = NULL;

1410 data->allocated = false;

1411

1412 data->npos = 0;

1413 }

1414 else

1415 {

1416

1418 res = subres;

1419 }

1420 }

1421

1422 StopMiddle++;

1423 }

1424

1425 if (data && npos > 0)

1426 {

1427

1428 data->pos = allpos;

1432 data->allocated = true;

1434 }

1435 }

1436

1437 return res;

1438}

1439

1440

1441

1442

1443

1444

1445

1446

1447

1448

1449

1450

1451

1452

1453

1454

1455

1456

1457

1458

1459

1460

1461

1462

1463#define TSPO_L_ONLY 0x01

1464#define TSPO_R_ONLY 0x02

1465#define TSPO_BOTH 0x04

1466

1471 int emit,

1472 int Loffset,

1473 int Roffset,

1474 int max_npos)

1475{

1476 int Lindex,

1477 Rindex;

1478

1479

1480 Lindex = Rindex = 0;

1481 while (Lindex < Ldata->npos || Rindex < Rdata->npos)

1482 {

1483 int Lpos,

1484 Rpos;

1485 int output_pos = 0;

1486

1487

1488

1489

1490

1491 if (Lindex < Ldata->npos)

1492 Lpos = WEP_GETPOS(Ldata->pos[Lindex]) + Loffset;

1493 else

1494 {

1495

1497 break;

1498 Lpos = INT_MAX;

1499 }

1500 if (Rindex < Rdata->npos)

1501 Rpos = WEP_GETPOS(Rdata->pos[Rindex]) + Roffset;

1502 else

1503 {

1504

1506 break;

1507 Rpos = INT_MAX;

1508 }

1509

1510

1511 if (Lpos < Rpos)

1512 {

1513

1515 output_pos = Lpos;

1516 Lindex++;

1517 }

1518 else if (Lpos == Rpos)

1519 {

1520

1522 output_pos = Rpos;

1523 Lindex++;

1524 Rindex++;

1525 }

1526 else

1527 {

1528

1530 output_pos = Rpos;

1531 Rindex++;

1532 }

1533

1534 if (output_pos > 0)

1535 {

1537 {

1538

1539 if (data->pos == NULL)

1540 {

1543 data->allocated = true;

1544 }

1545 data->pos[data->npos++] = output_pos;

1546 }

1547 else

1548 {

1549

1550

1551

1552

1554 }

1555 }

1556 }

1557

1559 {

1560

1563 }

1565}

1566

1567

1568

1569

1570

1571

1572

1573

1574

1575

1576

1577

1578

1579

1580

1581

1582

1583

1584

1585

1586

1587

1588

1589

1590

1591

1592

1593

1594

1595

1596

1597

1598

1599

1600

1601

1602

1603

1604

1605

1606

1607

1612{

1614 Rdata;

1616 rmatch;

1617 int Loffset,

1618 Roffset,

1619 maxwidth;

1620

1621

1623

1624

1626

1629

1631 {

1633

1634

1635

1636

1637

1639 {

1640

1642 data->negate = true;

1644 }

1646 {

1648

1650 data->negate = true;

1653 if (data->npos > 0)

1654 {

1655

1656 data->negate = data->negate;

1658 }

1659 else if (data->negate)

1660 {

1661

1662 data->negate = false;

1664 }

1665

1667 break;

1669

1671 }

1672 break;

1673

1676 memset(&Ldata, 0, sizeof(Ldata));

1677 memset(&Rdata, 0, sizeof(Rdata));

1678

1680 arg, flags, chkcond, &Ldata);

1681 if (lmatch == TS_NO)

1683

1685 arg, flags, chkcond, &Rdata);

1686 if (rmatch == TS_NO)

1688

1689

1690

1691

1692

1695

1697 {

1698

1699

1700

1701

1703 Roffset = 0;

1707 }

1708 else

1709 {

1710

1711

1712

1713

1715 Loffset = maxwidth - Ldata.width;

1716 Roffset = maxwidth - Rdata.width;

1718 data->width = maxwidth;

1719 }

1720

1722 {

1723

1726 Loffset, Roffset,

1729 data->negate = true;

1731 }

1732 else if (Ldata.negate)

1733 {

1734

1737 Loffset, Roffset,

1738 Rdata.npos);

1739 }

1740 else if (Rdata.negate)

1741 {

1742

1745 Loffset, Roffset,

1746 Ldata.npos);

1747 }

1748 else

1749 {

1750

1753 Loffset, Roffset,

1755 }

1756

1758 memset(&Ldata, 0, sizeof(Ldata));

1759 memset(&Rdata, 0, sizeof(Rdata));

1760

1762 arg, flags, chkcond, &Ldata);

1764 arg, flags, chkcond, &Rdata);

1765

1766 if (lmatch == TS_NO && rmatch == TS_NO)

1768

1769

1770

1771

1772

1775

1776

1777

1778

1779

1780

1781 if (lmatch == TS_NO)

1782 Ldata.width = 0;

1783 if (rmatch == TS_NO)

1784 Rdata.width = 0;

1785

1786

1787

1788

1789

1790

1791

1793 Loffset = maxwidth - Ldata.width;

1794 Roffset = maxwidth - Rdata.width;

1795 data->width = maxwidth;

1796

1798 {

1799

1802 Loffset, Roffset,

1804 data->negate = true;

1806 }

1807 else if (Ldata.negate)

1808 {

1809

1812 Loffset, Roffset,

1813 Ldata.npos);

1814 data->negate = true;

1816 }

1817 else if (Rdata.negate)

1818 {

1819

1822 Loffset, Roffset,

1823 Rdata.npos);

1824 data->negate = true;

1826 }

1827 else

1828 {

1829

1832 Loffset, Roffset,

1834 }

1835

1836 default:

1838 }

1839

1840

1842}

1843

1844

1845

1846

1847

1848

1849

1850

1851

1852

1853bool

1856{

1857

1858

1859

1860

1861

1863}

1864

1865

1866

1867

1868

1869

1873{

1875}

1876

1877

1878

1879

1880

1881

1885{

1887

1888

1890

1891

1893

1896 NULL );

1897

1899 {

1904 {

1911 }

1912 break;

1913

1916 flags, chkcond);

1917 if (lmatch == TS_NO)

1920 {

1924 return lmatch;

1927 }

1928 break;

1929

1932 flags, chkcond);

1933 if (lmatch == TS_YES)

1936 {

1938 return lmatch;

1943 }

1944 break;

1945

1947

1948

1949

1950

1951

1952

1953

1954

1955

1956

1958 {

1965 }

1966 break;

1967

1968 default:

1970 }

1971

1972

1974}

1975

1976

1977

1978

1979

1980

1981

1982

1983

1984

1985

1986

1987

1988

1989

1990

1991

1992

1993

1994

1995

1996

1997

1998

1999

2000

2001

2002

2003

2004

2005

2010{

2011 List *result;

2012

2013

2016 return result;

2017 return NIL;

2018}

2019

2020

2021

2022

2023

2024static bool

2027 List **locations)

2028{

2029 bool lmatch,

2030 rmatch;

2031 List *llocations,

2032 *rlocations;

2034

2035

2037

2038

2040

2041

2042 *locations = NIL;

2043

2045 {

2048 {

2050 return true;

2051 }

2053 return false;

2054 }

2055

2057 {

2060 &llocations))

2061 return true;

2062 return false;

2063

2066 arg, chkcond,

2067 &llocations))

2068 return false;

2070 arg, chkcond,

2071 &rlocations))

2072 return false;

2073 *locations = list_concat(llocations, rlocations);

2074 return true;

2075

2078 arg, chkcond,

2079 &llocations);

2081 arg, chkcond,

2082 &rlocations);

2083 if (lmatch || rmatch)

2084 {

2085

2086

2087

2088

2089

2090

2091

2092

2093 if (llocations == NIL)

2094 *locations = rlocations;

2095 else if (rlocations == NIL)

2096 *locations = llocations;

2097 else

2098 {

2100

2101 foreach(ll, llocations)

2102 {

2105

2106 foreach(lr, rlocations)

2107 {

2109

2113 0, 0,

2115

2118 }

2119 }

2120 }

2121

2122 return true;

2123 }

2124 return false;

2125

2127

2131 {

2132 if (data->negate)

2134 return true;

2135 }

2137 return false;

2138

2139 default:

2141 }

2142

2143

2144 return false;

2145}

2146

2147

2148

2149

2150

2151

2152

2153

2154

2155bool

2157{

2158

2160

2162 return true;

2163

2165 {

2167

2168

2169

2170

2171

2172

2173 return false;

2174

2176

2177

2178

2179

2181

2183 return true;

2184 else

2186

2188

2191 else

2192 return false;

2193

2194 default:

2196 }

2197

2198

2199 return false;

2200}

2201

2202

2203

2204

2207{

2211}

2212

2215{

2219 bool result;

2220

2221

2222 if (!query->size)

2223 {

2227 }

2228

2234 &chkval,

2237

2241}

2242

2245{

2248 bool res;

2249

2254

2258

2261

2263}

2264

2267{

2270 bool res;

2271

2274

2278

2281

2283}

2284

2285

2286

2287

2288

2289

2290

2291

2292

2293

2294static int

2296{

2298 int num = 0;

2300

2301 while (len--)

2302 {

2304 num++;

2305 ptr++;

2306 }

2307 return num;

2308}

2309

2310#define compareStatWord(a,e,t) \

2311 tsCompareString((a)->lexeme, (a)->lenlexeme, \

2312 STRPTR(t) + (e)->pos, (e)->len, \

2313 false)

2314

2315static void

2317{

2320 *pnode = NULL;

2321 int n,

2322 res = 0;

2324

2325 if (stat->weight == 0)

2327 else

2329

2330 if (n == 0)

2331 return;

2332

2333 while (node)

2334 {

2336

2337 if (res == 0)

2338 {

2339 break;

2340 }

2341 else

2342 {

2343 pnode = node;

2344 node = (res < 0) ? node->left : node->right;

2345 }

2346 depth++;

2347 }

2348

2349 if (depth > stat->maxdepth)

2350 stat->maxdepth = depth;

2351

2352 if (node == NULL)

2353 {

2355 node->left = node->right = NULL;

2356 node->ndoc = 1;

2360

2361 if (pnode == NULL)

2362 {

2363 stat->root = node;

2364 }

2365 else

2366 {

2367 if (res < 0)

2368 pnode->left = node;

2369 else

2370 pnode->right = node;

2371 }

2372 }

2373 else

2374 {

2375 node->ndoc++;

2377 }

2378}

2379

2380static void

2383{

2385 uint32 middle = (low + high) >> 1;

2386

2387 pos = (low + middle) >> 1;

2388 if (low != middle && pos >= offset && pos - offset < txt->size)

2390 pos = (high + middle + 1) >> 1;

2391 if (middle + 1 != high && pos >= offset && pos - offset < txt->size)

2393

2394 if (low != middle)

2396 if (high != middle + 1)

2398}

2399

2400

2401

2402

2403

2404

2405

2406

2407

2408

2409

2410

2411

2414{

2417 nbit = 0,

2418 offset;

2419

2420 if (stat == NULL)

2421 {

2423 stat->maxdepth = 1;

2424 }

2425

2426

2427 if (txt == NULL || txt->size == 0)

2428 {

2431 return stat;

2432 }

2433

2434 i = txt->size - 1;

2435 for (; i > 0; i >>= 1)

2436 nbit++;

2437

2438 nbit = 1 << nbit;

2439 offset = (nbit - txt->size) / 2;

2440

2443

2444 return stat;

2445}

2446

2447static void

2450{

2454

2456

2458

2460 stat->stackpos = 0;

2461

2462 node = stat->root;

2463

2464 if (node == NULL)

2465 stat->stack[stat->stackpos] = NULL;

2466 else

2467 for (;;)

2468 {

2469 stat->stack[stat->stackpos] = node;

2470 if (node->left)

2471 {

2472 stat->stackpos++;

2473 node = node->left;

2474 }

2475 else

2476 break;

2477 }

2479

2481 elog(ERROR, "return type must be a row type");

2484

2486}

2487

2490{

2492

2493 if (node == NULL)

2494 return NULL;

2495

2496 if (node->ndoc != 0)

2497 {

2498

2499 return node;

2500 }

2501 else if (node->right && node->right != stat->stack[stat->stackpos + 1])

2502 {

2503

2504 stat->stackpos++;

2505 node = node->right;

2506

2507

2508 for (;;)

2509 {

2510 stat->stack[stat->stackpos] = node;

2511 if (node->left)

2512 {

2513 stat->stackpos++;

2514 node = node->left;

2515 }

2516 else

2517 break;

2518 }

2520 }

2521 else

2522 {

2523

2524 if (stat->stackpos == 0)

2525 return NULL;

2526

2527 stat->stackpos--;

2529 }

2530

2531 return node;

2532}

2533

2536{

2539

2541

2543

2544 if (entry != NULL)

2545 {

2548 char ndoc[16];

2551

2559

2562

2564

2565

2566 entry->ndoc = 0;

2567

2568 return result;

2569 }

2570

2571 return (Datum) 0;

2572}

2573

2576{

2579 bool isnull;

2582

2584

2585 elog(ERROR, "SPI_prepare(\"%s\") failed", query);

2586

2588

2589 elog(ERROR, "SPI_cursor_open(\"%s\") failed", query);

2590

2592

2596 TSVECTOROID))

2598 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),

2599 errmsg("ts_stat query must return one tsvector column")));

2600

2602 stat->maxdepth = 1;

2603

2604 if (ws)

2605 {

2606 char *buf;

2607

2610 {

2612 {

2613 switch (*buf)

2614 {

2615 case 'A':

2616 case 'a':

2617 stat->weight |= 1 << 3;

2618 break;

2619 case 'B':

2620 case 'b':

2621 stat->weight |= 1 << 2;

2622 break;

2623 case 'C':

2624 case 'c':

2625 stat->weight |= 1 << 1;

2626 break;

2627 case 'D':

2628 case 'd':

2629 stat->weight |= 1;

2630 break;

2631 default:

2632 stat->weight |= 0;

2633 }

2634 }

2636 }

2637 }

2638

2640 {

2642

2644 {

2646

2647 if (!isnull)

2649 }

2650

2653 }

2654

2659

2660 return stat;

2661}

2662

2665{

2668

2670 {

2673

2680 }

2681

2686}

2687

2690{

2693

2695 {

2699

2707 }

2708

2713}

2714

2715

2716

2717

2718

2719

2720

2721

2722

2723

2724

2725

2728{

2730}

2731

2734{

2736}

2737

2740{

2745 int tsvector_attr_num,

2746 i;

2749 bool isnull;

2751 Oid cfgId;

2752 bool update_needed;

2753

2754

2756 elog(ERROR, "tsvector_update_trigger: not fired by trigger manager");

2757

2758 trigdata = (TriggerData *) fcinfo->context;

2760 elog(ERROR, "tsvector_update_trigger: must be fired for row");

2762 elog(ERROR, "tsvector_update_trigger: must be fired BEFORE event");

2763

2765 {

2767 update_needed = true;

2768 }

2770 {

2772 update_needed = false;

2773 }

2774 else

2775 elog(ERROR, "tsvector_update_trigger: must be fired for INSERT or UPDATE");

2776

2779

2780 if (trigger->tgnargs < 3)

2781 elog(ERROR, "tsvector_update_trigger: arguments must be tsvector_field, ts_config, text_field1, ...)");

2782

2783

2787 (errcode(ERRCODE_UNDEFINED_COLUMN),

2788 errmsg("tsvector column \"%s\" does not exist",

2789 trigger->tgargs[0])));

2790

2792 TSVECTOROID))

2794 (errcode(ERRCODE_DATATYPE_MISMATCH),

2795 errmsg("column \"%s\" is not of tsvector type",

2796 trigger->tgargs[0])));

2797

2798

2799 if (config_column)

2800 {

2801 int config_attr_num;

2802

2806 (errcode(ERRCODE_UNDEFINED_COLUMN),

2807 errmsg("configuration column \"%s\" does not exist",

2808 trigger->tgargs[1])));

2810 REGCONFIGOID))

2812 (errcode(ERRCODE_DATATYPE_MISMATCH),

2813 errmsg("column \"%s\" is not of regconfig type",

2814 trigger->tgargs[1])));

2815

2817 if (isnull)

2819 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),

2820 errmsg("configuration column \"%s\" must not be null",

2821 trigger->tgargs[1])));

2823 }

2824 else

2825 {

2826 List *names;

2827

2829

2832 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),

2833 errmsg("text search configuration name \"%s\" must be schema-qualified",

2834 trigger->tgargs[1])));

2836 }

2837

2838

2841 prs.pos = 0;

2843

2844

2845 for (i = 2; i < trigger->tgnargs; i++)

2846 {

2848

2852 (errcode(ERRCODE_UNDEFINED_COLUMN),

2853 errmsg("column \"%s\" does not exist",

2857 (errcode(ERRCODE_DATATYPE_MISMATCH),

2858 errmsg("column \"%s\" is not of a character type",

2860

2862 update_needed = true;

2863

2865 if (isnull)

2866 continue;

2867

2869

2871

2874 }

2875

2876 if (update_needed)

2877 {

2878

2880 isnull = false;

2881

2882

2884 1, &tsvector_attr_num,

2885 &datum, &isnull);

2886

2888 }

2889

2891}

#define PG_GETARG_ARRAYTYPE_P(n)

ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)

void deconstruct_array_builtin(const ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)

bool bms_is_member(int x, const Bitmapset *a)

static Datum values[MAXATTR]

#define FLEXIBLE_ARRAY_MEMBER

int errcode(int sqlerrcode)

int errmsg(const char *fmt,...)

#define ereport(elevel,...)

HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)

AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)

#define repalloc_array(pointer, type, count)

#define palloc_array(type, count)

#define palloc0_array(type, count)

#define palloc0_object(type)

#define PG_FREE_IF_COPY(ptr, n)

#define PG_GETARG_TEXT_PP(n)

#define DirectFunctionCall2(func, arg1, arg2)

#define PG_GETARG_CHAR(n)

#define DatumGetTextPP(X)

#define DirectFunctionCall1(func, arg1)

#define PG_GETARG_DATUM(n)

#define PG_RETURN_INT32(x)

#define PG_RETURN_DATUM(x)

#define PG_RETURN_POINTER(x)

#define PG_RETURN_BOOL(x)

TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)

#define SRF_IS_FIRSTCALL()

#define SRF_PERCALL_SETUP()

#define SRF_RETURN_NEXT(_funcctx, _result)

#define SRF_FIRSTCALL_INIT()

static Datum HeapTupleGetDatum(const HeapTupleData *tuple)

#define SRF_RETURN_DONE(_funcctx)

Datum difference(PG_FUNCTION_ARGS)

Assert(PointerIsAligned(start, uint64))

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)

#define CALCDATASIZE(x, lenstr)

static int pg_cmp_s32(int32 a, int32 b)

if(TABLE==NULL||TABLE_index==NULL)

List * lappend(List *list, void *datum)

List * list_concat(List *list1, const List *list2)

int pg_mblen(const char *mbstr)

void * MemoryContextAlloc(MemoryContext context, Size size)

void * MemoryContextAllocZero(MemoryContext context, Size size)

void pfree(void *pointer)

void * palloc0(Size size)

#define CHECK_FOR_INTERRUPTS()

Oid get_ts_config_oid(List *names, bool missing_ok)

static MemoryContext MemoryContextSwitchTo(MemoryContext context)

bool IsBinaryCoercible(Oid srctype, Oid targettype)

static int list_length(const List *l)

static char buf[DEFAULT_XLOG_SEG_SIZE]

#define qsort(a, b, c, d)

static bool DatumGetBool(Datum X)

static Datum PointerGetDatum(const void *X)

static Oid DatumGetObjectId(Datum X)

static Datum Int16GetDatum(int16 X)

static Pointer DatumGetPointer(Datum X)

static char DatumGetChar(Datum X)

static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))

static int cmp(const chr *x, const chr *y, size_t len)

List * stringToQualifiedNameList(const char *string, Node *escontext)

int SPI_fnumber(TupleDesc tupdesc, const char *fname)

Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber)

int SPI_freeplan(SPIPlanPtr plan)

SPITupleTable * SPI_tuptable

Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, const Datum *Values, const char *Nulls, bool read_only)

void SPI_cursor_fetch(Portal portal, bool forward, long count)

void SPI_freetuptable(SPITupleTable *tuptable)

SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)

void SPI_cursor_close(Portal portal)

Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)

#define SPI_ERROR_NOATTRIBUTE

void check_stack_depth(void)

AttInMetadata * attinmeta

MemoryContext multi_call_memory_ctx

char lexeme[FLEXIBLE_ARRAY_MEMBER]

const Bitmapset * tg_updatedcols

WordEntryPos pos[FLEXIBLE_ARRAY_MEMBER]

#define FirstLowInvalidHeapAttributeNumber

Datum to_tsvector(PG_FUNCTION_ARGS)

TSVector make_tsvector(ParsedText *prs)

Datum plainto_tsquery(PG_FUNCTION_ARGS)

#define TRIGGER_FIRED_BEFORE(event)

#define CALLED_AS_TRIGGER(fcinfo)

#define TRIGGER_FIRED_FOR_ROW(event)

#define TRIGGER_FIRED_BY_INSERT(event)

#define TRIGGER_FIRED_BY_UPDATE(event)

void parsetext(Oid cfgId, ParsedText *prs, char *buf, int buflen)

#define PG_GETARG_TSVECTOR(n)

static TSQuery DatumGetTSQuery(Datum X)

static TSVector DatumGetTSVector(Datum X)

static Datum TSVectorGetDatum(const TSVectorData *X)

#define PG_GETARG_TSQUERY(n)

#define PG_GETARG_TSVECTOR_COPY(n)

#define WEP_SETWEIGHT(x, v)

static Datum TSQueryGetDatum(const TSQueryData *X)

#define TS_EXEC_PHRASE_NO_POS

TSTernaryValue(* TSExecuteCallback)(void *arg, QueryOperand *val, ExecPhraseData *data)

int compareWordEntryPos(const void *a, const void *b)

Datum tsvector_setweight_by_filter(PG_FUNCTION_ARGS)

static Datum ts_process_call(FuncCallContext *funcctx)

static TSTernaryValue checkcondition_str(void *checkval, QueryOperand *val, ExecPhraseData *data)

bool TS_execute(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)

Datum ts_match_vq(PG_FUNCTION_ARGS)

Datum tsvector_update_trigger_byid(PG_FUNCTION_ARGS)

static int32 add_pos(TSVector src, WordEntry *srcptr, TSVector dest, WordEntry *destptr, int32 maxpos)

static TSVectorStat * ts_stat_sql(MemoryContext persistentContext, text *txt, text *ws)

List * TS_execute_locations(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)

Datum tsvector_delete_arr(PG_FUNCTION_ARGS)

Datum array_to_tsvector(PG_FUNCTION_ARGS)

Datum tsvector_filter(PG_FUNCTION_ARGS)

static TSTernaryValue TS_phrase_output(ExecPhraseData *data, ExecPhraseData *Ldata, ExecPhraseData *Rdata, int emit, int Loffset, int Roffset, int max_npos)

#define compareEntry(pa, a, pb, b)

Datum tsvector_setweight(PG_FUNCTION_ARGS)

#define TSVECTORCMPFUNC(type, action, ret)

static int check_weight(TSVector txt, WordEntry *wptr, int8 weight)

Datum tsvector_strip(PG_FUNCTION_ARGS)

struct StatEntry StatEntry

Datum tsvector_length(PG_FUNCTION_ARGS)

Datum tsvector_to_array(PG_FUNCTION_ARGS)

Datum ts_match_tq(PG_FUNCTION_ARGS)

static int silly_cmp_tsvector(const TSVectorData *a, const TSVectorData *b)

Datum ts_stat1(PG_FUNCTION_ARGS)

int32 tsCompareString(char *a, int lena, char *b, int lenb, bool prefix)

Datum tsvector_delete_str(PG_FUNCTION_ARGS)

static Datum tsvector_update_trigger(PG_FUNCTION_ARGS, bool config_column)

Datum ts_match_qv(PG_FUNCTION_ARGS)

bool tsquery_requires_match(QueryItem *curitem)

Datum tsvector_concat(PG_FUNCTION_ARGS)

Datum tsvector_update_trigger_bycolumn(PG_FUNCTION_ARGS)

static bool TS_execute_locations_recurse(QueryItem *curitem, void *arg, TSExecuteCallback chkcond, List **locations)

static TSTernaryValue TS_execute_recurse(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)

static TSVectorStat * ts_accum(MemoryContext persistentContext, TSVectorStat *stat, Datum data)

TSTernaryValue TS_execute_ternary(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond)

static int compare_int(const void *va, const void *vb)

static void ts_setup_firstcall(FunctionCallInfo fcinfo, FuncCallContext *funcctx, TSVectorStat *stat)

static void chooseNextStatEntry(MemoryContext persistentContext, TSVectorStat *stat, TSVector txt, uint32 low, uint32 high, uint32 offset)

Datum ts_match_tt(PG_FUNCTION_ARGS)

static TSTernaryValue TS_phrase_execute(QueryItem *curitem, void *arg, uint32 flags, TSExecuteCallback chkcond, ExecPhraseData *data)

static int tsvector_bsearch(const TSVectorData *tsv, char *lexeme, int lexeme_len)

static int compare_text_lexemes(const void *va, const void *vb)

static TSTernaryValue checkclass_str(CHKVAL *chkval, WordEntry *entry, QueryOperand *val, ExecPhraseData *data)

#define compareStatWord(a, e, t)

Datum tsvector_unnest(PG_FUNCTION_ARGS)

static StatEntry * walkStatEntryTree(TSVectorStat *stat)

Datum ts_stat2(PG_FUNCTION_ARGS)

static void insertStatEntry(MemoryContext persistentContext, TSVectorStat *stat, TSVector txt, uint32 off)

static TSVector tsvector_delete_by_indices(TSVector tsv, int *indices_to_delete, int indices_count)

TupleDesc CreateTemplateTupleDesc(int natts)

void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)

static Size VARSIZE_ANY_EXHDR(const void *PTR)

static Size VARSIZE(const void *PTR)

static char * VARDATA(const void *PTR)

static char * VARDATA_ANY(const void *PTR)

static void SET_VARSIZE(void *PTR, Size len)

text * cstring_to_text_with_len(const char *s, int len)

char * text_to_cstring(const text *t)