Use Params, rather than run-time-modified Const nodes, to handle

sublink results and COPY's domain constraint checking.  A Const that
isn't really constant is just a Bad Idea(tm).  Remove hacks in
parse_coerce and other places that were needed because of the former
klugery.
This commit is contained in:
Tom Lane 2002-11-26 03:01:59 +00:00
parent ac47950238
commit ea0b5c8569
9 changed files with 166 additions and 190 deletions

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.182 2002/11/25 21:29:34 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.183 2002/11/26 03:01:57 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -749,7 +749,6 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
FmgrInfo *in_functions; FmgrInfo *in_functions;
Oid *elements; Oid *elements;
Node **constraintexprs; Node **constraintexprs;
Const **constraintconsts;
bool hasConstraints = false; bool hasConstraints = false;
int i; int i;
List *cur; List *cur;
@ -805,7 +804,6 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
defmap = (int *) palloc(num_phys_attrs * sizeof(int)); defmap = (int *) palloc(num_phys_attrs * sizeof(int));
defexprs = (Node **) palloc(num_phys_attrs * sizeof(Node *)); defexprs = (Node **) palloc(num_phys_attrs * sizeof(Node *));
constraintexprs = (Node **) palloc0(num_phys_attrs * sizeof(Node *)); constraintexprs = (Node **) palloc0(num_phys_attrs * sizeof(Node *));
constraintconsts = (Const **) palloc(num_phys_attrs * sizeof(Const *));
for (i = 0; i < num_phys_attrs; i++) for (i = 0; i < num_phys_attrs; i++)
{ {
@ -840,7 +838,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
/* If it's a domain type, get info on domain constraints */ /* If it's a domain type, get info on domain constraints */
if (get_typtype(attr[i]->atttypid) == 'd') if (get_typtype(attr[i]->atttypid) == 'd')
{ {
Const *con; Param *prm;
Node *node; Node *node;
/* /*
@ -848,28 +846,21 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
* an expression that checks the constraints. (At present, * an expression that checks the constraints. (At present,
* the expression might contain a length-coercion-function call * the expression might contain a length-coercion-function call
* and/or ConstraintTest nodes.) The bottom of the expression * and/or ConstraintTest nodes.) The bottom of the expression
* is a Const node that we fill in with the actual datum during * is a Param node so that we can fill in the actual datum during
* the data input loop. * the data input loop.
*
* XXX to prevent premature constant folding in parse_coerce,
* pass in a NULL constant to start with. See the comments in
* coerce_type; this should be changed someday to use some sort
* of Param node instead of a Const.
*/ */
con = makeConst(attr[i]->atttypid, prm = makeNode(Param);
attr[i]->attlen, prm->paramkind = PARAM_EXEC;
(Datum) 0, prm->paramid = 0;
true, /* is null */ prm->paramtype = attr[i]->atttypid;
attr[i]->attbyval);
node = coerce_type_constraints((Node *) con, attr[i]->atttypid, node = coerce_type_constraints((Node *) prm, attr[i]->atttypid,
COERCE_IMPLICIT_CAST); COERCE_IMPLICIT_CAST);
/* check whether any constraints actually found */ /* check whether any constraints actually found */
if (node != (Node *) con) if (node != (Node *) prm)
{ {
constraintexprs[i] = node; constraintexprs[i] = node;
constraintconsts[i] = con;
hasConstraints = true; hasConstraints = true;
} }
} }
@ -931,6 +922,11 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
econtext = GetPerTupleExprContext(estate); econtext = GetPerTupleExprContext(estate);
/* Make room for a PARAM_EXEC value for domain constraint checks */
if (hasConstraints)
econtext->ecxt_param_exec_vals = (ParamExecData *)
palloc0(sizeof(ParamExecData));
while (!done) while (!done)
{ {
bool skip_tuple; bool skip_tuple;
@ -1153,19 +1149,19 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
*/ */
if (hasConstraints) if (hasConstraints)
{ {
ParamExecData *prmdata = &econtext->ecxt_param_exec_vals[0];
for (i = 0; i < num_phys_attrs; i++) for (i = 0; i < num_phys_attrs; i++)
{ {
Node *node = constraintexprs[i]; Node *node = constraintexprs[i];
Const *con;
bool isnull; bool isnull;
if (node == NULL) if (node == NULL)
continue; /* no constraint for this attr */ continue; /* no constraint for this attr */
/* Insert current row's value into the Const node */ /* Insert current row's value into the Param value */
con = constraintconsts[i]; prmdata->value = values[i];
con->constvalue = values[i]; prmdata->isnull = (nulls[i] == 'n');
con->constisnull = (nulls[i] == 'n');
/* /*
* Execute the constraint expression. Allow the expression * Execute the constraint expression. Allow the expression

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.33 2002/06/20 20:29:28 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.34 2002/11/26 03:01:57 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -150,37 +150,44 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
foreach(lst, sublink->oper) foreach(lst, sublink->oper)
{ {
Expr *expr = (Expr *) lfirst(lst); Expr *expr = (Expr *) lfirst(lst);
Const *con = lsecond(expr->args); Param *prm = lsecond(expr->args);
ParamExecData *prmdata;
Datum expresult; Datum expresult;
bool expnull; bool expnull;
/* /*
* The righthand side of the expression should be either a * The righthand side of the expression should be either a
* Const or a function call or RelabelType node taking a Const * Param or a function call or RelabelType node taking a Param
* as arg (these nodes represent run-time type coercions * as arg (these nodes represent run-time type coercions
* inserted by the parser to get to the input type needed by * inserted by the parser to get to the input type needed by
* the operator). Find the Const node and insert the actual * the operator). Find the Param node and insert the actual
* righthand-side value into it. * righthand-side value into the param's econtext slot.
*
* XXX possible improvement: could make a list of the ParamIDs
* at startup time, instead of repeating this check at each row.
*/ */
if (!IsA(con, Const)) if (!IsA(prm, Param))
{ {
switch (con->type) switch (nodeTag(prm))
{ {
case T_Expr: case T_Expr:
con = lfirst(((Expr *) con)->args); prm = lfirst(((Expr *) prm)->args);
break; break;
case T_RelabelType: case T_RelabelType:
con = (Const *) (((RelabelType *) con)->arg); prm = (Param *) (((RelabelType *) prm)->arg);
break; break;
default: default:
/* will fail below */ /* will fail below */
break; break;
} }
if (!IsA(con, Const)) if (!IsA(prm, Param))
elog(ERROR, "ExecSubPlan: failed to find placeholder for subplan result"); elog(ERROR, "ExecSubPlan: failed to find placeholder for subplan result");
} }
con->constvalue = heap_getattr(tup, col, tdesc, Assert(prm->paramkind == PARAM_EXEC);
&(con->constisnull)); prmdata = &(econtext->ecxt_param_exec_vals[prm->paramid]);
Assert(prmdata->execPlan == NULL);
prmdata->value = heap_getattr(tup, col, tdesc,
&(prmdata->isnull));
/* /*
* Now we can eval the combining operator for this column. * Now we can eval the combining operator for this column.

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.130 2002/11/21 00:42:19 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.131 2002/11/26 03:01:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -720,8 +720,6 @@ preprocess_expression(Query *parse, Node *expr, int kind)
* *
* Note that at this point quals have not yet been converted to * Note that at this point quals have not yet been converted to
* implicit-AND form, so we can apply eval_const_expressions directly. * implicit-AND form, so we can apply eval_const_expressions directly.
* Also note that we need to do this before SS_process_sublinks,
* because that routine inserts bogus "Const" nodes.
*/ */
expr = eval_const_expressions(expr); expr = eval_const_expressions(expr);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.55 2002/09/04 20:31:21 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.56 2002/11/26 03:01:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -44,24 +44,32 @@ int PlannerPlanId = 0; /* to assign unique ID to subquery plans */
* and update the list elements when we enter or exit a subplan * and update the list elements when we enter or exit a subplan
* recursion level. But we must pay attention not to confuse this * recursion level. But we must pay attention not to confuse this
* meaning with the normal meaning of varlevelsup. * meaning with the normal meaning of varlevelsup.
*
* We also need to create Param slots that don't correspond to any outer Var.
* For these, we set varno = 0 and varlevelsup = 0, so that they can't
* accidentally match an outer Var.
*-------------------- *--------------------
*/ */
static void convert_sublink_opers(SubLink *slink, List *targetlist,
List **setParams);
/* /*
* Create a new entry in the PlannerParamVar list, and return its index. * Create a new entry in the PlannerParamVar list, and return its index.
* *
* var contains the data to be copied, except for varlevelsup which * var contains the data to use, except for varlevelsup which
* is set from the absolute level value given by varlevel. * is set from the absolute level value given by varlevel. NOTE that
* the passed var is scribbled on and placed directly into the list!
* Generally, caller should have just created or copied it.
*/ */
static int static int
new_param(Var *var, Index varlevel) new_param(Var *var, Index varlevel)
{ {
Var *paramVar = (Var *) copyObject(var); var->varlevelsup = varlevel;
paramVar->varlevelsup = varlevel; PlannerParamVar = lappend(PlannerParamVar, var);
PlannerParamVar = lappend(PlannerParamVar, paramVar);
return length(PlannerParamVar) - 1; return length(PlannerParamVar) - 1;
} }
@ -107,7 +115,7 @@ replace_var(Var *var)
if (!ppv) if (!ppv)
{ {
/* Nope, so make a new one */ /* Nope, so make a new one */
i = new_param(var, varlevel); i = new_param((Var *) copyObject(var), varlevel);
} }
retval = makeNode(Param); retval = makeNode(Param);
@ -118,6 +126,22 @@ replace_var(Var *var)
return retval; return retval;
} }
/*
* Generate a new Param node that will not conflict with any other.
*/
static Param *
generate_new_param(Oid paramtype, int32 paramtypmod)
{
Var *var = makeVar(0, 0, paramtype, paramtypmod, 0);
Param *retval = makeNode(Param);
retval->paramkind = PARAM_EXEC;
retval->paramid = (AttrNumber) new_param(var, 0);
retval->paramtype = paramtype;
return retval;
}
/* /*
* Convert a bare SubLink (as created by the parser) into a SubPlan. * Convert a bare SubLink (as created by the parser) into a SubPlan.
*/ */
@ -216,13 +240,9 @@ make_subplan(SubLink *slink)
*/ */
if (node->parParam == NIL && slink->subLinkType == EXISTS_SUBLINK) if (node->parParam == NIL && slink->subLinkType == EXISTS_SUBLINK)
{ {
Var *var = makeVar(0, 0, BOOLOID, -1, 0); Param *prm;
Param *prm = makeNode(Param);
prm->paramkind = PARAM_EXEC; prm = generate_new_param(BOOLOID, -1);
prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
prm->paramtype = var->vartype;
pfree(var); /* var is only needed for new_param */
node->setParam = lappendi(node->setParam, prm->paramid); node->setParam = lappendi(node->setParam, prm->paramid);
PlannerInitPlan = lappend(PlannerInitPlan, node); PlannerInitPlan = lappend(PlannerInitPlan, node);
result = (Node *) prm; result = (Node *) prm;
@ -230,89 +250,27 @@ make_subplan(SubLink *slink)
else if (node->parParam == NIL && slink->subLinkType == EXPR_SUBLINK) else if (node->parParam == NIL && slink->subLinkType == EXPR_SUBLINK)
{ {
TargetEntry *te = lfirst(plan->targetlist); TargetEntry *te = lfirst(plan->targetlist);
Param *prm;
/* need a var node just to pass to new_param()... */ prm = generate_new_param(te->resdom->restype, te->resdom->restypmod);
Var *var = makeVar(0, 0, te->resdom->restype,
te->resdom->restypmod, 0);
Param *prm = makeNode(Param);
prm->paramkind = PARAM_EXEC;
prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
prm->paramtype = var->vartype;
pfree(var); /* var is only needed for new_param */
node->setParam = lappendi(node->setParam, prm->paramid); node->setParam = lappendi(node->setParam, prm->paramid);
PlannerInitPlan = lappend(PlannerInitPlan, node); PlannerInitPlan = lappend(PlannerInitPlan, node);
result = (Node *) prm; result = (Node *) prm;
} }
else if (node->parParam == NIL && slink->subLinkType == MULTIEXPR_SUBLINK) else if (node->parParam == NIL && slink->subLinkType == MULTIEXPR_SUBLINK)
{ {
List *newoper = NIL; convert_sublink_opers(slink, plan->targetlist, &node->setParam);
int i = 0;
/*
* Convert oper list of Opers into a list of Exprs, using lefthand
* arguments and Params representing inside results.
*/
foreach(lst, slink->oper)
{
Oper *oper = (Oper *) lfirst(lst);
Node *lefthand = nth(i, slink->lefthand);
TargetEntry *te = nth(i, plan->targetlist);
/* need a var node just to pass to new_param()... */
Var *var = makeVar(0, 0, te->resdom->restype,
te->resdom->restypmod, 0);
Param *prm = makeNode(Param);
Operator tup;
Form_pg_operator opform;
Node *left,
*right;
prm->paramkind = PARAM_EXEC;
prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
prm->paramtype = var->vartype;
pfree(var); /* var is only needed for new_param */
Assert(IsA(oper, Oper));
tup = SearchSysCache(OPEROID,
ObjectIdGetDatum(oper->opno),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for operator %u", oper->opno);
opform = (Form_pg_operator) GETSTRUCT(tup);
/*
* Note: we use make_operand in case runtime type conversion
* function calls must be inserted for this operator!
*/
left = make_operand(lefthand,
exprType(lefthand), opform->oprleft);
right = make_operand((Node *) prm,
prm->paramtype, opform->oprright);
ReleaseSysCache(tup);
newoper = lappend(newoper,
make_opclause(oper,
(Var *) left,
(Var *) right));
node->setParam = lappendi(node->setParam, prm->paramid);
i++;
}
slink->oper = newoper;
slink->lefthand = NIL;
PlannerInitPlan = lappend(PlannerInitPlan, node); PlannerInitPlan = lappend(PlannerInitPlan, node);
if (i > 1) if (length(slink->oper) > 1)
result = (Node *) ((slink->useor) ? make_orclause(newoper) : result = (Node *) ((slink->useor) ? make_orclause(slink->oper) :
make_andclause(newoper)); make_andclause(slink->oper));
else else
result = (Node *) lfirst(newoper); result = (Node *) lfirst(slink->oper);
} }
else else
{ {
Expr *expr = makeNode(Expr); Expr *expr = makeNode(Expr);
List *args = NIL; List *args = NIL;
List *newoper = NIL;
int i = 0;
/* /*
* We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types
@ -379,6 +337,9 @@ make_subplan(SubLink *slink)
} }
} }
/* Fix the SubLink's oper list */
convert_sublink_opers(slink, plan->targetlist, NULL);
/* /*
* Make expression of SUBPLAN type * Make expression of SUBPLAN type
*/ */
@ -405,55 +366,84 @@ make_subplan(SubLink *slink)
} }
expr->args = args; expr->args = args;
/*
* Convert oper list of Opers into a list of Exprs, using lefthand
* arguments and Consts representing inside results.
*/
foreach(lst, slink->oper)
{
Oper *oper = (Oper *) lfirst(lst);
Node *lefthand = nth(i, slink->lefthand);
TargetEntry *te = nth(i, plan->targetlist);
Const *con;
Operator tup;
Form_pg_operator opform;
Node *left,
*right;
con = makeNullConst(te->resdom->restype);
Assert(IsA(oper, Oper));
tup = SearchSysCache(OPEROID,
ObjectIdGetDatum(oper->opno),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for operator %u", oper->opno);
opform = (Form_pg_operator) GETSTRUCT(tup);
/*
* Note: we use make_operand in case runtime type conversion
* function calls must be inserted for this operator!
*/
left = make_operand(lefthand,
exprType(lefthand), opform->oprleft);
right = make_operand((Node *) con,
con->consttype, opform->oprright);
ReleaseSysCache(tup);
newoper = lappend(newoper,
make_opclause(oper,
(Var *) left,
(Var *) right));
i++;
}
slink->oper = newoper;
slink->lefthand = NIL;
result = (Node *) expr; result = (Node *) expr;
} }
return result; return result;
} }
/*
* convert_sublink_opers: convert a SubLink's oper list from the
* parser/rewriter format into the executor's format.
*
* The oper list is initially just a list of Oper nodes. We replace it
* with a list of actually executable expressions, in which the specified
* operators are applied to corresponding elements of the lefthand list
* and Params representing the results of the subplan. lefthand is then
* set to NIL.
*
* If setParams is not NULL, the paramids of the Params created are added
* to the *setParams list.
*/
static void
convert_sublink_opers(SubLink *slink, List *targetlist,
List **setParams)
{
List *newoper = NIL;
List *leftlist = slink->lefthand;
List *lst;
foreach(lst, slink->oper)
{
Oper *oper = (Oper *) lfirst(lst);
Node *lefthand = lfirst(leftlist);
TargetEntry *te = lfirst(targetlist);
Param *prm;
Operator tup;
Form_pg_operator opform;
Node *left,
*right;
/* Make the Param node representing the subplan's result */
prm = generate_new_param(te->resdom->restype,
te->resdom->restypmod);
/* Record its ID if needed */
if (setParams)
*setParams = lappendi(*setParams, prm->paramid);
/* Look up the operator to check its declared input types */
Assert(IsA(oper, Oper));
tup = SearchSysCache(OPEROID,
ObjectIdGetDatum(oper->opno),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for operator %u", oper->opno);
opform = (Form_pg_operator) GETSTRUCT(tup);
/*
* Make the expression node.
*
* Note: we use make_operand in case runtime type conversion
* function calls must be inserted for this operator!
*/
left = make_operand(lefthand, exprType(lefthand), opform->oprleft);
right = make_operand((Node *) prm, prm->paramtype, opform->oprright);
newoper = lappend(newoper,
make_opclause(oper,
(Var *) left,
(Var *) right));
ReleaseSysCache(tup);
leftlist = lnext(leftlist);
targetlist = lnext(targetlist);
}
slink->oper = newoper;
slink->lefthand = NIL;
}
/* /*
* finalize_primnode: build lists of subplans and params appearing * finalize_primnode: build lists of subplans and params appearing
* in the given expression tree. NOTE: items are added to lists passed in, * in the given expression tree. NOTE: items are added to lists passed in,

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.112 2002/11/25 21:29:40 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.113 2002/11/26 03:01:58 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
@ -1135,14 +1135,6 @@ CommuteClause(Expr *clause)
* *
* We assume that the tree has already been type-checked and contains * We assume that the tree has already been type-checked and contains
* only operators and functions that are reasonable to try to execute. * only operators and functions that are reasonable to try to execute.
*
* This routine should be invoked before converting sublinks to subplans
* (subselect.c's SS_process_sublinks()). The converted form contains
* bogus "Const" nodes that are actually placeholders where the executor
* will insert values from the inner plan, and obviously we mustn't try
* to reduce the expression as though these were really constants.
* As a safeguard, if we happen to find an already-converted SubPlan node,
* we will return it unchanged rather than recursing into it.
*-------------------- *--------------------
*/ */
Node * Node *
@ -1411,11 +1403,13 @@ eval_const_expressions_mutator(Node *node, void *context)
case SUBPLAN_EXPR: case SUBPLAN_EXPR:
/* /*
* Safety measure per notes at head of this routine: * Return a SubPlan unchanged --- too late to do anything
* return a SubPlan unchanged. Too late to do anything
* with it. The arglist simplification above was wasted * with it. The arglist simplification above was wasted
* work (the list probably only contains Var nodes * work (the list probably only contains Var nodes
* anyway). * anyway).
*
* XXX should we elog() here instead? Probably this routine
* should never be invoked after SubPlan creation.
*/ */
return (Node *) expr; return (Node *) expr;
default: default:
@ -1629,7 +1623,6 @@ simplify_op_or_func(Expr *expr, List *args)
* *
* Note we take the result type from the Oper or Func node, not the * Note we take the result type from the Oper or Func node, not the
* pg_proc tuple; probably necessary for binary-compatibility cases. * pg_proc tuple; probably necessary for binary-compatibility cases.
*
*/ */
if (expr->opType == OP_EXPR) if (expr->opType == OP_EXPR)
{ {

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.87 2002/11/25 21:29:41 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.88 2002/11/26 03:01:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -241,14 +241,8 @@ coerce_type(Node *node, Oid inputTypeId, Oid targetTypeId,
* *
* Note that no folding will occur if the conversion function is * Note that no folding will occur if the conversion function is
* not marked 'immutable'. * not marked 'immutable'.
*
* HACK: if constant is NULL, don't fold it here. This is needed
* by make_subplan(), which calls this routine on placeholder
* Const nodes that mustn't be collapsed. (It'd be a lot
* cleaner to make a separate node type for that purpose...)
*/ */
if (IsA(node, Const) && if (IsA(node, Const))
!((Const *) node)->constisnull)
result = eval_const_expressions(result); result = eval_const_expressions(result);
} }
else else

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.130 2002/11/15 02:50:09 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.131 2002/11/26 03:01:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -122,7 +122,6 @@ transformExpr(ParseState *pstate, Node *expr, ConstraintTestValue *domVal)
param = makeNode(Param); param = makeNode(Param);
param->paramkind = PARAM_NUM; param->paramkind = PARAM_NUM;
param->paramid = (AttrNumber) paramno; param->paramid = (AttrNumber) paramno;
param->paramname = "<unnamed>";
param->paramtype = paramtyp; param->paramtype = paramtyp;
result = (Node *) param; result = (Node *) param;
/* handle qualification, if any */ /* handle qualification, if any */

View File

@ -3,7 +3,7 @@
* back to source text * back to source text
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.126 2002/11/25 21:29:41 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.127 2002/11/26 03:01:58 tgl Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
@ -1921,7 +1921,6 @@ get_rule_expr(Node *node, deparse_context *context,
* same expression tree. * same expression tree.
* *
* There might be some work left here to support additional node types. * There might be some work left here to support additional node types.
* Can we ever see Param nodes here?
*/ */
switch (nodeTag(node)) switch (nodeTag(node))
{ {

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: primnodes.h,v 1.69 2002/11/25 21:29:42 tgl Exp $ * $Id: primnodes.h,v 1.70 2002/11/26 03:01:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -357,7 +357,7 @@ typedef struct Aggref
* 3. Finally, the planner converts the oper list to a list of normal Expr * 3. Finally, the planner converts the oper list to a list of normal Expr
* nodes representing the application of the operator(s) to the lefthand * nodes representing the application of the operator(s) to the lefthand
* expressions and values from the inner targetlist. The inner * expressions and values from the inner targetlist. The inner
* targetlist items are represented by placeholder Param or Const nodes. * targetlist items are represented by placeholder Param nodes.
* The lefthand field is set to NIL, since its expressions are now in * The lefthand field is set to NIL, since its expressions are now in
* the Expr list. This representation is passed to the executor. * the Expr list. This representation is passed to the executor.
* *