mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
Clean up inefficiency in ExecRelCheck, and cause it to do the right
thing when there are multiple result relations. Formerly, during something like 'UPDATE foo*', foo's constraints and *only* foo's constraints would be applied to all foo's children. Wrong-o ...
This commit is contained in:
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.119 2000/07/14 22:17:42 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.120 2000/08/06 04:26:40 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -827,9 +827,10 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
|
|||||||
* Check the constraints of the tuple
|
* Check the constraints of the tuple
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
|
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
|
||||||
|
|
||||||
if (rel->rd_att->constr)
|
if (rel->rd_att->constr)
|
||||||
ExecConstraints("CopyFrom", rel, tuple, estate);
|
ExecConstraints("CopyFrom", rel, slot, estate);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* OK, store the tuple and create index entries for it
|
* OK, store the tuple and create index entries for it
|
||||||
@ -838,10 +839,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
|
|||||||
heap_insert(rel, tuple);
|
heap_insert(rel, tuple);
|
||||||
|
|
||||||
if (relationInfo->ri_NumIndices > 0)
|
if (relationInfo->ri_NumIndices > 0)
|
||||||
{
|
|
||||||
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
|
|
||||||
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
|
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
|
||||||
}
|
|
||||||
|
|
||||||
/* AFTER ROW INSERT Triggers */
|
/* AFTER ROW INSERT Triggers */
|
||||||
if (rel->trigdesc &&
|
if (rel->trigdesc &&
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.122 2000/07/12 02:37:00 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.123 2000/08/06 04:26:26 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1296,10 +1296,6 @@ ExecAppend(TupleTableSlot *slot,
|
|||||||
resultRelationInfo = estate->es_result_relation_info;
|
resultRelationInfo = estate->es_result_relation_info;
|
||||||
resultRelationDesc = resultRelationInfo->ri_RelationDesc;
|
resultRelationDesc = resultRelationInfo->ri_RelationDesc;
|
||||||
|
|
||||||
/*
|
|
||||||
* have to add code to preform unique checking here. cim -12/1/89
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* BEFORE ROW INSERT Triggers */
|
/* BEFORE ROW INSERT Triggers */
|
||||||
if (resultRelationDesc->trigdesc &&
|
if (resultRelationDesc->trigdesc &&
|
||||||
resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
|
resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
|
||||||
@ -1320,18 +1316,20 @@ ExecAppend(TupleTableSlot *slot,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check the constraints of a tuple
|
* Check the constraints of the tuple
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (resultRelationDesc->rd_att->constr)
|
if (resultRelationDesc->rd_att->constr)
|
||||||
ExecConstraints("ExecAppend", resultRelationDesc, tuple, estate);
|
ExecConstraints("ExecAppend", resultRelationDesc, slot, estate);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* insert the tuple
|
* insert the tuple
|
||||||
*/
|
*/
|
||||||
newId = heap_insert(resultRelationDesc, /* relation desc */
|
newId = heap_insert(resultRelationDesc, tuple);
|
||||||
tuple); /* heap tuple */
|
|
||||||
IncrAppended();
|
IncrAppended();
|
||||||
|
(estate->es_processed)++;
|
||||||
|
estate->es_lastoid = newId;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* process indices
|
* process indices
|
||||||
@ -1343,8 +1341,6 @@ ExecAppend(TupleTableSlot *slot,
|
|||||||
numIndices = resultRelationInfo->ri_NumIndices;
|
numIndices = resultRelationInfo->ri_NumIndices;
|
||||||
if (numIndices > 0)
|
if (numIndices > 0)
|
||||||
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
|
ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);
|
||||||
(estate->es_processed)++;
|
|
||||||
estate->es_lastoid = newId;
|
|
||||||
|
|
||||||
/* AFTER ROW INSERT Triggers */
|
/* AFTER ROW INSERT Triggers */
|
||||||
if (resultRelationDesc->trigdesc)
|
if (resultRelationDesc->trigdesc)
|
||||||
@ -1466,7 +1462,7 @@ ExecReplace(TupleTableSlot *slot,
|
|||||||
*/
|
*/
|
||||||
if (IsBootstrapProcessingMode())
|
if (IsBootstrapProcessingMode())
|
||||||
{
|
{
|
||||||
elog(DEBUG, "ExecReplace: replace can't run without transactions");
|
elog(NOTICE, "ExecReplace: replace can't run without transactions");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1481,12 +1477,6 @@ ExecReplace(TupleTableSlot *slot,
|
|||||||
resultRelationInfo = estate->es_result_relation_info;
|
resultRelationInfo = estate->es_result_relation_info;
|
||||||
resultRelationDesc = resultRelationInfo->ri_RelationDesc;
|
resultRelationDesc = resultRelationInfo->ri_RelationDesc;
|
||||||
|
|
||||||
/*
|
|
||||||
* have to add code to preform unique checking here. in the event of
|
|
||||||
* unique tuples, this becomes a deletion of the original tuple
|
|
||||||
* affected by the replace. cim -12/1/89
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* BEFORE ROW UPDATE Triggers */
|
/* BEFORE ROW UPDATE Triggers */
|
||||||
if (resultRelationDesc->trigdesc &&
|
if (resultRelationDesc->trigdesc &&
|
||||||
resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)
|
resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)
|
||||||
@ -1507,11 +1497,11 @@ ExecReplace(TupleTableSlot *slot,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check the constraints of a tuple
|
* Check the constraints of the tuple
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (resultRelationDesc->rd_att->constr)
|
if (resultRelationDesc->rd_att->constr)
|
||||||
ExecConstraints("ExecReplace", resultRelationDesc, tuple, estate);
|
ExecConstraints("ExecReplace", resultRelationDesc, slot, estate);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* replace the heap tuple
|
* replace the heap tuple
|
||||||
@ -1555,9 +1545,9 @@ lreplace:;
|
|||||||
/*
|
/*
|
||||||
* Note: instead of having to update the old index tuples associated
|
* Note: instead of having to update the old index tuples associated
|
||||||
* with the heap tuple, all we do is form and insert new index
|
* with the heap tuple, all we do is form and insert new index
|
||||||
* tuples.. This is because replaces are actually deletes and inserts
|
* tuples. This is because replaces are actually deletes and inserts
|
||||||
* and index tuple deletion is done automagically by the vaccuum
|
* and index tuple deletion is done automagically by the vacuum
|
||||||
* deamon.. All we do is insert new index tuples. -cim 9/27/89
|
* daemon. All we do is insert new index tuples. -cim 9/27/89
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1579,109 +1569,55 @@ lreplace:;
|
|||||||
ExecARUpdateTriggers(estate, tupleid, tuple);
|
ExecARUpdateTriggers(estate, tupleid, tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NOT_USED
|
|
||||||
static HeapTuple
|
|
||||||
ExecAttrDefault(Relation rel, HeapTuple tuple)
|
|
||||||
{
|
|
||||||
int ndef = rel->rd_att->constr->num_defval;
|
|
||||||
AttrDefault *attrdef = rel->rd_att->constr->defval;
|
|
||||||
ExprContext *econtext = MakeExprContext(NULL, CurrentMemoryContext);
|
|
||||||
HeapTuple newtuple;
|
|
||||||
Node *expr;
|
|
||||||
bool isnull;
|
|
||||||
bool isdone;
|
|
||||||
Datum val;
|
|
||||||
Datum *replValue = NULL;
|
|
||||||
char *replNull = NULL;
|
|
||||||
char *repl = NULL;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ndef; i++)
|
|
||||||
{
|
|
||||||
if (!heap_attisnull(tuple, attrdef[i].adnum))
|
|
||||||
continue;
|
|
||||||
expr = (Node *) stringToNode(attrdef[i].adbin);
|
|
||||||
|
|
||||||
val = ExecEvalExprSwitchContext(expr, econtext, &isnull, &isdone);
|
|
||||||
|
|
||||||
if (isnull)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (repl == NULL)
|
|
||||||
{
|
|
||||||
repl = (char *) palloc(rel->rd_att->natts * sizeof(char));
|
|
||||||
replNull = (char *) palloc(rel->rd_att->natts * sizeof(char));
|
|
||||||
replValue = (Datum *) palloc(rel->rd_att->natts * sizeof(Datum));
|
|
||||||
MemSet(repl, ' ', rel->rd_att->natts * sizeof(char));
|
|
||||||
}
|
|
||||||
|
|
||||||
repl[attrdef[i].adnum - 1] = 'r';
|
|
||||||
replNull[attrdef[i].adnum - 1] = ' ';
|
|
||||||
replValue[attrdef[i].adnum - 1] = val;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (repl == NULL)
|
|
||||||
{
|
|
||||||
/* no changes needed */
|
|
||||||
newtuple = tuple;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newtuple = heap_modifytuple(tuple, rel, replValue, replNull, repl);
|
|
||||||
|
|
||||||
pfree(repl);
|
|
||||||
pfree(replNull);
|
|
||||||
pfree(replValue);
|
|
||||||
heap_freetuple(tuple);
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeMemoryContext(econtext);
|
|
||||||
|
|
||||||
return newtuple;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
ExecRelCheck(Relation rel, HeapTuple tuple, EState *estate)
|
ExecRelCheck(Relation rel, TupleTableSlot *slot, EState *estate)
|
||||||
{
|
{
|
||||||
int ncheck = rel->rd_att->constr->num_check;
|
int ncheck = rel->rd_att->constr->num_check;
|
||||||
ConstrCheck *check = rel->rd_att->constr->check;
|
ConstrCheck *check = rel->rd_att->constr->check;
|
||||||
TupleTableSlot *slot = makeNode(TupleTableSlot);
|
MemoryContext oldContext;
|
||||||
RangeTblEntry *rte = makeNode(RangeTblEntry);
|
ExprContext *econtext;
|
||||||
ExprContext *econtext = MakeExprContext(slot,
|
|
||||||
TransactionCommandContext);
|
|
||||||
List *rtlist;
|
|
||||||
List *qual;
|
List *qual;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
slot->val = tuple;
|
/*
|
||||||
slot->ttc_shouldFree = false;
|
* Make sure econtext, expressions, etc are placed in appropriate context.
|
||||||
slot->ttc_descIsNew = true;
|
*/
|
||||||
slot->ttc_tupleDescriptor = rel->rd_att;
|
oldContext = MemoryContextSwitchTo(TransactionCommandContext);
|
||||||
slot->ttc_buffer = InvalidBuffer;
|
|
||||||
slot->ttc_whichplan = -1;
|
|
||||||
rte->relname = RelationGetRelationName(rel);
|
|
||||||
rte->ref = makeNode(Attr);
|
|
||||||
rte->ref->relname = rte->relname;
|
|
||||||
rte->relid = RelationGetRelid(rel);
|
|
||||||
/* inh, inFromCl, inJoinSet, skipAcl won't be used, leave them zero */
|
|
||||||
rtlist = lcons(rte, NIL);
|
|
||||||
econtext->ecxt_range_table = rtlist; /* phony range table */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save the de-stringized constraint expressions in command-level
|
* Create or reset the exprcontext for evaluating constraint expressions.
|
||||||
* memory context. XXX should build the above stuff there too,
|
|
||||||
* instead of doing it over for each tuple.
|
|
||||||
* XXX Is it sufficient to have just one es_result_relation_constraints
|
|
||||||
* in an inherited insert/update?
|
|
||||||
*/
|
*/
|
||||||
if (estate->es_result_relation_constraints == NULL)
|
econtext = estate->es_constraint_exprcontext;
|
||||||
{
|
if (econtext == NULL)
|
||||||
MemoryContext oldContext;
|
estate->es_constraint_exprcontext = econtext =
|
||||||
|
MakeExprContext(NULL, TransactionCommandContext);
|
||||||
|
else
|
||||||
|
ResetExprContext(econtext);
|
||||||
|
|
||||||
oldContext = MemoryContextSwitchTo(TransactionCommandContext);
|
/*
|
||||||
|
* If first time through for current result relation, set up econtext's
|
||||||
|
* range table to refer to result rel, and build expression nodetrees
|
||||||
|
* for rel's constraint expressions. All this stuff is kept in
|
||||||
|
* TransactionCommandContext so it will still be here next time through.
|
||||||
|
*
|
||||||
|
* NOTE: if there are multiple result relations (eg, due to inheritance)
|
||||||
|
* then we leak storage for prior rel's expressions and rangetable.
|
||||||
|
* This should not be a big problem as long as result rels are processed
|
||||||
|
* sequentially within a command.
|
||||||
|
*/
|
||||||
|
if (econtext->ecxt_range_table == NIL ||
|
||||||
|
getrelid(1, econtext->ecxt_range_table) != RelationGetRelid(rel))
|
||||||
|
{
|
||||||
|
RangeTblEntry *rte = makeNode(RangeTblEntry);
|
||||||
|
|
||||||
|
rte->relname = RelationGetRelationName(rel);
|
||||||
|
rte->ref = makeNode(Attr);
|
||||||
|
rte->ref->relname = rte->relname;
|
||||||
|
rte->relid = RelationGetRelid(rel);
|
||||||
|
/* inh, inFromCl, inJoinSet, skipAcl won't be used, leave them zero */
|
||||||
|
|
||||||
|
/* Set up single-entry range table */
|
||||||
|
econtext->ecxt_range_table = lcons(rte, NIL);
|
||||||
|
|
||||||
estate->es_result_relation_constraints =
|
estate->es_result_relation_constraints =
|
||||||
(List **) palloc(ncheck * sizeof(List *));
|
(List **) palloc(ncheck * sizeof(List *));
|
||||||
@ -1691,10 +1627,15 @@ ExecRelCheck(Relation rel, HeapTuple tuple, EState *estate)
|
|||||||
qual = (List *) stringToNode(check[i].ccbin);
|
qual = (List *) stringToNode(check[i].ccbin);
|
||||||
estate->es_result_relation_constraints[i] = qual;
|
estate->es_result_relation_constraints[i] = qual;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryContextSwitchTo(oldContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Done with building long-lived items */
|
||||||
|
MemoryContextSwitchTo(oldContext);
|
||||||
|
|
||||||
|
/* Arrange for econtext's scan tuple to be the tuple under test */
|
||||||
|
econtext->ecxt_scantuple = slot;
|
||||||
|
|
||||||
|
/* And evaluate the constraints */
|
||||||
for (i = 0; i < ncheck; i++)
|
for (i = 0; i < ncheck; i++)
|
||||||
{
|
{
|
||||||
qual = estate->es_result_relation_constraints[i];
|
qual = estate->es_result_relation_constraints[i];
|
||||||
@ -1708,25 +1649,25 @@ ExecRelCheck(Relation rel, HeapTuple tuple, EState *estate)
|
|||||||
return check[i].ccname;
|
return check[i].ccname;
|
||||||
}
|
}
|
||||||
|
|
||||||
pfree(slot);
|
/* NULL result means no error */
|
||||||
pfree(rte);
|
|
||||||
pfree(rtlist);
|
|
||||||
|
|
||||||
FreeExprContext(econtext);
|
|
||||||
|
|
||||||
return (char *) NULL;
|
return (char *) NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ExecConstraints(char *caller, Relation rel, HeapTuple tuple, EState *estate)
|
ExecConstraints(char *caller, Relation rel,
|
||||||
|
TupleTableSlot *slot, EState *estate)
|
||||||
{
|
{
|
||||||
Assert(rel->rd_att->constr);
|
HeapTuple tuple = slot->val;
|
||||||
|
TupleConstr *constr = rel->rd_att->constr;
|
||||||
|
|
||||||
if (rel->rd_att->constr->has_not_null)
|
Assert(constr);
|
||||||
|
|
||||||
|
if (constr->has_not_null)
|
||||||
{
|
{
|
||||||
|
int natts = rel->rd_att->natts;
|
||||||
int attrChk;
|
int attrChk;
|
||||||
|
|
||||||
for (attrChk = 1; attrChk <= rel->rd_att->natts; attrChk++)
|
for (attrChk = 1; attrChk <= natts; attrChk++)
|
||||||
{
|
{
|
||||||
if (rel->rd_att->attrs[attrChk-1]->attnotnull &&
|
if (rel->rd_att->attrs[attrChk-1]->attnotnull &&
|
||||||
heap_attisnull(tuple, attrChk))
|
heap_attisnull(tuple, attrChk))
|
||||||
@ -1735,11 +1676,11 @@ ExecConstraints(char *caller, Relation rel, HeapTuple tuple, EState *estate)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rel->rd_att->constr->num_check > 0)
|
if (constr->num_check > 0)
|
||||||
{
|
{
|
||||||
char *failed;
|
char *failed;
|
||||||
|
|
||||||
if ((failed = ExecRelCheck(rel, tuple, estate)) != NULL)
|
if ((failed = ExecRelCheck(rel, slot, estate)) != NULL)
|
||||||
elog(ERROR, "%s: rejected due to CHECK constraint %s",
|
elog(ERROR, "%s: rejected due to CHECK constraint %s",
|
||||||
caller, failed);
|
caller, failed);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: executor.h,v 1.46 2000/07/12 02:37:30 tgl Exp $
|
* $Id: executor.h,v 1.47 2000/08/06 04:26:27 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -56,8 +56,8 @@ extern TupleDesc ExecutorStart(QueryDesc *queryDesc, EState *estate);
|
|||||||
extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, EState *estate,
|
extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, EState *estate,
|
||||||
int feature, Node *limoffset, Node *limcount);
|
int feature, Node *limoffset, Node *limcount);
|
||||||
extern void ExecutorEnd(QueryDesc *queryDesc, EState *estate);
|
extern void ExecutorEnd(QueryDesc *queryDesc, EState *estate);
|
||||||
extern void ExecConstraints(char *caller, Relation rel, HeapTuple tuple,
|
extern void ExecConstraints(char *caller, Relation rel,
|
||||||
EState *estate);
|
TupleTableSlot *slot, EState *estate);
|
||||||
extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
|
extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
|
||||||
ItemPointer tid);
|
ItemPointer tid);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: execnodes.h,v 1.44 2000/07/14 22:17:58 tgl Exp $
|
* $Id: execnodes.h,v 1.45 2000/08/06 04:26:29 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -215,7 +215,6 @@ typedef struct EState
|
|||||||
Snapshot es_snapshot;
|
Snapshot es_snapshot;
|
||||||
List *es_range_table;
|
List *es_range_table;
|
||||||
RelationInfo *es_result_relation_info;
|
RelationInfo *es_result_relation_info;
|
||||||
List **es_result_relation_constraints;
|
|
||||||
Relation es_into_relation_descriptor;
|
Relation es_into_relation_descriptor;
|
||||||
ParamListInfo es_param_list_info;
|
ParamListInfo es_param_list_info;
|
||||||
ParamExecData *es_param_exec_vals; /* this is for subselects */
|
ParamExecData *es_param_exec_vals; /* this is for subselects */
|
||||||
@ -224,6 +223,9 @@ typedef struct EState
|
|||||||
uint32 es_processed; /* # of tuples processed */
|
uint32 es_processed; /* # of tuples processed */
|
||||||
Oid es_lastoid; /* last oid processed (by INSERT) */
|
Oid es_lastoid; /* last oid processed (by INSERT) */
|
||||||
List *es_rowMark; /* not good place, but there is no other */
|
List *es_rowMark; /* not good place, but there is no other */
|
||||||
|
/* these two fields are storage space for ExecConstraints(): */
|
||||||
|
List **es_result_relation_constraints;
|
||||||
|
ExprContext *es_constraint_exprcontext;
|
||||||
/* Below is to re-evaluate plan qual in READ COMMITTED mode */
|
/* Below is to re-evaluate plan qual in READ COMMITTED mode */
|
||||||
struct Plan *es_origPlan;
|
struct Plan *es_origPlan;
|
||||||
Pointer es_evalPlanQual;
|
Pointer es_evalPlanQual;
|
||||||
|
Reference in New Issue
Block a user