]> granicus.if.org Git - postgresql/blobdiff - src/backend/optimizer/plan/planner.c
Add support for multi-row VALUES clauses as part of INSERT statements
[postgresql] / src / backend / optimizer / plan / planner.c
index 680bc1521c224db8087c6740dcbe6ab37133a8c1..42ae15cd4832fdc029dec3ccc5263f943dac43e3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.202 2006/07/11 17:26:58 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.206 2006/08/02 01:59:46 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,7 +18,6 @@
 #include <limits.h>
 
 #include "catalog/pg_operator.h"
-#include "catalog/pg_type.h"
 #include "executor/executor.h"
 #include "executor/nodeAgg.h"
 #include "miscadmin.h"
@@ -39,7 +38,6 @@
 #include "parser/parse_expr.h"
 #include "parser/parse_oper.h"
 #include "parser/parsetree.h"
-#include "utils/selfuncs.h"
 #include "utils/syscache.h"
 
 
@@ -50,9 +48,10 @@ ParamListInfo PlannerBoundParamList = NULL;          /* current boundParams */
 #define EXPRKIND_QUAL          0
 #define EXPRKIND_TARGET                1
 #define EXPRKIND_RTFUNC                2
-#define EXPRKIND_LIMIT         3
-#define EXPRKIND_ININFO                4
-#define EXPRKIND_APPINFO       5
+#define EXPRKIND_VALUES                3
+#define EXPRKIND_LIMIT         4
+#define EXPRKIND_ININFO                5
+#define EXPRKIND_APPINFO       6
 
 
 static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
@@ -61,7 +60,7 @@ static Plan *inheritance_planner(PlannerInfo *root);
 static Plan *grouping_planner(PlannerInfo *root, double tuple_fraction);
 static double preprocess_limit(PlannerInfo *root,
                                 double tuple_fraction,
-                                int *offset_est, int *count_est);
+                                int64 *offset_est, int64 *count_est);
 static bool choose_hashed_grouping(PlannerInfo *root, double tuple_fraction,
                                           Path *cheapest_path, Path *sorted_path,
                                           double dNumGroups, AggClauseCounts *agg_counts);
@@ -297,7 +296,7 @@ subquery_planner(Query *parse, double tuple_fraction,
                preprocess_expression(root, (Node *) root->append_rel_list,
                                                          EXPRKIND_APPINFO);
 
-       /* Also need to preprocess expressions for function RTEs */
+       /* Also need to preprocess expressions for function and values RTEs */
        foreach(l, parse->rtable)
        {
                RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
@@ -305,6 +304,10 @@ subquery_planner(Query *parse, double tuple_fraction,
                if (rte->rtekind == RTE_FUNCTION)
                        rte->funcexpr = preprocess_expression(root, rte->funcexpr,
                                                                                                  EXPRKIND_RTFUNC);
+               else if (rte->rtekind == RTE_VALUES)
+                       rte->values_lists = (List *)
+                               preprocess_expression(root, (Node *) rte->values_lists,
+                                                                         EXPRKIND_VALUES);
        }
 
        /*
@@ -420,8 +423,10 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
         * If the query has any join RTEs, replace join alias variables with
         * base-relation variables. We must do this before sublink processing,
         * else sublinks expanded out from join aliases wouldn't get processed.
+        * We can skip it in VALUES lists, however, since they can't contain
+        * any Vars at all.
         */
-       if (root->hasJoinRTEs)
+       if (root->hasJoinRTEs && kind != EXPRKIND_VALUES)
                expr = flatten_join_alias_vars(root, expr);
 
        /*
@@ -439,10 +444,14 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
         * and we will waste cycles copying the tree.  Notice however that we
         * still must do it for quals (to get AND/OR flatness); and if we are in a
         * subquery we should not assume it will be done only once.
+        *
+        * For VALUES lists we never do this at all, again on the grounds that
+        * we should optimize for one-time evaluation.
         */
-       if (root->parse->jointree->fromlist != NIL ||
-               kind == EXPRKIND_QUAL ||
-               PlannerQueryLevel > 1)
+       if (kind != EXPRKIND_VALUES &&
+               (root->parse->jointree->fromlist != NIL ||
+                kind == EXPRKIND_QUAL ||
+                PlannerQueryLevel > 1))
                expr = eval_const_expressions(expr);
 
        /*
@@ -467,7 +476,7 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
         * SS_replace_correlation_vars ...
         */
 
-       /* Replace uplevel vars with Param nodes */
+       /* Replace uplevel vars with Param nodes (this IS possible in VALUES) */
        if (PlannerQueryLevel > 1)
                expr = SS_replace_correlation_vars(expr);
 
@@ -633,8 +642,8 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
 {
        Query      *parse = root->parse;
        List       *tlist = parse->targetList;
-       int                     offset_est = 0;
-       int                     count_est = 0;
+       int64           offset_est = 0;
+       int64           count_est = 0;
        Plan       *result_plan;
        List       *current_pathkeys;
        List       *sort_pathkeys;
@@ -1082,7 +1091,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
  */
 static double
 preprocess_limit(PlannerInfo *root, double tuple_fraction,
-                                int *offset_est, int *count_est)
+                                int64 *offset_est, int64 *count_est)
 {
        Query      *parse = root->parse;
        Node       *est;
@@ -1107,7 +1116,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction,
                        }
                        else
                        {
-                               *count_est = DatumGetInt32(((Const *) est)->constvalue);
+                               *count_est = DatumGetInt64(((Const *) est)->constvalue);
                                if (*count_est <= 0)
                                        *count_est = 1;         /* force to at least 1 */
                        }
@@ -1130,7 +1139,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction,
                        }
                        else
                        {
-                               *offset_est = DatumGetInt32(((Const *) est)->constvalue);
+                               *offset_est = DatumGetInt64(((Const *) est)->constvalue);
                                if (*offset_est < 0)
                                        *offset_est = 0;        /* less than 0 is same as 0 */
                        }