1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-15 19:21:59 +03:00

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.
This commit is contained in:
Tom Lane
2002-12-12 20:35:16 +00:00
parent ff7349694f
commit b0422b215c
28 changed files with 222 additions and 292 deletions

View File

@ -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))

View File

@ -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
;

View File

@ -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},

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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,

View File

@ -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.*.");