1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-15 19:21:59 +03:00

Subselects in FROM clause, per ISO syntax: FROM (SELECT ...) [AS] alias.

(Don't forget that an alias is required.)  Views reimplemented as expanding
to subselect-in-FROM.  Grouping, aggregates, DISTINCT in views actually
work now (he says optimistically).  No UNION support in subselects/views
yet, but I have some ideas about that.  Rule-related permissions checking
moved out of rewriter and into executor.
INITDB REQUIRED!
This commit is contained in:
Tom Lane
2000-09-29 18:21:41 +00:00
parent 6f64c2e54a
commit 3a94e789f5
77 changed files with 3176 additions and 2661 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.64 2000/09/19 18:42:34 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.65 2000/09/29 18:21:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -19,6 +19,9 @@
#include "optimizer/geqo.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
#include "optimizer/plancat.h"
#include "optimizer/planner.h"
#include "parser/parsetree.h"
bool enable_geqo = true;
@ -26,7 +29,6 @@ int geqo_rels = DEFAULT_GEQO_RELS;
static void set_base_rel_pathlist(Query *root);
static List *build_jointree_rels(Query *root);
static RelOptInfo *make_one_rel_by_joins(Query *root, int levels_needed,
List *initial_rels);
@ -44,20 +46,7 @@ static void debug_print_rel(Query *root, RelOptInfo *rel);
RelOptInfo *
make_one_rel(Query *root)
{
int levels_needed;
List *initial_rels;
/*
* Count the number of top-level jointree nodes. This is the depth
* of the dynamic-programming algorithm we must employ to consider
* all ways of joining the top-level nodes. Currently, we build
* JoinExpr joins in exactly the order implied by the join expression,
* so no dynamic-programming search is needed within a JoinExpr.
*/
levels_needed = length(root->jointree);
if (levels_needed <= 0)
return NULL; /* nothing to do? */
RelOptInfo *rel;
/*
* Generate access paths for the base rels.
@ -65,27 +54,18 @@ make_one_rel(Query *root)
set_base_rel_pathlist(root);
/*
* Construct a list of rels corresponding to the toplevel jointree nodes.
* This may contain both base rels and rels constructed according to
* explicit JOIN directives.
* Generate access paths for the entire join tree.
*/
initial_rels = build_jointree_rels(root);
Assert(root->jointree != NULL && IsA(root->jointree, FromExpr));
if (levels_needed == 1)
{
/*
* Single jointree node, so we're done.
*/
return (RelOptInfo *) lfirst(initial_rels);
}
else
{
rel = make_fromexpr_rel(root, root->jointree);
/*
* Generate join tree.
*/
return make_one_rel_by_joins(root, levels_needed, initial_rels);
}
/*
* The result should join all the query's rels.
*/
Assert(length(rel->relids) == length(root->base_rel_list));
return rel;
}
/*
@ -102,36 +82,67 @@ set_base_rel_pathlist(Query *root)
foreach(rellist, root->base_rel_list)
{
RelOptInfo *rel = (RelOptInfo *) lfirst(rellist);
List *indices = find_relation_indices(root, rel);
RangeTblEntry *rte;
/* Mark rel with estimated output rows, width, etc */
set_baserel_size_estimates(root, rel);
Assert(length(rel->relids) == 1); /* better be base rel */
rte = rt_fetch(lfirsti(rel->relids), root->rtable);
/*
* Generate paths and add them to the rel's pathlist.
*
* Note: add_path() will discard any paths that are dominated by
* another available path, keeping only those paths that are
* superior along at least one dimension of cost or sortedness.
*/
if (rel->issubquery)
{
/* Subquery --- generate a separate plan for it */
/* Consider sequential scan */
add_path(rel, create_seqscan_path(rel));
/*
* XXX for now, we just apply any restrict clauses that came
* from the outer query as qpquals of the SubqueryScan node.
* Later, think about pushing them down into the subquery itself.
*/
/* Consider TID scans */
create_tidscan_paths(root, rel);
/* Generate the plan for the subquery */
rel->subplan = planner(rte->subquery);
/* Consider index paths for both simple and OR index clauses */
create_index_paths(root, rel, indices,
rel->baserestrictinfo,
rel->joininfo);
/* Copy number of output rows from subplan */
rel->tuples = rel->subplan->plan_rows;
/*
* Note: create_or_index_paths depends on create_index_paths to
* have marked OR restriction clauses with relevant indices; this
* is why it doesn't need to be given the list of indices.
*/
create_or_index_paths(root, rel, rel->baserestrictinfo);
/* Mark rel with estimated output rows, width, etc */
set_baserel_size_estimates(root, rel);
/* Generate appropriate path */
add_path(rel, create_subqueryscan_path(rel));
}
else
{
/* Plain relation */
List *indices = find_secondary_indexes(rte->relid);
/* Mark rel with estimated output rows, width, etc */
set_baserel_size_estimates(root, rel);
/*
* Generate paths and add them to the rel's pathlist.
*
* Note: add_path() will discard any paths that are dominated by
* another available path, keeping only those paths that are
* superior along at least one dimension of cost or sortedness.
*/
/* Consider sequential scan */
add_path(rel, create_seqscan_path(rel));
/* Consider TID scans */
create_tidscan_paths(root, rel);
/* Consider index paths for both simple and OR index clauses */
create_index_paths(root, rel, indices,
rel->baserestrictinfo,
rel->joininfo);
/*
* Note: create_or_index_paths depends on create_index_paths to
* have marked OR restriction clauses with relevant indices; this
* is why it doesn't need to be given the list of indices.
*/
create_or_index_paths(root, rel, rel->baserestrictinfo);
}
/* Now find the cheapest of the paths for this rel */
set_cheapest(rel);
@ -139,26 +150,57 @@ set_base_rel_pathlist(Query *root)
}
/*
* build_jointree_rels
* Construct a RelOptInfo for each item in the query's jointree.
*
* At present, we handle explicit joins in the FROM clause exactly as
* specified, with no search for other join orders. Only the cross-product
* joins at the top level are involved in the dynamic-programming search.
* make_fromexpr_rel
* Build access paths for a FromExpr jointree node.
*/
static List *
build_jointree_rels(Query *root)
RelOptInfo *
make_fromexpr_rel(Query *root, FromExpr *from)
{
List *rels = NIL;
int levels_needed;
List *initial_rels = NIL;
List *jt;
foreach(jt, root->jointree)
/*
* Count the number of child jointree nodes. This is the depth
* of the dynamic-programming algorithm we must employ to consider
* all ways of joining the child nodes.
*/
levels_needed = length(from->fromlist);
if (levels_needed <= 0)
return NULL; /* nothing to do? */
/*
* Construct a list of rels corresponding to the child jointree nodes.
* This may contain both base rels and rels constructed according to
* explicit JOIN directives.
*/
foreach(jt, from->fromlist)
{
Node *jtnode = (Node *) lfirst(jt);
rels = lappend(rels, make_rel_from_jointree(root, jtnode));
initial_rels = lappend(initial_rels,
make_jointree_rel(root, jtnode));
}
if (levels_needed == 1)
{
/*
* Single jointree node, so we're done.
*/
return (RelOptInfo *) lfirst(initial_rels);
}
else
{
/*
* Consider the different orders in which we could join the rels,
* using either GEQO or regular optimizer.
*/
if (enable_geqo && levels_needed >= geqo_rels)
return geqo(root, levels_needed, initial_rels);
else
return make_one_rel_by_joins(root, levels_needed, initial_rels);
}
return rels;
}
/*
@ -182,14 +224,6 @@ make_one_rel_by_joins(Query *root, int levels_needed, List *initial_rels)
int lev;
RelOptInfo *rel;
/*******************************************
* genetic query optimizer entry point *
* <utesch@aut.tu-freiberg.de> *
* rest will be skipped in case of GEQO *
*******************************************/
if (enable_geqo && levels_needed >= geqo_rels)
return geqo(root, levels_needed, initial_rels);
/*
* We employ a simple "dynamic programming" algorithm: we first find
* all ways to build joins of two jointree items, then all ways to
@ -243,12 +277,11 @@ make_one_rel_by_joins(Query *root, int levels_needed, List *initial_rels)
}
/*
* We should have a single rel at the final level,
* representing the join of all the base rels.
* We should have a single rel at the final level.
*/
Assert(length(joinitems[levels_needed]) == 1);
rel = (RelOptInfo *) lfirst(joinitems[levels_needed]);
Assert(length(rel->relids) == length(root->base_rel_list));
return rel;
}