aboutsummaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2019-01-28 17:54:10 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2019-01-28 17:54:23 -0500
commit4be058fe9ec5e630239b656af21fc083371f30ed (patch)
tree1e422ec3af7f08b7a1cdd7c57b71cd3215cec152 /src/include
parent5c1186751214416fdf88f33a89c3dc88391d2d60 (diff)
downloadpostgresql-4be058fe9ec5e630239b656af21fc083371f30ed.tar.gz
postgresql-4be058fe9ec5e630239b656af21fc083371f30ed.zip
In the planner, replace an empty FROM clause with a dummy RTE.
The fact that "SELECT expression" has no base relations has long been a thorn in the side of the planner. It makes it hard to flatten a sub-query that looks like that, or is a trivial VALUES() item, because the planner generally uses relid sets to identify sub-relations, and such a sub-query would have an empty relid set if we flattened it. prepjointree.c contains some baroque logic that works around this in certain special cases --- but there is a much better answer. We can replace an empty FROM clause with a dummy RTE that acts like a table of one row and no columns, and then there are no such corner cases to worry about. Instead we need some logic to get rid of useless dummy RTEs, but that's simpler and covers more cases than what was there before. For really trivial cases, where the query is just "SELECT expression" and nothing else, there's a hazard that adding the extra RTE makes for a noticeable slowdown; even though it's not much processing, there's not that much for the planner to do overall. However testing says that the penalty is very small, close to the noise level. In more complex queries, this is able to find optimizations that we could not find before. The new RTE type is called RTE_RESULT, since the "scan" plan type it gives rise to is a Result node (the same plan we produced for a "SELECT expression" query before). To avoid confusion, rename the old ResultPath path type to GroupResultPath, reflecting that it's only used in degenerate grouping cases where we know the query produces just one grouped row. (It wouldn't work to unify the two cases, because there are different rules about where the associated quals live during query_planner.) Note: although this touches readfuncs.c, I don't think a catversion bump is required, because the added case can't occur in stored rules, only plans. Patch by me, reviewed by David Rowley and Mark Dilger Discussion: https://postgr.es/m/15944.1521127664@sss.pgh.pa.us
Diffstat (limited to 'src/include')
-rw-r--r--src/include/nodes/nodes.h2
-rw-r--r--src/include/nodes/parsenodes.h5
-rw-r--r--src/include/nodes/relation.h11
-rw-r--r--src/include/optimizer/cost.h3
-rw-r--r--src/include/optimizer/pathnode.h9
-rw-r--r--src/include/optimizer/prep.h2
6 files changed, 21 insertions, 11 deletions
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 10dac60cd35..4808a9e76d4 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -237,7 +237,7 @@ typedef enum NodeTag
T_HashPath,
T_AppendPath,
T_MergeAppendPath,
- T_ResultPath,
+ T_GroupResultPath,
T_MaterialPath,
T_UniquePath,
T_GatherPath,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index addc2c2ec7a..4ec8a835417 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -950,7 +950,10 @@ typedef enum RTEKind
RTE_TABLEFUNC, /* TableFunc(.., column list) */
RTE_VALUES, /* VALUES (<exprlist>), (<exprlist>), ... */
RTE_CTE, /* common table expr (WITH list element) */
- RTE_NAMEDTUPLESTORE /* tuplestore, e.g. for AFTER triggers */
+ RTE_NAMEDTUPLESTORE, /* tuplestore, e.g. for AFTER triggers */
+ RTE_RESULT /* RTE represents an empty FROM clause; such
+ * RTEs are added by the planner, they're not
+ * present during parsing or rewriting */
} RTEKind;
typedef struct RangeTblEntry
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 34300613615..420ca05c30a 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -324,7 +324,6 @@ typedef struct PlannerInfo
* partitioned table */
bool hasJoinRTEs; /* true if any RTEs are RTE_JOIN kind */
bool hasLateralRTEs; /* true if any RTEs are marked LATERAL */
- bool hasDeletedRTEs; /* true if any RTE was deleted from jointree */
bool hasHavingQual; /* true if havingQual was non-null */
bool hasPseudoConstantQuals; /* true if any RestrictInfo has
* pseudoconstant = true */
@@ -1345,17 +1344,17 @@ typedef struct MergeAppendPath
} MergeAppendPath;
/*
- * ResultPath represents use of a Result plan node to compute a variable-free
- * targetlist with no underlying tables (a "SELECT expressions" query).
- * The query could have a WHERE clause, too, represented by "quals".
+ * GroupResultPath represents use of a Result plan node to compute the
+ * output of a degenerate GROUP BY case, wherein we know we should produce
+ * exactly one row, which might then be filtered by a HAVING qual.
*
* Note that quals is a list of bare clauses, not RestrictInfos.
*/
-typedef struct ResultPath
+typedef struct GroupResultPath
{
Path path;
List *quals;
-} ResultPath;
+} GroupResultPath;
/*
* MaterialPath represents use of a Material plan node, i.e., caching of
diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h
index e7005b4a0cf..623f733d7df 100644
--- a/src/include/optimizer/cost.h
+++ b/src/include/optimizer/cost.h
@@ -105,6 +105,8 @@ extern void cost_ctescan(Path *path, PlannerInfo *root,
RelOptInfo *baserel, ParamPathInfo *param_info);
extern void cost_namedtuplestorescan(Path *path, PlannerInfo *root,
RelOptInfo *baserel, ParamPathInfo *param_info);
+extern void cost_resultscan(Path *path, PlannerInfo *root,
+ RelOptInfo *baserel, ParamPathInfo *param_info);
extern void cost_recursive_union(Path *runion, Path *nrterm, Path *rterm);
extern void cost_sort(Path *path, PlannerInfo *root,
List *pathkeys, Cost input_cost, double tuples, int width,
@@ -196,6 +198,7 @@ extern void set_cte_size_estimates(PlannerInfo *root, RelOptInfo *rel,
double cte_rows);
extern void set_tablefunc_size_estimates(PlannerInfo *root, RelOptInfo *rel);
extern void set_namedtuplestore_size_estimates(PlannerInfo *root, RelOptInfo *rel);
+extern void set_result_size_estimates(PlannerInfo *root, RelOptInfo *rel);
extern void set_foreign_size_estimates(PlannerInfo *root, RelOptInfo *rel);
extern PathTarget *set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target);
extern double compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel,
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index bd905d3328e..aaaf3f4ff50 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -75,8 +75,10 @@ extern MergeAppendPath *create_merge_append_path(PlannerInfo *root,
List *pathkeys,
Relids required_outer,
List *partitioned_rels);
-extern ResultPath *create_result_path(PlannerInfo *root, RelOptInfo *rel,
- PathTarget *target, List *resconstantqual);
+extern GroupResultPath *create_group_result_path(PlannerInfo *root,
+ RelOptInfo *rel,
+ PathTarget *target,
+ List *havingqual);
extern MaterialPath *create_material_path(RelOptInfo *rel, Path *subpath);
extern UniquePath *create_unique_path(PlannerInfo *root, RelOptInfo *rel,
Path *subpath, SpecialJoinInfo *sjinfo);
@@ -105,6 +107,8 @@ extern Path *create_ctescan_path(PlannerInfo *root, RelOptInfo *rel,
Relids required_outer);
extern Path *create_namedtuplestorescan_path(PlannerInfo *root, RelOptInfo *rel,
Relids required_outer);
+extern Path *create_resultscan_path(PlannerInfo *root, RelOptInfo *rel,
+ Relids required_outer);
extern Path *create_worktablescan_path(PlannerInfo *root, RelOptInfo *rel,
Relids required_outer);
extern ForeignPath *create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
@@ -275,7 +279,6 @@ extern Relids min_join_parameterization(PlannerInfo *root,
Relids joinrelids,
RelOptInfo *outer_rel,
RelOptInfo *inner_rel);
-extern RelOptInfo *build_empty_join_rel(PlannerInfo *root);
extern RelOptInfo *fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind,
Relids relids);
extern Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel);
diff --git a/src/include/optimizer/prep.h b/src/include/optimizer/prep.h
index 62d45dd1426..a03a024ce93 100644
--- a/src/include/optimizer/prep.h
+++ b/src/include/optimizer/prep.h
@@ -21,11 +21,13 @@
/*
* prototypes for prepjointree.c
*/
+extern void replace_empty_jointree(Query *parse);
extern void pull_up_sublinks(PlannerInfo *root);
extern void inline_set_returning_functions(PlannerInfo *root);
extern void pull_up_subqueries(PlannerInfo *root);
extern void flatten_simple_union_all(PlannerInfo *root);
extern void reduce_outer_joins(PlannerInfo *root);
+extern void remove_useless_result_rtes(PlannerInfo *root);
extern Relids get_relids_in_jointree(Node *jtnode, bool include_joins);
extern Relids get_relids_for_join(PlannerInfo *root, int joinrelid);