00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "postgres.h"
00044
00045 #include "access/relscan.h"
00046 #include "access/transam.h"
00047 #include "catalog/index.h"
00048 #include "executor/execdebug.h"
00049 #include "nodes/nodeFuncs.h"
00050 #include "parser/parsetree.h"
00051 #include "storage/lmgr.h"
00052 #include "utils/memutils.h"
00053 #include "utils/tqual.h"
00054
00055
00056 static bool get_last_attnums(Node *node, ProjectionInfo *projInfo);
00057 static bool index_recheck_constraint(Relation index, Oid *constr_procs,
00058 Datum *existing_values, bool *existing_isnull,
00059 Datum *new_values);
00060 static void ShutdownExprContext(ExprContext *econtext, bool isCommit);
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 EState *
00081 CreateExecutorState(void)
00082 {
00083 EState *estate;
00084 MemoryContext qcontext;
00085 MemoryContext oldcontext;
00086
00087
00088
00089
00090 qcontext = AllocSetContextCreate(CurrentMemoryContext,
00091 "ExecutorState",
00092 ALLOCSET_DEFAULT_MINSIZE,
00093 ALLOCSET_DEFAULT_INITSIZE,
00094 ALLOCSET_DEFAULT_MAXSIZE);
00095
00096
00097
00098
00099
00100 oldcontext = MemoryContextSwitchTo(qcontext);
00101
00102 estate = makeNode(EState);
00103
00104
00105
00106
00107 estate->es_direction = ForwardScanDirection;
00108 estate->es_snapshot = SnapshotNow;
00109 estate->es_crosscheck_snapshot = InvalidSnapshot;
00110 estate->es_range_table = NIL;
00111 estate->es_plannedstmt = NULL;
00112
00113 estate->es_junkFilter = NULL;
00114
00115 estate->es_output_cid = (CommandId) 0;
00116
00117 estate->es_result_relations = NULL;
00118 estate->es_num_result_relations = 0;
00119 estate->es_result_relation_info = NULL;
00120
00121 estate->es_trig_target_relations = NIL;
00122 estate->es_trig_tuple_slot = NULL;
00123 estate->es_trig_oldtup_slot = NULL;
00124 estate->es_trig_newtup_slot = NULL;
00125
00126 estate->es_param_list_info = NULL;
00127 estate->es_param_exec_vals = NULL;
00128
00129 estate->es_query_cxt = qcontext;
00130
00131 estate->es_tupleTable = NIL;
00132
00133 estate->es_rowMarks = NIL;
00134
00135 estate->es_processed = 0;
00136 estate->es_lastoid = InvalidOid;
00137
00138 estate->es_top_eflags = 0;
00139 estate->es_instrument = 0;
00140 estate->es_finished = false;
00141
00142 estate->es_exprcontexts = NIL;
00143
00144 estate->es_subplanstates = NIL;
00145
00146 estate->es_auxmodifytables = NIL;
00147
00148 estate->es_per_tuple_exprcontext = NULL;
00149
00150 estate->es_epqTuple = NULL;
00151 estate->es_epqTupleSet = NULL;
00152 estate->es_epqScanDone = NULL;
00153
00154
00155
00156
00157 MemoryContextSwitchTo(oldcontext);
00158
00159 return estate;
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 void
00178 FreeExecutorState(EState *estate)
00179 {
00180
00181
00182
00183
00184
00185
00186 while (estate->es_exprcontexts)
00187 {
00188
00189
00190
00191
00192 FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts),
00193 true);
00194
00195 }
00196
00197
00198
00199
00200
00201 MemoryContextDelete(estate->es_query_cxt);
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 ExprContext *
00218 CreateExprContext(EState *estate)
00219 {
00220 ExprContext *econtext;
00221 MemoryContext oldcontext;
00222
00223
00224 oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
00225
00226 econtext = makeNode(ExprContext);
00227
00228
00229 econtext->ecxt_scantuple = NULL;
00230 econtext->ecxt_innertuple = NULL;
00231 econtext->ecxt_outertuple = NULL;
00232
00233 econtext->ecxt_per_query_memory = estate->es_query_cxt;
00234
00235
00236
00237
00238 econtext->ecxt_per_tuple_memory =
00239 AllocSetContextCreate(estate->es_query_cxt,
00240 "ExprContext",
00241 ALLOCSET_DEFAULT_MINSIZE,
00242 ALLOCSET_DEFAULT_INITSIZE,
00243 ALLOCSET_DEFAULT_MAXSIZE);
00244
00245 econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
00246 econtext->ecxt_param_list_info = estate->es_param_list_info;
00247
00248 econtext->ecxt_aggvalues = NULL;
00249 econtext->ecxt_aggnulls = NULL;
00250
00251 econtext->caseValue_datum = (Datum) 0;
00252 econtext->caseValue_isNull = true;
00253
00254 econtext->domainValue_datum = (Datum) 0;
00255 econtext->domainValue_isNull = true;
00256
00257 econtext->ecxt_estate = estate;
00258
00259 econtext->ecxt_callbacks = NULL;
00260
00261
00262
00263
00264
00265
00266 estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
00267
00268 MemoryContextSwitchTo(oldcontext);
00269
00270 return econtext;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 ExprContext *
00292 CreateStandaloneExprContext(void)
00293 {
00294 ExprContext *econtext;
00295
00296
00297 econtext = makeNode(ExprContext);
00298
00299
00300 econtext->ecxt_scantuple = NULL;
00301 econtext->ecxt_innertuple = NULL;
00302 econtext->ecxt_outertuple = NULL;
00303
00304 econtext->ecxt_per_query_memory = CurrentMemoryContext;
00305
00306
00307
00308
00309 econtext->ecxt_per_tuple_memory =
00310 AllocSetContextCreate(CurrentMemoryContext,
00311 "ExprContext",
00312 ALLOCSET_DEFAULT_MINSIZE,
00313 ALLOCSET_DEFAULT_INITSIZE,
00314 ALLOCSET_DEFAULT_MAXSIZE);
00315
00316 econtext->ecxt_param_exec_vals = NULL;
00317 econtext->ecxt_param_list_info = NULL;
00318
00319 econtext->ecxt_aggvalues = NULL;
00320 econtext->ecxt_aggnulls = NULL;
00321
00322 econtext->caseValue_datum = (Datum) 0;
00323 econtext->caseValue_isNull = true;
00324
00325 econtext->domainValue_datum = (Datum) 0;
00326 econtext->domainValue_isNull = true;
00327
00328 econtext->ecxt_estate = NULL;
00329
00330 econtext->ecxt_callbacks = NULL;
00331
00332 return econtext;
00333 }
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 void
00353 FreeExprContext(ExprContext *econtext, bool isCommit)
00354 {
00355 EState *estate;
00356
00357
00358 ShutdownExprContext(econtext, isCommit);
00359
00360 MemoryContextDelete(econtext->ecxt_per_tuple_memory);
00361
00362 estate = econtext->ecxt_estate;
00363 if (estate)
00364 estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts,
00365 econtext);
00366
00367 pfree(econtext);
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 void
00380 ReScanExprContext(ExprContext *econtext)
00381 {
00382
00383 ShutdownExprContext(econtext, true);
00384
00385 MemoryContextReset(econtext->ecxt_per_tuple_memory);
00386 }
00387
00388
00389
00390
00391
00392
00393
00394 ExprContext *
00395 MakePerTupleExprContext(EState *estate)
00396 {
00397 if (estate->es_per_tuple_exprcontext == NULL)
00398 estate->es_per_tuple_exprcontext = CreateExprContext(estate);
00399
00400 return estate->es_per_tuple_exprcontext;
00401 }
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 void
00422 ExecAssignExprContext(EState *estate, PlanState *planstate)
00423 {
00424 planstate->ps_ExprContext = CreateExprContext(estate);
00425 }
00426
00427
00428
00429
00430
00431 void
00432 ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc)
00433 {
00434 TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
00435
00436 ExecSetSlotDescriptor(slot, tupDesc);
00437 }
00438
00439
00440
00441
00442
00443 void
00444 ExecAssignResultTypeFromTL(PlanState *planstate)
00445 {
00446 bool hasoid;
00447 TupleDesc tupDesc;
00448
00449 if (ExecContextForcesOids(planstate, &hasoid))
00450 {
00451
00452 }
00453 else
00454 {
00455
00456 hasoid = false;
00457 }
00458
00459
00460
00461
00462
00463
00464 tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
00465 ExecAssignResultType(planstate, tupDesc);
00466 }
00467
00468
00469
00470
00471
00472 TupleDesc
00473 ExecGetResultType(PlanState *planstate)
00474 {
00475 TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
00476
00477 return slot->tts_tupleDescriptor;
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 ProjectionInfo *
00496 ExecBuildProjectionInfo(List *targetList,
00497 ExprContext *econtext,
00498 TupleTableSlot *slot,
00499 TupleDesc inputDesc)
00500 {
00501 ProjectionInfo *projInfo = makeNode(ProjectionInfo);
00502 int len = ExecTargetListLength(targetList);
00503 int *workspace;
00504 int *varSlotOffsets;
00505 int *varNumbers;
00506 int *varOutputCols;
00507 List *exprlist;
00508 int numSimpleVars;
00509 bool directMap;
00510 ListCell *tl;
00511
00512 projInfo->pi_exprContext = econtext;
00513 projInfo->pi_slot = slot;
00514
00515 workspace = (int *) palloc(len * 3 * sizeof(int));
00516 projInfo->pi_varSlotOffsets = varSlotOffsets = workspace;
00517 projInfo->pi_varNumbers = varNumbers = workspace + len;
00518 projInfo->pi_varOutputCols = varOutputCols = workspace + len * 2;
00519 projInfo->pi_lastInnerVar = 0;
00520 projInfo->pi_lastOuterVar = 0;
00521 projInfo->pi_lastScanVar = 0;
00522
00523
00524
00525
00526
00527
00528
00529
00530 exprlist = NIL;
00531 numSimpleVars = 0;
00532 directMap = true;
00533 foreach(tl, targetList)
00534 {
00535 GenericExprState *gstate = (GenericExprState *) lfirst(tl);
00536 Var *variable = (Var *) gstate->arg->expr;
00537 bool isSimpleVar = false;
00538
00539 if (variable != NULL &&
00540 IsA(variable, Var) &&
00541 variable->varattno > 0)
00542 {
00543 if (!inputDesc)
00544 isSimpleVar = true;
00545 else if (variable->varattno <= inputDesc->natts)
00546 {
00547 Form_pg_attribute attr;
00548
00549 attr = inputDesc->attrs[variable->varattno - 1];
00550 if (!attr->attisdropped && variable->vartype == attr->atttypid)
00551 isSimpleVar = true;
00552 }
00553 }
00554
00555 if (isSimpleVar)
00556 {
00557 TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
00558 AttrNumber attnum = variable->varattno;
00559
00560 varNumbers[numSimpleVars] = attnum;
00561 varOutputCols[numSimpleVars] = tle->resno;
00562 if (tle->resno != numSimpleVars + 1)
00563 directMap = false;
00564
00565 switch (variable->varno)
00566 {
00567 case INNER_VAR:
00568 varSlotOffsets[numSimpleVars] = offsetof(ExprContext,
00569 ecxt_innertuple);
00570 if (projInfo->pi_lastInnerVar < attnum)
00571 projInfo->pi_lastInnerVar = attnum;
00572 break;
00573
00574 case OUTER_VAR:
00575 varSlotOffsets[numSimpleVars] = offsetof(ExprContext,
00576 ecxt_outertuple);
00577 if (projInfo->pi_lastOuterVar < attnum)
00578 projInfo->pi_lastOuterVar = attnum;
00579 break;
00580
00581
00582
00583 default:
00584 varSlotOffsets[numSimpleVars] = offsetof(ExprContext,
00585 ecxt_scantuple);
00586 if (projInfo->pi_lastScanVar < attnum)
00587 projInfo->pi_lastScanVar = attnum;
00588 break;
00589 }
00590 numSimpleVars++;
00591 }
00592 else
00593 {
00594
00595 exprlist = lappend(exprlist, gstate);
00596
00597 get_last_attnums((Node *) variable, projInfo);
00598 }
00599 }
00600 projInfo->pi_targetlist = exprlist;
00601 projInfo->pi_numSimpleVars = numSimpleVars;
00602 projInfo->pi_directMap = directMap;
00603
00604 if (exprlist == NIL)
00605 projInfo->pi_itemIsDone = NULL;
00606 else
00607 projInfo->pi_itemIsDone = (ExprDoneCond *)
00608 palloc(len * sizeof(ExprDoneCond));
00609
00610 return projInfo;
00611 }
00612
00613
00614
00615
00616
00617
00618
00619 static bool
00620 get_last_attnums(Node *node, ProjectionInfo *projInfo)
00621 {
00622 if (node == NULL)
00623 return false;
00624 if (IsA(node, Var))
00625 {
00626 Var *variable = (Var *) node;
00627 AttrNumber attnum = variable->varattno;
00628
00629 switch (variable->varno)
00630 {
00631 case INNER_VAR:
00632 if (projInfo->pi_lastInnerVar < attnum)
00633 projInfo->pi_lastInnerVar = attnum;
00634 break;
00635
00636 case OUTER_VAR:
00637 if (projInfo->pi_lastOuterVar < attnum)
00638 projInfo->pi_lastOuterVar = attnum;
00639 break;
00640
00641
00642
00643 default:
00644 if (projInfo->pi_lastScanVar < attnum)
00645 projInfo->pi_lastScanVar = attnum;
00646 break;
00647 }
00648 return false;
00649 }
00650
00651
00652
00653
00654
00655
00656 if (IsA(node, Aggref))
00657 return false;
00658 if (IsA(node, WindowFunc))
00659 return false;
00660 return expression_tree_walker(node, get_last_attnums,
00661 (void *) projInfo);
00662 }
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 void
00674 ExecAssignProjectionInfo(PlanState *planstate,
00675 TupleDesc inputDesc)
00676 {
00677 planstate->ps_ProjInfo =
00678 ExecBuildProjectionInfo(planstate->targetlist,
00679 planstate->ps_ExprContext,
00680 planstate->ps_ResultTupleSlot,
00681 inputDesc);
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701 void
00702 ExecFreeExprContext(PlanState *planstate)
00703 {
00704
00705
00706
00707
00708 planstate->ps_ExprContext = NULL;
00709 }
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725 TupleDesc
00726 ExecGetScanType(ScanState *scanstate)
00727 {
00728 TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
00729
00730 return slot->tts_tupleDescriptor;
00731 }
00732
00733
00734
00735
00736
00737 void
00738 ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
00739 {
00740 TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
00741
00742 ExecSetSlotDescriptor(slot, tupDesc);
00743 }
00744
00745
00746
00747
00748
00749 void
00750 ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
00751 {
00752 PlanState *outerPlan;
00753 TupleDesc tupDesc;
00754
00755 outerPlan = outerPlanState(scanstate);
00756 tupDesc = ExecGetResultType(outerPlan);
00757
00758 ExecAssignScanType(scanstate, tupDesc);
00759 }
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774 bool
00775 ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
00776 {
00777 ResultRelInfo *resultRelInfos;
00778 int i;
00779
00780 resultRelInfos = estate->es_result_relations;
00781 for (i = 0; i < estate->es_num_result_relations; i++)
00782 {
00783 if (resultRelInfos[i].ri_RangeTableIndex == scanrelid)
00784 return true;
00785 }
00786 return false;
00787 }
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 Relation
00801 ExecOpenScanRelation(EState *estate, Index scanrelid, int eflags)
00802 {
00803 Relation rel;
00804 Oid reloid;
00805 LOCKMODE lockmode;
00806
00807
00808
00809
00810
00811
00812 lockmode = AccessShareLock;
00813 if (ExecRelationIsTargetRelation(estate, scanrelid))
00814 lockmode = NoLock;
00815 else
00816 {
00817 ListCell *l;
00818
00819 foreach(l, estate->es_rowMarks)
00820 {
00821 ExecRowMark *erm = lfirst(l);
00822
00823 if (erm->rti == scanrelid)
00824 {
00825 lockmode = NoLock;
00826 break;
00827 }
00828 }
00829 }
00830
00831
00832 reloid = getrelid(scanrelid, estate->es_range_table);
00833 rel = heap_open(reloid, lockmode);
00834
00835
00836
00837
00838
00839
00840 if ((eflags & (EXEC_FLAG_EXPLAIN_ONLY | EXEC_FLAG_WITH_NO_DATA)) == 0 &&
00841 !RelationIsScannable(rel))
00842 ereport(ERROR,
00843 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
00844 errmsg("materialized view \"%s\" has not been populated",
00845 RelationGetRelationName(rel)),
00846 errhint("Use the REFRESH MATERIALIZED VIEW command.")));
00847
00848 return rel;
00849 }
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 void
00866 ExecCloseScanRelation(Relation scanrel)
00867 {
00868 heap_close(scanrel, NoLock);
00869 }
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887 void
00888 ExecOpenIndices(ResultRelInfo *resultRelInfo)
00889 {
00890 Relation resultRelation = resultRelInfo->ri_RelationDesc;
00891 List *indexoidlist;
00892 ListCell *l;
00893 int len,
00894 i;
00895 RelationPtr relationDescs;
00896 IndexInfo **indexInfoArray;
00897
00898 resultRelInfo->ri_NumIndices = 0;
00899
00900
00901 if (!RelationGetForm(resultRelation)->relhasindex)
00902 return;
00903
00904
00905
00906
00907 indexoidlist = RelationGetIndexList(resultRelation);
00908 len = list_length(indexoidlist);
00909 if (len == 0)
00910 return;
00911
00912
00913
00914
00915 relationDescs = (RelationPtr) palloc(len * sizeof(Relation));
00916 indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));
00917
00918 resultRelInfo->ri_NumIndices = len;
00919 resultRelInfo->ri_IndexRelationDescs = relationDescs;
00920 resultRelInfo->ri_IndexRelationInfo = indexInfoArray;
00921
00922
00923
00924
00925
00926
00927
00928
00929 i = 0;
00930 foreach(l, indexoidlist)
00931 {
00932 Oid indexOid = lfirst_oid(l);
00933 Relation indexDesc;
00934 IndexInfo *ii;
00935
00936 indexDesc = index_open(indexOid, RowExclusiveLock);
00937
00938
00939 ii = BuildIndexInfo(indexDesc);
00940
00941 relationDescs[i] = indexDesc;
00942 indexInfoArray[i] = ii;
00943 i++;
00944 }
00945
00946 list_free(indexoidlist);
00947 }
00948
00949
00950
00951
00952
00953
00954
00955 void
00956 ExecCloseIndices(ResultRelInfo *resultRelInfo)
00957 {
00958 int i;
00959 int numIndices;
00960 RelationPtr indexDescs;
00961
00962 numIndices = resultRelInfo->ri_NumIndices;
00963 indexDescs = resultRelInfo->ri_IndexRelationDescs;
00964
00965 for (i = 0; i < numIndices; i++)
00966 {
00967 if (indexDescs[i] == NULL)
00968 continue;
00969
00970
00971 index_close(indexDescs[i], RowExclusiveLock);
00972 }
00973
00974
00975
00976
00977
00978 }
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000 List *
01001 ExecInsertIndexTuples(TupleTableSlot *slot,
01002 ItemPointer tupleid,
01003 EState *estate)
01004 {
01005 List *result = NIL;
01006 ResultRelInfo *resultRelInfo;
01007 int i;
01008 int numIndices;
01009 RelationPtr relationDescs;
01010 Relation heapRelation;
01011 IndexInfo **indexInfoArray;
01012 ExprContext *econtext;
01013 Datum values[INDEX_MAX_KEYS];
01014 bool isnull[INDEX_MAX_KEYS];
01015
01016
01017
01018
01019 resultRelInfo = estate->es_result_relation_info;
01020 numIndices = resultRelInfo->ri_NumIndices;
01021 relationDescs = resultRelInfo->ri_IndexRelationDescs;
01022 indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
01023 heapRelation = resultRelInfo->ri_RelationDesc;
01024
01025
01026
01027
01028
01029 econtext = GetPerTupleExprContext(estate);
01030
01031
01032 econtext->ecxt_scantuple = slot;
01033
01034
01035
01036
01037 for (i = 0; i < numIndices; i++)
01038 {
01039 Relation indexRelation = relationDescs[i];
01040 IndexInfo *indexInfo;
01041 IndexUniqueCheck checkUnique;
01042 bool satisfiesConstraint;
01043
01044 if (indexRelation == NULL)
01045 continue;
01046
01047 indexInfo = indexInfoArray[i];
01048
01049
01050 if (!indexInfo->ii_ReadyForInserts)
01051 continue;
01052
01053
01054 if (indexInfo->ii_Predicate != NIL)
01055 {
01056 List *predicate;
01057
01058
01059
01060
01061
01062 predicate = indexInfo->ii_PredicateState;
01063 if (predicate == NIL)
01064 {
01065 predicate = (List *)
01066 ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
01067 estate);
01068 indexInfo->ii_PredicateState = predicate;
01069 }
01070
01071
01072 if (!ExecQual(predicate, econtext, false))
01073 continue;
01074 }
01075
01076
01077
01078
01079
01080 FormIndexDatum(indexInfo,
01081 slot,
01082 estate,
01083 values,
01084 isnull);
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096 if (!indexRelation->rd_index->indisunique)
01097 checkUnique = UNIQUE_CHECK_NO;
01098 else if (indexRelation->rd_index->indimmediate)
01099 checkUnique = UNIQUE_CHECK_YES;
01100 else
01101 checkUnique = UNIQUE_CHECK_PARTIAL;
01102
01103 satisfiesConstraint =
01104 index_insert(indexRelation,
01105 values,
01106 isnull,
01107 tupleid,
01108 heapRelation,
01109 checkUnique);
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122 if (indexInfo->ii_ExclusionOps != NULL)
01123 {
01124 bool errorOK = !indexRelation->rd_index->indimmediate;
01125
01126 satisfiesConstraint =
01127 check_exclusion_constraint(heapRelation,
01128 indexRelation, indexInfo,
01129 tupleid, values, isnull,
01130 estate, false, errorOK);
01131 }
01132
01133 if ((checkUnique == UNIQUE_CHECK_PARTIAL ||
01134 indexInfo->ii_ExclusionOps != NULL) &&
01135 !satisfiesConstraint)
01136 {
01137
01138
01139
01140
01141
01142 result = lappend_oid(result, RelationGetRelid(indexRelation));
01143 }
01144 }
01145
01146 return result;
01147 }
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173 bool
01174 check_exclusion_constraint(Relation heap, Relation index, IndexInfo *indexInfo,
01175 ItemPointer tupleid, Datum *values, bool *isnull,
01176 EState *estate, bool newIndex, bool errorOK)
01177 {
01178 Oid *constr_procs = indexInfo->ii_ExclusionProcs;
01179 uint16 *constr_strats = indexInfo->ii_ExclusionStrats;
01180 Oid *index_collations = index->rd_indcollation;
01181 int index_natts = index->rd_index->indnatts;
01182 IndexScanDesc index_scan;
01183 HeapTuple tup;
01184 ScanKeyData scankeys[INDEX_MAX_KEYS];
01185 SnapshotData DirtySnapshot;
01186 int i;
01187 bool conflict;
01188 bool found_self;
01189 ExprContext *econtext;
01190 TupleTableSlot *existing_slot;
01191 TupleTableSlot *save_scantuple;
01192
01193
01194
01195
01196
01197 for (i = 0; i < index_natts; i++)
01198 {
01199 if (isnull[i])
01200 return true;
01201 }
01202
01203
01204
01205
01206
01207 InitDirtySnapshot(DirtySnapshot);
01208
01209 for (i = 0; i < index_natts; i++)
01210 {
01211 ScanKeyEntryInitialize(&scankeys[i],
01212 0,
01213 i + 1,
01214 constr_strats[i],
01215 InvalidOid,
01216 index_collations[i],
01217 constr_procs[i],
01218 values[i]);
01219 }
01220
01221
01222
01223
01224
01225
01226
01227
01228 existing_slot = MakeSingleTupleTableSlot(RelationGetDescr(heap));
01229
01230 econtext = GetPerTupleExprContext(estate);
01231 save_scantuple = econtext->ecxt_scantuple;
01232 econtext->ecxt_scantuple = existing_slot;
01233
01234
01235
01236
01237
01238 retry:
01239 conflict = false;
01240 found_self = false;
01241 index_scan = index_beginscan(heap, index, &DirtySnapshot, index_natts, 0);
01242 index_rescan(index_scan, scankeys, index_natts, NULL, 0);
01243
01244 while ((tup = index_getnext(index_scan,
01245 ForwardScanDirection)) != NULL)
01246 {
01247 TransactionId xwait;
01248 Datum existing_values[INDEX_MAX_KEYS];
01249 bool existing_isnull[INDEX_MAX_KEYS];
01250 char *error_new;
01251 char *error_existing;
01252
01253
01254
01255
01256 if (ItemPointerEquals(tupleid, &tup->t_self))
01257 {
01258 if (found_self)
01259 elog(ERROR, "found self tuple multiple times in index \"%s\"",
01260 RelationGetRelationName(index));
01261 found_self = true;
01262 continue;
01263 }
01264
01265
01266
01267
01268
01269 ExecStoreTuple(tup, existing_slot, InvalidBuffer, false);
01270 FormIndexDatum(indexInfo, existing_slot, estate,
01271 existing_values, existing_isnull);
01272
01273
01274 if (index_scan->xs_recheck)
01275 {
01276 if (!index_recheck_constraint(index,
01277 constr_procs,
01278 existing_values,
01279 existing_isnull,
01280 values))
01281 continue;
01282
01283 }
01284
01285
01286
01287
01288
01289
01290 if (errorOK)
01291 {
01292 conflict = true;
01293 break;
01294 }
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304 xwait = TransactionIdIsValid(DirtySnapshot.xmin) ?
01305 DirtySnapshot.xmin : DirtySnapshot.xmax;
01306
01307 if (TransactionIdIsValid(xwait))
01308 {
01309 index_endscan(index_scan);
01310 XactLockTableWait(xwait);
01311 goto retry;
01312 }
01313
01314
01315
01316
01317 error_new = BuildIndexValueDescription(index, values, isnull);
01318 error_existing = BuildIndexValueDescription(index, existing_values,
01319 existing_isnull);
01320 if (newIndex)
01321 ereport(ERROR,
01322 (errcode(ERRCODE_EXCLUSION_VIOLATION),
01323 errmsg("could not create exclusion constraint \"%s\"",
01324 RelationGetRelationName(index)),
01325 errdetail("Key %s conflicts with key %s.",
01326 error_new, error_existing),
01327 errtableconstraint(heap,
01328 RelationGetRelationName(index))));
01329 else
01330 ereport(ERROR,
01331 (errcode(ERRCODE_EXCLUSION_VIOLATION),
01332 errmsg("conflicting key value violates exclusion constraint \"%s\"",
01333 RelationGetRelationName(index)),
01334 errdetail("Key %s conflicts with existing key %s.",
01335 error_new, error_existing),
01336 errtableconstraint(heap,
01337 RelationGetRelationName(index))));
01338 }
01339
01340 index_endscan(index_scan);
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350 econtext->ecxt_scantuple = save_scantuple;
01351
01352 ExecDropSingleTupleTableSlot(existing_slot);
01353
01354 return !conflict;
01355 }
01356
01357
01358
01359
01360
01361 static bool
01362 index_recheck_constraint(Relation index, Oid *constr_procs,
01363 Datum *existing_values, bool *existing_isnull,
01364 Datum *new_values)
01365 {
01366 int index_natts = index->rd_index->indnatts;
01367 int i;
01368
01369 for (i = 0; i < index_natts; i++)
01370 {
01371
01372 if (existing_isnull[i])
01373 return false;
01374
01375 if (!DatumGetBool(OidFunctionCall2Coll(constr_procs[i],
01376 index->rd_indcollation[i],
01377 existing_values[i],
01378 new_values[i])))
01379 return false;
01380 }
01381
01382 return true;
01383 }
01384
01385
01386
01387
01388
01389 void
01390 UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
01391 {
01392 Bitmapset *parmset;
01393
01394
01395
01396
01397
01398 parmset = bms_intersect(node->plan->allParam, newchg);
01399
01400
01401
01402
01403
01404 if (!bms_is_empty(parmset))
01405 node->chgParam = bms_join(node->chgParam, parmset);
01406 else
01407 bms_free(parmset);
01408 }
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420 void
01421 RegisterExprContextCallback(ExprContext *econtext,
01422 ExprContextCallbackFunction function,
01423 Datum arg)
01424 {
01425 ExprContext_CB *ecxt_callback;
01426
01427
01428 ecxt_callback = (ExprContext_CB *)
01429 MemoryContextAlloc(econtext->ecxt_per_query_memory,
01430 sizeof(ExprContext_CB));
01431
01432 ecxt_callback->function = function;
01433 ecxt_callback->arg = arg;
01434
01435
01436 ecxt_callback->next = econtext->ecxt_callbacks;
01437 econtext->ecxt_callbacks = ecxt_callback;
01438 }
01439
01440
01441
01442
01443
01444
01445
01446 void
01447 UnregisterExprContextCallback(ExprContext *econtext,
01448 ExprContextCallbackFunction function,
01449 Datum arg)
01450 {
01451 ExprContext_CB **prev_callback;
01452 ExprContext_CB *ecxt_callback;
01453
01454 prev_callback = &econtext->ecxt_callbacks;
01455
01456 while ((ecxt_callback = *prev_callback) != NULL)
01457 {
01458 if (ecxt_callback->function == function && ecxt_callback->arg == arg)
01459 {
01460 *prev_callback = ecxt_callback->next;
01461 pfree(ecxt_callback);
01462 }
01463 else
01464 prev_callback = &ecxt_callback->next;
01465 }
01466 }
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477 static void
01478 ShutdownExprContext(ExprContext *econtext, bool isCommit)
01479 {
01480 ExprContext_CB *ecxt_callback;
01481 MemoryContext oldcontext;
01482
01483
01484 if (econtext->ecxt_callbacks == NULL)
01485 return;
01486
01487
01488
01489
01490
01491 oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
01492
01493
01494
01495
01496 while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
01497 {
01498 econtext->ecxt_callbacks = ecxt_callback->next;
01499 if (isCommit)
01500 (*ecxt_callback->function) (ecxt_callback->arg);
01501 pfree(ecxt_callback);
01502 }
01503
01504 MemoryContextSwitchTo(oldcontext);
01505 }