Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8ae2313

Browse files
committed
Clean up inefficiency in ExecRelCheck, and cause it to do the right
thing when there are multiple result relations. Formerly, duringsomething like 'UPDATE foo*', foo's constraints and *only* foo'sconstraints would be applied to all foo's children. Wrong-o ...
1 parent925418d commit8ae2313

File tree

4 files changed

+79
-138
lines changed

4 files changed

+79
-138
lines changed

‎src/backend/commands/copy.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.119 2000/07/14 22:17:42 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.120 2000/08/06 04:26:40 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -827,9 +827,10 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
827827
* Check the constraints of the tuple
828828
* ----------------
829829
*/
830+
ExecStoreTuple(tuple,slot,InvalidBuffer, false);
830831

831832
if (rel->rd_att->constr)
832-
ExecConstraints("CopyFrom",rel,tuple,estate);
833+
ExecConstraints("CopyFrom",rel,slot,estate);
833834

834835
/* ----------------
835836
* OK, store the tuple and create index entries for it
@@ -838,10 +839,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
838839
heap_insert(rel,tuple);
839840

840841
if (relationInfo->ri_NumIndices>0)
841-
{
842-
ExecStoreTuple(tuple,slot,InvalidBuffer, false);
843842
ExecInsertIndexTuples(slot,&(tuple->t_self),estate, false);
844-
}
845843

846844
/* AFTER ROW INSERT Triggers */
847845
if (rel->trigdesc&&

‎src/backend/executor/execMain.c

Lines changed: 69 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
*
2828
*
2929
* IDENTIFICATION
30-
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.122 2000/07/12 02:37:00 tgl Exp $
30+
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.123 2000/08/06 04:26:26 tgl Exp $
3131
*
3232
*-------------------------------------------------------------------------
3333
*/
@@ -1296,10 +1296,6 @@ ExecAppend(TupleTableSlot *slot,
12961296
resultRelationInfo=estate->es_result_relation_info;
12971297
resultRelationDesc=resultRelationInfo->ri_RelationDesc;
12981298

1299-
/*
1300-
* have to add code to preform unique checking here. cim -12/1/89
1301-
*/
1302-
13031299
/* BEFORE ROW INSERT Triggers */
13041300
if (resultRelationDesc->trigdesc&&
13051301
resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_INSERT]>0)
@@ -1320,18 +1316,20 @@ ExecAppend(TupleTableSlot *slot,
13201316
}
13211317

13221318
/*
1323-
* Check the constraints ofa tuple
1319+
* Check the constraints ofthe tuple
13241320
*/
13251321

13261322
if (resultRelationDesc->rd_att->constr)
1327-
ExecConstraints("ExecAppend",resultRelationDesc,tuple,estate);
1323+
ExecConstraints("ExecAppend",resultRelationDesc,slot,estate);
13281324

13291325
/*
13301326
* insert the tuple
13311327
*/
1332-
newId=heap_insert(resultRelationDesc,/* relation desc */
1333-
tuple);/* heap tuple */
1328+
newId=heap_insert(resultRelationDesc,tuple);
1329+
13341330
IncrAppended();
1331+
(estate->es_processed)++;
1332+
estate->es_lastoid=newId;
13351333

13361334
/*
13371335
* process indices
@@ -1343,8 +1341,6 @@ ExecAppend(TupleTableSlot *slot,
13431341
numIndices=resultRelationInfo->ri_NumIndices;
13441342
if (numIndices>0)
13451343
ExecInsertIndexTuples(slot,&(tuple->t_self),estate, false);
1346-
(estate->es_processed)++;
1347-
estate->es_lastoid=newId;
13481344

13491345
/* AFTER ROW INSERT Triggers */
13501346
if (resultRelationDesc->trigdesc)
@@ -1466,7 +1462,7 @@ ExecReplace(TupleTableSlot *slot,
14661462
*/
14671463
if (IsBootstrapProcessingMode())
14681464
{
1469-
elog(DEBUG,"ExecReplace: replace can't run without transactions");
1465+
elog(NOTICE,"ExecReplace: replace can't run without transactions");
14701466
return;
14711467
}
14721468

@@ -1481,12 +1477,6 @@ ExecReplace(TupleTableSlot *slot,
14811477
resultRelationInfo=estate->es_result_relation_info;
14821478
resultRelationDesc=resultRelationInfo->ri_RelationDesc;
14831479

1484-
/*
1485-
* have to add code to preform unique checking here. in the event of
1486-
* unique tuples, this becomes a deletion of the original tuple
1487-
* affected by the replace. cim -12/1/89
1488-
*/
1489-
14901480
/* BEFORE ROW UPDATE Triggers */
14911481
if (resultRelationDesc->trigdesc&&
14921482
resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE]>0)
@@ -1507,11 +1497,11 @@ ExecReplace(TupleTableSlot *slot,
15071497
}
15081498

15091499
/*
1510-
* Check the constraints ofa tuple
1500+
* Check the constraints ofthe tuple
15111501
*/
15121502

15131503
if (resultRelationDesc->rd_att->constr)
1514-
ExecConstraints("ExecReplace",resultRelationDesc,tuple,estate);
1504+
ExecConstraints("ExecReplace",resultRelationDesc,slot,estate);
15151505

15161506
/*
15171507
* replace the heap tuple
@@ -1555,9 +1545,9 @@ lreplace:;
15551545
/*
15561546
* Note: instead of having to update the old index tuples associated
15571547
* with the heap tuple, all we do is form and insert new index
1558-
* tuples.. This is because replaces are actually deletes and inserts
1559-
* and index tuple deletion is done automagically by thevaccuum
1560-
*deamon.. All we do is insert new index tuples. -cim 9/27/89
1548+
* tuples. This is because replaces are actually deletes and inserts
1549+
* and index tuple deletion is done automagically by thevacuum
1550+
*daemon. All we do is insert new index tuples. -cim 9/27/89
15611551
*/
15621552

15631553
/*
@@ -1579,109 +1569,55 @@ lreplace:;
15791569
ExecARUpdateTriggers(estate,tupleid,tuple);
15801570
}
15811571

1582-
#ifdefNOT_USED
1583-
staticHeapTuple
1584-
ExecAttrDefault(Relationrel,HeapTupletuple)
1585-
{
1586-
intndef=rel->rd_att->constr->num_defval;
1587-
AttrDefault*attrdef=rel->rd_att->constr->defval;
1588-
ExprContext*econtext=MakeExprContext(NULL,CurrentMemoryContext);
1589-
HeapTuplenewtuple;
1590-
Node*expr;
1591-
boolisnull;
1592-
boolisdone;
1593-
Datumval;
1594-
Datum*replValue=NULL;
1595-
char*replNull=NULL;
1596-
char*repl=NULL;
1597-
inti;
1598-
1599-
for (i=0;i<ndef;i++)
1600-
{
1601-
if (!heap_attisnull(tuple,attrdef[i].adnum))
1602-
continue;
1603-
expr= (Node*)stringToNode(attrdef[i].adbin);
1604-
1605-
val=ExecEvalExprSwitchContext(expr,econtext,&isnull,&isdone);
1606-
1607-
if (isnull)
1608-
continue;
1609-
1610-
if (repl==NULL)
1611-
{
1612-
repl= (char*)palloc(rel->rd_att->natts*sizeof(char));
1613-
replNull= (char*)palloc(rel->rd_att->natts*sizeof(char));
1614-
replValue= (Datum*)palloc(rel->rd_att->natts*sizeof(Datum));
1615-
MemSet(repl,' ',rel->rd_att->natts*sizeof(char));
1616-
}
1617-
1618-
repl[attrdef[i].adnum-1]='r';
1619-
replNull[attrdef[i].adnum-1]=' ';
1620-
replValue[attrdef[i].adnum-1]=val;
1621-
1622-
}
1623-
1624-
if (repl==NULL)
1625-
{
1626-
/* no changes needed */
1627-
newtuple=tuple;
1628-
}
1629-
else
1630-
{
1631-
newtuple=heap_modifytuple(tuple,rel,replValue,replNull,repl);
1632-
1633-
pfree(repl);
1634-
pfree(replNull);
1635-
pfree(replValue);
1636-
heap_freetuple(tuple);
1637-
}
1638-
1639-
FreeMemoryContext(econtext);
1640-
1641-
returnnewtuple;
1642-
}
1643-
1644-
#endif
1645-
16461572
staticchar*
1647-
ExecRelCheck(Relationrel,HeapTupletuple,EState*estate)
1573+
ExecRelCheck(Relationrel,TupleTableSlot*slot,EState*estate)
16481574
{
16491575
intncheck=rel->rd_att->constr->num_check;
16501576
ConstrCheck*check=rel->rd_att->constr->check;
1651-
TupleTableSlot*slot=makeNode(TupleTableSlot);
1652-
RangeTblEntry*rte=makeNode(RangeTblEntry);
1653-
ExprContext*econtext=MakeExprContext(slot,
1654-
TransactionCommandContext);
1655-
List*rtlist;
1577+
MemoryContextoldContext;
1578+
ExprContext*econtext;
16561579
List*qual;
16571580
inti;
16581581

1659-
slot->val=tuple;
1660-
slot->ttc_shouldFree= false;
1661-
slot->ttc_descIsNew= true;
1662-
slot->ttc_tupleDescriptor=rel->rd_att;
1663-
slot->ttc_buffer=InvalidBuffer;
1664-
slot->ttc_whichplan=-1;
1665-
rte->relname=RelationGetRelationName(rel);
1666-
rte->ref=makeNode(Attr);
1667-
rte->ref->relname=rte->relname;
1668-
rte->relid=RelationGetRelid(rel);
1669-
/* inh, inFromCl, inJoinSet, skipAcl won't be used, leave them zero */
1670-
rtlist=lcons(rte,NIL);
1671-
econtext->ecxt_range_table=rtlist;/* phony range table */
1582+
/*
1583+
* Make sure econtext, expressions, etc are placed in appropriate context.
1584+
*/
1585+
oldContext=MemoryContextSwitchTo(TransactionCommandContext);
1586+
1587+
/*
1588+
* Create or reset the exprcontext for evaluating constraint expressions.
1589+
*/
1590+
econtext=estate->es_constraint_exprcontext;
1591+
if (econtext==NULL)
1592+
estate->es_constraint_exprcontext=econtext=
1593+
MakeExprContext(NULL,TransactionCommandContext);
1594+
else
1595+
ResetExprContext(econtext);
16721596

16731597
/*
1674-
* Save the de-stringized constraint expressions in command-level
1675-
* memory context. XXX should build the above stuff there too,
1676-
* instead of doing it over for each tuple.
1677-
* XXX Is it sufficient to have just one es_result_relation_constraints
1678-
* in an inherited insert/update?
1598+
* If first time through for current result relation, set up econtext's
1599+
* range table to refer to result rel, and build expression nodetrees
1600+
* for rel's constraint expressions. All this stuff is kept in
1601+
* TransactionCommandContext so it will still be here next time through.
1602+
*
1603+
* NOTE: if there are multiple result relations (eg, due to inheritance)
1604+
* then we leak storage for prior rel's expressions and rangetable.
1605+
* This should not be a big problem as long as result rels are processed
1606+
* sequentially within a command.
16791607
*/
1680-
if (estate->es_result_relation_constraints==NULL)
1608+
if (econtext->ecxt_range_table==NIL||
1609+
getrelid(1,econtext->ecxt_range_table)!=RelationGetRelid(rel))
16811610
{
1682-
MemoryContextoldContext;
1611+
RangeTblEntry*rte=makeNode(RangeTblEntry);
1612+
1613+
rte->relname=RelationGetRelationName(rel);
1614+
rte->ref=makeNode(Attr);
1615+
rte->ref->relname=rte->relname;
1616+
rte->relid=RelationGetRelid(rel);
1617+
/* inh, inFromCl, inJoinSet, skipAcl won't be used, leave them zero */
16831618

1684-
oldContext=MemoryContextSwitchTo(TransactionCommandContext);
1619+
/* Set up single-entry range table */
1620+
econtext->ecxt_range_table=lcons(rte,NIL);
16851621

16861622
estate->es_result_relation_constraints=
16871623
(List**)palloc(ncheck*sizeof(List*));
@@ -1691,10 +1627,15 @@ ExecRelCheck(Relation rel, HeapTuple tuple, EState *estate)
16911627
qual= (List*)stringToNode(check[i].ccbin);
16921628
estate->es_result_relation_constraints[i]=qual;
16931629
}
1694-
1695-
MemoryContextSwitchTo(oldContext);
16961630
}
16971631

1632+
/* Done with building long-lived items */
1633+
MemoryContextSwitchTo(oldContext);
1634+
1635+
/* Arrange for econtext's scan tuple to be the tuple under test */
1636+
econtext->ecxt_scantuple=slot;
1637+
1638+
/* And evaluate the constraints */
16981639
for (i=0;i<ncheck;i++)
16991640
{
17001641
qual=estate->es_result_relation_constraints[i];
@@ -1708,25 +1649,25 @@ ExecRelCheck(Relation rel, HeapTuple tuple, EState *estate)
17081649
returncheck[i].ccname;
17091650
}
17101651

1711-
pfree(slot);
1712-
pfree(rte);
1713-
pfree(rtlist);
1714-
1715-
FreeExprContext(econtext);
1716-
1652+
/* NULL result means no error */
17171653
return (char*)NULL;
17181654
}
17191655

17201656
void
1721-
ExecConstraints(char*caller,Relationrel,HeapTupletuple,EState*estate)
1657+
ExecConstraints(char*caller,Relationrel,
1658+
TupleTableSlot*slot,EState*estate)
17221659
{
1723-
Assert(rel->rd_att->constr);
1660+
HeapTupletuple=slot->val;
1661+
TupleConstr*constr=rel->rd_att->constr;
1662+
1663+
Assert(constr);
17241664

1725-
if (rel->rd_att->constr->has_not_null)
1665+
if (constr->has_not_null)
17261666
{
1667+
intnatts=rel->rd_att->natts;
17271668
intattrChk;
17281669

1729-
for (attrChk=1;attrChk <=rel->rd_att->natts;attrChk++)
1670+
for (attrChk=1;attrChk <=natts;attrChk++)
17301671
{
17311672
if (rel->rd_att->attrs[attrChk-1]->attnotnull&&
17321673
heap_attisnull(tuple,attrChk))
@@ -1735,11 +1676,11 @@ ExecConstraints(char *caller, Relation rel, HeapTuple tuple, EState *estate)
17351676
}
17361677
}
17371678

1738-
if (rel->rd_att->constr->num_check>0)
1679+
if (constr->num_check>0)
17391680
{
17401681
char*failed;
17411682

1742-
if ((failed=ExecRelCheck(rel,tuple,estate))!=NULL)
1683+
if ((failed=ExecRelCheck(rel,slot,estate))!=NULL)
17431684
elog(ERROR,"%s: rejected due to CHECK constraint %s",
17441685
caller,failed);
17451686
}

‎src/include/executor/executor.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: executor.h,v 1.46 2000/07/12 02:37:30 tgl Exp $
10+
* $Id: executor.h,v 1.47 2000/08/06 04:26:27 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -56,8 +56,8 @@ extern TupleDesc ExecutorStart(QueryDesc *queryDesc, EState *estate);
5656
externTupleTableSlot*ExecutorRun(QueryDesc*queryDesc,EState*estate,
5757
intfeature,Node*limoffset,Node*limcount);
5858
externvoidExecutorEnd(QueryDesc*queryDesc,EState*estate);
59-
externvoidExecConstraints(char*caller,Relationrel,HeapTupletuple,
60-
EState*estate);
59+
externvoidExecConstraints(char*caller,Relationrel,
60+
TupleTableSlot*slot,EState*estate);
6161
externTupleTableSlot*EvalPlanQual(EState*estate,Indexrti,
6262
ItemPointertid);
6363

‎src/include/nodes/execnodes.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: execnodes.h,v 1.44 2000/07/14 22:17:58 tgl Exp $
10+
* $Id: execnodes.h,v 1.45 2000/08/06 04:26:29 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -215,7 +215,6 @@ typedef struct EState
215215
Snapshotes_snapshot;
216216
List*es_range_table;
217217
RelationInfo*es_result_relation_info;
218-
List**es_result_relation_constraints;
219218
Relationes_into_relation_descriptor;
220219
ParamListInfoes_param_list_info;
221220
ParamExecData*es_param_exec_vals;/* this is for subselects */
@@ -224,6 +223,9 @@ typedef struct EState
224223
uint32es_processed;/* # of tuples processed */
225224
Oides_lastoid;/* last oid processed (by INSERT) */
226225
List*es_rowMark;/* not good place, but there is no other */
226+
/* these two fields are storage space for ExecConstraints(): */
227+
List**es_result_relation_constraints;
228+
ExprContext*es_constraint_exprcontext;
227229
/* Below is to re-evaluate plan qual in READ COMMITTED mode */
228230
structPlan*es_origPlan;
229231
Pointeres_evalPlanQual;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp