diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2002-12-12 20:35:16 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2002-12-12 20:35:16 +0000 |
commit | b0422b215c100bb29c1071872012a1f3c6681058 (patch) | |
tree | a764deb63dc546abe6c0b283feac110fd22d01c4 /src | |
parent | ff7349694f399d0063b51419ea6e25770334f363 (diff) | |
download | postgresql-b0422b215c100bb29c1071872012a1f3c6681058.tar.gz postgresql-b0422b215c100bb29c1071872012a1f3c6681058.zip |
Preliminary code review for domain CHECK constraints patch: add documentation,
make VALUE a non-reserved word again, use less invasive method of passing
ConstraintTestValue into transformExpr, fix problems with nested constraint
testing, do correct thing with NULL result from a constraint expression,
remove memory leak. Domain checks still need much more work if we are going
to allow ALTER DOMAIN, however.
Diffstat (limited to 'src')
26 files changed, 199 insertions, 289 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index bd068271acd..424684d74d7 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.236 2002/12/12 15:49:23 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.237 2002/12/12 20:35:08 tgl Exp $ * * * INTERFACE ROUTINES @@ -1567,7 +1567,7 @@ AddRelationRawConstraints(Relation rel, /* * Transform raw parsetree to executable expression. */ - expr = transformExpr(pstate, cdef->raw_expr, NULL); + expr = transformExpr(pstate, cdef->raw_expr); /* * Make sure it yields a boolean result. @@ -1691,7 +1691,7 @@ cookDefault(ParseState *pstate, /* * Transform raw parsetree to executable expression. */ - expr = transformExpr(pstate, raw_default, NULL); + expr = transformExpr(pstate, raw_default); /* * Make sure default expr does not refer to any vars. diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 8c274caf3b7..e724034969c 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.11 2002/12/06 05:00:10 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.12 2002/12/12 20:35:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -439,18 +439,16 @@ RemoveConstraintById(Oid conId) con = (Form_pg_constraint) GETSTRUCT(tup); /* - * If the constraint is for a relation, open and exclusive-lock - * the relation it's for. - * - * If the constraint is for a domain, open and lock the pg_type entry - * tye constraint is used on. - * - * XXX not clear what we should lock, if anything, for assert constraints. + * Special processing depending on what the constraint is for. */ if (OidIsValid(con->conrelid)) { Relation rel; + /* + * If the constraint is for a relation, open and exclusive-lock the + * relation it's for. + */ rel = heap_open(con->conrelid, AccessExclusiveLock); /* @@ -490,34 +488,14 @@ RemoveConstraintById(Oid conId) /* Keep lock on constraint's rel until end of xact */ heap_close(rel, NoLock); } - /* Lock the domain row in pg_type */ else if (OidIsValid(con->contypid)) { - Relation typRel; - HeapTuple typTup; - ScanKeyData typKey[1]; - SysScanDesc typScan; - int nkeys = 0; - - typRel = heap_openr(TypeRelationName, RowExclusiveLock); - - ScanKeyEntryInitialize(&typKey[nkeys++], 0x0, - ObjectIdAttributeNumber, F_OIDEQ, - ObjectIdGetDatum(con->contypid)); - - typScan = systable_beginscan(typRel, TypeOidIndex, true, - SnapshotNow, nkeys, typKey); - - typTup = systable_getnext(typScan); - - if (!HeapTupleIsValid(typTup)) - elog(ERROR, "RemoveConstraintById: Type %d does not exist", - con->contypid); - - systable_endscan(typScan); - - /* Keep lock on domain type until end of xact */ - heap_close(typRel, NoLock); + /* + * XXX for now, do nothing special when dropping a domain constraint + * + * Probably there should be some form of locking on the domain type, + * but we have no such concept at the moment. + */ } else { diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 19687737337..9f5d89a87fb 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.58 2002/12/12 15:49:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.59 2002/12/12 20:35:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2737,7 +2737,7 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr) /* * Convert the A_EXPR in raw_expr into an EXPR */ - expr = transformExpr(pstate, constr->raw_expr, NULL); + expr = transformExpr(pstate, constr->raw_expr); /* * Make sure it yields a boolean result. diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index e16942acd72..989bc36ee82 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.22 2002/12/12 15:49:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.23 2002/12/12 20:35:12 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -562,14 +562,14 @@ DefineDomain(CreateDomainStmt *stmt) break; case CONSTR_NOTNULL: - if (nullDefined) + if (nullDefined && !typNotNull) elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint"); typNotNull = true; nullDefined = true; break; case CONSTR_NULL: - if (nullDefined) + if (nullDefined && typNotNull) elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint"); typNotNull = false; nullDefined = true; @@ -644,14 +644,9 @@ DefineDomain(CreateDomainStmt *stmt) switch (constr->contype) { case CONSTR_CHECK: - { - char *junk; - - /* Returns the cooked constraint which is not needed during creation */ - junk = domainAddConstraint(domainoid, domainNamespace, - basetypeoid, stmt->typename->typmod, - constr, &counter, domainName); - } + domainAddConstraint(domainoid, domainNamespace, + basetypeoid, stmt->typename->typmod, + constr, &counter, domainName); break; /* Other constraint types were fully processed above */ @@ -1247,6 +1242,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) List *rels; List *rt; Form_pg_type typTup; + ExprContext *econtext; char *ccbin; Node *expr; int counter = 0; @@ -1261,7 +1257,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) /* Lock the type table */ rel = heap_openr(TypeRelationName, RowExclusiveLock); - /* Use LookupTypeName here so that shell types can be removed. */ + /* Use LookupTypeName here so that shell types can be found. */ domainoid = LookupTypeName(typename); if (!OidIsValid(domainoid)) elog(ERROR, "Type \"%s\" does not exist", @@ -1328,10 +1324,10 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) /* * Since all other constraint types throw errors, this must be - * a check constraint. + * a check constraint. First, process the constraint expression + * and add an entry to pg_constraint. */ - /* Returns the cooked constraint which is not needed during creation */ ccbin = domainAddConstraint(HeapTupleGetOid(tup), typTup->typnamespace, typTup->typbasetype, typTup->typtypmod, constr, &counter, NameStr(typTup->typname)); @@ -1342,61 +1338,46 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) */ expr = stringToNode(ccbin); fix_opfuncids(expr); + + /* Make an expression context for ExecQual */ + econtext = MakeExprContext(NULL, CurrentMemoryContext); + rels = get_rels_with_domain(domainoid); foreach (rt, rels) { - Relation typrel; + relToCheck *rtc = (relToCheck *) lfirst(rt); + Relation testrel; + TupleDesc tupdesc; HeapTuple tuple; HeapScanDesc scan; - TupleDesc tupdesc; - ExprContext *econtext; - TupleTableSlot *slot; - relToCheck *rtc = (relToCheck *) lfirst(rt); - - /* Lock relation */ - typrel = heap_open(rtc->relOid, ExclusiveLock); - /* Test attributes */ - tupdesc = RelationGetDescr(typrel); + /* Lock relation against changes */ + testrel = heap_open(rtc->relOid, ShareLock); - /* Make tuple slot to hold tuples */ - slot = MakeTupleTableSlot(); - ExecSetSlotDescriptor(slot, RelationGetDescr(typrel), false); - - /* Make an expression context for ExecQual */ - econtext = MakeExprContext(slot, CurrentMemoryContext); + tupdesc = RelationGetDescr(testrel); /* Scan through table */ - scan = heap_beginscan(typrel, SnapshotNow, 0, NULL); + scan = heap_beginscan(testrel, SnapshotNow, 0, NULL); while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { int i; - ExecStoreTuple(tuple, slot, InvalidBuffer, false); - /* Loop through each attribute of the tuple with a domain */ for (i = 0; i < rtc->natts; i++) { Datum d; bool isNull; Datum conResult; - ExprDoneCond isDone; d = heap_getattr(tuple, rtc->atts[i], tupdesc, &isNull); - if (isNull) - elog(ERROR, "ALTER DOMAIN: Relation \"%s\" Attribute \"%s\" " - "contains NULL values", - RelationGetRelationName(typrel), - NameStr(*attnumAttName(typrel, rtc->atts[i]))); - econtext->domainValue_datum = d; econtext->domainValue_isNull = isNull; - conResult = ExecEvalExpr(expr, econtext, &isNull, &isDone); + conResult = ExecEvalExpr(expr, econtext, &isNull, NULL); - if (!DatumGetBool(conResult)) + if (!isNull && !DatumGetBool(conResult)) elog(ERROR, "AlterDomainAddConstraint: Domain %s constraint %s failed", NameStr(typTup->typname), constr->name); } @@ -1406,13 +1387,12 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) heap_endscan(scan); - FreeExprContext(econtext); - pfree(slot); - - /* Hold type lock */ - heap_close(typrel, NoLock); + /* Hold relation lock till commit (XXX bad for concurrency) */ + heap_close(testrel, NoLock); } + FreeExprContext(econtext); + /* Clean up */ heap_close(rel, NoLock); } @@ -1524,11 +1504,12 @@ domainPermissionCheck(HeapTuple tup, TypeName *typename) /* - * domainAddConstraint + * domainAddConstraint - code shared between CREATE and ALTER DOMAIN */ -char * +static char * domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, - int typMod, Constraint *constr, int *counter, char *domainName) + int typMod, Constraint *constr, + int *counter, char *domainName) { Node *expr; char *ccsrc; @@ -1556,26 +1537,24 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, counter); /* - * Convert the A_EXPR in raw_expr into an - * EXPR + * Convert the A_EXPR in raw_expr into an EXPR */ pstate = make_parsestate(NULL); /* - * We want to have the domain VALUE node type filled in so - * that proper casting can occur. + * Set up a ConstraintTestValue to represent the occurrence of VALUE + * in the expression. Note that it will appear to have the type of the + * base type, not the domain. This seems correct since within the + * check expression, we should not assume the input value can be considered + * a member of the domain. */ domVal = makeNode(ConstraintTestValue); domVal->typeId = baseTypeOid; domVal->typeMod = typMod; - expr = transformExpr(pstate, constr->raw_expr, domVal); + pstate->p_value_substitute = (Node *) domVal; - /* - * Domains don't allow var clauses - */ - if (contain_var_clause(expr)) - elog(ERROR, "cannot use column references in domain CHECK clause"); + expr = transformExpr(pstate, constr->raw_expr); /* * Make sure it yields a boolean result. @@ -1590,6 +1569,13 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, elog(ERROR, "Relations cannot be referenced in domain CHECK constraint"); /* + * Domains don't allow var clauses (this should be redundant with the + * above check, but make it anyway) + */ + if (contain_var_clause(expr)) + elog(ERROR, "cannot use column references in domain CHECK clause"); + + /* * No subplans or aggregates, either... */ if (contain_subplans(expr)) @@ -1618,7 +1604,9 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, InvalidOid), false, false); - /* Write the constraint */ + /* + * Store the constraint in pg_constraint + */ CreateConstraintEntry(constr->name, /* Constraint Name */ domainNamespace, /* namespace */ CONSTRAINT_CHECK, /* Constraint Type */ @@ -1640,8 +1628,8 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid, ccsrc); /* Source form check constraint */ /* - * Return the constraint so the calling routine can perform any additional - * required tests. + * Return the compiled constraint expression so the calling routine can + * perform any additional required tests. */ return ccbin; } diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index d96e983fa30..79796f1c0b2 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.117 2002/12/12 15:49:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.118 2002/12/12 20:35:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -77,8 +77,7 @@ static Datum ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone); static Datum ExecEvalConstraintTestValue(ConstraintTestValue *conVal, - ExprContext *econtext, - bool *isNull, ExprDoneCond *isDone); + ExprContext *econtext, bool *isNull); /*---------- @@ -1554,23 +1553,6 @@ ExecEvalBooleanTest(BooleanTest *btest, } /* - * ExecEvalConstraintTestValue - * - * Return the value stored by constraintTest. - */ -static Datum -ExecEvalConstraintTestValue(ConstraintTestValue *conVal, ExprContext *econtext, - bool *isNull, ExprDoneCond *isDone) -{ - /* - * If the Datum hasn't been set, then it's ExecEvalConstraintTest - * hasn't been called. - */ - *isNull = econtext->domainValue_isNull; - return econtext->domainValue_datum; -} - -/* * ExecEvalConstraintTest * * Test the constraint against the data provided. If the data fits @@ -1585,6 +1567,9 @@ ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext, result = ExecEvalExpr((Node *) constraint->arg, econtext, isNull, isDone); + if (isDone && *isDone == ExprEndResult) + return result; /* nothing to check */ + switch (constraint->testtype) { case CONSTR_TEST_NOTNULL: @@ -1595,16 +1580,32 @@ ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext, case CONSTR_TEST_CHECK: { Datum conResult; + bool conIsNull; + Datum save_datum; + bool save_isNull; + + /* + * Set up value to be returned by ConstraintTestValue nodes. + * We must save and restore prior setting of econtext's + * domainValue fields, in case this node is itself within + * a check expression for another domain. + */ + save_datum = econtext->domainValue_datum; + save_isNull = econtext->domainValue_isNull; - /* Var with attnum == UnassignedAttrNum uses the result */ econtext->domainValue_datum = result; econtext->domainValue_isNull = *isNull; - conResult = ExecEvalExpr((Node *) constraint->check_expr, econtext, isNull, isDone); + conResult = ExecEvalExpr((Node *) constraint->check_expr, + econtext, &conIsNull, NULL); - if (!DatumGetBool(conResult)) + if (!conIsNull && + !DatumGetBool(conResult)) elog(ERROR, "ExecEvalConstraintTest: Domain %s constraint %s failed", constraint->domname, constraint->name); + + econtext->domainValue_datum = save_datum; + econtext->domainValue_isNull = save_isNull; } break; default: @@ -1616,6 +1617,19 @@ ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext, return result; } +/* + * ExecEvalConstraintTestValue + * + * Return the value stored by constraintTest. + */ +static Datum +ExecEvalConstraintTestValue(ConstraintTestValue *conVal, ExprContext *econtext, + bool *isNull) +{ + *isNull = econtext->domainValue_isNull; + return econtext->domainValue_datum; +} + /* ---------------------------------------------------------------- * ExecEvalFieldSelect * @@ -1811,9 +1825,8 @@ ExecEvalExpr(Node *expression, break; case T_ConstraintTestValue: retDatum = ExecEvalConstraintTestValue((ConstraintTestValue *) expression, - econtext, - isNull, - isDone); + econtext, + isNull); break; default: elog(ERROR, "ExecEvalExpr: unknown expression type %d", diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index f7aa8fcb7ec..258e1a1188c 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.230 2002/12/12 15:49:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.231 2002/12/12 20:35:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1297,14 +1297,6 @@ _copyTypeName(TypeName *from) return newnode; } -static DomainConstraintValue * -_copyDomainConstraintValue(DomainConstraintValue *from) -{ - DomainConstraintValue *newnode = makeNode(DomainConstraintValue); - - return newnode; -} - static SortGroupBy * _copySortGroupBy(SortGroupBy *from) { @@ -2763,9 +2755,6 @@ copyObject(void *from) case T_TypeCast: retval = _copyTypeCast(from); break; - case T_DomainConstraintValue: - retval = _copyDomainConstraintValue(from); - break; case T_SortGroupBy: retval = _copySortGroupBy(from); break; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 3b510382068..3fc924024e2 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -18,7 +18,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.175 2002/12/12 15:49:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.176 2002/12/12 20:35:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -649,12 +649,6 @@ _equalInsertDefault(InsertDefault *a, InsertDefault *b) } static bool -_equalDomainConstraintValue(DomainConstraintValue *a, DomainConstraintValue *b) -{ - return true; -} - -static bool _equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b) { COMPARE_STRING_FIELD(portalname); @@ -1931,9 +1925,6 @@ equal(void *a, void *b) case T_InsertDefault: retval = _equalInsertDefault(a, b); break; - case T_DomainConstraintValue: - retval = _equalDomainConstraintValue(a, b); - break; default: elog(WARNING, "equal: don't know whether nodes of type %d are equal", diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index bd44816e6fa..9ae71555095 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.187 2002/12/12 15:49:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.188 2002/12/12 20:35:12 tgl Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -1300,12 +1300,6 @@ _outExprFieldSelect(StringInfo str, ExprFieldSelect *node) } static void -_outDomainConstraintValue(StringInfo str, DomainConstraintValue *node) -{ - WRITE_NODE_TYPE("DOMAINCONSTRAINTVALUE"); -} - -static void _outConstraint(StringInfo str, Constraint *node) { WRITE_NODE_TYPE("CONSTRAINT"); @@ -1637,9 +1631,6 @@ _outNode(StringInfo str, void *obj) case T_ExprFieldSelect: _outExprFieldSelect(str, obj); break; - case T_DomainConstraintValue: - _outDomainConstraintValue(str, obj); - break; case T_Constraint: _outConstraint(str, obj); break; diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index bb4a565a8b5..ba46a4f088c 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.141 2002/12/12 15:49:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.142 2002/12/12 20:35:12 tgl Exp $ * * NOTES * Path and Plan nodes do not have any readfuncs support, because we @@ -793,17 +793,6 @@ _readExprFieldSelect(void) } /* - * _readDomainConstraintValue - */ -static DomainConstraintValue * -_readDomainConstraintValue(void) -{ - READ_LOCALS_NO_FIELDS(DomainConstraintValue); - - READ_DONE(); -} - -/* * _readRangeTblEntry */ static RangeTblEntry * @@ -935,8 +924,6 @@ parseNodeString(void) return_value = _readTypeName(); else if (MATCH("EXPRFIELDSELECT", 15)) return_value = _readExprFieldSelect(); - else if (MATCH("DOMAINCONSTRAINTVALUE", 21)) - return_value = _readDomainConstraintValue(); else if (MATCH("RTE", 3)) return_value = _readRangeTblEntry(); else diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index ef317c5b223..83c05a5d5fd 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.116 2002/12/12 15:49:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.117 2002/12/12 20:35:12 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -2129,6 +2129,7 @@ expression_tree_walker(Node *node, case T_Var: case T_Const: case T_Param: + case T_ConstraintTestValue: case T_RangeTblRef: /* primitive node types with no subnodes */ break; @@ -2265,8 +2266,6 @@ expression_tree_walker(Node *node, if (walker(((ConstraintTest *) node)->arg, context)) return true; return walker(((ConstraintTest *) node)->check_expr, context); - case T_ConstraintTestValue: - break; case T_TargetEntry: return walker(((TargetEntry *) node)->expr, context); case T_Query: @@ -2474,6 +2473,7 @@ expression_tree_mutator(Node *node, case T_Var: case T_Const: case T_Param: + case T_ConstraintTestValue: case T_RangeTblRef: /* primitive node types with no subnodes */ return (Node *) copyObject(node); @@ -2651,15 +2651,6 @@ expression_tree_mutator(Node *node, return (Node *) newnode; } break; - case T_ConstraintTestValue: - { - ConstraintTestValue *ctest = (ConstraintTestValue *) node; - ConstraintTestValue *newnode; - - FLATCOPY(newnode, ctest, ConstraintTestValue); - return (Node *) newnode; - } - break; case T_TargetEntry: { /* diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 56f0fdd955a..a7ead103188 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.255 2002/12/12 15:49:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.256 2002/12/12 20:35:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2401,7 +2401,7 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt) Oid expected_type_id, given_type_id; - expr = transformExpr(pstate, expr, NULL); + expr = transformExpr(pstate, expr); /* Cannot contain subselects or aggregates */ if (contain_subplans(expr)) diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 53e1a5999fe..bb94d1f8e82 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.387 2002/12/12 15:49:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.388 2002/12/12 20:35:13 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -393,7 +393,7 @@ static void doNegateFloat(Value *v); UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL UPDATE USAGE USER USING - VACUUM VALID VALIDATOR VALUE VALUES VARCHAR VARYING + VACUUM VALID VALIDATOR VALUES VARCHAR VARYING VERBOSE VERSION VIEW VOLATILE WHEN WHERE WITH WITHOUT WORK WRITE @@ -6464,11 +6464,6 @@ c_expr: columnref { $$ = (Node *) $1; } n->subselect = $2; $$ = (Node *)n; } - | VALUE - { - DomainConstraintValue *n = makeNode(DomainConstraintValue); - $$ = (Node *)n; - } ; /* @@ -7378,7 +7373,6 @@ reserved_keyword: | UNIQUE | USER | USING - | VALUE | WHEN | WHERE ; diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index de8a6e09b1a..5373b974cbe 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.131 2002/11/15 02:50:08 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.132 2002/12/12 20:35:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -314,7 +314,6 @@ static const ScanKeyword ScanKeywords[] = { {"vacuum", VACUUM}, {"valid", VALID}, {"validator", VALIDATOR}, - {"value", VALUE}, {"values", VALUES}, {"varchar", VARCHAR}, {"varying", VARYING}, diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 6f05ee329cd..71375f62c97 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.101 2002/12/12 15:49:38 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.102 2002/12/12 20:35:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -283,7 +283,7 @@ transformJoinUsingClause(ParseState *pstate, List *leftVars, List *rightVars) * transformJoinOnClause() does. Just invoke transformExpr() to fix * up the operators, and we're done. */ - result = transformExpr(pstate, result, NULL); + result = transformExpr(pstate, result); result = coerce_to_boolean(result, "JOIN/USING"); @@ -317,7 +317,7 @@ transformJoinOnClause(ParseState *pstate, JoinExpr *j, pstate->p_namespace = makeList2(j->larg, j->rarg); /* This part is just like transformWhereClause() */ - result = transformExpr(pstate, j->quals, NULL); + result = transformExpr(pstate, j->quals); result = coerce_to_boolean(result, "JOIN/ON"); @@ -478,7 +478,7 @@ transformRangeFunction(ParseState *pstate, RangeFunction *r) save_namespace = pstate->p_namespace; pstate->p_namespace = NIL; - funcexpr = transformExpr(pstate, r->funccallnode, NULL); + funcexpr = transformExpr(pstate, r->funccallnode); pstate->p_namespace = save_namespace; @@ -950,7 +950,7 @@ transformWhereClause(ParseState *pstate, Node *clause) if (clause == NULL) return NULL; - qual = transformExpr(pstate, clause, NULL); + qual = transformExpr(pstate, clause); qual = coerce_to_boolean(qual, "WHERE"); @@ -1093,7 +1093,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause) * willing to match a resjunk target here, though the above cases must * ignore resjunk targets. */ - expr = transformExpr(pstate, node, NULL); + expr = transformExpr(pstate, node); foreach(tl, tlist) { diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 3856939d404..af184eca6d1 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.90 2002/12/12 15:49:38 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.91 2002/12/12 20:35:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -458,9 +458,8 @@ coerce_type_constraints(Node *arg, Oid typeId, CoercionForm cformat) r->testtype = CONSTR_TEST_CHECK; r->name = NameStr(c->conname); r->domname = NameStr(typTup->typname); - r->check_expr = stringToNode(MemoryContextStrdup(CacheMemoryContext, - DatumGetCString(DirectFunctionCall1(textout, - val)))); + r->check_expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout, + val))); arg = (Node *) r; } diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 7dcbf59a4e3..db0667ef16e 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.136 2002/12/12 15:49:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.137 2002/12/12 20:35:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,7 +20,6 @@ #include "miscadmin.h" #include "nodes/makefuncs.h" #include "nodes/params.h" -#include "optimizer/clauses.h" #include "parser/analyze.h" #include "parser/gramparse.h" #include "parser/parse.h" @@ -84,7 +83,7 @@ parse_expr_init(void) * input and output of transformExpr; see SubLink for example. */ Node * -transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) +transformExpr(ParseState *pstate, Node *expr) { Node *result = NULL; @@ -152,7 +151,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) ExprFieldSelect *efs = (ExprFieldSelect *) expr; List *fields; - result = transformExpr(pstate, efs->arg, domVal); + result = transformExpr(pstate, efs->arg); /* handle qualification, if any */ foreach(fields, efs->fields) { @@ -169,7 +168,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) case T_TypeCast: { TypeCast *tc = (TypeCast *) expr; - Node *arg = transformExpr(pstate, tc->arg, domVal); + Node *arg = transformExpr(pstate, tc->arg); result = typecast_expression(arg, tc->typename); break; @@ -204,14 +203,14 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) n->arg = (Expr *) a->lexpr; result = transformExpr(pstate, - (Node *) n, domVal); + (Node *) n); } else { Node *lexpr = transformExpr(pstate, - a->lexpr, domVal); + a->lexpr); Node *rexpr = transformExpr(pstate, - a->rexpr, domVal); + a->rexpr); result = (Node *) make_op(a->name, lexpr, @@ -222,9 +221,9 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) case AND: { Node *lexpr = transformExpr(pstate, - a->lexpr, domVal); + a->lexpr); Node *rexpr = transformExpr(pstate, - a->rexpr, domVal); + a->rexpr); lexpr = coerce_to_boolean(lexpr, "AND"); rexpr = coerce_to_boolean(rexpr, "AND"); @@ -237,9 +236,9 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) case OR: { Node *lexpr = transformExpr(pstate, - a->lexpr, domVal); + a->lexpr); Node *rexpr = transformExpr(pstate, - a->rexpr, domVal); + a->rexpr); lexpr = coerce_to_boolean(lexpr, "OR"); rexpr = coerce_to_boolean(rexpr, "OR"); @@ -252,7 +251,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) case NOT: { Node *rexpr = transformExpr(pstate, - a->rexpr, domVal); + a->rexpr); rexpr = coerce_to_boolean(rexpr, "NOT"); @@ -263,9 +262,9 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) case DISTINCT: { Node *lexpr = transformExpr(pstate, - a->lexpr, domVal); + a->lexpr); Node *rexpr = transformExpr(pstate, - a->rexpr, domVal); + a->rexpr); result = (Node *) make_op(a->name, lexpr, @@ -291,7 +290,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) * Will result in a boolean constant node. */ Node *lexpr = transformExpr(pstate, - a->lexpr, domVal); + a->lexpr); ltype = exprType(lexpr); foreach(telem, (List *) a->rexpr) @@ -315,7 +314,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) n->val.val.str = (matched ? "t" : "f"); n->typename = SystemTypeName("bool"); - result = transformExpr(pstate, (Node *) n, domVal); + result = transformExpr(pstate, (Node *) n); } break; } @@ -329,7 +328,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) /* transform the list of arguments */ foreach(args, fn->args) lfirst(args) = transformExpr(pstate, - (Node *) lfirst(args), domVal); + (Node *) lfirst(args)); result = ParseFuncOrColumn(pstate, fn->funcname, fn->args, @@ -403,7 +402,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) List *elist; foreach(elist, left_list) - lfirst(elist) = transformExpr(pstate, lfirst(elist), domVal); + lfirst(elist) = transformExpr(pstate, lfirst(elist)); Assert(IsA(sublink->oper, A_Expr)); op = ((A_Expr *) sublink->oper)->name; @@ -507,7 +506,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) (Node *) c->arg, warg); } - neww->expr = (Expr *) transformExpr(pstate, warg, domVal); + neww->expr = (Expr *) transformExpr(pstate, warg); neww->expr = (Expr *) coerce_to_boolean((Node *) neww->expr, "CASE/WHEN"); @@ -524,7 +523,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) n->val.type = T_Null; warg = (Node *) n; } - neww->result = (Expr *) transformExpr(pstate, warg, domVal); + neww->result = (Expr *) transformExpr(pstate, warg); newargs = lappend(newargs, neww); typeids = lappendi(typeids, exprType((Node *) neww->result)); @@ -548,7 +547,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) n->val.type = T_Null; defresult = (Node *) n; } - newc->defresult = (Expr *) transformExpr(pstate, defresult, domVal); + newc->defresult = (Expr *) transformExpr(pstate, defresult); /* * Note: default result is considered the most significant @@ -586,7 +585,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) { NullTest *n = (NullTest *) expr; - n->arg = (Expr *) transformExpr(pstate, (Node *) n->arg, domVal); + n->arg = (Expr *) transformExpr(pstate, (Node *) n->arg); /* the argument can be any type, so don't coerce it */ result = expr; break; @@ -623,7 +622,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) clausename = NULL; /* keep compiler quiet */ } - b->arg = (Expr *) transformExpr(pstate, (Node *) b->arg, domVal); + b->arg = (Expr *) transformExpr(pstate, (Node *) b->arg); b->arg = (Expr *) coerce_to_boolean((Node *) b->arg, clausename); @@ -631,21 +630,6 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) break; } - case T_DomainConstraintValue: - { - /* - * If domVal is NULL, we are not translating an expression that - * can use it - */ - if (domVal == NULL) - elog(ERROR, "VALUE is not allowed in expression for node %d", - nodeTag(expr)); - - result = (Node *) copyObject(domVal); - - break; - } - /********************************************* * Quietly accept node types that may be presented when we are * called on an already-transformed tree. @@ -663,6 +647,7 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) case T_FieldSelect: case T_RelabelType: case T_ConstraintTest: + case T_ConstraintTestValue: { result = (Node *) expr; break; @@ -700,6 +685,7 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) int numnames = length(cref->fields); Node *node; RangeVar *rv; + int levels_up; /*---------- * The allowed syntaxes are: @@ -740,18 +726,30 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) if (node == NULL) { /* - * Not known as a column of any range-table entry, so - * try to find the name as a relation ... but not if + * Not known as a column of any range-table entry. + * + * Consider the possibility that it's VALUE in a domain + * check expression. (We handle VALUE as a name, not a + * keyword, to avoid breaking a lot of applications that + * have used VALUE as a column name in the past.) + */ + if (pstate->p_value_substitute != NULL && + strcmp(name, "value") == 0) + { + node = (Node *) copyObject(pstate->p_value_substitute); + break; + } + + /* + * Try to find the name as a relation ... but not if * subscripts appear. Note also that only relations * already entered into the rangetable will be * recognized. * * This is a hack for backwards compatibility with - * PostQUEL- inspired syntax. The preferred form now + * PostQUEL-inspired syntax. The preferred form now * is "rel.*". */ - int levels_up; - if (cref->indirection == NIL && refnameRangeTblEntry(pstate, NULL, name, &levels_up) != NULL) @@ -1055,7 +1053,8 @@ exprTypmod(Node *expr) break; case T_ConstraintTest: return exprTypmod((Node *) ((ConstraintTest *) expr)->arg); - + case T_ConstraintTestValue: + return ((ConstraintTestValue *) expr)->typeMod; default: break; } diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index a246344c7bd..9de23d0cb8e 100644 --- a/src/backend/parser/parse_node.c +++ b/src/backend/parser/parse_node.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.75 2002/12/12 15:49:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.76 2002/12/12 20:35:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -272,7 +272,7 @@ transformArraySubscripts(ParseState *pstate, { if (ai->lidx) { - subexpr = transformExpr(pstate, ai->lidx, NULL); + subexpr = transformExpr(pstate, ai->lidx); /* If it's not int4 already, try to coerce */ subexpr = coerce_to_target_type(subexpr, exprType(subexpr), INT4OID, -1, @@ -292,7 +292,7 @@ transformArraySubscripts(ParseState *pstate, } lowerIndexpr = lappend(lowerIndexpr, subexpr); } - subexpr = transformExpr(pstate, ai->uidx, NULL); + subexpr = transformExpr(pstate, ai->uidx); /* If it's not int4 already, try to coerce */ subexpr = coerce_to_target_type(subexpr, exprType(subexpr), INT4OID, -1, diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c index 5e4e23db920..7e73b1b7b0c 100644 --- a/src/backend/parser/parse_target.c +++ b/src/backend/parser/parse_target.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.93 2002/12/12 15:49:39 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.94 2002/12/12 20:35:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -56,7 +56,7 @@ transformTargetEntry(ParseState *pstate, /* Transform the node if caller didn't do it already */ if (expr == NULL) - expr = transformExpr(pstate, node, NULL); + expr = transformExpr(pstate, node); if (IsA(expr, RangeVar)) elog(ERROR, "You can't use relation names alone in the target list, try relation.*."); diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index a4f10ef4c06..db8e431c769 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: execnodes.h,v 1.82 2002/12/05 15:50:38 tgl Exp $ + * $Id: execnodes.h,v 1.83 2002/12/12 20:35:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -82,7 +82,7 @@ typedef struct ExprContext_CB * * ecxt_per_query_memory is a relatively long-lived context (such as * TransactionCommandContext); typically it's the same context the * ExprContext node itself is allocated in. This context can be - * used for purposes such as storing operator/function fcache nodes. + * used for purposes such as storing function call cache info. * * ecxt_per_tuple_memory is a short-term context for expression results. * As the name suggests, it will typically be reset once per tuple, * before we begin to evaluate expressions for that tuple. Each @@ -112,10 +112,7 @@ typedef struct ExprContext Datum *ecxt_aggvalues; /* precomputed values for Aggref nodes */ bool *ecxt_aggnulls; /* null flags for Aggref nodes */ - /* - * Carry the domain value through the executor for application - * in a domain constraint - */ + /* Value to substitute for ConstraintTestValue nodes in expression */ Datum domainValue_datum; bool domainValue_isNull; diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index aacdf60dd9a..0c031b830e1 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: nodes.h,v 1.130 2002/12/12 15:49:40 tgl Exp $ + * $Id: nodes.h,v 1.131 2002/12/12 20:35:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -252,7 +252,6 @@ typedef enum NodeTag T_FuncWithArgs, T_PrivTarget, T_InsertDefault, - T_DomainConstraintValue, T_CreateOpClassItem, T_CompositeTypeStmt, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index f2d92431b71..c409ec7ea84 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.222 2002/12/12 15:49:40 tgl Exp $ + * $Id: parsenodes.h,v 1.223 2002/12/12 20:35:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -276,15 +276,6 @@ typedef struct InsertDefault } InsertDefault; /* - * Empty node used as raw-parse-tree representation of VALUE keyword - * for domain check constraints. - */ -typedef struct DomainConstraintValue -{ - NodeTag type; -} DomainConstraintValue; - -/* * SortGroupBy - for ORDER BY clause */ typedef struct SortGroupBy diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index ec0ad4235c9..ae0df7e441c 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -10,7 +10,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: primnodes.h,v 1.72 2002/12/12 15:49:40 tgl Exp $ + * $Id: primnodes.h,v 1.73 2002/12/12 20:35:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -599,15 +599,19 @@ typedef struct ConstraintTest } ConstraintTest; /* - * Placeholder node for the value to be processed by a domains - * check constraint. This is effectively like a Param; could we use - * a Param node instead? + * Placeholder node for the value to be processed by a domain's check + * constraint. This is effectively like a Param, but can be implemented more + * simply since we need only one replacement value at a time. + * + * Note: the typeId/typeMod will be set from the domain's base type, not + * the domain itself. This is because we shouldn't consider the value to + * be a member of the domain if we haven't yet checked its constraints. */ typedef struct ConstraintTestValue { Expr xpr; - Oid typeId; - int32 typeMod; + Oid typeId; /* type for substituted value */ + int32 typeMod; /* typemod for substituted value */ } ConstraintTestValue; diff --git a/src/include/optimizer/var.h b/src/include/optimizer/var.h index 68ffc8e373a..102e928a544 100644 --- a/src/include/optimizer/var.h +++ b/src/include/optimizer/var.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: var.h,v 1.22 2002/11/15 02:50:21 momjian Exp $ + * $Id: var.h,v 1.23 2002/12/12 20:35:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,7 +22,6 @@ extern bool contain_var_reference(Node *node, int varno, int varattno, int levelsup); extern bool contain_whole_tuple_var(Node *node, int varno, int levelsup); extern bool contain_var_clause(Node *node); -extern bool contain_var_tuple_clause(Node *node); extern List *pull_var_clause(Node *node, bool includeUpperVars); extern Node *flatten_join_alias_vars(Node *node, List *rtable, bool force); diff --git a/src/include/parser/parse_expr.h b/src/include/parser/parse_expr.h index bcf84912acf..6606d3913e5 100644 --- a/src/include/parser/parse_expr.h +++ b/src/include/parser/parse_expr.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parse_expr.h,v 1.29 2002/11/15 02:50:21 momjian Exp $ + * $Id: parse_expr.h,v 1.30 2002/12/12 20:35:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,7 +22,7 @@ extern int max_expr_depth; extern bool Transform_null_equals; -extern Node *transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal); +extern Node *transformExpr(ParseState *pstate, Node *expr); extern Oid exprType(Node *expr); extern int32 exprTypmod(Node *expr); extern bool exprIsLengthCoercion(Node *expr, int32 *coercedTypmod); diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index beb16e2cc8e..46c86e1f796 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parse_node.h,v 1.32 2002/09/18 21:35:24 tgl Exp $ + * $Id: parse_node.h,v 1.33 2002/12/12 20:35:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,6 +42,7 @@ typedef struct ParseState List *p_namespace; /* current lookup namespace (join items) */ int p_last_resno; /* last targetlist resno assigned */ List *p_forUpdate; /* FOR UPDATE clause, if any (see gram.y) */ + Node *p_value_substitute; /* what to replace VALUE with, if any */ bool p_hasAggs; bool p_hasSubLinks; bool p_is_insert; diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out index f91191bddb6..cbbb9023794 100644 --- a/src/test/regress/expected/domain.out +++ b/src/test/regress/expected/domain.out @@ -115,7 +115,7 @@ INSERT INTO nulltest DEFAULT VALUES; ERROR: Domain dnotnull does not allow NULL values INSERT INTO nulltest values ('a', 'b', 'c', 'd', 'c'); -- Good insert into nulltest values ('a', 'b', 'c', 'd', NULL); -ERROR: ExecEvalConstraintTest: Domain dcheck constraint $1 failed +ERROR: Domain dcheck does not allow NULL values insert into nulltest values ('a', 'b', 'c', 'd', 'a'); ERROR: ExecInsert: rejected due to CHECK constraint "nulltest_col5" on "nulltest" INSERT INTO nulltest values (NULL, 'b', 'c', 'd', 'd'); @@ -127,7 +127,7 @@ ERROR: ExecInsert: Fail to add null value in not null attribute col3 INSERT INTO nulltest values ('a', 'b', 'c', NULL, 'd'); -- Good -- Test copy COPY nulltest FROM stdin; --fail -ERROR: copy: line 1, ExecEvalConstraintTest: Domain dcheck constraint $1 failed +ERROR: copy: line 1, Domain dcheck does not allow NULL values lost synchronization with server, resetting connection SET autocommit TO 'on'; -- Last row is bad |