88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.219 2006/08/12 20:05:55 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.220 2006/09/06 20:40:47 tgl Exp $
1212 *
1313 * HISTORY
1414 * AUTHOR DATE MAJOR EVENT
@@ -1462,7 +1462,9 @@ eval_const_expressions(Node *node)
14621462 *
14631463 * Currently the extra steps that are taken in this mode are:
14641464 * 1. Substitute values for Params, where a bound Param value has been made
1465- * available by the caller of planner().
1465+ * available by the caller of planner(), even if the Param isn't marked
1466+ * constant. This effectively means that we plan using the first supplied
1467+ * value of the Param.
14661468 * 2. Fold stable, as well as immutable, functions to constants.
14671469 *--------------------
14681470 */
@@ -1487,33 +1489,38 @@ eval_const_expressions_mutator(Node *node,
14871489 {
14881490 Param * param = (Param * ) node ;
14891491
1490- /* OK to try to substitute value? */
1491- if (context -> estimate && param -> paramkind == PARAM_EXTERN &&
1492- PlannerBoundParamList != NULL )
1492+ /* Look to see if we've been given a value for this Param */
1493+ if (param -> paramkind == PARAM_EXTERN &&
1494+ PlannerBoundParamList != NULL &&
1495+ param -> paramid > 0 &&
1496+ param -> paramid <= PlannerBoundParamList -> numParams )
14931497 {
1494- /* Look to see if we've been given a value for this Param */
1495- if (param -> paramid > 0 &&
1496- param -> paramid <= PlannerBoundParamList -> numParams )
1497- {
1498- ParamExternData * prm = & PlannerBoundParamList -> params [param -> paramid - 1 ];
1498+ ParamExternData * prm = & PlannerBoundParamList -> params [param -> paramid - 1 ];
14991499
1500- if (OidIsValid (prm -> ptype ))
1500+ if (OidIsValid (prm -> ptype ))
1501+ {
1502+ /* OK to substitute parameter value? */
1503+ if (context -> estimate || (prm -> pflags & PARAM_FLAG_CONST ))
15011504 {
15021505 /*
1503- * Found it, so return a Const representing the param
1504- * value. Note that we don't copy pass-by-ref datatypes,
1505- * so the Const will only be valid as long as the bound
1506- * parameter list exists. This is okay for intended uses
1507- * of estimate_expression_value().
1506+ * Return a Const representing the param value. Must copy
1507+ * pass-by-ref datatypes, since the Param might be in a
1508+ * memory context shorter-lived than our output plan
1509+ * should be.
15081510 */
15091511 int16 typLen ;
15101512 bool typByVal ;
1513+ Datum pval ;
15111514
15121515 Assert (prm -> ptype == param -> paramtype );
15131516 get_typlenbyval (param -> paramtype , & typLen , & typByVal );
1517+ if (prm -> isnull || typByVal )
1518+ pval = prm -> value ;
1519+ else
1520+ pval = datumCopy (prm -> value , typByVal , typLen );
15141521 return (Node * ) makeConst (param -> paramtype ,
15151522 (int ) typLen ,
1516- prm -> value ,
1523+ pval ,
15171524 prm -> isnull ,
15181525 typByVal );
15191526 }
@@ -3016,10 +3023,9 @@ evaluate_expr(Expr *expr, Oid result_type)
30163023 * stage. In particular, it handles List nodes since a cnf-ified qual clause
30173024 * will have List structure at the top level, and it handles TargetEntry nodes
30183025 * so that a scan of a target list can be handled without additional code.
3019- * (But only the "expr" part of a TargetEntry is examined, unless the walker
3020- * chooses to process TargetEntry nodes specially.) Also, RangeTblRef,
3021- * FromExpr, JoinExpr, and SetOperationStmt nodes are handled, so that query
3022- * jointrees and setOperation trees can be processed without additional code.
3026+ * Also, RangeTblRef, FromExpr, JoinExpr, and SetOperationStmt nodes are
3027+ * handled, so that query jointrees and setOperation trees can be processed
3028+ * without additional code.
30233029 *
30243030 * expression_tree_walker will handle SubLink nodes by recursing normally
30253031 * into the "testexpr" subtree (which is an expression belonging to the outer
@@ -3364,6 +3370,38 @@ query_tree_walker(Query *query,
33643370 return true;
33653371 if (range_table_walker (query -> rtable , walker , context , flags ))
33663372 return true;
3373+ if (query -> utilityStmt )
3374+ {
3375+ /*
3376+ * Certain utility commands contain general-purpose Querys embedded
3377+ * in them --- if this is one, invoke the walker on the sub-Query.
3378+ */
3379+ if (IsA (query -> utilityStmt , CopyStmt ))
3380+ {
3381+ if (walker (((CopyStmt * ) query -> utilityStmt )-> query , context ))
3382+ return true;
3383+ }
3384+ if (IsA (query -> utilityStmt , DeclareCursorStmt ))
3385+ {
3386+ if (walker (((DeclareCursorStmt * ) query -> utilityStmt )-> query , context ))
3387+ return true;
3388+ }
3389+ if (IsA (query -> utilityStmt , ExplainStmt ))
3390+ {
3391+ if (walker (((ExplainStmt * ) query -> utilityStmt )-> query , context ))
3392+ return true;
3393+ }
3394+ if (IsA (query -> utilityStmt , PrepareStmt ))
3395+ {
3396+ if (walker (((PrepareStmt * ) query -> utilityStmt )-> query , context ))
3397+ return true;
3398+ }
3399+ if (IsA (query -> utilityStmt , ViewStmt ))
3400+ {
3401+ if (walker (((ViewStmt * ) query -> utilityStmt )-> query , context ))
3402+ return true;
3403+ }
3404+ }
33673405 return false;
33683406}
33693407
0 commit comments