LCOV - differential code coverage report
Current view: top level - src/backend/executor - execIndexing.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 93.0 % 256 238 4 13 1 4 142 2 90 13 144
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 9 9 7 2 7
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 100.0 % 2 2 2
Legend: Lines: hit not hit (240..) days: 92.9 % 254 236 4 13 1 4 142 90 13 139
Function coverage date bins:
(240..) days: 56.2 % 16 9 7 2 7

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * execIndexing.c
                                  4                 :  *    routines for inserting index tuples and enforcing unique and
                                  5                 :  *    exclusion constraints.
                                  6                 :  *
                                  7                 :  * ExecInsertIndexTuples() is the main entry point.  It's called after
                                  8                 :  * inserting a tuple to the heap, and it inserts corresponding index tuples
                                  9                 :  * into all indexes.  At the same time, it enforces any unique and
                                 10                 :  * exclusion constraints:
                                 11                 :  *
                                 12                 :  * Unique Indexes
                                 13                 :  * --------------
                                 14                 :  *
                                 15                 :  * Enforcing a unique constraint is straightforward.  When the index AM
                                 16                 :  * inserts the tuple to the index, it also checks that there are no
                                 17                 :  * conflicting tuples in the index already.  It does so atomically, so that
                                 18                 :  * even if two backends try to insert the same key concurrently, only one
                                 19                 :  * of them will succeed.  All the logic to ensure atomicity, and to wait
                                 20                 :  * for in-progress transactions to finish, is handled by the index AM.
                                 21                 :  *
                                 22                 :  * If a unique constraint is deferred, we request the index AM to not
                                 23                 :  * throw an error if a conflict is found.  Instead, we make note that there
                                 24                 :  * was a conflict and return the list of indexes with conflicts to the
                                 25                 :  * caller.  The caller must re-check them later, by calling index_insert()
                                 26                 :  * with the UNIQUE_CHECK_EXISTING option.
                                 27                 :  *
                                 28                 :  * Exclusion Constraints
                                 29                 :  * ---------------------
                                 30                 :  *
                                 31                 :  * Exclusion constraints are different from unique indexes in that when the
                                 32                 :  * tuple is inserted to the index, the index AM does not check for
                                 33                 :  * duplicate keys at the same time.  After the insertion, we perform a
                                 34                 :  * separate scan on the index to check for conflicting tuples, and if one
                                 35                 :  * is found, we throw an error and the transaction is aborted.  If the
                                 36                 :  * conflicting tuple's inserter or deleter is in-progress, we wait for it
                                 37                 :  * to finish first.
                                 38                 :  *
                                 39                 :  * There is a chance of deadlock, if two backends insert a tuple at the
                                 40                 :  * same time, and then perform the scan to check for conflicts.  They will
                                 41                 :  * find each other's tuple, and both try to wait for each other.  The
                                 42                 :  * deadlock detector will detect that, and abort one of the transactions.
                                 43                 :  * That's fairly harmless, as one of them was bound to abort with a
                                 44                 :  * "duplicate key error" anyway, although you get a different error
                                 45                 :  * message.
                                 46                 :  *
                                 47                 :  * If an exclusion constraint is deferred, we still perform the conflict
                                 48                 :  * checking scan immediately after inserting the index tuple.  But instead
                                 49                 :  * of throwing an error if a conflict is found, we return that information
                                 50                 :  * to the caller.  The caller must re-check them later by calling
                                 51                 :  * check_exclusion_constraint().
                                 52                 :  *
                                 53                 :  * Speculative insertion
                                 54                 :  * ---------------------
                                 55                 :  *
                                 56                 :  * Speculative insertion is a two-phase mechanism used to implement
                                 57                 :  * INSERT ... ON CONFLICT DO UPDATE/NOTHING.  The tuple is first inserted
                                 58                 :  * to the heap and update the indexes as usual, but if a constraint is
                                 59                 :  * violated, we can still back out the insertion without aborting the whole
                                 60                 :  * transaction.  In an INSERT ... ON CONFLICT statement, if a conflict is
                                 61                 :  * detected, the inserted tuple is backed out and the ON CONFLICT action is
                                 62                 :  * executed instead.
                                 63                 :  *
                                 64                 :  * Insertion to a unique index works as usual: the index AM checks for
                                 65                 :  * duplicate keys atomically with the insertion.  But instead of throwing
                                 66                 :  * an error on a conflict, the speculatively inserted heap tuple is backed
                                 67                 :  * out.
                                 68                 :  *
                                 69                 :  * Exclusion constraints are slightly more complicated.  As mentioned
                                 70                 :  * earlier, there is a risk of deadlock when two backends insert the same
                                 71                 :  * key concurrently.  That was not a problem for regular insertions, when
                                 72                 :  * one of the transactions has to be aborted anyway, but with a speculative
                                 73                 :  * insertion we cannot let a deadlock happen, because we only want to back
                                 74                 :  * out the speculatively inserted tuple on conflict, not abort the whole
                                 75                 :  * transaction.
                                 76                 :  *
                                 77                 :  * When a backend detects that the speculative insertion conflicts with
                                 78                 :  * another in-progress tuple, it has two options:
                                 79                 :  *
                                 80                 :  * 1. back out the speculatively inserted tuple, then wait for the other
                                 81                 :  *    transaction, and retry. Or,
                                 82                 :  * 2. wait for the other transaction, with the speculatively inserted tuple
                                 83                 :  *    still in place.
                                 84                 :  *
                                 85                 :  * If two backends insert at the same time, and both try to wait for each
                                 86                 :  * other, they will deadlock.  So option 2 is not acceptable.  Option 1
                                 87                 :  * avoids the deadlock, but it is prone to a livelock instead.  Both
                                 88                 :  * transactions will wake up immediately as the other transaction backs
                                 89                 :  * out.  Then they both retry, and conflict with each other again, lather,
                                 90                 :  * rinse, repeat.
                                 91                 :  *
                                 92                 :  * To avoid the livelock, one of the backends must back out first, and then
                                 93                 :  * wait, while the other one waits without backing out.  It doesn't matter
                                 94                 :  * which one backs out, so we employ an arbitrary rule that the transaction
                                 95                 :  * with the higher XID backs out.
                                 96                 :  *
                                 97                 :  *
                                 98                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                 99                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                100                 :  *
                                101                 :  *
                                102                 :  * IDENTIFICATION
                                103                 :  *    src/backend/executor/execIndexing.c
                                104                 :  *
                                105                 :  *-------------------------------------------------------------------------
                                106                 :  */
                                107                 : #include "postgres.h"
                                108                 : 
                                109                 : #include "access/genam.h"
                                110                 : #include "access/relscan.h"
                                111                 : #include "access/tableam.h"
                                112                 : #include "access/xact.h"
                                113                 : #include "catalog/index.h"
                                114                 : #include "executor/executor.h"
                                115                 : #include "nodes/nodeFuncs.h"
                                116                 : #include "storage/lmgr.h"
                                117                 : #include "utils/snapmgr.h"
                                118                 : 
                                119                 : /* waitMode argument to check_exclusion_or_unique_constraint() */
                                120                 : typedef enum
                                121                 : {
                                122                 :     CEOUC_WAIT,
                                123                 :     CEOUC_NOWAIT,
                                124                 :     CEOUC_LIVELOCK_PREVENTING_WAIT
                                125                 : } CEOUC_WAIT_MODE;
                                126                 : 
                                127                 : static bool check_exclusion_or_unique_constraint(Relation heap, Relation index,
                                128                 :                                                  IndexInfo *indexInfo,
                                129                 :                                                  ItemPointer tupleid,
                                130                 :                                                  Datum *values, bool *isnull,
                                131                 :                                                  EState *estate, bool newIndex,
                                132                 :                                                  CEOUC_WAIT_MODE waitMode,
                                133                 :                                                  bool violationOK,
                                134                 :                                                  ItemPointer conflictTid);
                                135                 : 
                                136                 : static bool index_recheck_constraint(Relation index, Oid *constr_procs,
                                137                 :                                      Datum *existing_values, bool *existing_isnull,
                                138                 :                                      Datum *new_values);
                                139                 : static bool index_unchanged_by_update(ResultRelInfo *resultRelInfo,
                                140                 :                                       EState *estate, IndexInfo *indexInfo,
                                141                 :                                       Relation indexRelation);
                                142                 : static bool index_expression_changed_walker(Node *node,
                                143                 :                                             Bitmapset *allUpdatedCols);
                                144                 : 
                                145                 : /* ----------------------------------------------------------------
                                146                 :  *      ExecOpenIndices
                                147                 :  *
                                148                 :  *      Find the indices associated with a result relation, open them,
                                149                 :  *      and save information about them in the result ResultRelInfo.
                                150                 :  *
                                151                 :  *      At entry, caller has already opened and locked
                                152                 :  *      resultRelInfo->ri_RelationDesc.
                                153                 :  * ----------------------------------------------------------------
                                154                 :  */
                                155                 : void
 2893 andres                    156 CBC     2371282 : ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative)
                                157                 : {
 2907 heikki.linnakangas        158         2371282 :     Relation    resultRelation = resultRelInfo->ri_RelationDesc;
                                159                 :     List       *indexoidlist;
                                160                 :     ListCell   *l;
                                161                 :     int         len,
                                162                 :                 i;
                                163                 :     RelationPtr relationDescs;
                                164                 :     IndexInfo **indexInfoArray;
                                165                 : 
                                166         2371282 :     resultRelInfo->ri_NumIndices = 0;
                                167                 : 
                                168                 :     /* fast path if no indexes */
                                169         2371282 :     if (!RelationGetForm(resultRelation)->relhasindex)
                                170          242770 :         return;
                                171                 : 
                                172                 :     /*
                                173                 :      * Get cached list of index OIDs
                                174                 :      */
                                175         2128512 :     indexoidlist = RelationGetIndexList(resultRelation);
                                176         2128512 :     len = list_length(indexoidlist);
                                177         2128512 :     if (len == 0)
                                178           20325 :         return;
                                179                 : 
                                180                 :     /*
                                181                 :      * allocate space for result arrays
                                182                 :      */
                                183         2108187 :     relationDescs = (RelationPtr) palloc(len * sizeof(Relation));
                                184         2108187 :     indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));
                                185                 : 
                                186         2108187 :     resultRelInfo->ri_NumIndices = len;
                                187         2108187 :     resultRelInfo->ri_IndexRelationDescs = relationDescs;
                                188         2108187 :     resultRelInfo->ri_IndexRelationInfo = indexInfoArray;
                                189                 : 
                                190                 :     /*
                                191                 :      * For each index, open the index relation and save pg_index info. We
                                192                 :      * acquire RowExclusiveLock, signifying we will update the index.
                                193                 :      *
                                194                 :      * Note: we do this even if the index is not indisready; it's not worth
                                195                 :      * the trouble to optimize for the case where it isn't.
                                196                 :      */
                                197         2108187 :     i = 0;
                                198         6210559 :     foreach(l, indexoidlist)
                                199                 :     {
                                200         4102372 :         Oid         indexOid = lfirst_oid(l);
                                201                 :         Relation    indexDesc;
                                202                 :         IndexInfo  *ii;
                                203                 : 
                                204         4102372 :         indexDesc = index_open(indexOid, RowExclusiveLock);
                                205                 : 
                                206                 :         /* extract index key information from the index's pg_index info */
                                207         4102372 :         ii = BuildIndexInfo(indexDesc);
                                208                 : 
                                209                 :         /*
                                210                 :          * If the indexes are to be used for speculative insertion, add extra
                                211                 :          * information required by unique index entries.
                                212                 :          */
 2893 andres                    213         4102372 :         if (speculative && ii->ii_Unique)
                                214             603 :             BuildSpeculativeIndexInfo(indexDesc, ii);
                                215                 : 
 2907 heikki.linnakangas        216         4102372 :         relationDescs[i] = indexDesc;
                                217         4102372 :         indexInfoArray[i] = ii;
                                218         4102372 :         i++;
                                219                 :     }
                                220                 : 
                                221         2108187 :     list_free(indexoidlist);
                                222                 : }
                                223                 : 
                                224                 : /* ----------------------------------------------------------------
                                225                 :  *      ExecCloseIndices
                                226                 :  *
                                227                 :  *      Close the index relations stored in resultRelInfo
                                228                 :  * ----------------------------------------------------------------
                                229                 :  */
                                230                 : void
                                231         2421886 : ExecCloseIndices(ResultRelInfo *resultRelInfo)
                                232                 : {
                                233                 :     int         i;
                                234                 :     int         numIndices;
                                235                 :     RelationPtr indexDescs;
                                236                 : 
                                237         2421886 :     numIndices = resultRelInfo->ri_NumIndices;
                                238         2421886 :     indexDescs = resultRelInfo->ri_IndexRelationDescs;
                                239                 : 
                                240         6523506 :     for (i = 0; i < numIndices; i++)
                                241                 :     {
                                242         4101620 :         if (indexDescs[i] == NULL)
 2907 heikki.linnakangas        243 UBC           0 :             continue;           /* shouldn't happen? */
                                244                 : 
                                245                 :         /* Drop lock acquired by ExecOpenIndices */
 2907 heikki.linnakangas        246 CBC     4101620 :         index_close(indexDescs[i], RowExclusiveLock);
                                247                 :     }
                                248                 : 
                                249                 :     /*
                                250                 :      * XXX should free indexInfo array here too?  Currently we assume that
                                251                 :      * such stuff will be cleaned up automatically in FreeExecutorState.
                                252                 :      */
                                253         2421886 : }
                                254                 : 
                                255                 : /* ----------------------------------------------------------------
                                256                 :  *      ExecInsertIndexTuples
                                257                 :  *
                                258                 :  *      This routine takes care of inserting index tuples
                                259                 :  *      into all the relations indexing the result relation
                                260                 :  *      when a heap tuple is inserted into the result relation.
                                261                 :  *
                                262                 :  *      When 'update' is true and 'onlySummarizing' is false,
                                263                 :  *      executor is performing an UPDATE that could not use an
                                264                 :  *      optimization like heapam's HOT (in more general terms a
                                265                 :  *      call to table_tuple_update() took place and set
                                266                 :  *      'update_indexes' to TUUI_All).  Receiving this hint makes
                                267                 :  *      us consider if we should pass down the 'indexUnchanged'
                                268                 :  *      hint in turn.  That's something that we figure out for
                                269                 :  *      each index_insert() call iff 'update' is true.
                                270                 :  *      (When 'update' is false we already know not to pass the
                                271                 :  *      hint to any index.)
                                272                 :  *
                                273                 :  *      If onlySummarizing is set, an equivalent optimization to
                                274                 :  *      HOT has been applied and any updated columns are indexed
                                275                 :  *      only by summarizing indexes (or in more general terms a
                                276                 :  *      call to table_tuple_update() took place and set
                                277                 :  *      'update_indexes' to TUUI_Summarizing). We can (and must)
                                278                 :  *      therefore only update the indexes that have
                                279                 :  *      'amsummarizing' = true.
                                280                 :  *
                                281                 :  *      Unique and exclusion constraints are enforced at the same
                                282                 :  *      time.  This returns a list of index OIDs for any unique or
                                283                 :  *      exclusion constraints that are deferred and that had
                                284                 :  *      potential (unconfirmed) conflicts.  (if noDupErr == true,
                                285                 :  *      the same is done for non-deferred constraints, but report
                                286                 :  *      if conflict was speculative or deferred conflict to caller)
                                287                 :  *
                                288                 :  *      If 'arbiterIndexes' is nonempty, noDupErr applies only to
                                289                 :  *      those indexes.  NIL means noDupErr applies to all indexes.
                                290                 :  * ----------------------------------------------------------------
                                291                 :  */
                                292                 : List *
  907 heikki.linnakangas        293 GIC     2009170 : ExecInsertIndexTuples(ResultRelInfo *resultRelInfo,
                                294                 :                       TupleTableSlot *slot,
                                295                 :                       EState *estate,
                                296                 :                       bool update,
                                297                 :                       bool noDupErr,
                                298                 :                       bool *specConflict,
                                299                 :                       List *arbiterIndexes,
                                300                 :                       bool onlySummarizing)
                                301                 : {
 1478 andres                    302         2009170 :     ItemPointer tupleid = &slot->tts_tid;
 2907 heikki.linnakangas        303 CBC     2009170 :     List       *result = NIL;
                                304                 :     int         i;
                                305                 :     int         numIndices;
                                306                 :     RelationPtr relationDescs;
                                307                 :     Relation    heapRelation;
                                308                 :     IndexInfo **indexInfoArray;
                                309                 :     ExprContext *econtext;
                                310                 :     Datum       values[INDEX_MAX_KEYS];
                                311                 :     bool        isnull[INDEX_MAX_KEYS];
 2907 heikki.linnakangas        312 ECB             : 
 1478 andres                    313 CBC     2009170 :     Assert(ItemPointerIsValid(tupleid));
                                314                 : 
                                315                 :     /*
                                316                 :      * Get information from the result relation info structure.
                                317                 :      */
 2907 heikki.linnakangas        318 GIC     2009170 :     numIndices = resultRelInfo->ri_NumIndices;
                                319         2009170 :     relationDescs = resultRelInfo->ri_IndexRelationDescs;
                                320         2009170 :     indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
                                321         2009170 :     heapRelation = resultRelInfo->ri_RelationDesc;
                                322                 : 
 1404 drowley                   323 ECB             :     /* Sanity check: slot must belong to the same rel as the resultRelInfo. */
 1404 drowley                   324 GIC     2009170 :     Assert(slot->tts_tableOid == RelationGetRelid(heapRelation));
                                325                 : 
                                326                 :     /*
                                327                 :      * We will use the EState's per-tuple context for evaluating predicates
 2907 heikki.linnakangas        328 ECB             :      * and index expressions (creating it if it's not already there).
                                329                 :      */
 2907 heikki.linnakangas        330 CBC     2009170 :     econtext = GetPerTupleExprContext(estate);
 2907 heikki.linnakangas        331 ECB             : 
                                332                 :     /* Arrange for econtext's scan tuple to be the tuple under test */
 2907 heikki.linnakangas        333 GIC     2009170 :     econtext->ecxt_scantuple = slot;
 2907 heikki.linnakangas        334 ECB             : 
                                335                 :     /*
                                336                 :      * for each index, form and insert the index tuple
                                337                 :      */
 2907 heikki.linnakangas        338 GIC     4251376 :     for (i = 0; i < numIndices; i++)
                                339                 :     {
 2907 heikki.linnakangas        340 CBC     2242491 :         Relation    indexRelation = relationDescs[i];
                                341                 :         IndexInfo  *indexInfo;
                                342                 :         bool        applyNoDupErr;
 2907 heikki.linnakangas        343 ECB             :         IndexUniqueCheck checkUnique;
                                344                 :         bool        indexUnchanged;
                                345                 :         bool        satisfiesConstraint;
                                346                 : 
 2907 heikki.linnakangas        347 GIC     2242491 :         if (indexRelation == NULL)
 2907 heikki.linnakangas        348 LBC           0 :             continue;
                                349                 : 
 2907 heikki.linnakangas        350 CBC     2242491 :         indexInfo = indexInfoArray[i];
                                351                 : 
                                352                 :         /* If the index is marked as read-only, ignore it */
 2907 heikki.linnakangas        353 GIC     2242491 :         if (!indexInfo->ii_ReadyForInserts)
                                354             106 :             continue;
                                355                 : 
                                356                 :         /*
                                357                 :          * Skip processing of non-summarizing indexes if we only
                                358                 :          * update summarizing indexes
                                359                 :          */
   20 tomas.vondra              360 GNC     2242385 :         if (onlySummarizing && !indexInfo->ii_Summarizing)
                                361               3 :             continue;
                                362                 : 
                                363                 :         /* Check for partial index */
 2907 heikki.linnakangas        364 CBC     2242382 :         if (indexInfo->ii_Predicate != NIL)
 2907 heikki.linnakangas        365 EUB             :         {
                                366                 :             ExprState  *predicate;
 2907 heikki.linnakangas        367 ECB             : 
                                368                 :             /*
                                369                 :              * If predicate state not set up yet, create it (in the estate's
                                370                 :              * per-query context)
                                371                 :              */
 2907 heikki.linnakangas        372 GIC      200545 :             predicate = indexInfo->ii_PredicateState;
 2217 andres                    373          200545 :             if (predicate == NULL)
                                374                 :             {
                                375             130 :                 predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
 2907 heikki.linnakangas        376             130 :                 indexInfo->ii_PredicateState = predicate;
 2907 heikki.linnakangas        377 ECB             :             }
                                378                 : 
                                379                 :             /* Skip this index-update if the predicate isn't satisfied */
 2217 andres                    380 GIC      200545 :             if (!ExecQual(predicate, econtext))
 2907 heikki.linnakangas        381 CBC      200274 :                 continue;
                                382                 :         }
                                383                 : 
                                384                 :         /*
                                385                 :          * FormIndexDatum fills in its values and isnull parameters with the
                                386                 :          * appropriate values for the column(s) of the index.
                                387                 :          */
 2907 heikki.linnakangas        388 GIC     2042108 :         FormIndexDatum(indexInfo,
 2907 heikki.linnakangas        389 ECB             :                        slot,
                                390                 :                        estate,
                                391                 :                        values,
                                392                 :                        isnull);
                                393                 : 
                                394                 :         /* Check whether to apply noDupErr to this index */
 2470 tgl                       395 GIC     2044103 :         applyNoDupErr = noDupErr &&
                                396            1995 :             (arbiterIndexes == NIL ||
 2470 tgl                       397 CBC        1995 :              list_member_oid(arbiterIndexes,
                                398            1995 :                              indexRelation->rd_index->indexrelid));
                                399                 : 
                                400                 :         /*
                                401                 :          * The index AM does the actual insertion, plus uniqueness checking.
                                402                 :          *
                                403                 :          * For an immediate-mode unique index, we just tell the index AM to
                                404                 :          * throw error if not unique.
 2907 heikki.linnakangas        405 ECB             :          *
                                406                 :          * For a deferrable unique index, we tell the index AM to just detect
                                407                 :          * possible non-uniqueness, and we add the index OID to the result
                                408                 :          * list if further checking is needed.
                                409                 :          *
                                410                 :          * For a speculative insertion (used by INSERT ... ON CONFLICT), do
                                411                 :          * the same as for a deferrable unique index.
                                412                 :          */
 2907 heikki.linnakangas        413 CBC     2042108 :         if (!indexRelation->rd_index->indisunique)
                                414          930743 :             checkUnique = UNIQUE_CHECK_NO;
 2470 tgl                       415         1111365 :         else if (applyNoDupErr)
 2893 andres                    416 GIC        2016 :             checkUnique = UNIQUE_CHECK_PARTIAL;
 2907 heikki.linnakangas        417         1109349 :         else if (indexRelation->rd_index->indimmediate)
                                418         1109274 :             checkUnique = UNIQUE_CHECK_YES;
                                419                 :         else
                                420              75 :             checkUnique = UNIQUE_CHECK_PARTIAL;
                                421                 : 
                                422                 :         /*
                                423                 :          * There's definitely going to be an index_insert() call for this
                                424                 :          * index.  If we're being called as part of an UPDATE statement,
                                425                 :          * consider if the 'indexUnchanged' = true hint should be passed.
                                426                 :          */
  816 pg                        427         2042108 :         indexUnchanged = update && index_unchanged_by_update(resultRelInfo,
                                428                 :                                                              estate,
                                429                 :                                                              indexInfo,
  816 pg                        430 ECB             :                                                              indexRelation);
                                431                 : 
 2907 heikki.linnakangas        432                 :         satisfiesConstraint =
 2907 heikki.linnakangas        433 CBC     2042108 :             index_insert(indexRelation, /* index relation */
 2907 heikki.linnakangas        434 ECB             :                          values,    /* array of index Datums */
                                435                 :                          isnull,    /* null flags */
                                436                 :                          tupleid,   /* tid of heap tuple */
                                437                 :                          heapRelation,  /* heap relation */
                                438                 :                          checkUnique,   /* type of uniqueness check to do */
                                439                 :                          indexUnchanged,    /* UPDATE without logical change? */
                                440                 :                          indexInfo);    /* index AM may need this */
                                441                 : 
                                442                 :         /*
                                443                 :          * If the index has an associated exclusion constraint, check that.
                                444                 :          * This is simpler than the process for uniqueness checks since we
                                445                 :          * always insert first and then check.  If the constraint is deferred,
                                446                 :          * we check now anyway, but don't throw error on violation or wait for
                                447                 :          * a conclusive outcome from a concurrent insertion; instead we'll
                                448                 :          * queue a recheck event.  Similarly, noDupErr callers (speculative
                                449                 :          * inserters) will recheck later, and wait for a conclusive outcome
 2893 andres                    450                 :          * then.
                                451                 :          *
                                452                 :          * An index for an exclusion constraint can't also be UNIQUE (not an
                                453                 :          * essential property, we just don't allow it in the grammar), so no
                                454                 :          * need to preserve the prior state of satisfiesConstraint.
                                455                 :          */
 2907 heikki.linnakangas        456 GIC     2041848 :         if (indexInfo->ii_ExclusionOps != NULL)
                                457                 :         {
                                458                 :             bool        violationOK;
                                459                 :             CEOUC_WAIT_MODE waitMode;
                                460                 : 
 2470 tgl                       461             153 :             if (applyNoDupErr)
                                462                 :             {
 2893 andres                    463 UIC           0 :                 violationOK = true;
                                464               0 :                 waitMode = CEOUC_LIVELOCK_PREVENTING_WAIT;
                                465                 :             }
 2893 andres                    466 GIC         153 :             else if (!indexRelation->rd_index->indimmediate)
                                467                 :             {
                                468              21 :                 violationOK = true;
                                469              21 :                 waitMode = CEOUC_NOWAIT;
                                470                 :             }
                                471                 :             else
                                472                 :             {
 2893 andres                    473 CBC         132 :                 violationOK = false;
 2893 andres                    474 GIC         132 :                 waitMode = CEOUC_WAIT;
                                475                 :             }
                                476                 : 
                                477                 :             satisfiesConstraint =
 2893 andres                    478 CBC         153 :                 check_exclusion_or_unique_constraint(heapRelation,
                                479                 :                                                      indexRelation, indexInfo,
 2893 andres                    480 EUB             :                                                      tupleid, values, isnull,
                                481                 :                                                      estate, false,
                                482                 :                                                      waitMode, violationOK, NULL);
 2907 heikki.linnakangas        483 ECB             :         }
                                484                 : 
 2907 heikki.linnakangas        485 CBC     2041823 :         if ((checkUnique == UNIQUE_CHECK_PARTIAL ||
                                486         2039732 :              indexInfo->ii_ExclusionOps != NULL) &&
 2907 heikki.linnakangas        487 GIC        2219 :             !satisfiesConstraint)
                                488                 :         {
                                489                 :             /*
 2907 heikki.linnakangas        490 ECB             :              * The tuple potentially violates the uniqueness or exclusion
                                491                 :              * constraint, so make a note of the index so that we can re-check
                                492                 :              * it later.  Speculative inserters are told if there was a
                                493                 :              * speculative conflict, since that always requires a restart.
                                494                 :              */
 2907 heikki.linnakangas        495 CBC          66 :             result = lappend_oid(result, RelationGetRelid(indexRelation));
 2893 andres                    496 GIC          66 :             if (indexRelation->rd_index->indimmediate && specConflict)
                                497               5 :                 *specConflict = true;
                                498                 :         }
                                499                 :     }
                                500                 : 
 2907 heikki.linnakangas        501         2008885 :     return result;
 2907 heikki.linnakangas        502 ECB             : }
                                503                 : 
 2893 andres                    504                 : /* ----------------------------------------------------------------
                                505                 :  *      ExecCheckIndexConstraints
                                506                 :  *
                                507                 :  *      This routine checks if a tuple violates any unique or
                                508                 :  *      exclusion constraints.  Returns true if there is no conflict.
                                509                 :  *      Otherwise returns false, and the TID of the conflicting
                                510                 :  *      tuple is returned in *conflictTid.
                                511                 :  *
                                512                 :  *      If 'arbiterIndexes' is given, only those indexes are checked.
                                513                 :  *      NIL means all indexes.
                                514                 :  *
                                515                 :  *      Note that this doesn't lock the values in any way, so it's
                                516                 :  *      possible that a conflicting tuple is inserted immediately
                                517                 :  *      after this returns.  But this can be used for a pre-check
                                518                 :  *      before insertion.
                                519                 :  * ----------------------------------------------------------------
                                520                 :  */
                                521                 : bool
  907 heikki.linnakangas        522 GIC        4695 : ExecCheckIndexConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot,
                                523                 :                           EState *estate, ItemPointer conflictTid,
                                524                 :                           List *arbiterIndexes)
                                525                 : {
                                526                 :     int         i;
                                527                 :     int         numIndices;
                                528                 :     RelationPtr relationDescs;
                                529                 :     Relation    heapRelation;
                                530                 :     IndexInfo **indexInfoArray;
                                531                 :     ExprContext *econtext;
                                532                 :     Datum       values[INDEX_MAX_KEYS];
                                533                 :     bool        isnull[INDEX_MAX_KEYS];
                                534                 :     ItemPointerData invalidItemPtr;
 2893 andres                    535            4695 :     bool        checkedIndex = false;
                                536                 : 
                                537            4695 :     ItemPointerSetInvalid(conflictTid);
                                538            4695 :     ItemPointerSetInvalid(&invalidItemPtr);
 2893 andres                    539 ECB             : 
                                540                 :     /*
                                541                 :      * Get information from the result relation info structure.
                                542                 :      */
 2893 andres                    543 GIC        4695 :     numIndices = resultRelInfo->ri_NumIndices;
                                544            4695 :     relationDescs = resultRelInfo->ri_IndexRelationDescs;
                                545            4695 :     indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
                                546            4695 :     heapRelation = resultRelInfo->ri_RelationDesc;
                                547                 : 
                                548                 :     /*
                                549                 :      * We will use the EState's per-tuple context for evaluating predicates
                                550                 :      * and index expressions (creating it if it's not already there).
                                551                 :      */
 2893 andres                    552 CBC        4695 :     econtext = GetPerTupleExprContext(estate);
                                553                 : 
 2893 andres                    554 ECB             :     /* Arrange for econtext's scan tuple to be the tuple under test */
 2893 andres                    555 CBC        4695 :     econtext->ecxt_scantuple = slot;
                                556                 : 
                                557                 :     /*
                                558                 :      * For each index, form index tuple and check if it satisfies the
                                559                 :      * constraint.
 2893 andres                    560 ECB             :      */
 2893 andres                    561 CBC        6752 :     for (i = 0; i < numIndices; i++)
 2893 andres                    562 ECB             :     {
 2893 andres                    563 CBC        4739 :         Relation    indexRelation = relationDescs[i];
                                564                 :         IndexInfo  *indexInfo;
                                565                 :         bool        satisfiesConstraint;
                                566                 : 
 2893 andres                    567 GIC        4739 :         if (indexRelation == NULL)
 2893 andres                    568 UIC           0 :             continue;
 2893 andres                    569 ECB             : 
 2893 andres                    570 GIC        4739 :         indexInfo = indexInfoArray[i];
                                571                 : 
 2893 andres                    572 CBC        4739 :         if (!indexInfo->ii_Unique && !indexInfo->ii_ExclusionOps)
 2893 andres                    573 GIC           2 :             continue;
                                574                 : 
                                575                 :         /* If the index is marked as read-only, ignore it */
                                576            4737 :         if (!indexInfo->ii_ReadyForInserts)
 2893 andres                    577 UIC           0 :             continue;
 2893 andres                    578 ECB             : 
                                579                 :         /* When specific arbiter indexes requested, only examine them */
 2893 andres                    580 CBC        4737 :         if (arbiterIndexes != NIL &&
 2893 andres                    581 GIC        4647 :             !list_member_oid(arbiterIndexes,
                                582            4647 :                              indexRelation->rd_index->indexrelid))
                                583              39 :             continue;
 2893 andres                    584 ECB             : 
 2893 andres                    585 GBC        4698 :         if (!indexRelation->rd_index->indimmediate)
 2893 andres                    586 GIC           3 :             ereport(ERROR,
 2735 rhaas                     587 ECB             :                     (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                                588                 :                      errmsg("ON CONFLICT does not support deferrable unique constraints/exclusion constraints as arbiters"),
 2893 andres                    589                 :                      errtableconstraint(heapRelation,
 2118 tgl                       590                 :                                         RelationGetRelationName(indexRelation))));
                                591                 : 
 2893 andres                    592 GIC        4695 :         checkedIndex = true;
 2893 andres                    593 ECB             : 
 2893 andres                    594 EUB             :         /* Check for partial index */
 2893 andres                    595 GIC        4695 :         if (indexInfo->ii_Predicate != NIL)
                                596                 :         {
 2217 andres                    597 ECB             :             ExprState  *predicate;
 2893                           598                 : 
                                599                 :             /*
                                600                 :              * If predicate state not set up yet, create it (in the estate's
                                601                 :              * per-query context)
                                602                 :              */
 2893 andres                    603 CBC          15 :             predicate = indexInfo->ii_PredicateState;
 2217 andres                    604 GIC          15 :             if (predicate == NULL)
                                605                 :             {
                                606              15 :                 predicate = ExecPrepareQual(indexInfo->ii_Predicate, estate);
 2893                           607              15 :                 indexInfo->ii_PredicateState = predicate;
                                608                 :             }
 2893 andres                    609 ECB             : 
                                610                 :             /* Skip this index-update if the predicate isn't satisfied */
 2217 andres                    611 GIC          15 :             if (!ExecQual(predicate, econtext))
 2893 andres                    612 LBC           0 :                 continue;
                                613                 :         }
                                614                 : 
                                615                 :         /*
                                616                 :          * FormIndexDatum fills in its values and isnull parameters with the
                                617                 :          * appropriate values for the column(s) of the index.
                                618                 :          */
 2893 andres                    619 GIC        4695 :         FormIndexDatum(indexInfo,
 2893 andres                    620 ECB             :                        slot,
                                621                 :                        estate,
                                622                 :                        values,
                                623                 :                        isnull);
                                624                 : 
                                625                 :         satisfiesConstraint =
 2893 andres                    626 GIC        4695 :             check_exclusion_or_unique_constraint(heapRelation, indexRelation,
                                627                 :                                                  indexInfo, &invalidItemPtr,
 2118 tgl                       628 ECB             :                                                  values, isnull, estate, false,
 2893 andres                    629 EUB             :                                                  CEOUC_WAIT, true,
                                630                 :                                                  conflictTid);
 2893 andres                    631 GIC        4695 :         if (!satisfiesConstraint)
                                632            2679 :             return false;
                                633                 :     }
                                634                 : 
                                635            2013 :     if (arbiterIndexes != NIL && !checkedIndex)
 2893 andres                    636 LBC           0 :         elog(ERROR, "unexpected failure to find arbiter index");
                                637                 : 
 2893 andres                    638 GIC        2013 :     return true;
                                639                 : }
                                640                 : 
                                641                 : /*
                                642                 :  * Check for violation of an exclusion or unique constraint
 2907 heikki.linnakangas        643 ECB             :  *
                                644                 :  * heap: the table containing the new tuple
                                645                 :  * index: the index supporting the constraint
                                646                 :  * indexInfo: info about the index, including the exclusion properties
                                647                 :  * tupleid: heap TID of the new tuple we have just inserted (invalid if we
 2893 andres                    648                 :  *      haven't inserted a new tuple yet)
 2907 heikki.linnakangas        649                 :  * values, isnull: the *index* column values computed for the new tuple
                                650                 :  * estate: an EState we can do evaluation in
                                651                 :  * newIndex: if true, we are trying to build a new index (this affects
                                652                 :  *      only the wording of error messages)
 2893 andres                    653 EUB             :  * waitMode: whether to wait for concurrent inserters/deleters
                                654                 :  * violationOK: if true, don't throw error for violation
 2893 andres                    655 ECB             :  * conflictTid: if not-NULL, the TID of the conflicting tuple is returned here
                                656                 :  *
                                657                 :  * Returns true if OK, false if actual or potential violation
                                658                 :  *
                                659                 :  * 'waitMode' determines what happens if a conflict is detected with a tuple
                                660                 :  * that was inserted or deleted by a transaction that's still running.
                                661                 :  * CEOUC_WAIT means that we wait for the transaction to commit, before
                                662                 :  * throwing an error or returning.  CEOUC_NOWAIT means that we report the
                                663                 :  * violation immediately; so the violation is only potential, and the caller
                                664                 :  * must recheck sometime later.  This behavior is convenient for deferred
                                665                 :  * exclusion checks; we need not bother queuing a deferred event if there is
                                666                 :  * definitely no conflict at insertion time.
                                667                 :  *
                                668                 :  * CEOUC_LIVELOCK_PREVENTING_WAIT is like CEOUC_NOWAIT, but we will sometimes
                                669                 :  * wait anyway, to prevent livelocking if two transactions try inserting at
                                670                 :  * the same time.  This is used with speculative insertions, for INSERT ON
                                671                 :  * CONFLICT statements. (See notes in file header)
                                672                 :  *
                                673                 :  * If violationOK is true, we just report the potential or actual violation to
                                674                 :  * the caller by returning 'false'.  Otherwise we throw a descriptive error
                                675                 :  * message here.  When violationOK is false, a false result is impossible.
                                676                 :  *
                                677                 :  * Note: The indexam is normally responsible for checking unique constraints,
                                678                 :  * so this normally only needs to be used for exclusion constraints.  But this
                                679                 :  * function is also called when doing a "pre-check" for conflicts on a unique
                                680                 :  * constraint, when doing speculative insertion.  Caller may use the returned
                                681                 :  * conflict TID to take further steps.
                                682                 :  */
                                683                 : static bool
 2893 andres                    684 GIC        4883 : check_exclusion_or_unique_constraint(Relation heap, Relation index,
                                685                 :                                      IndexInfo *indexInfo,
                                686                 :                                      ItemPointer tupleid,
                                687                 :                                      Datum *values, bool *isnull,
                                688                 :                                      EState *estate, bool newIndex,
                                689                 :                                      CEOUC_WAIT_MODE waitMode,
                                690                 :                                      bool violationOK,
                                691                 :                                      ItemPointer conflictTid)
                                692                 : {
                                693                 :     Oid        *constr_procs;
                                694                 :     uint16     *constr_strats;
 2907 heikki.linnakangas        695            4883 :     Oid        *index_collations = index->rd_indcollation;
 1828 teodor                    696            4883 :     int         indnkeyatts = IndexRelationGetNumberOfKeyAttributes(index);
                                697                 :     IndexScanDesc index_scan;
                                698                 :     ScanKeyData scankeys[INDEX_MAX_KEYS];
                                699                 :     SnapshotData DirtySnapshot;
                                700                 :     int         i;
 2907 heikki.linnakangas        701 ECB             :     bool        conflict;
                                702                 :     bool        found_self;
                                703                 :     ExprContext *econtext;
                                704                 :     TupleTableSlot *existing_slot;
                                705                 :     TupleTableSlot *save_scantuple;
                                706                 : 
 2893 andres                    707 GIC        4883 :     if (indexInfo->ii_ExclusionOps)
                                708                 :     {
                                709             194 :         constr_procs = indexInfo->ii_ExclusionProcs;
                                710             194 :         constr_strats = indexInfo->ii_ExclusionStrats;
                                711                 :     }
 2893 andres                    712 ECB             :     else
                                713                 :     {
 2893 andres                    714 GIC        4689 :         constr_procs = indexInfo->ii_UniqueProcs;
                                715            4689 :         constr_strats = indexInfo->ii_UniqueStrats;
                                716                 :     }
                                717                 : 
                                718                 :     /*
                                719                 :      * If any of the input values are NULL, and the index uses the default
                                720                 :      * nulls-are-distinct mode, the constraint check is assumed to pass (i.e.,
                                721                 :      * we assume the operators are strict).  Otherwise, we interpret the
                                722                 :      * constraint as specifying IS NULL for each column whose input value is
                                723                 :      * NULL.
 2907 heikki.linnakangas        724 ECB             :      */
  248 tgl                       725 GIC        4883 :     if (!indexInfo->ii_NullsNotDistinct)
 2907 heikki.linnakangas        726 ECB             :     {
  248 tgl                       727 CBC        9848 :         for (i = 0; i < indnkeyatts; i++)
                                728                 :         {
  248 tgl                       729 GIC        4968 :             if (isnull[i])
  248 tgl                       730 UIC           0 :                 return true;
  248 tgl                       731 ECB             :         }
 2907 heikki.linnakangas        732                 :     }
                                733                 : 
                                734                 :     /*
                                735                 :      * Search the tuples that are in the index for any violations, including
                                736                 :      * tuples that aren't visible yet.
                                737                 :      */
 2907 heikki.linnakangas        738 GIC        4883 :     InitDirtySnapshot(DirtySnapshot);
                                739                 : 
 1828 teodor                    740            9854 :     for (i = 0; i < indnkeyatts; i++)
                                741                 :     {
 2907 heikki.linnakangas        742 CBC        4971 :         ScanKeyEntryInitialize(&scankeys[i],
  248 tgl                       743 GIC        4971 :                                isnull[i] ? SK_ISNULL | SK_SEARCHNULL : 0,
 2907 heikki.linnakangas        744 CBC        4971 :                                i + 1,
 2907 heikki.linnakangas        745 GIC        4971 :                                constr_strats[i],
 2907 heikki.linnakangas        746 ECB             :                                InvalidOid,
 2907 heikki.linnakangas        747 GBC        4971 :                                index_collations[i],
 2907 heikki.linnakangas        748 GIC        4971 :                                constr_procs[i],
                                749            4971 :                                values[i]);
                                750                 :     }
                                751                 : 
                                752                 :     /*
                                753                 :      * Need a TupleTableSlot to put existing tuples in.
                                754                 :      *
 2907 heikki.linnakangas        755 ECB             :      * To use FormIndexDatum, we have to make the econtext's scantuple point
                                756                 :      * to this slot.  Be sure to save and restore caller's value for
                                757                 :      * scantuple.
                                758                 :      */
 1490 andres                    759 CBC        4883 :     existing_slot = table_slot_create(heap, NULL);
 2907 heikki.linnakangas        760 ECB             : 
 2907 heikki.linnakangas        761 CBC        4883 :     econtext = GetPerTupleExprContext(estate);
                                762            4883 :     save_scantuple = econtext->ecxt_scantuple;
 2907 heikki.linnakangas        763 GIC        4883 :     econtext->ecxt_scantuple = existing_slot;
 2907 heikki.linnakangas        764 ECB             : 
                                765                 :     /*
                                766                 :      * May have to restart scan from this point if a potential conflict is
                                767                 :      * found.
                                768                 :      */
 2907 heikki.linnakangas        769 GIC        4918 : retry:
                                770            4918 :     conflict = false;
                                771            4918 :     found_self = false;
 1828 teodor                    772            4918 :     index_scan = index_beginscan(heap, index, &DirtySnapshot, indnkeyatts, 0);
                                773            4918 :     index_rescan(index_scan, scankeys, indnkeyatts, NULL, 0);
                                774                 : 
 1490 andres                    775            5084 :     while (index_getnext_slot(index_scan, ForwardScanDirection, existing_slot))
 2907 heikki.linnakangas        776 ECB             :     {
                                777                 :         TransactionId xwait;
 2495 rhaas                     778                 :         XLTW_Oper   reason_wait;
 2907 heikki.linnakangas        779                 :         Datum       existing_values[INDEX_MAX_KEYS];
                                780                 :         bool        existing_isnull[INDEX_MAX_KEYS];
                                781                 :         char       *error_new;
                                782                 :         char       *error_existing;
                                783                 : 
                                784                 :         /*
                                785                 :          * Ignore the entry for the tuple we're trying to check.
                                786                 :          */
 2893 andres                    787 CBC        3150 :         if (ItemPointerIsValid(tupleid) &&
 1490                           788             218 :             ItemPointerEquals(tupleid, &existing_slot->tts_tid))
 2907 heikki.linnakangas        789 ECB             :         {
 2907 heikki.linnakangas        790 CBC         139 :             if (found_self)     /* should not happen */
 2907 heikki.linnakangas        791 UIC           0 :                 elog(ERROR, "found self tuple multiple times in index \"%s\"",
 2907 heikki.linnakangas        792 ECB             :                      RelationGetRelationName(index));
 2907 heikki.linnakangas        793 GIC         139 :             found_self = true;
                                794             166 :             continue;
                                795                 :         }
                                796                 : 
                                797                 :         /*
                                798                 :          * Extract the index column values and isnull flags from the existing
                                799                 :          * tuple.
                                800                 :          */
                                801            2793 :         FormIndexDatum(indexInfo, existing_slot, estate,
                                802                 :                        existing_values, existing_isnull);
                                803                 : 
 2907 heikki.linnakangas        804 ECB             :         /* If lossy indexscan, must recheck the condition */
 2907 heikki.linnakangas        805 CBC        2793 :         if (index_scan->xs_recheck)
                                806                 :         {
                                807              36 :             if (!index_recheck_constraint(index,
 2907 heikki.linnakangas        808 EUB             :                                           constr_procs,
                                809                 :                                           existing_values,
 2907 heikki.linnakangas        810 ECB             :                                           existing_isnull,
                                811                 :                                           values))
 2907 heikki.linnakangas        812 GIC          27 :                 continue;       /* tuple doesn't actually match, so no
                                813                 :                                  * conflict */
                                814                 :         }
                                815                 : 
                                816                 :         /*
                                817                 :          * At this point we have either a conflict or a potential conflict.
 2893 andres                    818 ECB             :          *
                                819                 :          * If an in-progress transaction is affecting the visibility of this
                                820                 :          * tuple, we need to wait for it to complete and then recheck (unless
                                821                 :          * the caller requested not to).  For simplicity we do rechecking by
                                822                 :          * just restarting the whole scan --- this case probably doesn't
                                823                 :          * happen often enough to be worth trying harder, and anyway we don't
                                824                 :          * want to hold any index internal locks while waiting.
                                825                 :          */
 2907 heikki.linnakangas        826 GIC        5532 :         xwait = TransactionIdIsValid(DirtySnapshot.xmin) ?
                                827            2766 :             DirtySnapshot.xmin : DirtySnapshot.xmax;
                                828                 : 
 2893 andres                    829 CBC        2766 :         if (TransactionIdIsValid(xwait) &&
 2893 andres                    830 UIC           0 :             (waitMode == CEOUC_WAIT ||
                                831               0 :              (waitMode == CEOUC_LIVELOCK_PREVENTING_WAIT &&
                                832               0 :               DirtySnapshot.speculativeToken &&
                                833               0 :               TransactionIdPrecedes(GetCurrentTransactionId(), xwait))))
                                834                 :         {
 2581 sfrost                    835 GIC          70 :             reason_wait = indexInfo->ii_ExclusionOps ?
                                836              35 :                 XLTW_RecheckExclusionConstr : XLTW_InsertIndex;
 2907 heikki.linnakangas        837              35 :             index_endscan(index_scan);
 2893 andres                    838              35 :             if (DirtySnapshot.speculativeToken)
                                839               1 :                 SpeculativeInsertionWait(DirtySnapshot.xmin,
                                840                 :                                          DirtySnapshot.speculativeToken);
                                841                 :             else
 1490                           842              34 :                 XactLockTableWait(xwait, heap,
 1490 andres                    843 ECB             :                                   &existing_slot->tts_tid, reason_wait);
 2907 heikki.linnakangas        844 CBC          35 :             goto retry;
                                845                 :         }
 2907 heikki.linnakangas        846 ECB             : 
 2907 heikki.linnakangas        847 EUB             :         /*
 2893 andres                    848                 :          * We have a definite conflict (or a potential one, but the caller
                                849                 :          * didn't want to wait).  Return it to caller, or report it.
 2907 heikki.linnakangas        850                 :          */
 2893 andres                    851 GIC        2731 :         if (violationOK)
 2893 andres                    852 ECB             :         {
 2893 andres                    853 CBC        2691 :             conflict = true;
                                854            2691 :             if (conflictTid)
 1490                           855            2679 :                 *conflictTid = existing_slot->tts_tid;
 2893                           856            2691 :             break;
                                857                 :         }
                                858                 : 
 2907 heikki.linnakangas        859              40 :         error_new = BuildIndexValueDescription(index, values, isnull);
 2907 heikki.linnakangas        860 GIC          40 :         error_existing = BuildIndexValueDescription(index, existing_values,
 2907 heikki.linnakangas        861 ECB             :                                                     existing_isnull);
 2907 heikki.linnakangas        862 GIC          40 :         if (newIndex)
                                863               6 :             ereport(ERROR,
                                864                 :                     (errcode(ERRCODE_EXCLUSION_VIOLATION),
                                865                 :                      errmsg("could not create exclusion constraint \"%s\"",
                                866                 :                             RelationGetRelationName(index)),
                                867                 :                      error_new && error_existing ?
 2878 bruce                     868 ECB             :                      errdetail("Key %s conflicts with key %s.",
                                869                 :                                error_new, error_existing) :
                                870                 :                      errdetail("Key conflicts exist."),
 2907 heikki.linnakangas        871                 :                      errtableconstraint(heap,
                                872                 :                                         RelationGetRelationName(index))));
                                873                 :         else
 2907 heikki.linnakangas        874 GIC          34 :             ereport(ERROR,
                                875                 :                     (errcode(ERRCODE_EXCLUSION_VIOLATION),
 2907 heikki.linnakangas        876 ECB             :                      errmsg("conflicting key value violates exclusion constraint \"%s\"",
                                877                 :                             RelationGetRelationName(index)),
                                878                 :                      error_new && error_existing ?
 2878 bruce                     879                 :                      errdetail("Key %s conflicts with existing key %s.",
                                880                 :                                error_new, error_existing) :
                                881                 :                      errdetail("Key conflicts with existing key."),
                                882                 :                      errtableconstraint(heap,
                                883                 :                                         RelationGetRelationName(index))));
                                884                 :     }
                                885                 : 
 2907 heikki.linnakangas        886 GIC        4843 :     index_endscan(index_scan);
                                887                 : 
                                888                 :     /*
                                889                 :      * Ordinarily, at this point the search should have found the originally
                                890                 :      * inserted tuple (if any), unless we exited the loop early because of
 2893 andres                    891 ECB             :      * conflict.  However, it is possible to define exclusion constraints for
                                892                 :      * which that wouldn't be true --- for instance, if the operator is <>. So
                                893                 :      * we no longer complain if found_self is still false.
                                894                 :      */
                                895                 : 
 2907 heikki.linnakangas        896 GIC        4843 :     econtext->ecxt_scantuple = save_scantuple;
                                897                 : 
                                898            4843 :     ExecDropSingleTupleTableSlot(existing_slot);
                                899                 : 
                                900            4843 :     return !conflict;
                                901                 : }
                                902                 : 
 2893 andres                    903 ECB             : /*
                                904                 :  * Check for violation of an exclusion constraint
                                905                 :  *
                                906                 :  * This is a dumbed down version of check_exclusion_or_unique_constraint
                                907                 :  * for external callers. They don't need all the special modes.
                                908                 :  */
                                909                 : void
 2893 andres                    910 GIC          35 : check_exclusion_constraint(Relation heap, Relation index,
                                911                 :                            IndexInfo *indexInfo,
                                912                 :                            ItemPointer tupleid,
 2893 andres                    913 ECB             :                            Datum *values, bool *isnull,
                                914                 :                            EState *estate, bool newIndex)
                                915                 : {
 2893 andres                    916 GIC          35 :     (void) check_exclusion_or_unique_constraint(heap, index, indexInfo, tupleid,
 2893 andres                    917 ECB             :                                                 values, isnull,
                                918                 :                                                 estate, newIndex,
                                919                 :                                                 CEOUC_WAIT, false, NULL);
 2893 andres                    920 GIC          20 : }
                                921                 : 
                                922                 : /*
                                923                 :  * Check existing tuple's index values to see if it really matches the
                                924                 :  * exclusion condition against the new_values.  Returns true if conflict.
                                925                 :  */
                                926                 : static bool
 2907 heikki.linnakangas        927 CBC          36 : index_recheck_constraint(Relation index, Oid *constr_procs,
                                928                 :                          Datum *existing_values, bool *existing_isnull,
                                929                 :                          Datum *new_values)
                                930                 : {
 1828 teodor                    931 GIC          36 :     int         indnkeyatts = IndexRelationGetNumberOfKeyAttributes(index);
                                932                 :     int         i;
 2907 heikki.linnakangas        933 ECB             : 
 1828 teodor                    934 GIC          72 :     for (i = 0; i < indnkeyatts; i++)
                                935                 :     {
                                936                 :         /* Assume the exclusion operators are strict */
 2907 heikki.linnakangas        937 CBC          63 :         if (existing_isnull[i])
 2907 heikki.linnakangas        938 UIC           0 :             return false;
                                939                 : 
 2907 heikki.linnakangas        940 GIC          63 :         if (!DatumGetBool(OidFunctionCall2Coll(constr_procs[i],
                                941              63 :                                                index->rd_indcollation[i],
                                942              63 :                                                existing_values[i],
                                943              63 :                                                new_values[i])))
 2907 heikki.linnakangas        944 CBC          27 :             return false;
                                945                 :     }
                                946                 : 
 2907 heikki.linnakangas        947 GIC           9 :     return true;
 2907 heikki.linnakangas        948 ECB             : }
                                949                 : 
                                950                 : /*
  816 pg                        951                 :  * Check if ExecInsertIndexTuples() should pass indexUnchanged hint.
                                952                 :  *
                                953                 :  * When the executor performs an UPDATE that requires a new round of index
                                954                 :  * tuples, determine if we should pass 'indexUnchanged' = true hint for one
  816 pg                        955 EUB             :  * single index.
                                956                 :  */
  816 pg                        957 ECB             : static bool
  816 pg                        958 CBC      252521 : index_unchanged_by_update(ResultRelInfo *resultRelInfo, EState *estate,
  816 pg                        959 ECB             :                           IndexInfo *indexInfo, Relation indexRelation)
                                960                 : {
  452                           961                 :     Bitmapset  *updatedCols;
                                962                 :     Bitmapset  *extraUpdatedCols;
                                963                 :     Bitmapset  *allUpdatedCols;
  816 pg                        964 CBC      252521 :     bool        hasexpression = false;
                                965                 :     List       *idxExprs;
                                966                 : 
                                967                 :     /*
                                968                 :      * Check cache first
                                969                 :      */
  452 pg                        970 GIC      252521 :     if (indexInfo->ii_CheckedUnchanged)
                                971          230258 :         return indexInfo->ii_IndexUnchanged;
                                972           22263 :     indexInfo->ii_CheckedUnchanged = true;
                                973                 : 
                                974                 :     /*
  816 pg                        975 ECB             :      * Check for indexed attribute overlap with updated columns.
                                976                 :      *
                                977                 :      * Only do this for key columns.  A change to a non-key column within an
                                978                 :      * INCLUDE index should not be counted here.  Non-key column values are
                                979                 :      * opaque payload state to the index AM, a little like an extra table TID.
                                980                 :      *
  452                           981                 :      * Note that row-level BEFORE triggers won't affect our behavior, since
                                982                 :      * they don't affect the updatedCols bitmaps generally.  It doesn't seem
                                983                 :      * worth the trouble of checking which attributes were changed directly.
                                984                 :      */
  452 pg                        985 GIC       22263 :     updatedCols = ExecGetUpdatedCols(resultRelInfo, estate);
                                986           22263 :     extraUpdatedCols = ExecGetExtraUpdatedCols(resultRelInfo, estate);
  816 pg                        987 CBC       24836 :     for (int attr = 0; attr < indexInfo->ii_NumIndexKeyAttrs; attr++)
  816 pg                        988 ECB             :     {
  816 pg                        989 CBC       23276 :         int         keycol = indexInfo->ii_IndexAttrNumbers[attr];
                                990                 : 
  816 pg                        991 GIC       23276 :         if (keycol <= 0)
                                992                 :         {
                                993                 :             /*
                                994                 :              * Skip expressions for now, but remember to deal with them later
                                995                 :              * on
                                996                 :              */
                                997              15 :             hasexpression = true;
                                998              15 :             continue;
                                999                 :         }
                               1000                 : 
                               1001           23261 :         if (bms_is_member(keycol - FirstLowInvalidHeapAttributeNumber,
  816 pg                       1002 CBC        2558 :                           updatedCols) ||
                               1003            2558 :             bms_is_member(keycol - FirstLowInvalidHeapAttributeNumber,
  816 pg                       1004 ECB             :                           extraUpdatedCols))
                               1005                 :         {
                               1006                 :             /* Changed key column -- don't hint for this index */
  452 pg                       1007 GIC       20703 :             indexInfo->ii_IndexUnchanged = false;
  816 pg                       1008 CBC       20703 :             return false;
                               1009                 :         }
                               1010                 :     }
                               1011                 : 
                               1012                 :     /*
                               1013                 :      * When we get this far and index has no expressions, return true so that
  816 pg                       1014 ECB             :      * index_insert() call will go on to pass 'indexUnchanged' = true hint.
                               1015                 :      *
                               1016                 :      * The _absence_ of an indexed key attribute that overlaps with updated
                               1017                 :      * attributes (in addition to the total absence of indexed expressions)
                               1018                 :      * shows that the index as a whole is logically unchanged by UPDATE.
                               1019                 :      */
  816 pg                       1020 CBC        1560 :     if (!hasexpression)
                               1021                 :     {
  452 pg                       1022 GIC        1548 :         indexInfo->ii_IndexUnchanged = true;
  816                          1023            1548 :         return true;
  452 pg                       1024 ECB             :     }
  816                          1025                 : 
                               1026                 :     /*
                               1027                 :      * Need to pass only one bms to expression_tree_walker helper function.
                               1028                 :      * Avoid allocating memory in common case where there are no extra cols.
                               1029                 :      */
  816 pg                       1030 GIC          12 :     if (!extraUpdatedCols)
                               1031              12 :         allUpdatedCols = updatedCols;
                               1032                 :     else
  816 pg                       1033 UIC           0 :         allUpdatedCols = bms_union(updatedCols, extraUpdatedCols);
                               1034                 : 
                               1035                 :     /*
                               1036                 :      * We have to work slightly harder in the event of indexed expressions,
  816 pg                       1037 ECB             :      * but the principle is the same as before: try to find columns (Vars,
                               1038                 :      * actually) that overlap with known-updated columns.
                               1039                 :      *
                               1040                 :      * If we find any matching Vars, don't pass hint for index.  Otherwise
                               1041                 :      * pass hint.
                               1042                 :      */
  816 pg                       1043 GIC          12 :     idxExprs = RelationGetIndexExpressions(indexRelation);
                               1044              12 :     hasexpression = index_expression_changed_walker((Node *) idxExprs,
                               1045                 :                                                     allUpdatedCols);
                               1046              12 :     list_free(idxExprs);
  816 pg                       1047 CBC          12 :     if (extraUpdatedCols)
  816 pg                       1048 LBC           0 :         bms_free(allUpdatedCols);
                               1049                 : 
  816 pg                       1050 GBC          12 :     if (hasexpression)
                               1051                 :     {
  452 pg                       1052 GIC           9 :         indexInfo->ii_IndexUnchanged = false;
  816                          1053               9 :         return false;
                               1054                 :     }
                               1055                 : 
                               1056                 :     /*
                               1057                 :      * Deliberately don't consider index predicates.  We should even give the
                               1058                 :      * hint when result rel's "updated tuple" has no corresponding index
                               1059                 :      * tuple, which is possible with a partial index (provided the usual
  452 pg                       1060 ECB             :      * conditions are met).
                               1061                 :      */
  452 pg                       1062 GIC           3 :     indexInfo->ii_IndexUnchanged = true;
  816 pg                       1063 CBC           3 :     return true;
  816 pg                       1064 ECB             : }
  816 pg                       1065 EUB             : 
                               1066                 : /*
  816 pg                       1067 ECB             :  * Indexed expression helper for index_unchanged_by_update().
                               1068                 :  *
                               1069                 :  * Returns true when Var that appears within allUpdatedCols located.
                               1070                 :  */
                               1071                 : static bool
  816 pg                       1072 GIC          38 : index_expression_changed_walker(Node *node, Bitmapset *allUpdatedCols)
                               1073                 : {
                               1074              38 :     if (node == NULL)
  816 pg                       1075 UIC           0 :         return false;
                               1076                 : 
  816 pg                       1077 GIC          38 :     if (IsA(node, Var))
                               1078                 :     {
  816 pg                       1079 CBC          12 :         Var        *var = (Var *) node;
  816 pg                       1080 ECB             : 
  816 pg                       1081 GIC          12 :         if (bms_is_member(var->varattno - FirstLowInvalidHeapAttributeNumber,
                               1082                 :                           allUpdatedCols))
                               1083                 :         {
                               1084                 :             /* Var was updated -- indicates that we should not hint */
                               1085               9 :             return true;
                               1086                 :         }
                               1087                 : 
                               1088                 :         /* Still haven't found a reason to not pass the hint */
  816 pg                       1089 CBC           3 :         return false;
                               1090                 :     }
  816 pg                       1091 ECB             : 
  816 pg                       1092 GBC          26 :     return expression_tree_walker(node, index_expression_changed_walker,
                               1093                 :                                   (void *) allUpdatedCols);
  816 pg                       1094 ECB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a