PostgreSQL Source Code: src/backend/executor/execIndexing.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

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

108

120

121

122typedef enum

123{

128

133 EState *estate, bool newIndex,

135 bool violationOK,

137

139 const Datum *existing_values, const bool *existing_isnull,

140 const Datum *new_values);

147 char typtype, Oid atttypid);

148

149

150

151

152

153

154

155

156

157

158

159void

161{

163 List *indexoidlist;

166 i;

169

171

172

174 return;

175

176

177

178

181 if (len == 0)

182 return;

183

184

186

187

188

189

192

196

197

198

199

200

201

202

203

204 i = 0;

205 foreach(l, indexoidlist)

206 {

210

212

213

215

216

217

218

219

220 if (speculative && ii->ii_Unique && !indexDesc->rd_index->indisexclusion)

222

223 relationDescs[i] = indexDesc;

224 indexInfoArray[i] = ii;

225 i++;

226 }

227

229}

230

231

232

233

234

235

236

237void

239{

240 int i;

241 int numIndices;

244

248

249 for (i = 0; i < numIndices; i++)

250 {

251

252 Assert(indexDescs[i] != NULL);

253

254

256

257

259

260

261 indexDescs[i] = NULL;

262 }

263

264

265

266

267

268

269}

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

312 bool update,

313 bool noDupErr,

314 bool *specConflict,

315 List *arbiterIndexes,

316 bool onlySummarizing)

317{

320 int i;

321 int numIndices;

328

330

331

332

333

338

339

341

342

343

344

345

347

348

350

351

352

353

354 for (i = 0; i < numIndices; i++)

355 {

356 Relation indexRelation = relationDescs[i];

358 bool applyNoDupErr;

360 bool indexUnchanged;

361 bool satisfiesConstraint;

362

363 if (indexRelation == NULL)

364 continue;

365

366 indexInfo = indexInfoArray[i];

367

368

370 continue;

371

372

373

374

375

377 continue;

378

379

381 {

383

384

385

386

387

389 if (predicate == NULL)

390 {

393 }

394

395

396 if (ExecQual(predicate, econtext))

397 continue;

398 }

399

400

401

402

403

405 slot,

406 estate,

408 isnull);

409

410

411 applyNoDupErr = noDupErr &&

412 (arbiterIndexes == NIL ||

414 indexRelation->rd_index->indexrelid));

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429 if (!indexRelation->rd_index->indisunique)

431 else if (applyNoDupErr)

433 else if (indexRelation->rd_index->indimmediate)

435 else

437

438

439

440

441

442

444 estate,

445 indexInfo,

446 indexRelation);

447

448 satisfiesConstraint =

449 index_insert(indexRelation,

450 values,

451 isnull,

452 tupleid,

453 heapRelation,

454 checkUnique,

455 indexUnchanged,

456 indexInfo);

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

473 {

474 bool violationOK;

476

477 if (applyNoDupErr)

478 {

479 violationOK = true;

481 }

482 else if (!indexRelation->rd_index->indimmediate)

483 {

484 violationOK = true;

486 }

487 else

488 {

489 violationOK = false;

491 }

492

493 satisfiesConstraint =

495 indexRelation, indexInfo,

496 tupleid, values, isnull,

497 estate, false,

498 waitMode, violationOK, NULL);

499 }

500

503 !satisfiesConstraint)

504 {

505

506

507

508

509

510

512 if (indexRelation->rd_index->indimmediate && specConflict)

513 *specConflict = true;

514 }

515 }

516

517 return result;

518}

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541bool

545{

546 int i;

547 int numIndices;

555 bool checkedIndex = false;

556

559

560

561

562

567

568

569

570

571

573

574

576

577

578

579

580

581 for (i = 0; i < numIndices; i++)

582 {

583 Relation indexRelation = relationDescs[i];

585 bool satisfiesConstraint;

586

587 if (indexRelation == NULL)

588 continue;

589

590 indexInfo = indexInfoArray[i];

591

593 continue;

594

595

597 continue;

598

599

600 if (arbiterIndexes != NIL &&

602 indexRelation->rd_index->indexrelid))

603 continue;

604

605 if (!indexRelation->rd_index->indimmediate)

607 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),

608 errmsg("ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters"),

611

612 checkedIndex = true;

613

614

616 {

618

619

620

621

622

624 if (predicate == NULL)

625 {

628 }

629

630

631 if (ExecQual(predicate, econtext))

632 continue;

633 }

634

635

636

637

638

640 slot,

641 estate,

643 isnull);

644

645 satisfiesConstraint =

647 indexInfo, tupleid,

648 values, isnull, estate, false,

650 conflictTid);

651 if (!satisfiesConstraint)

652 return false;

653 }

654

655 if (arbiterIndexes != NIL && !checkedIndex)

656 elog(ERROR, "unexpected failure to find arbiter index");

657

658 return true;

659}

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

695

696

697

698

699

700

701

702

703static bool

708 EState *estate, bool newIndex,

710 bool violationOK,

712{

713 Oid *constr_procs;

714 uint16 *constr_strats;

715 Oid *index_collations = index->rd_indcollation;

720 int i;

721 bool conflict;

722 bool found_self;

726

728 {

731 }

732 else

733 {

736 }

737

738

739

740

741

742

743

745 {

746

747

748

749

751

752 if (!isnull[indnkeyatts - 1])

753 {

757

759 values[indnkeyatts - 1],

760 typcache->typtype, att->atttypid);

761 }

762 }

763

764

765

766

767

768

769

770

772 {

773 for (i = 0; i < indnkeyatts; i++)

774 {

775 if (isnull[i])

776 return true;

777 }

778 }

779

780

781

782

783

785

786 for (i = 0; i < indnkeyatts; i++)

787 {

790 i + 1,

791 constr_strats[i],

793 index_collations[i],

794 constr_procs[i],

796 }

797

798

799

800

801

802

803

804

806

810

811

812

813

814

815retry:

816 conflict = false;

817 found_self = false;

818 index_scan = index_beginscan(heap, index, &DirtySnapshot, NULL, indnkeyatts, 0);

819 index_rescan(index_scan, scankeys, indnkeyatts, NULL, 0);

820

822 {

827 char *error_new;

828 char *error_existing;

829

830

831

832

835 {

836 if (found_self)

837 elog(ERROR, "found self tuple multiple times in index \"%s\"",

839 found_self = true;

840 continue;

841 }

842

843

844

845

846

848 existing_values, existing_isnull);

849

850

852 {

854 constr_procs,

855 existing_values,

856 existing_isnull,

858 continue;

859

860 }

861

862

863

864

865

866

867

868

869

870

871

873 DirtySnapshot.xmin : DirtySnapshot.xmax;

874

880 {

887 else

889 &existing_slot->tts_tid, reason_wait);

890 goto retry;

891 }

892

893

894

895

896

897 if (violationOK)

898 {

899 conflict = true;

900 if (conflictTid)

901 *conflictTid = existing_slot->tts_tid;

902 break;

903 }

904

907 existing_isnull);

908 if (newIndex)

910 (errcode(ERRCODE_EXCLUSION_VIOLATION),

911 errmsg("could not create exclusion constraint \"%s\"",

913 error_new && error_existing ?

914 errdetail("Key %s conflicts with key %s.",

915 error_new, error_existing) :

916 errdetail("Key conflicts exist."),

919 else

921 (errcode(ERRCODE_EXCLUSION_VIOLATION),

922 errmsg("conflicting key value violates exclusion constraint \"%s\"",

924 error_new && error_existing ?

925 errdetail("Key %s conflicts with existing key %s.",

926 error_new, error_existing) :

927 errdetail("Key conflicts with existing key."),

930 }

931

933

934

935

936

937

938

939

940

941

943

945

946 return !conflict;

947}

948

949

950

951

952

953

954

955void

960 EState *estate, bool newIndex)

961{

964 estate, newIndex,

966}

967

968

969

970

971

972static bool

974 const Datum *existing_values, const bool *existing_isnull,

975 const Datum *new_values)

976{

978 int i;

979

980 for (i = 0; i < indnkeyatts; i++)

981 {

982

983 if (existing_isnull[i])

984 return false;

985

987 index->rd_indcollation[i],

988 existing_values[i],

989 new_values[i])))

990 return false;

991 }

992

993 return true;

994}

995

996

997

998

999

1000

1001

1002

1003static bool

1006{

1010 bool hasexpression = false;

1011 List *idxExprs;

1012

1013

1014

1015

1019

1020

1021

1022

1023

1024

1025

1026

1027

1028

1029

1030

1034 {

1036

1037 if (keycol <= 0)

1038 {

1039

1040

1041

1042

1043 hasexpression = true;

1044 continue;

1045 }

1046

1048 updatedCols) ||

1050 extraUpdatedCols))

1051 {

1052

1054 return false;

1055 }

1056 }

1057

1058

1059

1060

1061

1062

1063

1064

1065

1066 if (!hasexpression)

1067 {

1069 return true;

1070 }

1071

1072

1073

1074

1075

1076 if (!extraUpdatedCols)

1077 allUpdatedCols = updatedCols;

1078 else

1079 allUpdatedCols = bms_union(updatedCols, extraUpdatedCols);

1080

1081

1082

1083

1084

1085

1086

1087

1088

1091 allUpdatedCols);

1093 if (extraUpdatedCols)

1095

1096 if (hasexpression)

1097 {

1099 return false;

1100 }

1101

1102

1103

1104

1105

1106

1107

1109 return true;

1110}

1111

1112

1113

1114

1115

1116

1117static bool

1119{

1120 if (node == NULL)

1121 return false;

1122

1124 {

1125 Var *var = (Var *) node;

1126

1128 allUpdatedCols))

1129 {

1130

1131 return true;

1132 }

1133

1134

1135 return false;

1136 }

1137

1139 allUpdatedCols);

1140}

1141

1142

1143

1144

1145

1146static void

1148{

1149 bool isempty;

1152

1153 switch (typtype)

1154 {

1155 case TYPTYPE_RANGE:

1158 break;

1159 case TYPTYPE_MULTIRANGE:

1162 break;

1163 default:

1164 elog(ERROR, "WITHOUT OVERLAPS column \"%s\" is not a range or multirange",

1166 }

1167

1168

1169 if (isempty)

1171 (errcode(ERRCODE_CHECK_VIOLATION),

1172 errmsg("empty WITHOUT OVERLAPS value found in column \"%s\" in relation \"%s\"",

1174}

void bms_free(Bitmapset *a)

bool bms_is_member(int x, const Bitmapset *a)

Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)

static Datum values[MAXATTR]

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

int errcode(int sqlerrcode)

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

#define ereport(elevel,...)

ExprState * ExecPrepareQual(List *qual, EState *estate)

static bool index_unchanged_by_update(ResultRelInfo *resultRelInfo, EState *estate, IndexInfo *indexInfo, Relation indexRelation)

static bool check_exclusion_or_unique_constraint(Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, const Datum *values, const bool *isnull, EState *estate, bool newIndex, CEOUC_WAIT_MODE waitMode, bool violationOK, ItemPointer conflictTid)

void ExecCloseIndices(ResultRelInfo *resultRelInfo)

static bool index_recheck_constraint(Relation index, const Oid *constr_procs, const Datum *existing_values, const bool *existing_isnull, const Datum *new_values)

void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)

@ CEOUC_LIVELOCK_PREVENTING_WAIT

bool ExecCheckIndexConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, ItemPointer conflictTid, ItemPointer tupleid, List *arbiterIndexes)

static bool index_expression_changed_walker(Node *node, Bitmapset *allUpdatedCols)

List * ExecInsertIndexTuples(ResultRelInfo *resultRelInfo, TupleTableSlot *slot, EState *estate, bool update, bool noDupErr, bool *specConflict, List *arbiterIndexes, bool onlySummarizing)

void check_exclusion_constraint(Relation heap, Relation index, IndexInfo *indexInfo, ItemPointer tupleid, const Datum *values, const bool *isnull, EState *estate, bool newIndex)

static void ExecWithoutOverlapsNotEmpty(Relation rel, NameData attname, Datum attval, char typtype, Oid atttypid)

void ExecDropSingleTupleTableSlot(TupleTableSlot *slot)

Bitmapset * ExecGetExtraUpdatedCols(ResultRelInfo *relinfo, EState *estate)

Bitmapset * ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate)

#define GetPerTupleExprContext(estate)

static bool ExecQual(ExprState *state, ExprContext *econtext)

Datum OidFunctionCall2Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2)

char * BuildIndexValueDescription(Relation indexRelation, const Datum *values, const bool *isnull)

Assert(PointerIsAligned(start, uint64))

IndexInfo * BuildIndexInfo(Relation index)

void BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)

void FormIndexDatum(IndexInfo *indexInfo, TupleTableSlot *slot, EState *estate, Datum *values, bool *isnull)

bool index_getnext_slot(IndexScanDesc scan, ScanDirection direction, TupleTableSlot *slot)

bool index_insert(Relation indexRelation, Datum *values, bool *isnull, ItemPointer heap_t_ctid, Relation heapRelation, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)

IndexScanDesc index_beginscan(Relation heapRelation, Relation indexRelation, Snapshot snapshot, IndexScanInstrumentation *instrument, int nkeys, int norderbys)

void index_insert_cleanup(Relation indexRelation, IndexInfo *indexInfo)

void index_close(Relation relation, LOCKMODE lockmode)

void index_endscan(IndexScanDesc scan)

Relation index_open(Oid relationId, LOCKMODE lockmode)

void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)

bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)

static void ItemPointerSetInvalid(ItemPointerData *pointer)

static bool ItemPointerIsValid(const ItemPointerData *pointer)

List * lappend_oid(List *list, Oid datum)

void list_free(List *list)

bool list_member_oid(const List *list, Oid datum)

void XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, XLTW_Oper oper)

void SpeculativeInsertionWait(TransactionId xid, uint32 token)

@ XLTW_RecheckExclusionConstr

#define MultirangeIsEmpty(mr)

static MultirangeType * DatumGetMultirangeTypeP(Datum X)

#define expression_tree_walker(n, w, c)

#define IsA(nodeptr, _type_)

FormData_pg_attribute * Form_pg_attribute

static int list_length(const List *l)

static bool DatumGetBool(Datum X)

static RangeType * DatumGetRangeTypeP(Datum X)

#define RelationGetForm(relation)

#define RelationGetRelid(relation)

#define RelationGetDescr(relation)

#define RelationGetRelationName(relation)

#define IndexRelationGetNumberOfKeyAttributes(relation)

List * RelationGetIndexList(Relation relation)

int errtableconstraint(Relation rel, const char *conname)

List * RelationGetIndexExpressions(Relation relation)

void ScanKeyEntryInitialize(ScanKey entry, int flags, AttrNumber attributeNumber, StrategyNumber strategy, Oid subtype, Oid collation, RegProcedure procedure, Datum argument)

#define InitDirtySnapshot(snapshotdata)

TupleTableSlot * ecxt_scantuple

uint16 * ii_ExclusionStrats

ExprState * ii_PredicateState

AttrNumber ii_IndexAttrNumbers[INDEX_MAX_KEYS]

RelationPtr ri_IndexRelationDescs

IndexInfo ** ri_IndexRelationInfo

#define FirstLowInvalidHeapAttributeNumber

TupleTableSlot * table_slot_create(Relation relation, List **reglist)

bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)

#define TransactionIdIsValid(xid)

static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)

TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)

TransactionId GetCurrentTransactionId(void)