mirror of
https://github.com/postgres/postgres.git
synced 2025-11-21 00:42:43 +03:00
Restructure representation of join alias variables. An explicit JOIN
now has an RTE of its own, and references to its outputs now are Vars referencing the JOIN RTE, rather than CASE-expressions. This allows reverse-listing in ruleutils.c to use the correct alias easily, rather than painfully reverse-engineering the alias namespace as it used to do. Also, nested FULL JOINs work correctly, because the result of the inner joins are simple Vars that the planner can cope with. This fixes a bug reported a couple times now, notably by Tatsuo on 18-Nov-01. The alias Vars are expanded into COALESCE expressions where needed at the very end of planning, rather than during parsing. Also, beginnings of support for showing plan qualifier expressions in EXPLAIN. There are probably still cases that need work. initdb forced due to change of stored-rule representation.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parsenodes.h,v 1.159 2002/03/08 04:37:18 tgl Exp $
|
||||
* $Id: parsenodes.h,v 1.160 2002/03/12 00:52:01 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -430,9 +430,12 @@ typedef struct TargetEntry
|
||||
* RangeTblEntry -
|
||||
* A range table is a List of RangeTblEntry nodes.
|
||||
*
|
||||
* Currently we use the same node type for both plain relation references
|
||||
* and sub-selects in the FROM clause. It might be cleaner to abstract
|
||||
* the common fields into a "superclass" nodetype.
|
||||
* A range table entry may represent a plain relation, a sub-select in
|
||||
* FROM, or the result of a JOIN clause. (Only explicit JOIN syntax
|
||||
* produces an RTE, not the implicit join resulting from multiple FROM
|
||||
* items. This is because we only need the RTE to deal with SQL features
|
||||
* like outer joins and join-output-column aliasing.) Other special
|
||||
* RTE types also exist, as indicated by RTEKind.
|
||||
*
|
||||
* alias is an Attr node representing the AS alias-clause attached to the
|
||||
* FROM expression, or NULL if no clause.
|
||||
@@ -445,7 +448,7 @@ typedef struct TargetEntry
|
||||
*
|
||||
* inh is TRUE for relation references that should be expanded to include
|
||||
* inheritance children, if the rel has any. This *must* be FALSE for
|
||||
* subquery RTEs.
|
||||
* RTEs other than RTE_RELATION entries.
|
||||
*
|
||||
* inFromCl marks those range variables that are listed in the FROM clause.
|
||||
* In SQL, the query can only refer to range variables listed in the
|
||||
@@ -465,12 +468,28 @@ typedef struct TargetEntry
|
||||
* (This allows rules to act as setuid gateways.)
|
||||
*--------------------
|
||||
*/
|
||||
typedef enum RTEKind
|
||||
{
|
||||
RTE_RELATION, /* ordinary relation reference */
|
||||
RTE_SUBQUERY, /* subquery in FROM */
|
||||
RTE_JOIN, /* join */
|
||||
RTE_SPECIAL /* special rule relation (NEW or OLD) */
|
||||
} RTEKind;
|
||||
|
||||
typedef struct RangeTblEntry
|
||||
{
|
||||
NodeTag type;
|
||||
|
||||
RTEKind rtekind; /* see above */
|
||||
|
||||
/*
|
||||
* Fields valid for a plain relation RTE (else NULL/zero):
|
||||
* XXX the fields applicable to only some rte kinds should be merged
|
||||
* into a union. I didn't do this yet because the diffs would impact
|
||||
* a lot of code that is being actively worked on. FIXME later.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Fields valid for a plain relation or inh_relation RTE (else NULL/zero):
|
||||
*/
|
||||
char *relname; /* real name of the relation */
|
||||
Oid relid; /* OID of the relation */
|
||||
@@ -480,6 +499,21 @@ typedef struct RangeTblEntry
|
||||
*/
|
||||
Query *subquery; /* the sub-query */
|
||||
|
||||
/*
|
||||
* Fields valid for a join RTE (else NULL):
|
||||
*
|
||||
* joincoltypes/joincoltypmods identify the column datatypes of the
|
||||
* join result. joinleftcols and joinrightcols identify the source
|
||||
* columns from the join's inputs: each entry is either a source column
|
||||
* AttrNumber or zero. For normal columns exactly one is nonzero,
|
||||
* but both are nonzero for a column "merged" by USING or NATURAL.
|
||||
*/
|
||||
JoinType jointype; /* type of join */
|
||||
List *joincoltypes; /* integer list of column type OIDs */
|
||||
List *joincoltypmods; /* integer list of column typmods */
|
||||
List *joinleftcols; /* integer list of left-side column #s */
|
||||
List *joinrightcols; /* integer list of right-side column #s */
|
||||
|
||||
/*
|
||||
* Fields valid in all RTEs:
|
||||
*/
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: plannodes.h,v 1.53 2001/11/05 17:46:34 momjian Exp $
|
||||
* $Id: plannodes.h,v 1.54 2002/03/12 00:52:01 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -254,6 +254,7 @@ typedef struct SubqueryScan
|
||||
* jointype: rule for joining tuples from left and right subtrees
|
||||
* joinqual: qual conditions that came from JOIN/ON or JOIN/USING
|
||||
* (plan.qual contains conditions that came from WHERE)
|
||||
* joinrti: rtable index of corresponding JOIN RTE, if any (0 if none)
|
||||
*
|
||||
* When jointype is INNER, joinqual and plan.qual are semantically
|
||||
* interchangeable. For OUTER jointypes, the two are *not* interchangeable;
|
||||
@@ -262,6 +263,8 @@ typedef struct SubqueryScan
|
||||
* (But plan.qual is still applied before actually returning a tuple.)
|
||||
* For an outer join, only joinquals are allowed to be used as the merge
|
||||
* or hash condition of a merge or hash join.
|
||||
*
|
||||
* joinrti is for the convenience of setrefs.c; it's not used in execution.
|
||||
* ----------------
|
||||
*/
|
||||
typedef struct Join
|
||||
@@ -269,6 +272,7 @@ typedef struct Join
|
||||
Plan plan;
|
||||
JoinType jointype;
|
||||
List *joinqual; /* JOIN quals (in addition to plan.qual) */
|
||||
Index joinrti; /* JOIN RTE, if any */
|
||||
} Join;
|
||||
|
||||
/* ----------------
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: primnodes.h,v 1.57 2001/11/05 17:46:34 momjian Exp $
|
||||
* $Id: primnodes.h,v 1.58 2002/03/12 00:52:02 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -513,10 +513,9 @@ typedef struct RangeTblRef
|
||||
* alias has a critical impact on semantics, because a join with an alias
|
||||
* restricts visibility of the tables/columns inside it.
|
||||
*
|
||||
* During parse analysis, colnames is filled with a list of String nodes
|
||||
* giving the column names (real or alias) of the output of the join,
|
||||
* and colvars is filled with a list of expressions that can be copied to
|
||||
* reference the output columns.
|
||||
* During parse analysis, an RTE is created for the Join, and its index
|
||||
* is filled into rtindex. This RTE is present mainly so that Vars can
|
||||
* be created that refer to the outputs of the join.
|
||||
*----------
|
||||
*/
|
||||
typedef struct JoinExpr
|
||||
@@ -529,9 +528,7 @@ typedef struct JoinExpr
|
||||
List *using; /* USING clause, if any (list of String) */
|
||||
Node *quals; /* qualifiers on join, if any */
|
||||
struct Attr *alias; /* user-written alias clause, if any */
|
||||
List *colnames; /* output column names (list of String) */
|
||||
List *colvars; /* output column nodes (list of
|
||||
* expressions) */
|
||||
int rtindex; /* RT index assigned for join */
|
||||
} JoinExpr;
|
||||
|
||||
/*----------
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: relation.h,v 1.62 2002/03/01 06:01:20 tgl Exp $
|
||||
* $Id: relation.h,v 1.63 2002/03/12 00:52:02 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -39,18 +39,39 @@ typedef enum CostSelector
|
||||
* RelOptInfo
|
||||
* Per-relation information for planning/optimization
|
||||
*
|
||||
* For planning purposes, a "base rel" is either a plain relation (a
|
||||
* table) or the output of a sub-SELECT that appears in the range table.
|
||||
* In either case it is uniquely identified by an RT index. A "joinrel"
|
||||
* is the joining of two or more base rels. A joinrel is identified by
|
||||
* the set of RT indexes for its component baserels.
|
||||
* For planning purposes, a "base rel" is either a plain relation (a table)
|
||||
* or the output of a sub-SELECT that appears in the range table.
|
||||
* In either case it is uniquely identified by an RT index. A "joinrel"
|
||||
* is the joining of two or more base rels. A joinrel is identified by
|
||||
* the set of RT indexes for its component baserels. We create RelOptInfo
|
||||
* nodes for each baserel and joinrel, and store them in the Query's
|
||||
* base_rel_list and join_rel_list respectively.
|
||||
*
|
||||
* Note that there is only one joinrel for any given set of component
|
||||
* baserels, no matter what order we assemble them in; so an unordered
|
||||
* set is the right datatype to identify it with.
|
||||
* Note that there is only one joinrel for any given set of component
|
||||
* baserels, no matter what order we assemble them in; so an unordered
|
||||
* set is the right datatype to identify it with.
|
||||
*
|
||||
* Parts of this data structure are specific to various scan and join
|
||||
* mechanisms. It didn't seem worth creating new node types for them.
|
||||
* We also have "other rels", which are like base rels in that they refer to
|
||||
* single RT indexes; but they are not part of the join tree, and are stored
|
||||
* in other_rel_list not base_rel_list. An otherrel is created for each
|
||||
* join RTE as an aid in processing Vars that refer to the join's outputs,
|
||||
* but it serves no other purpose in planning. It is important not to
|
||||
* confuse this otherrel with the joinrel that represents the matching set
|
||||
* of base relations.
|
||||
*
|
||||
* A second category of otherrels are those made for child relations of an
|
||||
* inheritance scan (SELECT FROM foo*). The parent table's RTE and
|
||||
* corresponding baserel represent the whole result of the inheritance scan.
|
||||
* The planner creates separate RTEs and associated RelOptInfos for each child
|
||||
* table (including the parent table, in its capacity as a member of the
|
||||
* inheritance set). These RelOptInfos are physically identical to baserels,
|
||||
* but are otherrels because they are not in the main join tree. These added
|
||||
* RTEs and otherrels are used to plan the scans of the individual tables in
|
||||
* the inheritance set; then the parent baserel is given an Append plan
|
||||
* comprising the best plans for the individual child tables.
|
||||
*
|
||||
* Parts of this data structure are specific to various scan and join
|
||||
* mechanisms. It didn't seem worth creating new node types for them.
|
||||
*
|
||||
* relids - List of base-relation identifiers; it is a base relation
|
||||
* if there is just one, a join relation if more than one
|
||||
@@ -69,7 +90,7 @@ typedef enum CostSelector
|
||||
* pruneable - flag to let the planner know whether it can prune the
|
||||
* pathlist of this RelOptInfo or not.
|
||||
*
|
||||
* * If the relation is a base relation it will have these fields set:
|
||||
* If the relation is a base relation it will have these fields set:
|
||||
*
|
||||
* issubquery - true if baserel is a subquery RTE rather than a table
|
||||
* indexlist - list of IndexOptInfo nodes for relation's indexes
|
||||
@@ -82,25 +103,30 @@ typedef enum CostSelector
|
||||
* upon creation of the RelOptInfo object; they are filled in when
|
||||
* set_base_rel_pathlist processes the object.
|
||||
*
|
||||
* Note: if a base relation is the root of an inheritance tree
|
||||
* (SELECT FROM foo*) it is still considered a base rel. We will
|
||||
* generate a list of candidate Paths for accessing that table itself,
|
||||
* and also generate baserel RelOptInfo nodes for each child table,
|
||||
* with their own candidate Path lists. Then, an AppendPath is built
|
||||
* from the cheapest Path for each of these tables, and set to be the
|
||||
* only available Path for the inheritance baserel.
|
||||
* For otherrels that are inheritance children, these fields are filled
|
||||
* in just as for a baserel. In otherrels for join RTEs, these fields
|
||||
* are empty --- the only useful field of a join otherrel is its
|
||||
* outerjoinset.
|
||||
*
|
||||
* * The presence of the remaining fields depends on the restrictions
|
||||
* and joins that the relation participates in:
|
||||
* If the relation is a join relation it will have these fields set:
|
||||
*
|
||||
* joinrti - RT index of corresponding JOIN RTE, if any; 0 if none
|
||||
* joinrteids - List of RT indexes of JOIN RTEs included in this join
|
||||
* (including joinrti)
|
||||
*
|
||||
* The presence of the remaining fields depends on the restrictions
|
||||
* and joins that the relation participates in:
|
||||
*
|
||||
* baserestrictinfo - List of RestrictInfo nodes, containing info about
|
||||
* each qualification clause in which this relation
|
||||
* participates (only used for base rels)
|
||||
* baserestrictcost - Estimated cost of evaluating the baserestrictinfo
|
||||
* clauses at a single tuple (only used for base rels)
|
||||
* outerjoinset - If the rel appears within the nullable side of an outer
|
||||
* join, the list of all relids participating in the highest
|
||||
* such outer join; else NIL (only used for base rels)
|
||||
* outerjoinset - For a base rel: if the rel appears within the nullable
|
||||
* side of an outer join, the list of all relids
|
||||
* participating in the highest such outer join; else NIL.
|
||||
* For a join otherrel: the list of all baserel relids
|
||||
* syntactically within the join. Otherwise, unused.
|
||||
* joininfo - List of JoinInfo nodes, containing info about each join
|
||||
* clause in which this relation participates
|
||||
* innerjoin - List of Path nodes that represent indices that may be used
|
||||
@@ -128,11 +154,20 @@ typedef enum CostSelector
|
||||
* until after the outer join is performed.
|
||||
*----------
|
||||
*/
|
||||
typedef enum RelOptKind
|
||||
{
|
||||
RELOPT_BASEREL,
|
||||
RELOPT_JOINREL,
|
||||
RELOPT_OTHER_JOIN_REL,
|
||||
RELOPT_OTHER_CHILD_REL
|
||||
} RelOptKind;
|
||||
|
||||
typedef struct RelOptInfo
|
||||
{
|
||||
NodeTag type;
|
||||
|
||||
RelOptKind reloptkind;
|
||||
|
||||
/* all relations included in this RelOptInfo */
|
||||
Relids relids; /* integer list of base relids (RT
|
||||
* indexes) */
|
||||
@@ -155,6 +190,10 @@ typedef struct RelOptInfo
|
||||
double tuples;
|
||||
struct Plan *subplan;
|
||||
|
||||
/* information about a join rel (not set for base rels!) */
|
||||
Index joinrti;
|
||||
List *joinrteids;
|
||||
|
||||
/* used by various scans and joins: */
|
||||
List *baserestrictinfo; /* RestrictInfo structures (if
|
||||
* base rel) */
|
||||
@@ -228,6 +267,16 @@ typedef struct IndexOptInfo
|
||||
bool unique; /* if a unique index */
|
||||
} IndexOptInfo;
|
||||
|
||||
|
||||
/*
|
||||
* A Var is considered to belong to a relation if it's either from one
|
||||
* of the actual base rels making up the relation, or it's a join alias
|
||||
* var that is included in the relation.
|
||||
*/
|
||||
#define VARISRELMEMBER(varno,rel) (intMember((varno), (rel)->relids) || \
|
||||
intMember((varno), (rel)->joinrteids))
|
||||
|
||||
|
||||
/*
|
||||
* PathKeys
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user