*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.63 1999/02/08 04:29:03 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.64 1999/02/09 03:51:12 momjian Exp $
*
*-------------------------------------------------------------------------
*/
newnode->path_cost = from->path_cost;
- newnode->path_order.ordtype = from->path_order.ordtype;
- if (from->path_order.ordtype == SORTOP_ORDER)
+ newnode->path_order = makeNode(PathOrder);
+ newnode->path_order->ordtype = from->path_order->ordtype;
+ if (from->path_order->ordtype == SORTOP_ORDER)
{
int len,
i;
- Oid *ordering = from->path_order.ord.sortop;
+ Oid *ordering = from->path_order->ord.sortop;
if (ordering)
{
for (len = 0; ordering[len] != 0; len++)
;
- newnode->path_order.ord.sortop = (Oid *) palloc(sizeof(Oid) * (len + 1));
+ newnode->path_order->ord.sortop = (Oid *) palloc(sizeof(Oid) * (len + 1));
for (i = 0; i < len; i++)
- newnode->path_order.ord.sortop[i] = ordering[i];
- newnode->path_order.ord.sortop[len] = 0;
+ newnode->path_order->ord.sortop[i] = ordering[i];
+ newnode->path_order->ord.sortop[len] = 0;
}
}
else
- Node_Copy(from, newnode, path_order.ord.merge);
+ Node_Copy(from, newnode, path_order->ord.merge);
Node_Copy(from, newnode, keys);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.26 1999/02/08 04:29:04 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.27 1999/02/09 03:51:12 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/*
* if (a->path_cost != b->path_cost) return(false);
*/
- if (a->path_order.ordtype == SORTOP_ORDER)
+ if (a->path_order->ordtype == SORTOP_ORDER)
{
int i = 0;
- if (a->path_order.ord.sortop == NULL ||
- b->path_order.ord.sortop == NULL)
+ if (a->path_order->ord.sortop == NULL ||
+ b->path_order->ord.sortop == NULL)
{
- if (a->path_order.ord.sortop != b->path_order.ord.sortop)
+ if (a->path_order->ord.sortop != b->path_order->ord.sortop)
return false;
}
else
{
- while (a->path_order.ord.sortop[i] != 0 &&
- b->path_order.ord.sortop[i] != 0)
+ while (a->path_order->ord.sortop[i] != 0 &&
+ b->path_order->ord.sortop[i] != 0)
{
- if (a->path_order.ord.sortop[i] != b->path_order.ord.sortop[i])
+ if (a->path_order->ord.sortop[i] != b->path_order->ord.sortop[i])
return false;
i++;
}
- if (a->path_order.ord.sortop[i] != 0 ||
- b->path_order.ord.sortop[i] != 0)
+ if (a->path_order->ord.sortop[i] != 0 ||
+ b->path_order->ord.sortop[i] != 0)
return false;
}
}
else
{
- if (!equal(a->path_order.ord.merge, b->path_order.ord.merge))
+ if (!equal(a->path_order->ord.merge, b->path_order->ord.merge))
return false;
}
if (!equal(a->keys, b->keys))
return false;
if (!equal((a->path_hashclauses), (b->path_hashclauses)))
return false;
- if (!equal((a->outerhashkeys), (b->outerhashkeys)))
+ if (!equal(a->outerhashkeys, b->outerhashkeys))
return false;
- if (!equal((a->innerhashkeys), (b->innerhashkeys)))
+ if (!equal(a->innerhashkeys, b->innerhashkeys))
return false;
return true;
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.2 1999/02/08 04:29:04 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.3 1999/02/09 03:51:12 momjian Exp $
*
*-------------------------------------------------------------------------
*/
static void
FreePathFields(Path *node)
{
- if (node->path_order.ordtype == SORTOP_ORDER)
+ if (node->path_order->ordtype == SORTOP_ORDER)
{
- if (node->path_order.ord.sortop)
- pfree(node->path_order.ord.sortop);
+ if (node->path_order->ord.sortop)
+ pfree(node->path_order->ord.sortop);
}
else
- freeObject(node->path_order.ord.merge);
+ freeObject(node->path_order->ord.merge);
+
+ pfree(node->path_order); /* is it an object, but we don't have
+ separate free for it */
freeObject(node->keys);
switch (nodeTag(node))
{
-
/*
* PLAN NODES
*/
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.15 1998/09/01 04:29:05 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.16 1999/02/09 03:51:13 momjian Exp $
*
* NOTES
* XXX a few of the following functions are duplicated to handle
List *i;
foreach(i, l2)
- if (equal((Node *) (lfirst(i)), (Node *) l1))
- return true;
+ if (equal((Node *) l1, (Node *) lfirst(i)))
+ return true;
return false;
}
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: outfuncs.c,v 1.65 1999/02/05 19:59:25 momjian Exp $
+ * $Id: outfuncs.c,v 1.66 1999/02/09 03:51:13 momjian Exp $
*
* NOTES
* Every (plan) node in POSTGRES has an associated "out" routine which
* Stuff from relation.h
*/
static void
-_outRelOptInfo(StringInfo str, RelOptInfo * node)
+_outRelOptInfo(StringInfo str, RelOptInfo *node)
{
appendStringInfo(str, " RELOPTINFO :relids ");
_outIntList(str, node->relids);
appendStringInfo(str, " ROWMARK :rti %u :info %u", node->rti, node->info);
}
+/*
+ * Path is a subclass of Node.
+ */
+static void
+_outPathOrder(StringInfo str, PathOrder *node)
+{
+ appendStringInfo(str, " PATHORDER :ordtype %d ",
+ node->ordtype);
+ if (node->ordtype == SORTOP_ORDER)
+ {
+ int i;
+
+ appendStringInfo(str, " :sortop ");
+ if (node->ord.sortop == NULL)
+ appendStringInfo(str, "<>");
+ else
+ {
+ for (i=0; node->ord.sortop[i] != 0; i++)
+ appendStringInfo(str, " %d ", node->ord.sortop[i]);
+ appendStringInfo(str, " %d ", 0);
+ }
+ }
+ else
+ {
+ appendStringInfo(str, " :merge ");
+ _outNode(str,node->ord.merge);
+ }
+}
+
/*
* Path is a subclass of Node.
*/
node->pathtype,
node->path_cost);
_outNode(str, node->keys);
+
+ appendStringInfo(str, " :path_order ");
+ _outNode(str, node->path_order);
}
/*
node->path.path_cost);
_outNode(str, node->path.keys);
+ appendStringInfo(str, " :path_order ");
+ _outNode(str, node->path.path_order);
+
appendStringInfo(str, " :indexid ");
_outIntList(str, node->indexid);
node->path.path_cost);
_outNode(str, node->path.keys);
+ appendStringInfo(str, " :path_order ");
+ _outNode(str, node->path.path_order);
+
appendStringInfo(str, " :pathinfo ");
_outNode(str, node->pathinfo);
node->jpath.path.path_cost);
_outNode(str, node->jpath.path.keys);
+ appendStringInfo(str, " :path_order ");
+ _outNode(str, node->jpath.path.path_order);
+
appendStringInfo(str, " :pathinfo ");
_outNode(str, node->jpath.pathinfo);
node->jpath.path.path_cost);
_outNode(str, node->jpath.path.keys);
+ appendStringInfo(str, " :path_order ");
+ _outNode(str, node->jpath.path.path_order);
+
appendStringInfo(str, " :pathinfo ");
_outNode(str, node->jpath.pathinfo);
case T_RowMark:
_outRowMark(str, obj);
break;
+ case T_PathOrder:
+ _outPathOrder(str, obj);
+ break;
case T_Path:
_outPath(str, obj);
break;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.50 1999/02/08 04:29:04 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.51 1999/02/09 03:51:13 momjian Exp $
*
* NOTES
* Most of the read functions for plan nodes are tested. (In fact, they
#include "utils/lsyscache.h"
#include "utils/syscache.h"
+#include "catalog/pg_index.h"
#include "catalog/pg_type.h"
#include "nodes/primnodes.h"
return local_node;
}
+/* ----------------
+ * _readPathOrder
+ *
+ * PathOrder is part of Path and it's subclasses.
+ * ----------------
+ */
+static PathOrder *
+_readPathOrder()
+{
+ PathOrder *local_node;
+ char *token;
+ int length;
+
+ local_node = makeNode(PathOrder);
+
+ token = lsptok(NULL, &length); /* get :ordtype */
+ token = lsptok(NULL, &length); /* now read it */
+ local_node->ordtype = atol(token);
+
+ if (local_node->ordtype == SORTOP_ORDER)
+ {
+ token = lsptok(NULL, &length); /* get :sortop */
+
+ if (length == 0)
+ local_node->ord.sortop = NULL;
+ else
+ {
+ int i = -1;
+
+ local_node->ord.sortop = palloc(sizeof(Oid) * (INDEX_MAX_KEYS+1));
+
+ do {
+ i++;
+ Assert(i <= INDEX_MAX_KEYS);
+ token = lsptok(NULL, &length); /* now read it */
+ local_node->ord.sortop[i] = strtoul(token, NULL, 10);
+ } while (local_node->ord.sortop[i] != 0);
+ }
+ }
+ else
+ {
+ token = lsptok(NULL, &length); /* get :merge */
+ local_node->ord.merge = nodeRead(true); /* now read it */
+ }
+
+ return local_node;
+}
+
/* ----------------
* _readPath
*
token = lsptok(NULL, &length); /* now read it */
local_node->path_cost = (Cost) atof(token);
-#if 0
token = lsptok(NULL, &length); /* get :path_order */
- local_node->path_order = nodeRead(true); /* now read it */
-#endif
+ local_node->path_order = nodeRead(true); /* now read it */
token = lsptok(NULL, &length); /* get :keys */
local_node->keys = nodeRead(true); /* now read it */
token = lsptok(NULL, &length); /* now read it */
local_node->path.path_cost = (Cost) atof(token);
-#if 0
token = lsptok(NULL, &length); /* get :path_order */
- local_node->path.path_order = nodeRead(true); /* now read it */
-#endif
+ local_node->path.path_order = nodeRead(true); /* now read it */
token = lsptok(NULL, &length); /* get :keys */
local_node->path.keys = nodeRead(true); /* now read it */
token = lsptok(NULL, &length); /* now read it */
local_node->path.path_cost = (Cost) atof(token);
-#if 0
token = lsptok(NULL, &length); /* get :path_order */
local_node->path.path_order = nodeRead(true); /* now read it */
-#endif
token = lsptok(NULL, &length); /* get :keys */
local_node->path.keys = nodeRead(true); /* now read it */
local_node->jpath.path.path_cost = (Cost) atof(token);
-#if 0
token = lsptok(NULL, &length); /* get :path_order */
local_node->jpath.path.path_order = nodeRead(true); /* now read it */
-#endif
token = lsptok(NULL, &length); /* get :keys */
local_node->jpath.path.keys = nodeRead(true); /* now read it */
local_node->jpath.path.path_cost = (Cost) atof(token);
-#if 0
token = lsptok(NULL, &length); /* get :path_order */
local_node->jpath.path.path_order = nodeRead(true); /* now read it */
-#endif
token = lsptok(NULL, &length); /* get :keys */
local_node->jpath.path.keys = nodeRead(true); /* now read it */
return_value = _readTargetEntry();
else if (!strncmp(token, "RTE", length))
return_value = _readRangeTblEntry();
+ else if (!strncmp(token, "PATHORDER", length))
+ return_value = _readPathOrder();
else if (!strncmp(token, "PATH", length))
return_value = _readPath();
else if (!strncmp(token, "INDEXPATH", length))
+Summary
+-------
+
The optimizer generates optimial query plans by doing several steps:
-Take each relation in a query, and make a RelOptInfo structure for it.
+1) Take each relation in a query, and make a RelOptInfo structure for it.
Find each way of accessing the relation, called a Path, including
sequential and index scans, and add it to the RelOptInfo.path_order
list.
+2) Join each RelOptInfo to each other RelOptInfo as specified in the
+WHERE clause. At this point each RelOptInfo is a single relation, so
+you are joining every relation to every relation it is joined to in the
+WHERE clause.
+
+Joins occur using two RelOptInfos. One is outer, the other inner.
+Outers drive lookups of values in the inner. In a nested loop, lookups
+of values in the inner occur by scanning to find each matching inner
+row. In a mergejoin, inner rows are ordered, and are accessed in order,
+so only one scan of inner is required to perform the entire join. In a
+hashjoin, inner rows are hashed for lookups.
+
+Each unique join combination becomes a new RelOptInfo. The RelOptInfo
+is now the joining of two relations. RelOptInfo.path_order are various
+paths to create the joined result, having different orderings depending
+on the join method used.
+
+3) At this point, every RelOptInfo is joined to each other again, with
+a new relation added to each RelOptInfo. This continues until all
+relations have been joined into one RelOptInfo, and the cheapest Path is
+chosen.
+
+ SELECT *
+ FROM tab1, tab2, tab3, tab4
+ WHERE tab1.col = tab2.col AND
+ tab2.col = tab3.col AND
+ tab3.col = tab4.col
+
+ Tables 1, 2, 3, and 4 are joined as:
+ {1 2},{2 3},{3 4}
+ {1 2 3},{2 3 4}
+ {1 2 3 4}
+
+ SELECT *
+ FROM tab1, tab2, tab3, tab4
+ WHERE tab1.col = tab2.col AND
+ tab1.col = tab3.col AND
+ tab1.col = tab4.col
+
+ Tables 1, 2, 3, and 4 are joined as:
+ {1 2},{1 3},{1 4}
+ {1 2 3},{1 3 4},{1,2,4}
+ {1 2 3 4}
Optimizer Functions
-------------------
one relation, return
find selectivity of columns used in joins
-----find_join_paths()
- Summary: With OPTIMIZER_DEBUG defined, you see:
-
- Tables 1, 2, 3, and 4 are joined as:
- {1 2},{1 3},{1 4},{2 3},{2 4}
- {1 2 3},{1 2 4},{2 3 4}
- {1 2 3 4}
-
- Actual output tests show combinations:
- {4 2},{3 2},{1 4},{1 3},{1 2}
- {4 2 3},{1 4 2},{1 3 2}
- {4 2 3 1}
-
- Cheapest join order shows:
- {4 2},{3 2},{1 4},{1 3},{1 2}
- {3 2 4},{1 4 2},{1 3 2}
- {1 4 2 3}
-
- It first finds the best way to join each table to every other
- table. It then takes those joined table combinations, and joins
- them to the other joined table combinations, until all tables are
- joined.
-
jump to geqo if needed
again:
find_join_rels():
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: geqo_paths.c,v 1.13 1999/02/08 04:29:06 momjian Exp $
+ * $Id: geqo_paths.c,v 1.14 1999/02/09 03:51:15 momjian Exp $
*
*-------------------------------------------------------------------------
*/
{
path = (Path *) lfirst(y);
- if (!path->path_order.ord.sortop)
+ if (!path->path_order->ord.sortop)
break;
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.39 1999/02/08 04:29:08 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.40 1999/02/09 03:51:17 momjian Exp $
*
*-------------------------------------------------------------------------
*/
pathnode->path.pathtype = T_IndexScan;
pathnode->path.parent = rel;
- pathnode->path.path_order.ordtype = SORTOP_ORDER;
- pathnode->path.path_order.ord.sortop = index->ordering;
+ pathnode->path.path_order = makeNode(PathOrder);
+ pathnode->path.path_order->ordtype = SORTOP_ORDER;
+ pathnode->path.path_order->ord.sortop = index->ordering;
pathnode->path.keys = NIL; /* not sure about this, bjm 1998/09/21 */
pathnode->indexid = index->relids;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.15 1999/02/08 04:29:11 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.16 1999/02/09 03:51:19 momjian Exp $
*
*-------------------------------------------------------------------------
*/
List *clauses = NIL;
List *matchedJoinKeys = NIL;
List *matchedJoinClauses = NIL;
- MergeInfo *xmergeinfo = (MergeInfo *) NULL;
+ MergeInfo *xmergeinfo = (MergeInfo *) NULL;
outerpath = (Path *) lfirst(i);
- outerpath_ordering = &outerpath->path_order;
+ outerpath_ordering = outerpath->path_order;
if (outerpath_ordering)
{
foreach(i, innerpath_list)
{
- MergeInfo *xmergeinfo = (MergeInfo *) NULL;
+ MergeInfo *xmergeinfo = (MergeInfo *) NULL;
List *clauses = NIL;
List *matchedJoinKeys = NIL;
List *matchedJoinClauses = NIL;
innerpath = (Path *) lfirst(i);
- innerpath_ordering = &innerpath->path_order;
+ innerpath_ordering = innerpath->path_order;
if (innerpath_ordering)
{
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/joinutils.c,v 1.11 1999/02/08 04:29:12 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/joinutils.c,v 1.12 1999/02/09 03:51:20 momjian Exp $
*
*-------------------------------------------------------------------------
*/
key_match = every_func(joinkeys, path->keys, which_subkey);
- if (equal_path_ordering(ordering,
- &path->path_order) &&
+ if (equal_path_ordering(ordering, path->path_order) &&
length(joinkeys) == length(path->keys) &&
key_match)
{
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/mergeutils.c,v 1.14 1999/02/08 04:29:12 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/mergeutils.c,v 1.15 1999/02/09 03:51:20 momjian Exp $
*
*-------------------------------------------------------------------------
*/
* Create a new mergeinfo node and add it to 'mergeinfo-list'
* if one does not yet exist for this merge ordering.
*/
- PathOrder path_order;
- MergeInfo *xmergeinfo;
+ PathOrder *path_order;
+ MergeInfo *xmergeinfo;
Expr *clause = restrictinfo->clause;
Var *leftop = get_leftop(clause);
Var *rightop = get_rightop(clause);
JoinKey *keys;
- path_order.ordtype = MERGE_ORDER;
- path_order.ord.merge = merge_ordering;
- xmergeinfo = match_order_mergeinfo(&path_order, mergeinfo_list);
+ path_order = makeNode(PathOrder);
+ path_order->ordtype = MERGE_ORDER;
+ path_order->ord.merge = merge_ordering;
+ xmergeinfo = match_order_mergeinfo(path_order, mergeinfo_list);
if (inner_relid == leftop->varno)
{
keys = makeNode(JoinKey);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.15 1999/02/08 04:29:12 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.16 1999/02/09 03:51:20 momjian Exp $
*
*-------------------------------------------------------------------------
*/
pathnode->path.pathtype = T_IndexScan;
pathnode->path.parent = rel;
- pathnode->path.path_order.ordtype = SORTOP_ORDER;
+ pathnode->path.path_order = makeNode(PathOrder);
+ pathnode->path.path_order->ordtype = SORTOP_ORDER;
/*
* This is an IndexScan, but it does index lookups based
* on the order of the fields specified in the WHERE clause,
* not in any order, so the sortop is NULL.
*/
- pathnode->path.path_order.ord.sortop = NULL;
+ pathnode->path.path_order->ord.sortop = NULL;
pathnode->path.keys = NIL; /* not sure about this, bjm 1998/09/21 */
pathnode->indexqual = lcons(clausenode, NIL);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/prune.c,v 1.24 1999/02/08 04:29:12 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/prune.c,v 1.25 1999/02/09 03:51:21 momjian Exp $
*
*-------------------------------------------------------------------------
*/
{
path = (Path *) lfirst(y);
- if (!path->path_order.ord.sortop)
+ if (!path->path_order->ord.sortop)
break;
}
cheapest = (JoinPath *) prune_rel_path(rel, path);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.38 1999/02/08 04:29:17 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.39 1999/02/09 03:51:21 momjian Exp $
*
*-------------------------------------------------------------------------
*/
outer_tlist,
inner_tlist));
- opcode = get_opcode((best_path->jpath.path.path_order.ord.merge)->join_operator);
+ opcode = get_opcode((best_path->jpath.path.path_order->ord.merge)->join_operator);
outer_order = (Oid *) palloc(sizeof(Oid) * 2);
- outer_order[0] = (best_path->jpath.path.path_order.ord.merge)->left_operator;
+ outer_order[0] = (best_path->jpath.path.path_order->ord.merge)->left_operator;
outer_order[1] = 0;
inner_order = (Oid *) palloc(sizeof(Oid) * 2);
- inner_order[0] = (best_path->jpath.path.path_order.ord.merge)->right_operator;
+ inner_order[0] = (best_path->jpath.path.path_order->ord.merge)->right_operator;
inner_order[1] = 0;
/*
resdom = tlist_member((Var *) keys, tlist);
if (resdom)
{
-
/*
* Order the resdom keys and replace the operator OID for each
* key with the regproc OID.
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/keys.c,v 1.10 1999/02/01 04:20:50 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/keys.c,v 1.11 1999/02/09 03:51:26 momjian Exp $
*
*-------------------------------------------------------------------------
*/
for (key1 = keys1, key2 = keys2; key1 != NIL && key2 != NIL;
key1 = lnext(key1), key2 = lnext(key2))
- if (!member(lfirst(key1), lfirst(key2)))
+ if (!member(lfirst((List *)lfirst(key1)), lfirst(key2)))
return false;
/* Now the result should be true if list keys2 has at least as many
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.20 1999/02/08 04:29:21 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.21 1999/02/09 03:51:27 momjian Exp $
*
*-------------------------------------------------------------------------
*/
{
path = (Path *) lfirst(temp);
+#ifdef OPTDUP_DEBUG
+ if (!samekeys(path->keys, new_path->keys))
+ {
+ printf("oldpath\n");
+ pprint(path->keys);
+ printf("newpath\n");
+ pprint(new_path->keys);
+ if (path->keys && new_path->keys &&
+ length(lfirst(path->keys)) >= 2 &&
+ length(lfirst(path->keys)) < length(lfirst(new_path->keys)))
+ sleep(0); /* set breakpoint here */
+ }
+ if (!equal_path_ordering(path->path_order,
+ new_path->path_order))
+ {
+ printf("oldord\n");
+ pprint(path->path_order);
+ printf("neword\n");
+ pprint(new_path->path_order);
+ }
+#endif
+
if (samekeys(path->keys, new_path->keys) &&
- equal_path_ordering(&path->path_order,
- &new_path->path_order))
+ equal_path_ordering(path->path_order,
+ new_path->path_order))
{
old_path = path;
break;
pathnode->pathtype = T_SeqScan;
pathnode->parent = rel;
pathnode->path_cost = 0.0;
- pathnode->path_order.ordtype = SORTOP_ORDER;
- pathnode->path_order.ord.sortop = NULL;
+ pathnode->path_order = makeNode(PathOrder);
+ pathnode->path_order->ordtype = SORTOP_ORDER;
+ pathnode->path_order->ord.sortop = NULL;
pathnode->keys = NIL;
/*
pathnode->path.pathtype = T_IndexScan;
pathnode->path.parent = rel;
- pathnode->path.path_order.ordtype = SORTOP_ORDER;
- pathnode->path.path_order.ord.sortop = index->ordering;
+ pathnode->path.path_order = makeNode(PathOrder);
+ pathnode->path.path_order->ordtype = SORTOP_ORDER;
+ pathnode->path.path_order->ord.sortop = index->ordering;
pathnode->indexid = index->relids;
pathnode->indexkeys = index->indexkeys;
* The index must have an ordering for the path to have (ordering)
* keys, and vice versa.
*/
- if (pathnode->path.path_order.ord.sortop)
+ if (pathnode->path.path_order->ord.sortop)
{
pathnode->path.keys = collect_index_pathkeys(index->indexkeys,
rel->targetlist);
* if no index keys were found, we can't order the path).
*/
if (pathnode->path.keys == NULL)
- pathnode->path.path_order.ord.sortop = NULL;
+ pathnode->path.path_order->ord.sortop = NULL;
}
else
pathnode->path.keys = NULL;
pathnode->path.joinid = NIL;
pathnode->path.outerjoincost = (Cost) 0.0;
pathnode->path.loc_restrictinfo = NIL;
-
+ pathnode->path.path_order = makeNode(PathOrder);
+
if (keys)
{
- pathnode->path.path_order.ordtype = outer_path->path_order.ordtype;
- if (outer_path->path_order.ordtype == SORTOP_ORDER)
- {
- pathnode->path.path_order.ord.sortop = outer_path->path_order.ord.sortop;
- }
+ pathnode->path.path_order->ordtype = outer_path->path_order->ordtype;
+ if (outer_path->path_order->ordtype == SORTOP_ORDER)
+ pathnode->path.path_order->ord.sortop = outer_path->path_order->ord.sortop;
else
- {
- pathnode->path.path_order.ord.merge = outer_path->path_order.ord.merge;
- }
+ pathnode->path.path_order->ord.merge = outer_path->path_order->ord.merge;
}
else
{
- pathnode->path.path_order.ordtype = SORTOP_ORDER;
- pathnode->path.path_order.ord.sortop = NULL;
+ pathnode->path.path_order->ordtype = SORTOP_ORDER;
+ pathnode->path.path_order->ord.sortop = NULL;
}
pathnode->path.path_cost = cost_nestloop(outer_path->path_cost,
pathnode->jpath.innerjoinpath = inner_path;
pathnode->jpath.pathinfo = joinrel->restrictinfo;
pathnode->jpath.path.keys = keys;
- pathnode->jpath.path.path_order.ordtype = MERGE_ORDER;
- pathnode->jpath.path.path_order.ord.merge = order;
+ pathnode->jpath.path.path_order = makeNode(PathOrder);
+ pathnode->jpath.path.path_order->ordtype = MERGE_ORDER;
+ pathnode->jpath.path.path_order->ord.merge = order;
pathnode->path_mergeclauses = mergeclauses;
pathnode->jpath.path.loc_restrictinfo = NIL;
pathnode->outersortkeys = outersortkeys;
pathnode->jpath.pathinfo = joinrel->restrictinfo;
pathnode->jpath.path.loc_restrictinfo = NIL;
pathnode->jpath.path.keys = keys;
- pathnode->jpath.path.path_order.ordtype = SORTOP_ORDER;
- pathnode->jpath.path.path_order.ord.sortop = NULL;
+ pathnode->jpath.path.path_order = makeNode(PathOrder);
+ pathnode->jpath.path.path_order->ordtype = SORTOP_ORDER;
+ pathnode->jpath.path.path_order->ord.sortop = NULL;
pathnode->jpath.path.outerjoincost = (Cost) 0.0;
pathnode->jpath.path.joinid = (Relid) NULL;
/* pathnode->hashjoinoperator = operator; */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/Attic/gram.c,v 2.69 1999/02/07 19:04:59 wieck Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/Attic/gram.c,v 2.70 1999/02/09 03:51:30 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
-1, -1, -1, -1, -1, -1, -1, -1, -1, 215
};
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
-#line 3 "/usr/share/bison.simple"
+#line 3 "/usr/local/bison/bison.simple"
/* Skeleton output parser for bison,
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
#define YYMAXDEPTH 10000
#endif
-#ifndef YYPARSE_RETURN_TYPE
-#define YYPARSE_RETURN_TYPE int
-#endif
-
/* Prevent warning if -Wstrict-prototypes. */
#ifdef __GNUC__
-YYPARSE_RETURN_TYPE yyparse (void);
+int yyparse (void);
#endif
\f
#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
#endif
#endif
\f
-#line 196 "/usr/share/bison.simple"
+#line 196 "/usr/local/bison/bison.simple"
/* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *.
#define YYPARSE_PARAM_DECL
#endif /* not YYPARSE_PARAM */
-YYPARSE_RETURN_TYPE
+int
yyparse(YYPARSE_PARAM_ARG)
YYPARSE_PARAM_DECL
{
break;}
}
/* the action file gets copied in in place of this dollarsign */
-#line 498 "/usr/share/bison.simple"
+#line 498 "/usr/local/bison/bison.simple"
\f
yyvsp -= yylen;
yyssp -= yylen;
/* A lexical scanner generated by flex */
/* Scanner skeleton version:
- * $Header: /cvsroot/pgsql/src/backend/parser/Attic/scan.c,v 1.33 1999/02/07 23:58:52 tgl Exp $
+ * /master/usr.bin/lex/skel.c,v 1.3 1997/09/25 00:10:23 jch Exp
*/
#define FLEX_SCANNER
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/Attic/scan.c,v 1.33 1999/02/07 23:58:52 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/Attic/scan.c,v 1.34 1999/02/09 03:51:39 momjian Exp $
*
*-------------------------------------------------------------------------
*/
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: nodes.h,v 1.39 1999/02/06 16:50:31 wieck Exp $
+ * $Id: nodes.h,v 1.40 1999/02/09 03:51:41 momjian Exp $
*
*-------------------------------------------------------------------------
*/
*---------------------
*/
T_RelOptInfo = 200,
+ T_PathOrder,
T_Path,
T_IndexPath,
T_JoinPath,
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: relation.h,v 1.16 1999/02/08 04:29:25 momjian Exp $
+ * $Id: relation.h,v 1.17 1999/02/09 03:51:42 momjian Exp $
*
*-------------------------------------------------------------------------
*/
typedef struct PathOrder
{
+ NodeTag type;
+
OrderType ordtype;
union
{
NodeTag pathtype;
- PathOrder path_order;
+ PathOrder *path_order;
- List *keys;
+ List *keys; /* this is a List of List of keys */
Cost outerjoincost;
Relid joinid;
List *loc_restrictinfo;