diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index f660a57da2..1bd0ef2cd1 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.129 2009/01/01 17:23:40 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.130 2009/01/09 15:46:10 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -50,7 +50,7 @@ #include "executor/executor.h" #include "miscadmin.h" #include "nodes/makefuncs.h" -#include "optimizer/planmain.h" +#include "optimizer/planner.h" #include "optimizer/var.h" #include "parser/parse_coerce.h" #include "parser/parse_expr.h" @@ -2390,8 +2390,8 @@ GetDomainConstraints(Oid typeOid) check_expr = (Expr *) stringToNode(TextDatumGetCString(val)); - /* ExecInitExpr assumes we already fixed opfuncids */ - fix_opfuncids((Node *) check_expr); + /* ExecInitExpr assumes we've planned the expression */ + check_expr = expression_planner(check_expr); r = makeNode(DomainConstraintState); r->constrainttype = DOM_CONSTRAINT_CHECK; diff --git a/src/backend/executor/README b/src/backend/executor/README index 7644cc2cc4..467d6272d1 100644 --- a/src/backend/executor/README +++ b/src/backend/executor/README @@ -1,4 +1,4 @@ -$PostgreSQL: pgsql/src/backend/executor/README,v 1.7 2008/03/21 13:23:28 momjian Exp $ +$PostgreSQL: pgsql/src/backend/executor/README,v 1.8 2009/01/09 15:46:10 tgl Exp $ The Postgres Executor ===================== @@ -124,7 +124,8 @@ be hidden inside function calls). This case has a flow of control like creates per-tuple context ExecPrepareExpr - switch to per-query context to run ExecInitExpr + temporarily switch to per-query context + run the expression through expression_planner ExecInitExpr Repeatedly do: diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index ed53a62e38..f74a5da6b2 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.240 2009/01/01 17:23:41 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.241 2009/01/09 15:46:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -45,7 +45,7 @@ #include "miscadmin.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" -#include "optimizer/planmain.h" +#include "optimizer/planner.h" #include "pgstat.h" #include "utils/acl.h" #include "utils/builtins.h" @@ -4794,10 +4794,11 @@ ExecInitExpr(Expr *node, PlanState *parent) * Plan tree context. * * This differs from ExecInitExpr in that we don't assume the caller is - * already running in the EState's per-query context. Also, we apply - * fix_opfuncids() to the passed expression tree to be sure it is ready - * to run. (In ordinary Plan trees the planner will have fixed opfuncids, - * but callers outside the executor will not have done this.) + * already running in the EState's per-query context. Also, we run the + * passed expression tree through expression_planner() to prepare it for + * execution. (In ordinary Plan trees the regular planning process will have + * made the appropriate transformations on expressions, but for standalone + * expressions this won't have happened.) */ ExprState * ExecPrepareExpr(Expr *node, EState *estate) @@ -4805,10 +4806,10 @@ ExecPrepareExpr(Expr *node, EState *estate) ExprState *result; MemoryContext oldcontext; - fix_opfuncids((Node *) node); - oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); + node = expression_planner(node); + result = ExecInitExpr(node, NULL); MemoryContextSwitchTo(oldcontext); diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 841d85f739..34747d0f97 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.250 2009/01/01 17:23:44 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.251 2009/01/09 15:46:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2576,3 +2576,39 @@ get_column_info_for_window(PlannerInfo *root, WindowClause *wc, List *tlist, elog(ERROR, "failed to deconstruct sort operators into partitioning/ordering operators"); } } + + +/* + * expression_planner + * Perform planner's transformations on a standalone expression. + * + * Various utility commands need to evaluate expressions that are not part + * of a plannable query. They can do so using the executor's regular + * expression-execution machinery, but first the expression has to be fed + * through here to transform it from parser output to something executable. + * + * Currently, we disallow sublinks in standalone expressions, so there's no + * real "planning" involved here. (That might not always be true though.) + * What we must do is run eval_const_expressions to ensure that any function + * default arguments get inserted. The fact that constant subexpressions + * get simplified is a side-effect that is useful when the expression will + * get evaluated more than once. Also, we must fix operator function IDs. + * + * Note: this must not make any damaging changes to the passed-in expression + * tree. (It would actually be okay to apply fix_opfuncids to it, but since + * we first do an expression_tree_mutator-based walk, what is returned will + * be a new node tree.) + */ +Expr * +expression_planner(Expr *expr) +{ + Node *result; + + /* Insert default arguments and simplify constant subexprs */ + result = eval_const_expressions(NULL, (Node *) expr); + + /* Fill in opfuncid values if missing */ + fix_opfuncids(result); + + return (Expr *) result; +} diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index a0205d7b8c..65c9b61458 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.274 2009/01/06 01:23:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.275 2009/01/09 15:46:10 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -2018,6 +2018,9 @@ rowtype_field_matches(Oid rowtypeid, int fieldnum, * * NOTE: the planner assumes that this will always flatten nested AND and * OR clauses into N-argument form. See comments in prepqual.c. + * + * NOTE: another critical effect is that any function calls that require + * default arguments will be expanded. *-------------------- */ Node * @@ -3854,10 +3857,14 @@ evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod) /* We can use the estate's working context to avoid memory leaks. */ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); + /* Make sure any opfuncids are filled in. */ + fix_opfuncids((Node *) expr); + /* - * Prepare expr for execution. + * Prepare expr for execution. (Note: we can't use ExecPrepareExpr + * because it'd result in recursively invoking eval_const_expressions.) */ - exprstate = ExecPrepareExpr(expr, estate); + exprstate = ExecInitExpr(expr, NULL); /* * And evaluate it. diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c index 4bbcb2fe22..678f560978 100644 --- a/src/backend/optimizer/util/predtest.c +++ b/src/backend/optimizer/util/predtest.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.23 2009/01/01 17:23:45 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.24 2009/01/09 15:46:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,6 +22,7 @@ #include "miscadmin.h" #include "nodes/nodeFuncs.h" #include "optimizer/clauses.h" +#include "optimizer/planmain.h" #include "optimizer/predtest.h" #include "utils/array.h" #include "utils/inval.h" @@ -1405,8 +1406,11 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it) (Expr *) pred_const, (Expr *) clause_const); + /* Fill in opfuncids */ + fix_opfuncids((Node *) test_expr); + /* Prepare it for execution */ - test_exprstate = ExecPrepareExpr(test_expr, estate); + test_exprstate = ExecInitExpr(test_expr, NULL); /* And execute it. */ test_result = ExecEvalExprSwitchContext(test_exprstate, diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h index a00bc4b1cf..ec43663b29 100644 --- a/src/include/optimizer/planner.h +++ b/src/include/optimizer/planner.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.46 2009/01/01 17:24:00 momjian Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.47 2009/01/09 15:46:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,9 +29,12 @@ extern PlannedStmt *planner(Query *parse, int cursorOptions, ParamListInfo boundParams); extern PlannedStmt *standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams); + extern Plan *subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction, PlannerInfo **subroot); +extern Expr *expression_planner(Expr *expr); + #endif /* PLANNER_H */