mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
+ ExecConstraints()
This commit is contained in:
@ -26,7 +26,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.18 1997/08/22 03:12:16 vadim Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.19 1997/08/22 14:28:20 vadim Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -73,8 +73,6 @@ static void ExecDelete(TupleTableSlot *slot, ItemPointer tupleid,
|
|||||||
static void ExecReplace(TupleTableSlot *slot, ItemPointer tupleid,
|
static void ExecReplace(TupleTableSlot *slot, ItemPointer tupleid,
|
||||||
EState *estate, Query *parseTree);
|
EState *estate, Query *parseTree);
|
||||||
|
|
||||||
static HeapTuple ExecAttrDefault (Relation rel, HeapTuple tuple);
|
|
||||||
|
|
||||||
/* end of local decls */
|
/* end of local decls */
|
||||||
|
|
||||||
#ifdef QUERY_LIMIT
|
#ifdef QUERY_LIMIT
|
||||||
@ -929,33 +927,19 @@ ExecAppend(TupleTableSlot *slot,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if ( resultRelationDesc->rd_att->constr )
|
if ( resultRelationDesc->rd_att->constr )
|
||||||
{
|
|
||||||
if ( resultRelationDesc->rd_att->constr->num_defval > 0 )
|
|
||||||
{
|
{
|
||||||
HeapTuple newtuple;
|
HeapTuple newtuple;
|
||||||
|
|
||||||
newtuple = ExecAttrDefault (resultRelationDesc, tuple);
|
newtuple = ExecConstraints ("ExecAppend", resultRelationDesc, tuple);
|
||||||
|
|
||||||
if ( newtuple != tuple )
|
if ( newtuple != tuple ) /* modified by DEFAULT */
|
||||||
{
|
{
|
||||||
Assert ( slot->ttc_shouldFree );
|
Assert ( slot->ttc_shouldFree );
|
||||||
|
pfree (tuple);
|
||||||
slot->val = tuple = newtuple;
|
slot->val = tuple = newtuple;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( resultRelationDesc->rd_att->constr->has_not_null )
|
|
||||||
{
|
|
||||||
int attrChk;
|
|
||||||
|
|
||||||
for (attrChk = 1; attrChk <= resultRelationDesc->rd_att->natts; attrChk++)
|
|
||||||
{
|
|
||||||
if (resultRelationDesc->rd_att->attrs[attrChk-1]->attnotnull && heap_attisnull(tuple,attrChk))
|
|
||||||
elog(WARN,"ExecAppend: Fail to add null value in not null attribute %s",
|
|
||||||
resultRelationDesc->rd_att->attrs[attrChk-1]->attname.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* insert the tuple
|
* insert the tuple
|
||||||
* ----------------
|
* ----------------
|
||||||
@ -1081,13 +1065,17 @@ ExecReplace(TupleTableSlot *slot,
|
|||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (resultRelationDesc->rd_att->constr && resultRelationDesc->rd_att->constr->has_not_null)
|
if ( resultRelationDesc->rd_att->constr )
|
||||||
{
|
{
|
||||||
int attrChk;
|
HeapTuple newtuple;
|
||||||
for (attrChk = 1; attrChk <= resultRelationDesc->rd_att->natts; attrChk++) {
|
|
||||||
if (resultRelationDesc->rd_att->attrs[attrChk-1]->attnotnull && heap_attisnull(tuple,attrChk))
|
newtuple = ExecConstraints ("ExecReplace", resultRelationDesc, tuple);
|
||||||
elog(WARN,"ExecReplace: Fail to update null value in not null attribute %s",
|
|
||||||
resultRelationDesc->rd_att->attrs[attrChk-1]->attname.data);
|
if ( newtuple != tuple ) /* modified by DEFAULT */
|
||||||
|
{
|
||||||
|
Assert ( slot->ttc_shouldFree );
|
||||||
|
pfree (tuple);
|
||||||
|
slot->val = tuple = newtuple;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1141,6 +1129,7 @@ ExecAttrDefault (Relation rel, HeapTuple tuple)
|
|||||||
int ndef = rel->rd_att->constr->num_defval;
|
int ndef = rel->rd_att->constr->num_defval;
|
||||||
AttrDefault *attrdef = rel->rd_att->constr->defval;
|
AttrDefault *attrdef = rel->rd_att->constr->defval;
|
||||||
ExprContext *econtext = makeNode (ExprContext);
|
ExprContext *econtext = makeNode (ExprContext);
|
||||||
|
HeapTuple newtuple;
|
||||||
Node *expr;
|
Node *expr;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
bool isdone;
|
bool isdone;
|
||||||
@ -1150,11 +1139,6 @@ ExecAttrDefault (Relation rel, HeapTuple tuple)
|
|||||||
char *repl = NULL;
|
char *repl = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ndef; i++)
|
|
||||||
{
|
|
||||||
if ( !heap_attisnull (tuple, attrdef[i].adnum) )
|
|
||||||
continue;
|
|
||||||
expr = (Node*) stringToNode (attrdef[i].adbin);
|
|
||||||
econtext->ecxt_scantuple = NULL; /* scan tuple slot */
|
econtext->ecxt_scantuple = NULL; /* scan tuple slot */
|
||||||
econtext->ecxt_innertuple = NULL; /* inner tuple slot */
|
econtext->ecxt_innertuple = NULL; /* inner tuple slot */
|
||||||
econtext->ecxt_outertuple = NULL; /* outer tuple slot */
|
econtext->ecxt_outertuple = NULL; /* outer tuple slot */
|
||||||
@ -1162,9 +1146,16 @@ ExecAttrDefault (Relation rel, HeapTuple tuple)
|
|||||||
econtext->ecxt_relid = 0; /* relid */
|
econtext->ecxt_relid = 0; /* relid */
|
||||||
econtext->ecxt_param_list_info = NULL; /* param list info */
|
econtext->ecxt_param_list_info = NULL; /* param list info */
|
||||||
econtext->ecxt_range_table = NULL; /* range table */
|
econtext->ecxt_range_table = NULL; /* range table */
|
||||||
|
for (i = 0; i < ndef; i++)
|
||||||
|
{
|
||||||
|
if ( !heap_attisnull (tuple, attrdef[i].adnum) )
|
||||||
|
continue;
|
||||||
|
expr = (Node*) stringToNode (attrdef[i].adbin);
|
||||||
|
|
||||||
val = ExecEvalExpr (expr, econtext, &isnull, &isdone);
|
val = ExecEvalExpr (expr, econtext, &isnull, &isdone);
|
||||||
|
|
||||||
|
pfree (expr);
|
||||||
|
|
||||||
if ( isnull )
|
if ( isnull )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1182,9 +1173,108 @@ ExecAttrDefault (Relation rel, HeapTuple tuple)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pfree (econtext);
|
||||||
|
|
||||||
if ( repl == NULL )
|
if ( repl == NULL )
|
||||||
return (tuple);
|
return (tuple);
|
||||||
|
|
||||||
return (heap_modifytuple (tuple, InvalidBuffer, rel, replValue, replNull, repl));
|
newtuple = heap_modifytuple (tuple, InvalidBuffer, rel, replValue, replNull, repl);
|
||||||
|
|
||||||
|
pfree (repl);
|
||||||
|
pfree (replNull);
|
||||||
|
pfree (replValue);
|
||||||
|
|
||||||
|
return (newtuple);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ExecRelCheck (Relation rel, HeapTuple tuple)
|
||||||
|
{
|
||||||
|
int ncheck = rel->rd_att->constr->num_check;
|
||||||
|
ConstrCheck *check = rel->rd_att->constr->check;
|
||||||
|
ExprContext *econtext = makeNode (ExprContext);
|
||||||
|
TupleTableSlot *slot = makeNode (TupleTableSlot);
|
||||||
|
RangeTblEntry *rte = makeNode (RangeTblEntry);
|
||||||
|
List *rtlist;
|
||||||
|
List *qual;
|
||||||
|
bool res;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
slot->val = tuple;
|
||||||
|
slot->ttc_shouldFree = false;
|
||||||
|
slot->ttc_descIsNew = true;
|
||||||
|
slot->ttc_tupleDescriptor = rel->rd_att;
|
||||||
|
slot->ttc_buffer = InvalidBuffer;
|
||||||
|
slot->ttc_whichplan = -1;
|
||||||
|
rte->relname = nameout (&(rel->rd_rel->relname));
|
||||||
|
rte->timeRange = NULL;
|
||||||
|
rte->refname = rte->relname;
|
||||||
|
rte->relid = rel->rd_id;
|
||||||
|
rte->inh = false;
|
||||||
|
rte->archive = false;
|
||||||
|
rte->inFromCl = true;
|
||||||
|
rte->timeQual = NULL;
|
||||||
|
rtlist = lcons (rte, NIL);
|
||||||
|
econtext->ecxt_scantuple = slot; /* scan tuple slot */
|
||||||
|
econtext->ecxt_innertuple = NULL; /* inner tuple slot */
|
||||||
|
econtext->ecxt_outertuple = NULL; /* outer tuple slot */
|
||||||
|
econtext->ecxt_relation = rel; /* relation */
|
||||||
|
econtext->ecxt_relid = 0; /* relid */
|
||||||
|
econtext->ecxt_param_list_info = NULL; /* param list info */
|
||||||
|
econtext->ecxt_range_table = rtlist; /* range table */
|
||||||
|
|
||||||
|
for (i = 0; i < ncheck; i++)
|
||||||
|
{
|
||||||
|
qual = (List*) stringToNode (check[i].ccbin);
|
||||||
|
|
||||||
|
res = ExecQual (qual, econtext);
|
||||||
|
|
||||||
|
pfree (qual);
|
||||||
|
|
||||||
|
if ( !res )
|
||||||
|
return (check[i].ccname);
|
||||||
|
}
|
||||||
|
|
||||||
|
pfree (slot);
|
||||||
|
pfree (rte->relname);
|
||||||
|
pfree (rte);
|
||||||
|
pfree (rtlist);
|
||||||
|
pfree (econtext);
|
||||||
|
|
||||||
|
return ((char *) NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapTuple
|
||||||
|
ExecConstraints (char *caller, Relation rel, HeapTuple tuple)
|
||||||
|
{
|
||||||
|
HeapTuple newtuple = tuple;
|
||||||
|
|
||||||
|
Assert ( rel->rd_att->constr );
|
||||||
|
|
||||||
|
if ( rel->rd_att->constr->num_defval > 0 )
|
||||||
|
newtuple = tuple = ExecAttrDefault (rel, tuple);
|
||||||
|
|
||||||
|
if ( rel->rd_att->constr->has_not_null )
|
||||||
|
{
|
||||||
|
int attrChk;
|
||||||
|
|
||||||
|
for (attrChk = 1; attrChk <= rel->rd_att->natts; attrChk++)
|
||||||
|
{
|
||||||
|
if (rel->rd_att->attrs[attrChk-1]->attnotnull && heap_attisnull (tuple,attrChk))
|
||||||
|
elog(WARN,"%s: Fail to add null value in not null attribute %s",
|
||||||
|
caller, rel->rd_att->attrs[attrChk-1]->attname.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rel->rd_att->constr->num_check > 0 )
|
||||||
|
{
|
||||||
|
char *failed;
|
||||||
|
|
||||||
|
if ( ( failed = ExecRelCheck (rel, tuple) ) != NULL )
|
||||||
|
elog(WARN,"%s: rejected due to CHECK constraint %s", caller, failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (newtuple);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user