mirror of
https://github.com/postgres/postgres.git
synced 2026-04-15 22:10:45 -04:00
Changed ExecConstraints() and ExecRelCheck() to cache constraint
qualification trees in the execution state to avoid memory exhaustion on INSERT, UPDATE and COPY to tables with check constraints. This also speeds up those operations substantial because the nodeToString() for the constraints ccbin is only performed once per query. Jan
This commit is contained in:
parent
ccf330d67e
commit
cff91fedff
4 changed files with 29 additions and 14 deletions
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.63 1998/10/26 00:59:21 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.63.2.1 1999/02/07 16:50:51 wieck Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
@ -402,6 +402,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
|
|||
Node **indexPred = NULL;
|
||||
TupleDesc rtupdesc;
|
||||
ExprContext *econtext = NULL;
|
||||
EState *estate = makeNode(EState);
|
||||
|
||||
#ifndef OMIT_PARTIAL_INDEX
|
||||
TupleTable tupleTable;
|
||||
|
|
@ -709,7 +710,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
|
|||
{
|
||||
HeapTuple newtuple;
|
||||
|
||||
newtuple = ExecConstraints("CopyFrom", rel, tuple);
|
||||
newtuple = ExecConstraints("CopyFrom", rel, tuple, estate);
|
||||
|
||||
if (newtuple != tuple)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.58 1998/10/14 05:10:00 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.58.2.1 1999/02/07 16:50:52 wieck Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
@ -965,7 +965,8 @@ ExecAppend(TupleTableSlot *slot,
|
|||
{
|
||||
HeapTuple newtuple;
|
||||
|
||||
newtuple = ExecConstraints("ExecAppend", resultRelationDesc, tuple);
|
||||
newtuple = ExecConstraints("ExecAppend", resultRelationDesc,
|
||||
tuple, estate);
|
||||
|
||||
if (newtuple != tuple) /* modified by DEFAULT */
|
||||
{
|
||||
|
|
@ -1148,7 +1149,8 @@ ExecReplace(TupleTableSlot *slot,
|
|||
{
|
||||
HeapTuple newtuple;
|
||||
|
||||
newtuple = ExecConstraints("ExecReplace", resultRelationDesc, tuple);
|
||||
newtuple = ExecConstraints("ExecReplace", resultRelationDesc,
|
||||
tuple, estate);
|
||||
|
||||
if (newtuple != tuple) /* modified by DEFAULT */
|
||||
{
|
||||
|
|
@ -1279,7 +1281,7 @@ ExecAttrDefault(Relation rel, HeapTuple tuple)
|
|||
#endif
|
||||
|
||||
static char *
|
||||
ExecRelCheck(Relation rel, HeapTuple tuple)
|
||||
ExecRelCheck(Relation rel, HeapTuple tuple, EState *estate)
|
||||
{
|
||||
int ncheck = rel->rd_att->constr->num_check;
|
||||
ConstrCheck *check = rel->rd_att->constr->check;
|
||||
|
|
@ -1312,14 +1314,24 @@ ExecRelCheck(Relation rel, HeapTuple tuple)
|
|||
econtext->ecxt_param_exec_vals = NULL; /* exec param values */
|
||||
econtext->ecxt_range_table = rtlist; /* range table */
|
||||
|
||||
if (estate->es_result_relation_constraints == NULL)
|
||||
{
|
||||
estate->es_result_relation_constraints =
|
||||
(List **)palloc(ncheck * sizeof(List *));
|
||||
|
||||
for (i = 0; i < ncheck; i++)
|
||||
{
|
||||
qual = (List *) stringToNode(check[i].ccbin);
|
||||
estate->es_result_relation_constraints[i] = qual;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ncheck; i++)
|
||||
{
|
||||
qual = (List *) stringToNode(check[i].ccbin);
|
||||
qual = estate->es_result_relation_constraints[i];
|
||||
|
||||
res = ExecQual(qual, econtext);
|
||||
|
||||
pfree(qual);
|
||||
|
||||
if (!res)
|
||||
return check[i].ccname;
|
||||
}
|
||||
|
|
@ -1335,7 +1347,7 @@ ExecRelCheck(Relation rel, HeapTuple tuple)
|
|||
}
|
||||
|
||||
HeapTuple
|
||||
ExecConstraints(char *caller, Relation rel, HeapTuple tuple)
|
||||
ExecConstraints(char *caller, Relation rel, HeapTuple tuple, EState *estate)
|
||||
{
|
||||
HeapTuple newtuple = tuple;
|
||||
|
||||
|
|
@ -1362,7 +1374,7 @@ ExecConstraints(char *caller, Relation rel, HeapTuple tuple)
|
|||
{
|
||||
char *failed;
|
||||
|
||||
if ((failed = ExecRelCheck(rel, tuple)) != NULL)
|
||||
if ((failed = ExecRelCheck(rel, tuple, estate)) != NULL)
|
||||
elog(ERROR, "%s: rejected due to CHECK constraint %s", caller, failed);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: executor.h,v 1.27 1998/10/14 05:10:05 momjian Exp $
|
||||
* $Id: executor.h,v 1.27.2.1 1999/02/07 16:50:54 wieck Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
@ -85,7 +85,8 @@ extern HeapTuple ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot);
|
|||
extern TupleDesc ExecutorStart(QueryDesc *queryDesc, EState *estate);
|
||||
extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count);
|
||||
extern void ExecutorEnd(QueryDesc *queryDesc, EState *estate);
|
||||
extern HeapTuple ExecConstraints(char *caller, Relation rel, HeapTuple tuple);
|
||||
extern HeapTuple ExecConstraints(char *caller, Relation rel, HeapTuple tuple,
|
||||
EState *estate);
|
||||
#ifdef QUERY_LIMIT
|
||||
extern int ExecutorLimit(int limit);
|
||||
extern int ExecutorGetLimit(void);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: execnodes.h,v 1.18 1998/09/01 04:36:35 momjian Exp $
|
||||
* $Id: execnodes.h,v 1.18.2.1 1999/02/07 16:50:55 wieck Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
@ -199,6 +199,7 @@ typedef struct EState
|
|||
Snapshot es_snapshot;
|
||||
List *es_range_table;
|
||||
RelationInfo *es_result_relation_info;
|
||||
List **es_result_relation_constraints;
|
||||
Relation es_into_relation_descriptor;
|
||||
ParamListInfo es_param_list_info;
|
||||
ParamExecData *es_param_exec_vals; /* this is for subselects */
|
||||
|
|
|
|||
Loading…
Reference in a new issue