mirror of https://github.com/postgres/postgres
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:
parent
ac47950238
commit
ea0b5c8569
|
@ -7,7 +7,7 @@
|
|||
*
|
||||
*
|
||||
* 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;
|
||||
Oid *elements;
|
||||
Node **constraintexprs;
|
||||
Const **constraintconsts;
|
||||
bool hasConstraints = false;
|
||||
int i;
|
||||
List *cur;
|
||||
|
@ -805,7 +804,6 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||
defmap = (int *) palloc(num_phys_attrs * sizeof(int));
|
||||
defexprs = (Node **) palloc(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++)
|
||||
{
|
||||
|
@ -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 (get_typtype(attr[i]->atttypid) == 'd')
|
||||
{
|
||||
Const *con;
|
||||
Param *prm;
|
||||
Node *node;
|
||||
|
||||
/*
|
||||
|
@ -848,28 +846,21 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||
* an expression that checks the constraints. (At present,
|
||||
* the expression might contain a length-coercion-function call
|
||||
* 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.
|
||||
*
|
||||
* 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,
|
||||
attr[i]->attlen,
|
||||
(Datum) 0,
|
||||
true, /* is null */
|
||||
attr[i]->attbyval);
|
||||
prm = makeNode(Param);
|
||||
prm->paramkind = PARAM_EXEC;
|
||||
prm->paramid = 0;
|
||||
prm->paramtype = attr[i]->atttypid;
|
||||
|
||||
node = coerce_type_constraints((Node *) con, attr[i]->atttypid,
|
||||
node = coerce_type_constraints((Node *) prm, attr[i]->atttypid,
|
||||
COERCE_IMPLICIT_CAST);
|
||||
|
||||
/* check whether any constraints actually found */
|
||||
if (node != (Node *) con)
|
||||
if (node != (Node *) prm)
|
||||
{
|
||||
constraintexprs[i] = node;
|
||||
constraintconsts[i] = con;
|
||||
hasConstraints = true;
|
||||
}
|
||||
}
|
||||
|
@ -931,6 +922,11 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||
|
||||
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)
|
||||
{
|
||||
bool skip_tuple;
|
||||
|
@ -1153,19 +1149,19 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
|
|||
*/
|
||||
if (hasConstraints)
|
||||
{
|
||||
ParamExecData *prmdata = &econtext->ecxt_param_exec_vals[0];
|
||||
|
||||
for (i = 0; i < num_phys_attrs; i++)
|
||||
{
|
||||
Node *node = constraintexprs[i];
|
||||
Const *con;
|
||||
bool isnull;
|
||||
|
||||
if (node == NULL)
|
||||
continue; /* no constraint for this attr */
|
||||
|
||||
/* Insert current row's value into the Const node */
|
||||
con = constraintconsts[i];
|
||||
con->constvalue = values[i];
|
||||
con->constisnull = (nulls[i] == 'n');
|
||||
/* Insert current row's value into the Param value */
|
||||
prmdata->value = values[i];
|
||||
prmdata->isnull = (nulls[i] == 'n');
|
||||
|
||||
/*
|
||||
* Execute the constraint expression. Allow the expression
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
Expr *expr = (Expr *) lfirst(lst);
|
||||
Const *con = lsecond(expr->args);
|
||||
Param *prm = lsecond(expr->args);
|
||||
ParamExecData *prmdata;
|
||||
Datum expresult;
|
||||
bool expnull;
|
||||
|
||||
/*
|
||||
* 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
|
||||
* inserted by the parser to get to the input type needed by
|
||||
* the operator). Find the Const node and insert the actual
|
||||
* righthand-side value into it.
|
||||
* the operator). Find the Param node and insert the actual
|
||||
* 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:
|
||||
con = lfirst(((Expr *) con)->args);
|
||||
prm = lfirst(((Expr *) prm)->args);
|
||||
break;
|
||||
case T_RelabelType:
|
||||
con = (Const *) (((RelabelType *) con)->arg);
|
||||
prm = (Param *) (((RelabelType *) prm)->arg);
|
||||
break;
|
||||
default:
|
||||
/* will fail below */
|
||||
break;
|
||||
}
|
||||
if (!IsA(con, Const))
|
||||
if (!IsA(prm, Param))
|
||||
elog(ERROR, "ExecSubPlan: failed to find placeholder for subplan result");
|
||||
}
|
||||
con->constvalue = heap_getattr(tup, col, tdesc,
|
||||
&(con->constisnull));
|
||||
Assert(prm->paramkind == PARAM_EXEC);
|
||||
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.
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
*
|
||||
* 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
|
||||
* 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);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* 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
|
||||
* recursion level. But we must pay attention not to confuse this
|
||||
* 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.
|
||||
*
|
||||
* var contains the data to be copied, except for varlevelsup which
|
||||
* is set from the absolute level value given by varlevel.
|
||||
* var contains the data to use, except for varlevelsup which
|
||||
* 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
|
||||
new_param(Var *var, Index varlevel)
|
||||
{
|
||||
Var *paramVar = (Var *) copyObject(var);
|
||||
var->varlevelsup = varlevel;
|
||||
|
||||
paramVar->varlevelsup = varlevel;
|
||||
|
||||
PlannerParamVar = lappend(PlannerParamVar, paramVar);
|
||||
PlannerParamVar = lappend(PlannerParamVar, var);
|
||||
|
||||
return length(PlannerParamVar) - 1;
|
||||
}
|
||||
|
@ -107,7 +115,7 @@ replace_var(Var *var)
|
|||
if (!ppv)
|
||||
{
|
||||
/* Nope, so make a new one */
|
||||
i = new_param(var, varlevel);
|
||||
i = new_param((Var *) copyObject(var), varlevel);
|
||||
}
|
||||
|
||||
retval = makeNode(Param);
|
||||
|
@ -118,6 +126,22 @@ replace_var(Var *var)
|
|||
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.
|
||||
*/
|
||||
|
@ -216,13 +240,9 @@ make_subplan(SubLink *slink)
|
|||
*/
|
||||
if (node->parParam == NIL && slink->subLinkType == EXISTS_SUBLINK)
|
||||
{
|
||||
Var *var = makeVar(0, 0, BOOLOID, -1, 0);
|
||||
Param *prm = makeNode(Param);
|
||||
Param *prm;
|
||||
|
||||
prm->paramkind = PARAM_EXEC;
|
||||
prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
|
||||
prm->paramtype = var->vartype;
|
||||
pfree(var); /* var is only needed for new_param */
|
||||
prm = generate_new_param(BOOLOID, -1);
|
||||
node->setParam = lappendi(node->setParam, prm->paramid);
|
||||
PlannerInitPlan = lappend(PlannerInitPlan, node);
|
||||
result = (Node *) prm;
|
||||
|
@ -230,89 +250,27 @@ make_subplan(SubLink *slink)
|
|||
else if (node->parParam == NIL && slink->subLinkType == EXPR_SUBLINK)
|
||||
{
|
||||
TargetEntry *te = lfirst(plan->targetlist);
|
||||
Param *prm;
|
||||
|
||||
/* 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);
|
||||
|
||||
prm->paramkind = PARAM_EXEC;
|
||||
prm->paramid = (AttrNumber) new_param(var, PlannerQueryLevel);
|
||||
prm->paramtype = var->vartype;
|
||||
pfree(var); /* var is only needed for new_param */
|
||||
prm = generate_new_param(te->resdom->restype, te->resdom->restypmod);
|
||||
node->setParam = lappendi(node->setParam, prm->paramid);
|
||||
PlannerInitPlan = lappend(PlannerInitPlan, node);
|
||||
result = (Node *) prm;
|
||||
}
|
||||
else if (node->parParam == NIL && slink->subLinkType == MULTIEXPR_SUBLINK)
|
||||
{
|
||||
List *newoper = NIL;
|
||||
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;
|
||||
convert_sublink_opers(slink, plan->targetlist, &node->setParam);
|
||||
PlannerInitPlan = lappend(PlannerInitPlan, node);
|
||||
if (i > 1)
|
||||
result = (Node *) ((slink->useor) ? make_orclause(newoper) :
|
||||
make_andclause(newoper));
|
||||
if (length(slink->oper) > 1)
|
||||
result = (Node *) ((slink->useor) ? make_orclause(slink->oper) :
|
||||
make_andclause(slink->oper));
|
||||
else
|
||||
result = (Node *) lfirst(newoper);
|
||||
result = (Node *) lfirst(slink->oper);
|
||||
}
|
||||
else
|
||||
{
|
||||
Expr *expr = makeNode(Expr);
|
||||
List *args = NIL;
|
||||
List *newoper = NIL;
|
||||
int i = 0;
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
@ -405,55 +366,84 @@ make_subplan(SubLink *slink)
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
* in the given expression tree. NOTE: items are added to lists passed in,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
*
|
||||
* 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
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
|
@ -1135,14 +1135,6 @@ CommuteClause(Expr *clause)
|
|||
*
|
||||
* We assume that the tree has already been type-checked and contains
|
||||
* 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 *
|
||||
|
@ -1411,11 +1403,13 @@ eval_const_expressions_mutator(Node *node, void *context)
|
|||
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
|
||||
* work (the list probably only contains Var nodes
|
||||
* anyway).
|
||||
*
|
||||
* XXX should we elog() here instead? Probably this routine
|
||||
* should never be invoked after SubPlan creation.
|
||||
*/
|
||||
return (Node *) expr;
|
||||
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
|
||||
* pg_proc tuple; probably necessary for binary-compatibility cases.
|
||||
*
|
||||
*/
|
||||
if (expr->opType == OP_EXPR)
|
||||
{
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
*
|
||||
* 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
|
||||
* 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) &&
|
||||
!((Const *) node)->constisnull)
|
||||
if (IsA(node, Const))
|
||||
result = eval_const_expressions(result);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
*
|
||||
* 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->paramkind = PARAM_NUM;
|
||||
param->paramid = (AttrNumber) paramno;
|
||||
param->paramname = "<unnamed>";
|
||||
param->paramtype = paramtyp;
|
||||
result = (Node *) param;
|
||||
/* handle qualification, if any */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* back to source text
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
|
@ -1921,7 +1921,6 @@ get_rule_expr(Node *node, deparse_context *context,
|
|||
* same expression tree.
|
||||
*
|
||||
* There might be some work left here to support additional node types.
|
||||
* Can we ever see Param nodes here?
|
||||
*/
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
|
|
|
@ -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.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
|
||||
* nodes representing the application of the operator(s) to the lefthand
|
||||
* 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 Expr list. This representation is passed to the executor.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue