aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/commands/typecmds.c8
-rw-r--r--src/backend/executor/README5
-rw-r--r--src/backend/executor/execQual.c17
-rw-r--r--src/backend/optimizer/plan/planner.c38
-rw-r--r--src/backend/optimizer/util/clauses.c13
-rw-r--r--src/backend/optimizer/util/predtest.c8
-rw-r--r--src/include/optimizer/planner.h5
7 files changed, 73 insertions, 21 deletions
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index f660a57da23..1bd0ef2cd13 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 7644cc2cc42..467d6272d1e 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 ed53a62e383..f74a5da6b28 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 841d85f7397..34747d0f971 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 a0205d7b8c6..65c9b614584 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 4bbcb2fe229..678f560978d 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 a00bc4b1cf7..ec43663b292 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 */