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 ((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 ((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 {
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)