diff options
author | Bruce Momjian <bruce@momjian.us> | 2002-11-15 02:50:21 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2002-11-15 02:50:21 +0000 |
commit | 6b603e67dcd1a93a56f3c6b5f36fd8f08e2ee35d (patch) | |
tree | 5d4a4a590f20c0516bb380e6169114120be3d58f /src/backend/parser | |
parent | 2986aa6a668bce3cfb83606bb52e9d01ae66ad6c (diff) | |
download | postgresql-6b603e67dcd1a93a56f3c6b5f36fd8f08e2ee35d.tar.gz postgresql-6b603e67dcd1a93a56f3c6b5f36fd8f08e2ee35d.zip |
Add DOMAIN check constraints.
Rod Taylor
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/analyze.c | 4 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 10 | ||||
-rw-r--r-- | src/backend/parser/keywords.c | 3 | ||||
-rw-r--r-- | src/backend/parser/parse_clause.c | 12 | ||||
-rw-r--r-- | src/backend/parser/parse_coerce.c | 56 | ||||
-rw-r--r-- | src/backend/parser/parse_expr.c | 57 | ||||
-rw-r--r-- | src/backend/parser/parse_node.c | 6 | ||||
-rw-r--r-- | src/backend/parser/parse_target.c | 4 |
8 files changed, 110 insertions, 42 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 30c8e8f15b9..18144f7b941 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.253 2002/10/21 22:06:19 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.254 2002/11/15 02:50:07 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -2401,7 +2401,7 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt) Oid expected_type_id, given_type_id; - expr = transformExpr(pstate, expr); + expr = transformExpr(pstate, expr, NULL); /* Cannot contain subselects or aggregates */ if (contain_subplans(expr)) diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 724424220b6..b3ca71013c9 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.377 2002/11/13 00:44:08 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.378 2002/11/15 02:50:08 momjian 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 VALUES VARCHAR VARYING + VACUUM VALID VALIDATOR VALUE VALUES VARCHAR VARYING VERBOSE VERSION VIEW VOLATILE WHEN WHERE WITH WITHOUT WORK WRITE @@ -6406,6 +6406,11 @@ c_expr: columnref { $$ = (Node *) $1; } n->subselect = $2; $$ = (Node *)n; } + | VALUE + { + DomainConstraintValue *n = makeNode(DomainConstraintValue); + $$ = (Node *)n; + } ; /* @@ -7315,6 +7320,7 @@ reserved_keyword: | UNIQUE | USER | USING + | VALUE | WHEN | WHERE ; diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index b86ffa522e4..de8a6e09b1a 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.130 2002/11/13 00:44:09 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.131 2002/11/15 02:50:08 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -314,6 +314,7 @@ 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 245c0ba422b..d9638753746 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.98 2002/09/18 21:35:22 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.99 2002/11/15 02:50:08 momjian 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); + result = transformExpr(pstate, result, NULL); 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); + result = transformExpr(pstate, j->quals, NULL); 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); + funcexpr = transformExpr(pstate, r->funccallnode, NULL); pstate->p_namespace = save_namespace; @@ -961,7 +961,7 @@ transformWhereClause(ParseState *pstate, Node *clause) if (clause == NULL) return NULL; - qual = transformExpr(pstate, clause); + qual = transformExpr(pstate, clause, NULL); qual = coerce_to_boolean(qual, "WHERE"); @@ -1104,7 +1104,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); + expr = transformExpr(pstate, node, NULL); foreach(tl, tlist) { diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index 4870b24de07..a24af2de3e1 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,13 +8,18 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.85 2002/10/24 22:09:00 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.86 2002/11/15 02:50:09 momjian Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include "access/genam.h" +#include "access/heapam.h" +#include "catalog/catname.h" +#include "catalog/indexing.h" #include "catalog/pg_cast.h" +#include "catalog/pg_constraint.h" #include "catalog/pg_proc.h" #include "nodes/makefuncs.h" #include "optimizer/clauses.h" @@ -405,8 +410,14 @@ coerce_type_constraints(Node *arg, Oid typeId, CoercionForm cformat) for (;;) { HeapTuple tup; + HeapTuple conTup; Form_pg_type typTup; + ScanKeyData key[1]; + int nkeys = 0; + SysScanDesc scan; + Relation conRel; + tup = SearchSysCache(TYPEOID, ObjectIdGetDatum(typeId), 0, 0, 0); @@ -419,7 +430,45 @@ coerce_type_constraints(Node *arg, Oid typeId, CoercionForm cformat) if (typTup->typnotnull && notNull == NULL) notNull = pstrdup(NameStr(typTup->typname)); - /* TODO: Add CHECK Constraints to domains */ + /* Add CHECK Constraints to domains */ + conRel = heap_openr(ConstraintRelationName, RowShareLock); + + ScanKeyEntryInitialize(&key[nkeys++], 0x0, + Anum_pg_constraint_contypid, F_OIDEQ, + ObjectIdGetDatum(typeId)); + + scan = systable_beginscan(conRel, ConstraintTypidIndex, true, + SnapshotNow, nkeys, key); + + while (HeapTupleIsValid(conTup = systable_getnext(scan))) + { + Datum val; + bool isNull; + ConstraintTest *r = makeNode(ConstraintTest); + Form_pg_constraint c = (Form_pg_constraint) GETSTRUCT(conTup); + + /* Not expecting conbin to be NULL, but we'll test for it anyway */ + val = fastgetattr(conTup, + Anum_pg_constraint_conbin, + conRel->rd_att, &isNull); + + if (isNull) + elog(ERROR, "coerce_type_constraints: domain %s constraint %s has NULL conbin", + NameStr(typTup->typname), NameStr(c->conname)); + + r->arg = arg; + 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)))); + + arg = (Node *) r; + } + + systable_endscan(scan); + heap_close(conRel, RowShareLock); if (typTup->typtype != 'd') { @@ -452,7 +501,8 @@ coerce_type_constraints(Node *arg, Oid typeId, CoercionForm cformat) r->arg = arg; r->testtype = CONSTR_TEST_NOTNULL; - r->name = notNull; + r->name = "NOT NULL"; + r->domname = notNull; r->check_expr = NULL; arg = (Node *) r; diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 3873fd37f0d..9a4a9c8bc91 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.129 2002/09/18 21:35:22 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.130 2002/11/15 02:50:09 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -20,6 +20,7 @@ #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" @@ -83,7 +84,7 @@ parse_expr_init(void) * input and output of transformExpr; see SubLink for example. */ Node * -transformExpr(ParseState *pstate, Node *expr) +transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal) { Node *result = NULL; @@ -152,7 +153,7 @@ transformExpr(ParseState *pstate, Node *expr) ExprFieldSelect *efs = (ExprFieldSelect *) expr; List *fields; - result = transformExpr(pstate, efs->arg); + result = transformExpr(pstate, efs->arg, domVal); /* handle qualification, if any */ foreach(fields, efs->fields) { @@ -169,7 +170,7 @@ transformExpr(ParseState *pstate, Node *expr) case T_TypeCast: { TypeCast *tc = (TypeCast *) expr; - Node *arg = transformExpr(pstate, tc->arg); + Node *arg = transformExpr(pstate, tc->arg, domVal); result = typecast_expression(arg, tc->typename); break; @@ -204,14 +205,14 @@ transformExpr(ParseState *pstate, Node *expr) n->arg = a->lexpr; result = transformExpr(pstate, - (Node *) n); + (Node *) n, domVal); } else { Node *lexpr = transformExpr(pstate, - a->lexpr); + a->lexpr, domVal); Node *rexpr = transformExpr(pstate, - a->rexpr); + a->rexpr, domVal); result = (Node *) make_op(a->name, lexpr, @@ -222,9 +223,9 @@ transformExpr(ParseState *pstate, Node *expr) case AND: { Node *lexpr = transformExpr(pstate, - a->lexpr); + a->lexpr, domVal); Node *rexpr = transformExpr(pstate, - a->rexpr); + a->rexpr, domVal); Expr *expr = makeNode(Expr); lexpr = coerce_to_boolean(lexpr, "AND"); @@ -239,9 +240,9 @@ transformExpr(ParseState *pstate, Node *expr) case OR: { Node *lexpr = transformExpr(pstate, - a->lexpr); + a->lexpr, domVal); Node *rexpr = transformExpr(pstate, - a->rexpr); + a->rexpr, domVal); Expr *expr = makeNode(Expr); lexpr = coerce_to_boolean(lexpr, "OR"); @@ -256,7 +257,7 @@ transformExpr(ParseState *pstate, Node *expr) case NOT: { Node *rexpr = transformExpr(pstate, - a->rexpr); + a->rexpr, domVal); Expr *expr = makeNode(Expr); rexpr = coerce_to_boolean(rexpr, "NOT"); @@ -270,9 +271,9 @@ transformExpr(ParseState *pstate, Node *expr) case DISTINCT: { Node *lexpr = transformExpr(pstate, - a->lexpr); + a->lexpr, domVal); Node *rexpr = transformExpr(pstate, - a->rexpr); + a->rexpr, domVal); result = (Node *) make_op(a->name, lexpr, @@ -293,7 +294,7 @@ transformExpr(ParseState *pstate, Node *expr) * Will result in a boolean constant node. */ Node *lexpr = transformExpr(pstate, - a->lexpr); + a->lexpr, domVal); ltype = exprType(lexpr); foreach(telem, (List *) a->rexpr) @@ -317,7 +318,7 @@ transformExpr(ParseState *pstate, Node *expr) n->val.val.str = (matched ? "t" : "f"); n->typename = SystemTypeName("bool"); - result = transformExpr(pstate, (Node *) n); + result = transformExpr(pstate, (Node *) n, domVal); } break; } @@ -331,7 +332,7 @@ transformExpr(ParseState *pstate, Node *expr) /* transform the list of arguments */ foreach(args, fn->args) lfirst(args) = transformExpr(pstate, - (Node *) lfirst(args)); + (Node *) lfirst(args), domVal); result = ParseFuncOrColumn(pstate, fn->funcname, fn->args, @@ -405,7 +406,7 @@ transformExpr(ParseState *pstate, Node *expr) List *elist; foreach(elist, left_list) - lfirst(elist) = transformExpr(pstate, lfirst(elist)); + lfirst(elist) = transformExpr(pstate, lfirst(elist), domVal); Assert(IsA(sublink->oper, A_Expr)); op = ((A_Expr *) sublink->oper)->name; @@ -504,7 +505,7 @@ transformExpr(ParseState *pstate, Node *expr) warg = (Node *) makeSimpleA_Expr(OP, "=", c->arg, warg); } - neww->expr = transformExpr(pstate, warg); + neww->expr = transformExpr(pstate, warg, domVal); neww->expr = coerce_to_boolean(neww->expr, "CASE/WHEN"); @@ -520,7 +521,7 @@ transformExpr(ParseState *pstate, Node *expr) n->val.type = T_Null; warg = (Node *) n; } - neww->result = transformExpr(pstate, warg); + neww->result = transformExpr(pstate, warg, domVal); newargs = lappend(newargs, neww); typeids = lappendi(typeids, exprType(neww->result)); @@ -544,7 +545,7 @@ transformExpr(ParseState *pstate, Node *expr) n->val.type = T_Null; defresult = (Node *) n; } - newc->defresult = transformExpr(pstate, defresult); + newc->defresult = transformExpr(pstate, defresult, domVal); /* * Note: default result is considered the most significant @@ -580,7 +581,7 @@ transformExpr(ParseState *pstate, Node *expr) { NullTest *n = (NullTest *) expr; - n->arg = transformExpr(pstate, n->arg); + n->arg = transformExpr(pstate, n->arg, domVal); /* the argument can be any type, so don't coerce it */ result = expr; break; @@ -617,7 +618,7 @@ transformExpr(ParseState *pstate, Node *expr) clausename = NULL; /* keep compiler quiet */ } - b->arg = transformExpr(pstate, b->arg); + b->arg = transformExpr(pstate, b->arg, domVal); b->arg = coerce_to_boolean(b->arg, clausename); @@ -625,6 +626,13 @@ transformExpr(ParseState *pstate, Node *expr) break; } + case T_DomainConstraintValue: + { + result = (Node *) copyObject(domVal); + + break; + } + /********************************************* * Quietly accept node types that may be presented when we are * called on an already-transformed tree. @@ -936,6 +944,9 @@ exprType(Node *expr) case T_ConstraintTest: type = exprType(((ConstraintTest *) expr)->arg); break; + case T_ConstraintTestValue: + type = ((ConstraintTestValue *) expr)->typeId; + break; default: elog(ERROR, "exprType: Do not know how to get type for %d node", nodeTag(expr)); diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c index f0bb1856ab3..608a67921c1 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.72 2002/11/13 00:39:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.73 2002/11/15 02:50:09 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -277,7 +277,7 @@ transformArraySubscripts(ParseState *pstate, { if (ai->lidx) { - subexpr = transformExpr(pstate, ai->lidx); + subexpr = transformExpr(pstate, ai->lidx, NULL); /* If it's not int4 already, try to coerce */ subexpr = coerce_to_target_type(subexpr, exprType(subexpr), INT4OID, -1, @@ -299,7 +299,7 @@ transformArraySubscripts(ParseState *pstate, } lowerIndexpr = lappend(lowerIndexpr, subexpr); } - subexpr = transformExpr(pstate, ai->uidx); + subexpr = transformExpr(pstate, ai->uidx, NULL); /* 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 c03db4f8b4b..1a2da6da1eb 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.91 2002/09/28 20:00:19 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.92 2002/11/15 02:50:09 momjian 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); + expr = transformExpr(pstate, node, NULL); if (IsA(expr, RangeVar)) elog(ERROR, "You can't use relation names alone in the target list, try relation.*."); |