summaryrefslogtreecommitdiff
path: root/src/include/nodes
diff options
context:
space:
mode:
authorTom Lane1999-08-16 02:17:58 +0000
committerTom Lane1999-08-16 02:17:58 +0000
commite6381966c1886badbc19c94ac1f1ffbc104125ab (patch)
tree9da3d5d073dcb4cff68bdb69f6118409b5315512 /src/include/nodes
parent08320bfb22b3ef006885de91f5163ef5fe831889 (diff)
Major planner/optimizer revision: get rid of PathOrder node type,
store all ordering information in pathkeys lists (which are now lists of lists of PathKeyItem nodes, not just lists of lists of vars). This was a big win --- the code is smaller and IMHO more understandable than it was, even though it handles more cases. I believe the node changes will not force an initdb for anyone; planner nodes don't show up in stored rules.
Diffstat (limited to 'src/include/nodes')
-rw-r--r--src/include/nodes/nodes.h40
-rw-r--r--src/include/nodes/pg_list.h40
-rw-r--r--src/include/nodes/primnodes.h16
-rw-r--r--src/include/nodes/relation.h306
4 files changed, 230 insertions, 172 deletions
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 322987c447c..37f47c53062 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: nodes.h,v 1.50 1999/07/15 15:21:17 momjian Exp $
+ * $Id: nodes.h,v 1.51 1999/08/16 02:17:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -64,27 +64,21 @@ typedef enum NodeTag
T_Func,
T_Array,
T_ArrayRef,
+ T_Iter,
/*---------------------
- * TAGS FOR INNER PLAN NODES (relation.h)
+ * TAGS FOR PLANNER NODES (relation.h)
*---------------------
*/
T_RelOptInfo = 200,
- T_PathOrder,
T_Path,
T_IndexPath,
T_NestPath,
T_MergePath,
T_HashPath,
- T_OrderKey,
- T_JoinKey,
- T_MergeOrder,
+ T_PathKeyItem,
T_RestrictInfo,
- T_JoinMethod,
- T_HashInfo,
- T_MergeInfo,
T_JoinInfo,
- T_Iter,
T_Stream,
/*---------------------
@@ -229,28 +223,27 @@ typedef struct Node
NodeTag type;
} Node;
-#define nodeTag(_node_) ((Node*)_node_)->type
+#define nodeTag(nodeptr) (((Node*)(nodeptr))->type)
-#define makeNode(_node_) (_node_*)newNode(sizeof(_node_),T_##_node_)
-#define NodeSetTag(n, t) ((Node *)n)->type = t
+#define makeNode(_type_) ((_type_ *) newNode(sizeof(_type_),T_##_type_))
+#define NodeSetTag(nodeptr,t) (((Node*)(nodeptr))->type = (t))
-#define IsA(_node_,_tag_) (nodeTag(_node_) == T_##_tag_)
+#define IsA(nodeptr,_type_) (nodeTag(nodeptr) == T_##_type_)
/* ----------------------------------------------------------------
- * IsA functions (no inheritence any more)
+ * IsA functions (no inheritance any more)
* ----------------------------------------------------------------
*/
#define IsA_JoinPath(jp) \
- (nodeTag(jp)==T_NestPath || nodeTag(jp)==T_MergePath || \
- nodeTag(jp)==T_HashPath)
+ (IsA(jp, NestPath) || IsA(jp, MergePath) || IsA(jp, HashPath))
-#define IsA_Join(j) \
- (nodeTag(j)==T_Join || nodeTag(j)==T_NestLoop || \
- nodeTag(j)==T_MergeJoin || nodeTag(j)==T_HashJoin)
+#define IsA_Join(jp) \
+ (IsA(jp, Join) || IsA(jp, NestLoop) || \
+ IsA(jp, MergeJoin) || IsA(jp, HashJoin))
#define IsA_Noname(t) \
- (nodeTag(t)==T_Noname || nodeTag(t)==T_Material || nodeTag(t)==T_Sort || \
- nodeTag(t)==T_Unique)
+ (IsA(t, Noname) || IsA(t, Material) || IsA(t, Sort) || \
+ IsA(t, Unique))
/* ----------------------------------------------------------------
* extern declarations follow
@@ -262,6 +255,9 @@ typedef struct Node
*/
extern Node *newNode(Size size, NodeTag tag);
+/*
+ * nodes/{outfuncs.c,print.c}
+ */
extern char *nodeToString(void *obj);
/*
diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h
index 3e20012b087..f3a7432adca 100644
--- a/src/include/nodes/pg_list.h
+++ b/src/include/nodes/pg_list.h
@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_list.h,v 1.12 1999/07/15 23:03:55 momjian Exp $
+ * $Id: pg_list.h,v 1.13 1999/08/16 02:17:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -35,9 +35,9 @@ typedef struct Value
} val;
} Value;
-#define intVal(v) (((Value *)v)->val.ival)
-#define floatVal(v) (((Value *)v)->val.dval)
-#define strVal(v) (((Value *)v)->val.str)
+#define intVal(v) (((Value *)(v))->val.ival)
+#define floatVal(v) (((Value *)(v))->val.dval)
+#define strVal(v) (((Value *)(v))->val.str)
/*----------------------
@@ -66,7 +66,7 @@ typedef struct List
/* pointer version of the list (where it makes a difference) */
#define lfirst(l) ((l)->elem.ptr_value)
#define lnext(l) ((l)->next)
-#define lsecond(l) (lfirst(lnext(l)))
+#define lsecond(l) lfirst(lnext(l))
#define lfirsti(l) ((l)->elem.int_value)
@@ -75,7 +75,7 @@ typedef struct List
* a convenience macro which loops through the list
*/
#define foreach(_elt_,_list_) \
- for(_elt_=_list_; _elt_!=NIL;_elt_=lnext(_elt_))
+ for(_elt_=(_list_); _elt_!=NIL; _elt_=lnext(_elt_))
/*
@@ -84,34 +84,34 @@ typedef struct List
extern int length(List *list);
extern List *nconc(List *list1, List *list2);
extern List *lcons(void *datum, List *list);
-extern bool member(void *foo, List *bar);
+extern List *lconsi(int datum, List *list);
+extern bool member(void *datum, List *list);
+extern bool intMember(int datum, List *list);
extern Value *makeInteger(long i);
extern Value *makeFloat(double d);
extern Value *makeString(char *str);
extern List *makeList(void *elem,...);
-extern List *lappend(List *list, void *obj);
+extern List *lappend(List *list, void *datum);
+extern List *lappendi(List *list, int datum);
extern List *lremove(void *elem, List *list);
-extern void freeList(List *list);
extern List *LispRemove(void *elem, List *list);
+extern List *ltruncate(int n, List *list);
extern void *nth(int n, List *l);
+extern int nthi(int n, List *l);
extern void set_nth(List *l, int n, void *elem);
-List *lconsi(int datum, List *list);
-List *lappendi(List *list, int datum);
-extern bool intMember(int, List *);
+extern List *set_difference(List *list1, List *list2);
+extern List *set_differencei(List *list1, List *list2);
+extern List *LispUnion(List *list1, List *list2);
+extern List *LispUnioni(List *list1, List *list2);
+extern bool same(List *list1, List *list2);
-extern int nthi(int n, List *l);
-
-extern List *set_difference(List *, List *);
-extern List *set_differencei(List *, List *);
-extern List *LispUnion(List *foo, List *bar);
-extern List *LispUnioni(List *foo, List *bar);
-extern bool same(List *foo, List *bar);
+extern void freeList(List *list);
/* should be in nodes.h but needs List */
/* in copyfuncs.c */
-extern List *listCopy(List *);
+extern List *listCopy(List *list);
#endif /* PG_LIST_H */
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index a4128a8d38a..2c4d0ffaa72 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: primnodes.h,v 1.32 1999/07/18 03:45:01 tgl Exp $
+ * $Id: primnodes.h,v 1.33 1999/08/16 02:17:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -256,6 +256,20 @@ typedef struct Func
} Func;
/* ----------------
+ * Iter
+ * can anyone explain what this is for? Seems to have something to do
+ * with evaluation of functions that return sets...
+ * ----------------
+ */
+typedef struct Iter
+{
+ NodeTag type;
+ Node *iterexpr;
+ Oid itertype; /* type of the iter expr (use for type
+ * checking) */
+} Iter;
+
+/* ----------------
* Aggref
* aggname - name of the aggregate
* basetype - base type Oid of the aggregate
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 4db2e9cea44..91fa85dd25e 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: relation.h,v 1.37 1999/07/27 03:51:09 tgl Exp $
+ * $Id: relation.h,v 1.38 1999/08/16 02:17:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,65 +18,75 @@
/*
* Relids
* List of relation identifiers (indexes into the rangetable).
+ *
+ * Note: these are lists of integers, not Nodes.
*/
typedef List *Relids;
/*
* RelOptInfo
- * Per-base-relation information
+ * Per-relation information for planning/optimization
*
* 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 relation indentifiers
+ * relids - List of base-relation identifiers; it is a base relation
+ * if there is just one, a join relation if more than one
* indexed - true if the relation has secondary indices
* pages - number of pages in the relation
* tuples - number of tuples in the relation
- * size - number of tuples in the relation after restrictions clauses
- * have been applied
- * width - number of bytes per tuple in the relation after the
+ * size - estimated number of tuples in the relation after restriction
+ * clauses have been applied
+ * width - avg. number of bytes per tuple in the relation after the
* appropriate projections have been done
* targetlist - List of TargetList nodes
- * pathlist - List of Path nodes, one for each possible method of
- * generating the relation
- * cheapestpath - least expensive Path (regardless of final order)
- * pruneable - flag to let the planner know whether it can prune the plan
- * space of this RelOptInfo or not.
+ * pathlist - List of Path nodes, one for each potentially useful
+ * method of generating the relation
+ * cheapestpath - least expensive Path (regardless of ordering)
+ * pruneable - flag to let the planner know whether it can prune the
+ * pathlist of this RelOptInfo or not.
*
* * If the relation is a (secondary) index it will have the following
- * three fields:
+ * fields set:
*
* classlist - List of PG_AMOPCLASS OIDs for the index
* indexkeys - List of base-relation attribute numbers that are index keys
* ordering - List of PG_OPERATOR OIDs which order the indexscan result
* relam - the OID of the pg_am of the index
*
+ * NB. the last element of the arrays classlist, indexkeys and ordering
+ * is always 0.
+ *
+ * Index relations do not participate in the join tree in the way
+ * that regular base relations do, but it is still convenient to
+ * represent them by RelOptInfos.
+ *
* * The presence of the remaining fields depends on the restrictions
- * and joins which the relation participates in:
+ * and joins that the relation participates in:
*
* restrictinfo - List of RestrictInfo nodes, containing info about each
* qualification clause in which this relation participates
* 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
- * as inner paths of nestloop joins
- *
- * NB. the last element of the arrays classlist, indexkeys and ordering
- * is always 0. 2/95 - ay
+ * as inner paths of nestloop joins. This field is non-null
+ * only for base rels, since join rels have no indices.
*/
typedef struct RelOptInfo
{
NodeTag type;
- /* all relations: */
- Relids relids; /* integer list of base relids involved */
+ /* all relations included in this RelOptInfo */
+ Relids relids; /* integer list of base relids */
/* catalog statistics information */
bool indexed;
int pages;
int tuples;
+
+ /* estimates generated by planner. XXX int is probably too small... */
int size;
int width;
@@ -89,65 +99,66 @@ typedef struct RelOptInfo
/* used solely by indices: */
Oid *classlist; /* classes of AM operators */
int *indexkeys; /* keys over which we're indexing */
+ Oid *ordering; /* OIDs of sort operators for each key */
Oid relam; /* OID of the access method (in pg_am) */
- Oid indproc;
- List *indpred;
+ Oid indproc; /* if a functional index */
+ List *indpred; /* if a partial index */
/* used by various scans and joins: */
- Oid *ordering; /* OID of operators in sort order */
List *restrictinfo; /* RestrictInfo structures */
List *joininfo; /* JoinInfo structures */
- List *innerjoin;
+ List *innerjoin; /* potential indexscans for nestloop joins */
+ /* innerjoin indexscans are not in the main pathlist because they are
+ * not usable except in specific join contexts; we have to test before
+ * seeing whether they can be used.
+ */
} RelOptInfo;
-extern Var *get_expr(TargetEntry *foo);
-extern Var *get_groupclause_expr(GroupClause *groupClause, List *targetList);
+/*
+ * PathKeys
+ *
+ * The sort ordering of a path is represented by a list of sublists of
+ * PathKeyItem nodes. An empty list implies no known ordering. Otherwise
+ * the first sublist represents the primary sort key, the second the
+ * first secondary sort key, etc. Each sublist contains one or more
+ * PathKeyItem nodes, each of which can be taken as the attribute that
+ * appears at that sort position. (See the top of optimizer/path/pathkeys.c
+ * for more information.)
+ */
-typedef struct MergeOrder
+typedef struct PathKeyItem
{
NodeTag type;
- Oid join_operator;
- Oid left_operator;
- Oid right_operator;
- Oid left_type;
- Oid right_type;
-} MergeOrder;
-
-typedef enum OrderType
-{
- MERGE_ORDER, SORTOP_ORDER
-} OrderType;
-typedef struct PathOrder
-{
- NodeTag type;
+ Node *key; /* the item that is ordered */
+ Oid sortop; /* the ordering operator ('<' op) */
+ /*
+ * key typically points to a Var node, ie a relation attribute,
+ * but it can also point to a Func clause representing the value
+ * indexed by a functional index. Someday we might allow arbitrary
+ * expressions as path keys, so don't assume more than you must.
+ */
+} PathKeyItem;
- OrderType ordtype;
- union
- {
- Oid *sortop;
- MergeOrder *merge;
- } ord;
-} PathOrder;
+/*
+ * Type "Path" is used as-is for sequential-scan paths. For other
+ * path types it is the first component of a larger struct.
+ */
typedef struct Path
{
NodeTag type;
- RelOptInfo *parent;
- Cost path_cost;
+ RelOptInfo *parent; /* the relation this path can build */
- NodeTag pathtype;
+ Cost path_cost; /* estimated execution cost of path */
- PathOrder *pathorder;
+ NodeTag pathtype; /* tag identifying scan/join method */
+ /* XXX why is pathtype separate from the NodeTag? */
- List *pathkeys; /* This is a List of List of Var nodes.
- * See the top of
- * optimizer/path/pathkeys.c for more
- * information. */
- Cost outerjoincost;
- Relids joinid;
+ List *pathkeys; /* sort ordering of path's output */
+ /* pathkeys is a List of Lists of PathKeyItem nodes; see above */
} Path;
/*----------
@@ -156,129 +167,163 @@ typedef struct Path
* different index during each scan. The result is the union (OR) of all the
* tuples matched during any scan. (The executor is smart enough not to return
* the same tuple more than once, even if it is matched in multiple scans.)
+ *
* 'indexid' is a list of index relation OIDs, one per scan to be performed.
* 'indexqual' is a list of index qualifications, also one per scan.
* Each entry in 'indexqual' is a sublist of qualification expressions with
- * implicit AND semantics across the sublist items. Each one of the sublist
- * items must be an operator expression of the form (var op something) or
- * (something op var), where the var is a field the associated index keys on
- * and the op is a member of the operator class of the index.
+ * implicit AND semantics across the sublist items. Only expressions that
+ * are usable as indexquals (as determined by indxpath.c) may appear here.
+ *
* NOTE that the semantics of the top-level list in 'indexqual' is OR
* combination, while the sublists are implicitly AND combinations!
*----------
*/
+
typedef struct IndexPath
{
Path path;
List *indexid;
List *indexqual;
- int *indexkeys; /* to transform heap attnos into index
- * ones */
+ /*
+ * joinrelids is only used in IndexPaths that are constructed for use
+ * as the inner path of a nestloop join. These paths have indexquals
+ * that refer to values of other rels, so those other rels must be
+ * included in the outer joinrel in order to make a usable join.
+ */
+ Relids joinrelids; /* other rels mentioned in indexqual */
} IndexPath;
-typedef struct NestPath
+/*
+ * All join-type paths share these fields.
+ */
+
+typedef struct JoinPath
{
Path path;
- List *pathinfo;
- Path *outerjoinpath;
- Path *innerjoinpath;
-} NestPath;
-typedef NestPath JoinPath;
+ List *pathinfo; /* copy of parent->restrictinfo; REMOVE? */
+
+ Path *outerjoinpath; /* path for the outer side of the join */
+ Path *innerjoinpath; /* path for the inner side of the join */
+} JoinPath;
+
+/*
+ * A nested-loop path needs no special fields.
+ */
+
+typedef JoinPath NestPath;
+
+/*
+ * A mergejoin path has these fields.
+ *
+ * Note that the mergeclauses are a subset of the parent relation's
+ * restriction-clause list. Any join clauses that are not mergejoinable
+ * appear only in the parent's restrict list, and must be checked by a
+ * qpqual at execution time.
+ */
typedef struct MergePath
{
JoinPath jpath;
- List *path_mergeclauses;
+ List *path_mergeclauses; /* join clauses used for merge */
+ /*
+ * outersortkeys (resp. innersortkeys) is NIL if the outer path
+ * (resp. inner path) is already ordered appropriately for the
+ * mergejoin. If it is not NIL then it is a PathKeys list describing
+ * the ordering that must be created by an explicit sort step.
+ */
List *outersortkeys;
List *innersortkeys;
} MergePath;
-typedef struct HashPath
-{
- JoinPath jpath;
- List *path_hashclauses;
- List *outerhashkeys;
- List *innerhashkeys;
-} HashPath;
-
/*
- * Keys
+ * A hashjoin path has these fields.
+ *
+ * The remarks above for mergeclauses apply for hashclauses as well.
+ * However, hashjoin does not care what order its inputs appear in,
+ * so we have no need for sortkeys.
*/
-typedef struct OrderKey
-{
- NodeTag type;
- int attribute_number;
- Index array_index;
-} OrderKey;
-
-typedef struct JoinKey
+typedef struct HashPath
{
- NodeTag type;
- Var *outer;
- Var *inner;
-} JoinKey;
+ JoinPath jpath;
+ List *path_hashclauses; /* join clauses used for hashing */
+} HashPath;
/*
* Restriction clause info.
+ *
* We create one of these for each AND sub-clause of a restriction condition
* (WHERE clause). Since the restriction clauses are logically ANDed, we
* can use any one of them or any subset of them to filter out tuples,
* without having to evaluate the rest. The RestrictInfo node itself stores
* data used by the optimizer while choosing the best query plan.
+ *
+ * A restriction clause will appear in the restrictinfo list of a RelOptInfo
+ * that describes exactly the set of base relations referenced by the
+ * restriction clause. It is not possible to apply the clause at any lower
+ * nesting level, and there is little point in delaying its evaluation to
+ * higher nesting levels. (The "predicate migration" code was once intended
+ * to push restriction clauses up and down the plan tree, but it's dead code
+ * and is unlikely to be resurrected in the foreseeable future.)
+ *
+ * If a restriction clause references more than one base rel, it will also
+ * appear in the JoinInfo list of every RelOptInfo that describes a strict
+ * subset of the base rels mentioned in the clause. The JoinInfo lists are
+ * used to drive join tree building by selecting plausible join candidates.
+ *
+ * In general, the referenced clause might be arbitrarily complex. The
+ * kinds of clauses we can handle as indexscan quals, mergejoin clauses,
+ * or hashjoin clauses are fairly limited --- the code for each kind of
+ * path is responsible for identifying the restrict clauses it can use
+ * and ignoring the rest. Clauses not implemented by an indexscan,
+ * mergejoin, or hashjoin will be placed in the qpqual field of the
+ * final Plan node, where they will be enforced by general-purpose
+ * qual-expression-evaluation code. (But we are still entitled to count
+ * their selectivity when estimating the result tuple count, if we
+ * can guess what it is...)
*/
typedef struct RestrictInfo
{
NodeTag type;
- Expr *clause; /* the represented subclause of WHERE cond */
- Cost selectivity; /* estimated selectivity */
- List *indexids; /* subclause index IDs if clause is an OR */
- /* mergejoin only */
- MergeOrder *mergejoinorder;
+ Expr *clause; /* the represented clause of WHERE cond */
+ Cost selectivity; /* estimated selectivity */
- /* hashjoin only */
- Oid hashjoinoperator;
-} RestrictInfo;
+ /* only used if clause is an OR clause: */
+ List *subclauseindices; /* lists of indexes matching subclauses */
-typedef struct JoinMethod
-{
- NodeTag type;
- List *jmkeys;
- List *clauses;
-} JoinMethod;
+ /* valid if clause is mergejoinable, else InvalidOid: */
+ Oid mergejoinoperator; /* copy of clause operator */
+ Oid left_sortop; /* leftside sortop needed for mergejoin */
+ Oid right_sortop; /* rightside sortop needed for mergejoin */
-typedef struct HashInfo
-{
- JoinMethod jmethod;
- Oid hashop;
-} HashInfo;
+ /* valid if clause is hashjoinable, else InvalidOid: */
+ Oid hashjoinoperator; /* copy of clause operator */
+} RestrictInfo;
-typedef struct MergeInfo
-{
- JoinMethod jmethod;
- MergeOrder *m_ordering;
-} MergeInfo;
+/*
+ * Join clause info.
+ *
+ * We make a list of these for each RelOptInfo, containing info about
+ * all the join clauses this RelOptInfo participates in. (For this
+ * purpose, a "join clause" is a WHERE clause that mentions both vars
+ * belonging to this relation and vars belonging to relations not yet
+ * joined to it.) We group these clauses according to the set of
+ * other base relations (unjoined relations) mentioned in them.
+ * There is one JoinInfo for each distinct set of unjoined_relids,
+ * and its jinfo_restrictinfo lists the clause(s) that use that set
+ * of other relations.
+ */
typedef struct JoinInfo
{
NodeTag type;
- Relids unjoined_relids;
- List *jinfo_restrictinfo;
- bool mergejoinable;
- bool hashjoinable;
+ Relids unjoined_relids; /* some rels not yet part of my RelOptInfo */
+ List *jinfo_restrictinfo; /* relevant RestrictInfos */
} JoinInfo;
-typedef struct Iter
-{
- NodeTag type;
- Node *iterexpr;
- Oid itertype; /* type of the iter expr (use for type
- * checking) */
-} Iter;
-
/*
* Stream:
* A stream represents a root-to-leaf path in a plan tree (i.e. a tree of
@@ -287,6 +332,9 @@ typedef struct Iter
* is used to make Path nodes and clauses look similar, so that Predicate
* Migration can run.
*
+ * XXX currently, Predicate Migration is dead code, and so is this node type.
+ * Probably should remove support for it.
+ *
* pathptr -- pointer to the current path node
* cinfo -- if NULL, this stream node referes to the path node.
* Otherwise this is a pointer to the current clause.
@@ -306,8 +354,8 @@ typedef struct Stream
Path *pathptr;
RestrictInfo *cinfo;
int *clausetype;
- struct Stream *upstream;
- struct Stream *downstream;
+ StreamPtr upstream;
+ StreamPtr downstream;
bool groupup;
Cost groupcost;
Cost groupsel;