133 EState *estate,
bool newIndex,
139 const Datum *existing_values,
const bool *existing_isnull,
140 const Datum *new_values);
147 char typtype,
Oid atttypid);
202 foreach(l, indexoidlist)
221 relationDescs[
i] = indexDesc;
222 indexInfoArray[
i] = ii;
247 for (
i = 0;
i < numIndices;
i++)
249 if (indexDescs[
i] == NULL)
309 List *arbiterIndexes,
310 bool onlySummarizing)
348 for (
i = 0;
i < numIndices;
i++)
350 Relation indexRelation = relationDescs[
i];
355 bool satisfiesConstraint;
357 if (indexRelation == NULL)
360 indexInfo = indexInfoArray[
i];
383 if (predicate == NULL)
405 applyNoDupErr = noDupErr &&
406 (arbiterIndexes ==
NIL ||
408 indexRelation->
rd_index->indexrelid));
423 if (!indexRelation->
rd_index->indisunique)
425 else if (applyNoDupErr)
427 else if (indexRelation->
rd_index->indimmediate)
442 satisfiesConstraint =
476 else if (!indexRelation->
rd_index->indimmediate)
487 satisfiesConstraint =
489 indexRelation, indexInfo,
492 waitMode, violationOK, NULL);
497 !satisfiesConstraint)
506 if (indexRelation->
rd_index->indimmediate && specConflict)
507 *specConflict =
true;
549 bool checkedIndex =
false;
575 for (
i = 0;
i < numIndices;
i++)
577 Relation indexRelation = relationDescs[
i];
579 bool satisfiesConstraint;
581 if (indexRelation == NULL)
584 indexInfo = indexInfoArray[
i];
594 if (arbiterIndexes !=
NIL &&
596 indexRelation->
rd_index->indexrelid))
599 if (!indexRelation->
rd_index->indimmediate)
601 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
602 errmsg(
"ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters"),
618 if (predicate == NULL)
639 satisfiesConstraint =
642 values, isnull, estate,
false,
645 if (!satisfiesConstraint)
649 if (arbiterIndexes !=
NIL && !checkedIndex)
650 elog(
ERROR,
"unexpected failure to find arbiter index");
702 EState *estate,
bool newIndex,
709 Oid *index_collations =
index->rd_indcollation;
746 if (!isnull[indnkeyatts - 1])
754 typcache->
typtype, att->atttypid);
767 for (
i = 0;
i < indnkeyatts;
i++)
780 for (
i = 0;
i < indnkeyatts;
i++)
813 index_rescan(index_scan, scankeys, indnkeyatts, NULL, 0);
822 char *error_existing;
831 elog(
ERROR,
"found self tuple multiple times in index \"%s\"",
842 existing_values, existing_isnull);
867 DirtySnapshot.
xmin : DirtySnapshot.
xmax;
883 &existing_slot->
tts_tid, reason_wait);
895 *conflictTid = existing_slot->
tts_tid;
904 (
errcode(ERRCODE_EXCLUSION_VIOLATION),
905 errmsg(
"could not create exclusion constraint \"%s\"",
907 error_new && error_existing ?
908 errdetail(
"Key %s conflicts with key %s.",
909 error_new, error_existing) :
915 (
errcode(ERRCODE_EXCLUSION_VIOLATION),
916 errmsg(
"conflicting key value violates exclusion constraint \"%s\"",
918 error_new && error_existing ?
919 errdetail(
"Key %s conflicts with existing key %s.",
920 error_new, error_existing) :
921 errdetail(
"Key conflicts with existing key."),
954 EState *estate,
bool newIndex)
968 const Datum *existing_values,
const bool *existing_isnull,
969 const Datum *new_values)
974 for (
i = 0;
i < indnkeyatts;
i++)
977 if (existing_isnull[
i])
981 index->rd_indcollation[
i],
1004 bool hasexpression =
false;
1037 hasexpression =
true;
1070 if (!extraUpdatedCols)
1071 allUpdatedCols = updatedCols;
1073 allUpdatedCols =
bms_union(updatedCols, extraUpdatedCols);
1087 if (extraUpdatedCols)
1153 case TYPTYPE_MULTIRANGE:
1158 elog(
ERROR,
"WITHOUT OVERLAPS column \"%s\" is not a range or multirange",
1165 (
errcode(ERRCODE_CHECK_VIOLATION),
1166 errmsg(
"empty WITHOUT OVERLAPS value found in column \"%s\" in relation \"%s\"",
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]
#define Assert(condition)
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)
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)
void index_insert_cleanup(Relation indexRelation, IndexInfo *indexInfo)
void index_close(Relation relation, LOCKMODE lockmode)
IndexScanDesc index_beginscan(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, int norderbys)
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)