mirror of
https://github.com/postgres/postgres.git
synced 2025-06-29 10:41:53 +03:00
Major optimizer improvement for joining a large number of tables.
This commit is contained in:
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1093,25 +1093,26 @@ CopyPathFields(Path *from, Path *newnode)
|
|||||||
|
|
||||||
newnode->path_cost = from->path_cost;
|
newnode->path_cost = from->path_cost;
|
||||||
|
|
||||||
newnode->path_order.ordtype = from->path_order.ordtype;
|
newnode->path_order = makeNode(PathOrder);
|
||||||
if (from->path_order.ordtype == SORTOP_ORDER)
|
newnode->path_order->ordtype = from->path_order->ordtype;
|
||||||
|
if (from->path_order->ordtype == SORTOP_ORDER)
|
||||||
{
|
{
|
||||||
int len,
|
int len,
|
||||||
i;
|
i;
|
||||||
Oid *ordering = from->path_order.ord.sortop;
|
Oid *ordering = from->path_order->ord.sortop;
|
||||||
|
|
||||||
if (ordering)
|
if (ordering)
|
||||||
{
|
{
|
||||||
for (len = 0; ordering[len] != 0; len++)
|
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++)
|
for (i = 0; i < len; i++)
|
||||||
newnode->path_order.ord.sortop[i] = ordering[i];
|
newnode->path_order->ord.sortop[i] = ordering[i];
|
||||||
newnode->path_order.ord.sortop[len] = 0;
|
newnode->path_order->ord.sortop[len] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Node_Copy(from, newnode, path_order.ord.merge);
|
Node_Copy(from, newnode, path_order->ord.merge);
|
||||||
|
|
||||||
Node_Copy(from, newnode, keys);
|
Node_Copy(from, newnode, keys);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -337,33 +337,33 @@ _equalPath(Path *a, Path *b)
|
|||||||
/*
|
/*
|
||||||
* if (a->path_cost != b->path_cost) return(false);
|
* 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;
|
int i = 0;
|
||||||
|
|
||||||
if (a->path_order.ord.sortop == NULL ||
|
if (a->path_order->ord.sortop == NULL ||
|
||||||
b->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;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (a->path_order.ord.sortop[i] != 0 &&
|
while (a->path_order->ord.sortop[i] != 0 &&
|
||||||
b->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;
|
return false;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (a->path_order.ord.sortop[i] != 0 ||
|
if (a->path_order->ord.sortop[i] != 0 ||
|
||||||
b->path_order.ord.sortop[i] != 0)
|
b->path_order->ord.sortop[i] != 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
if (!equal(a->keys, b->keys))
|
if (!equal(a->keys, b->keys))
|
||||||
@ -433,9 +433,9 @@ _equalHashPath(HashPath *a, HashPath *b)
|
|||||||
return false;
|
return false;
|
||||||
if (!equal((a->path_hashclauses), (b->path_hashclauses)))
|
if (!equal((a->path_hashclauses), (b->path_hashclauses)))
|
||||||
return false;
|
return false;
|
||||||
if (!equal((a->outerhashkeys), (b->outerhashkeys)))
|
if (!equal(a->outerhashkeys, b->outerhashkeys))
|
||||||
return false;
|
return false;
|
||||||
if (!equal((a->innerhashkeys), (b->innerhashkeys)))
|
if (!equal(a->innerhashkeys, b->innerhashkeys))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -756,13 +756,16 @@ _freeRelOptInfo(RelOptInfo * node)
|
|||||||
static void
|
static void
|
||||||
FreePathFields(Path *node)
|
FreePathFields(Path *node)
|
||||||
{
|
{
|
||||||
if (node->path_order.ordtype == SORTOP_ORDER)
|
if (node->path_order->ordtype == SORTOP_ORDER)
|
||||||
{
|
{
|
||||||
if (node->path_order.ord.sortop)
|
if (node->path_order->ord.sortop)
|
||||||
pfree(node->path_order.ord.sortop);
|
pfree(node->path_order->ord.sortop);
|
||||||
}
|
}
|
||||||
else
|
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);
|
freeObject(node->keys);
|
||||||
|
|
||||||
@ -1171,7 +1174,6 @@ freeObject(void *node)
|
|||||||
|
|
||||||
switch (nodeTag(node))
|
switch (nodeTag(node))
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PLAN NODES
|
* PLAN NODES
|
||||||
*/
|
*/
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* XXX a few of the following functions are duplicated to handle
|
* XXX a few of the following functions are duplicated to handle
|
||||||
@ -368,7 +368,7 @@ member(void *l1, List *l2)
|
|||||||
List *i;
|
List *i;
|
||||||
|
|
||||||
foreach(i, l2)
|
foreach(i, l2)
|
||||||
if (equal((Node *) (lfirst(i)), (Node *) l1))
|
if (equal((Node *) l1, (Node *) lfirst(i)))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
* NOTES
|
||||||
* Every (plan) node in POSTGRES has an associated "out" routine which
|
* Every (plan) node in POSTGRES has an associated "out" routine which
|
||||||
@ -855,7 +855,7 @@ _outEState(StringInfo str, EState *node)
|
|||||||
* Stuff from relation.h
|
* Stuff from relation.h
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
_outRelOptInfo(StringInfo str, RelOptInfo * node)
|
_outRelOptInfo(StringInfo str, RelOptInfo *node)
|
||||||
{
|
{
|
||||||
appendStringInfo(str, " RELOPTINFO :relids ");
|
appendStringInfo(str, " RELOPTINFO :relids ");
|
||||||
_outIntList(str, node->relids);
|
_outIntList(str, node->relids);
|
||||||
@ -924,6 +924,35 @@ _outRowMark(StringInfo str, RowMark *node)
|
|||||||
appendStringInfo(str, " ROWMARK :rti %u :info %u", node->rti, node->info);
|
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.
|
* Path is a subclass of Node.
|
||||||
*/
|
*/
|
||||||
@ -934,6 +963,9 @@ _outPath(StringInfo str, Path *node)
|
|||||||
node->pathtype,
|
node->pathtype,
|
||||||
node->path_cost);
|
node->path_cost);
|
||||||
_outNode(str, node->keys);
|
_outNode(str, node->keys);
|
||||||
|
|
||||||
|
appendStringInfo(str, " :path_order ");
|
||||||
|
_outNode(str, node->path_order);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -948,6 +980,9 @@ _outIndexPath(StringInfo str, IndexPath *node)
|
|||||||
node->path.path_cost);
|
node->path.path_cost);
|
||||||
_outNode(str, node->path.keys);
|
_outNode(str, node->path.keys);
|
||||||
|
|
||||||
|
appendStringInfo(str, " :path_order ");
|
||||||
|
_outNode(str, node->path.path_order);
|
||||||
|
|
||||||
appendStringInfo(str, " :indexid ");
|
appendStringInfo(str, " :indexid ");
|
||||||
_outIntList(str, node->indexid);
|
_outIntList(str, node->indexid);
|
||||||
|
|
||||||
@ -967,6 +1002,9 @@ _outJoinPath(StringInfo str, JoinPath *node)
|
|||||||
node->path.path_cost);
|
node->path.path_cost);
|
||||||
_outNode(str, node->path.keys);
|
_outNode(str, node->path.keys);
|
||||||
|
|
||||||
|
appendStringInfo(str, " :path_order ");
|
||||||
|
_outNode(str, node->path.path_order);
|
||||||
|
|
||||||
appendStringInfo(str, " :pathinfo ");
|
appendStringInfo(str, " :pathinfo ");
|
||||||
_outNode(str, node->pathinfo);
|
_outNode(str, node->pathinfo);
|
||||||
|
|
||||||
@ -995,6 +1033,9 @@ _outMergePath(StringInfo str, MergePath *node)
|
|||||||
node->jpath.path.path_cost);
|
node->jpath.path.path_cost);
|
||||||
_outNode(str, node->jpath.path.keys);
|
_outNode(str, node->jpath.path.keys);
|
||||||
|
|
||||||
|
appendStringInfo(str, " :path_order ");
|
||||||
|
_outNode(str, node->jpath.path.path_order);
|
||||||
|
|
||||||
appendStringInfo(str, " :pathinfo ");
|
appendStringInfo(str, " :pathinfo ");
|
||||||
_outNode(str, node->jpath.pathinfo);
|
_outNode(str, node->jpath.pathinfo);
|
||||||
|
|
||||||
@ -1032,6 +1073,9 @@ _outHashPath(StringInfo str, HashPath *node)
|
|||||||
node->jpath.path.path_cost);
|
node->jpath.path.path_cost);
|
||||||
_outNode(str, node->jpath.path.keys);
|
_outNode(str, node->jpath.path.keys);
|
||||||
|
|
||||||
|
appendStringInfo(str, " :path_order ");
|
||||||
|
_outNode(str, node->jpath.path.path_order);
|
||||||
|
|
||||||
appendStringInfo(str, " :pathinfo ");
|
appendStringInfo(str, " :pathinfo ");
|
||||||
_outNode(str, node->jpath.pathinfo);
|
_outNode(str, node->jpath.pathinfo);
|
||||||
|
|
||||||
@ -1548,6 +1592,9 @@ _outNode(StringInfo str, void *obj)
|
|||||||
case T_RowMark:
|
case T_RowMark:
|
||||||
_outRowMark(str, obj);
|
_outRowMark(str, obj);
|
||||||
break;
|
break;
|
||||||
|
case T_PathOrder:
|
||||||
|
_outPathOrder(str, obj);
|
||||||
|
break;
|
||||||
case T_Path:
|
case T_Path:
|
||||||
_outPath(str, obj);
|
_outPath(str, obj);
|
||||||
break;
|
break;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* Most of the read functions for plan nodes are tested. (In fact, they
|
* Most of the read functions for plan nodes are tested. (In fact, they
|
||||||
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
#include "catalog/pg_index.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
|
|
||||||
#include "nodes/primnodes.h"
|
#include "nodes/primnodes.h"
|
||||||
@ -1450,6 +1451,54 @@ _readRowMark()
|
|||||||
return local_node;
|
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
|
* _readPath
|
||||||
*
|
*
|
||||||
@ -1473,10 +1522,8 @@ _readPath()
|
|||||||
token = lsptok(NULL, &length); /* now read it */
|
token = lsptok(NULL, &length); /* now read it */
|
||||||
local_node->path_cost = (Cost) atof(token);
|
local_node->path_cost = (Cost) atof(token);
|
||||||
|
|
||||||
#if 0
|
|
||||||
token = lsptok(NULL, &length); /* get :path_order */
|
token = lsptok(NULL, &length); /* get :path_order */
|
||||||
local_node->path_order = nodeRead(true); /* now read it */
|
local_node->path_order = nodeRead(true); /* now read it */
|
||||||
#endif
|
|
||||||
|
|
||||||
token = lsptok(NULL, &length); /* get :keys */
|
token = lsptok(NULL, &length); /* get :keys */
|
||||||
local_node->keys = nodeRead(true); /* now read it */
|
local_node->keys = nodeRead(true); /* now read it */
|
||||||
@ -1507,10 +1554,8 @@ _readIndexPath()
|
|||||||
token = lsptok(NULL, &length); /* now read it */
|
token = lsptok(NULL, &length); /* now read it */
|
||||||
local_node->path.path_cost = (Cost) atof(token);
|
local_node->path.path_cost = (Cost) atof(token);
|
||||||
|
|
||||||
#if 0
|
|
||||||
token = lsptok(NULL, &length); /* get :path_order */
|
token = lsptok(NULL, &length); /* get :path_order */
|
||||||
local_node->path.path_order = nodeRead(true); /* now read it */
|
local_node->path.path_order = nodeRead(true); /* now read it */
|
||||||
#endif
|
|
||||||
|
|
||||||
token = lsptok(NULL, &length); /* get :keys */
|
token = lsptok(NULL, &length); /* get :keys */
|
||||||
local_node->path.keys = nodeRead(true); /* now read it */
|
local_node->path.keys = nodeRead(true); /* now read it */
|
||||||
@ -1548,10 +1593,8 @@ _readJoinPath()
|
|||||||
token = lsptok(NULL, &length); /* now read it */
|
token = lsptok(NULL, &length); /* now read it */
|
||||||
local_node->path.path_cost = (Cost) atof(token);
|
local_node->path.path_cost = (Cost) atof(token);
|
||||||
|
|
||||||
#if 0
|
|
||||||
token = lsptok(NULL, &length); /* get :path_order */
|
token = lsptok(NULL, &length); /* get :path_order */
|
||||||
local_node->path.path_order = nodeRead(true); /* now read it */
|
local_node->path.path_order = nodeRead(true); /* now read it */
|
||||||
#endif
|
|
||||||
|
|
||||||
token = lsptok(NULL, &length); /* get :keys */
|
token = lsptok(NULL, &length); /* get :keys */
|
||||||
local_node->path.keys = nodeRead(true); /* now read it */
|
local_node->path.keys = nodeRead(true); /* now read it */
|
||||||
@ -1615,10 +1658,8 @@ _readMergePath()
|
|||||||
|
|
||||||
local_node->jpath.path.path_cost = (Cost) atof(token);
|
local_node->jpath.path.path_cost = (Cost) atof(token);
|
||||||
|
|
||||||
#if 0
|
|
||||||
token = lsptok(NULL, &length); /* get :path_order */
|
token = lsptok(NULL, &length); /* get :path_order */
|
||||||
local_node->jpath.path.path_order = nodeRead(true); /* now read it */
|
local_node->jpath.path.path_order = nodeRead(true); /* now read it */
|
||||||
#endif
|
|
||||||
|
|
||||||
token = lsptok(NULL, &length); /* get :keys */
|
token = lsptok(NULL, &length); /* get :keys */
|
||||||
local_node->jpath.path.keys = nodeRead(true); /* now read it */
|
local_node->jpath.path.keys = nodeRead(true); /* now read it */
|
||||||
@ -1691,10 +1732,8 @@ _readHashPath()
|
|||||||
|
|
||||||
local_node->jpath.path.path_cost = (Cost) atof(token);
|
local_node->jpath.path.path_cost = (Cost) atof(token);
|
||||||
|
|
||||||
#if 0
|
|
||||||
token = lsptok(NULL, &length); /* get :path_order */
|
token = lsptok(NULL, &length); /* get :path_order */
|
||||||
local_node->jpath.path.path_order = nodeRead(true); /* now read it */
|
local_node->jpath.path.path_order = nodeRead(true); /* now read it */
|
||||||
#endif
|
|
||||||
|
|
||||||
token = lsptok(NULL, &length); /* get :keys */
|
token = lsptok(NULL, &length); /* get :keys */
|
||||||
local_node->jpath.path.keys = nodeRead(true); /* now read it */
|
local_node->jpath.path.keys = nodeRead(true); /* now read it */
|
||||||
@ -2071,6 +2110,8 @@ parsePlanString(void)
|
|||||||
return_value = _readTargetEntry();
|
return_value = _readTargetEntry();
|
||||||
else if (!strncmp(token, "RTE", length))
|
else if (!strncmp(token, "RTE", length))
|
||||||
return_value = _readRangeTblEntry();
|
return_value = _readRangeTblEntry();
|
||||||
|
else if (!strncmp(token, "PATHORDER", length))
|
||||||
|
return_value = _readPathOrder();
|
||||||
else if (!strncmp(token, "PATH", length))
|
else if (!strncmp(token, "PATH", length))
|
||||||
return_value = _readPath();
|
return_value = _readPath();
|
||||||
else if (!strncmp(token, "INDEXPATH", length))
|
else if (!strncmp(token, "INDEXPATH", length))
|
||||||
|
@ -1,10 +1,56 @@
|
|||||||
|
Summary
|
||||||
|
-------
|
||||||
|
|
||||||
The optimizer generates optimial query plans by doing several steps:
|
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
|
Find each way of accessing the relation, called a Path, including
|
||||||
sequential and index scans, and add it to the RelOptInfo.path_order
|
sequential and index scans, and add it to the RelOptInfo.path_order
|
||||||
list.
|
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
|
Optimizer Functions
|
||||||
-------------------
|
-------------------
|
||||||
@ -56,28 +102,6 @@ planner()
|
|||||||
one relation, return
|
one relation, return
|
||||||
find selectivity of columns used in joins
|
find selectivity of columns used in joins
|
||||||
-----find_join_paths()
|
-----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
|
jump to geqo if needed
|
||||||
again:
|
again:
|
||||||
find_join_rels():
|
find_join_rels():
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -113,7 +113,7 @@ geqo_rel_paths(RelOptInfo * rel)
|
|||||||
{
|
{
|
||||||
path = (Path *) lfirst(y);
|
path = (Path *) lfirst(y);
|
||||||
|
|
||||||
if (!path->path_order.ord.sortop)
|
if (!path->path_order->ord.sortop)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1290,8 +1290,9 @@ index_innerjoin(Query *root, RelOptInfo * rel, List *clausegroup_list,
|
|||||||
|
|
||||||
pathnode->path.pathtype = T_IndexScan;
|
pathnode->path.pathtype = T_IndexScan;
|
||||||
pathnode->path.parent = rel;
|
pathnode->path.parent = rel;
|
||||||
pathnode->path.path_order.ordtype = SORTOP_ORDER;
|
pathnode->path.path_order = makeNode(PathOrder);
|
||||||
pathnode->path.path_order.ord.sortop = index->ordering;
|
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->path.keys = NIL; /* not sure about this, bjm 1998/09/21 */
|
||||||
|
|
||||||
pathnode->indexid = index->relids;
|
pathnode->indexid = index->relids;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -328,7 +328,7 @@ match_unsorted_outer(RelOptInfo * joinrel,
|
|||||||
|
|
||||||
outerpath = (Path *) lfirst(i);
|
outerpath = (Path *) lfirst(i);
|
||||||
|
|
||||||
outerpath_ordering = &outerpath->path_order;
|
outerpath_ordering = outerpath->path_order;
|
||||||
|
|
||||||
if (outerpath_ordering)
|
if (outerpath_ordering)
|
||||||
{
|
{
|
||||||
@ -471,7 +471,7 @@ match_unsorted_inner(RelOptInfo * joinrel,
|
|||||||
|
|
||||||
innerpath = (Path *) lfirst(i);
|
innerpath = (Path *) lfirst(i);
|
||||||
|
|
||||||
innerpath_ordering = &innerpath->path_order;
|
innerpath_ordering = innerpath->path_order;
|
||||||
|
|
||||||
if (innerpath_ordering)
|
if (innerpath_ordering)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -218,8 +218,7 @@ match_paths_joinkeys(List *joinkeys,
|
|||||||
|
|
||||||
key_match = every_func(joinkeys, path->keys, which_subkey);
|
key_match = every_func(joinkeys, path->keys, which_subkey);
|
||||||
|
|
||||||
if (equal_path_ordering(ordering,
|
if (equal_path_ordering(ordering, path->path_order) &&
|
||||||
&path->path_order) &&
|
|
||||||
length(joinkeys) == length(path->keys) &&
|
length(joinkeys) == length(path->keys) &&
|
||||||
key_match)
|
key_match)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -52,16 +52,17 @@ group_clauses_by_order(List *restrictinfo_list,
|
|||||||
* Create a new mergeinfo node and add it to 'mergeinfo-list'
|
* Create a new mergeinfo node and add it to 'mergeinfo-list'
|
||||||
* if one does not yet exist for this merge ordering.
|
* if one does not yet exist for this merge ordering.
|
||||||
*/
|
*/
|
||||||
PathOrder path_order;
|
PathOrder *path_order;
|
||||||
MergeInfo *xmergeinfo;
|
MergeInfo *xmergeinfo;
|
||||||
Expr *clause = restrictinfo->clause;
|
Expr *clause = restrictinfo->clause;
|
||||||
Var *leftop = get_leftop(clause);
|
Var *leftop = get_leftop(clause);
|
||||||
Var *rightop = get_rightop(clause);
|
Var *rightop = get_rightop(clause);
|
||||||
JoinKey *keys;
|
JoinKey *keys;
|
||||||
|
|
||||||
path_order.ordtype = MERGE_ORDER;
|
path_order = makeNode(PathOrder);
|
||||||
path_order.ord.merge = merge_ordering;
|
path_order->ordtype = MERGE_ORDER;
|
||||||
xmergeinfo = match_order_mergeinfo(&path_order, mergeinfo_list);
|
path_order->ord.merge = merge_ordering;
|
||||||
|
xmergeinfo = match_order_mergeinfo(path_order, mergeinfo_list);
|
||||||
if (inner_relid == leftop->varno)
|
if (inner_relid == leftop->varno)
|
||||||
{
|
{
|
||||||
keys = makeNode(JoinKey);
|
keys = makeNode(JoinKey);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -104,13 +104,14 @@ create_or_index_paths(Query *root,
|
|||||||
|
|
||||||
pathnode->path.pathtype = T_IndexScan;
|
pathnode->path.pathtype = T_IndexScan;
|
||||||
pathnode->path.parent = rel;
|
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
|
* This is an IndexScan, but it does index lookups based
|
||||||
* on the order of the fields specified in the WHERE clause,
|
* on the order of the fields specified in the WHERE clause,
|
||||||
* not in any order, so the sortop is NULL.
|
* 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->path.keys = NIL; /* not sure about this, bjm 1998/09/21 */
|
||||||
|
|
||||||
pathnode->indexqual = lcons(clausenode, NIL);
|
pathnode->indexqual = lcons(clausenode, NIL);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -109,7 +109,7 @@ prune_rel_paths(List *rel_list)
|
|||||||
{
|
{
|
||||||
path = (Path *) lfirst(y);
|
path = (Path *) lfirst(y);
|
||||||
|
|
||||||
if (!path->path_order.ord.sortop)
|
if (!path->path_order->ord.sortop)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cheapest = (JoinPath *) prune_rel_path(rel, path);
|
cheapest = (JoinPath *) prune_rel_path(rel, path);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -529,14 +529,14 @@ create_mergejoin_node(MergePath *best_path,
|
|||||||
outer_tlist,
|
outer_tlist,
|
||||||
inner_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 = (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;
|
outer_order[1] = 0;
|
||||||
|
|
||||||
inner_order = (Oid *) palloc(sizeof(Oid) * 2);
|
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;
|
inner_order[1] = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -825,7 +825,6 @@ set_temp_tlist_operators(List *tlist, List *pathkeys, Oid *operators)
|
|||||||
resdom = tlist_member((Var *) keys, tlist);
|
resdom = tlist_member((Var *) keys, tlist);
|
||||||
if (resdom)
|
if (resdom)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Order the resdom keys and replace the operator OID for each
|
* Order the resdom keys and replace the operator OID for each
|
||||||
* key with the regproc OID.
|
* key with the regproc OID.
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -125,7 +125,7 @@ samekeys(List *keys1, List *keys2)
|
|||||||
|
|
||||||
for (key1 = keys1, key2 = keys2; key1 != NIL && key2 != NIL;
|
for (key1 = keys1, key2 = keys2; key1 != NIL && key2 != NIL;
|
||||||
key1 = lnext(key1), key2 = lnext(key2))
|
key1 = lnext(key1), key2 = lnext(key2))
|
||||||
if (!member(lfirst(key1), lfirst(key2)))
|
if (!member(lfirst((List *)lfirst(key1)), lfirst(key2)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Now the result should be true if list keys2 has at least as many
|
/* Now the result should be true if list keys2 has at least as many
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -164,9 +164,31 @@ better_path(Path *new_path, List *unique_paths, bool *noOther)
|
|||||||
{
|
{
|
||||||
path = (Path *) lfirst(temp);
|
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) &&
|
if (samekeys(path->keys, new_path->keys) &&
|
||||||
equal_path_ordering(&path->path_order,
|
equal_path_ordering(path->path_order,
|
||||||
&new_path->path_order))
|
new_path->path_order))
|
||||||
{
|
{
|
||||||
old_path = path;
|
old_path = path;
|
||||||
break;
|
break;
|
||||||
@ -207,8 +229,9 @@ create_seqscan_path(RelOptInfo * rel)
|
|||||||
pathnode->pathtype = T_SeqScan;
|
pathnode->pathtype = T_SeqScan;
|
||||||
pathnode->parent = rel;
|
pathnode->parent = rel;
|
||||||
pathnode->path_cost = 0.0;
|
pathnode->path_cost = 0.0;
|
||||||
pathnode->path_order.ordtype = SORTOP_ORDER;
|
pathnode->path_order = makeNode(PathOrder);
|
||||||
pathnode->path_order.ord.sortop = NULL;
|
pathnode->path_order->ordtype = SORTOP_ORDER;
|
||||||
|
pathnode->path_order->ord.sortop = NULL;
|
||||||
pathnode->keys = NIL;
|
pathnode->keys = NIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -256,8 +279,9 @@ create_index_path(Query *root,
|
|||||||
|
|
||||||
pathnode->path.pathtype = T_IndexScan;
|
pathnode->path.pathtype = T_IndexScan;
|
||||||
pathnode->path.parent = rel;
|
pathnode->path.parent = rel;
|
||||||
pathnode->path.path_order.ordtype = SORTOP_ORDER;
|
pathnode->path.path_order = makeNode(PathOrder);
|
||||||
pathnode->path.path_order.ord.sortop = index->ordering;
|
pathnode->path.path_order->ordtype = SORTOP_ORDER;
|
||||||
|
pathnode->path.path_order->ord.sortop = index->ordering;
|
||||||
|
|
||||||
pathnode->indexid = index->relids;
|
pathnode->indexid = index->relids;
|
||||||
pathnode->indexkeys = index->indexkeys;
|
pathnode->indexkeys = index->indexkeys;
|
||||||
@ -274,7 +298,7 @@ create_index_path(Query *root,
|
|||||||
* The index must have an ordering for the path to have (ordering)
|
* The index must have an ordering for the path to have (ordering)
|
||||||
* keys, and vice versa.
|
* 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,
|
pathnode->path.keys = collect_index_pathkeys(index->indexkeys,
|
||||||
rel->targetlist);
|
rel->targetlist);
|
||||||
@ -286,7 +310,7 @@ create_index_path(Query *root,
|
|||||||
* if no index keys were found, we can't order the path).
|
* if no index keys were found, we can't order the path).
|
||||||
*/
|
*/
|
||||||
if (pathnode->path.keys == NULL)
|
if (pathnode->path.keys == NULL)
|
||||||
pathnode->path.path_order.ord.sortop = NULL;
|
pathnode->path.path_order->ord.sortop = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pathnode->path.keys = NULL;
|
pathnode->path.keys = NULL;
|
||||||
@ -412,23 +436,20 @@ create_nestloop_path(RelOptInfo * joinrel,
|
|||||||
pathnode->path.joinid = NIL;
|
pathnode->path.joinid = NIL;
|
||||||
pathnode->path.outerjoincost = (Cost) 0.0;
|
pathnode->path.outerjoincost = (Cost) 0.0;
|
||||||
pathnode->path.loc_restrictinfo = NIL;
|
pathnode->path.loc_restrictinfo = NIL;
|
||||||
|
pathnode->path.path_order = makeNode(PathOrder);
|
||||||
|
|
||||||
if (keys)
|
if (keys)
|
||||||
{
|
{
|
||||||
pathnode->path.path_order.ordtype = outer_path->path_order.ordtype;
|
pathnode->path.path_order->ordtype = outer_path->path_order->ordtype;
|
||||||
if (outer_path->path_order.ordtype == SORTOP_ORDER)
|
if (outer_path->path_order->ordtype == SORTOP_ORDER)
|
||||||
{
|
pathnode->path.path_order->ord.sortop = outer_path->path_order->ord.sortop;
|
||||||
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;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pathnode->path.path_order.ord.merge = outer_path->path_order.ord.merge;
|
pathnode->path.path_order->ordtype = SORTOP_ORDER;
|
||||||
}
|
pathnode->path.path_order->ord.sortop = NULL;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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->path.path_cost = cost_nestloop(outer_path->path_cost,
|
||||||
@ -487,8 +508,9 @@ create_mergejoin_path(RelOptInfo * joinrel,
|
|||||||
pathnode->jpath.innerjoinpath = inner_path;
|
pathnode->jpath.innerjoinpath = inner_path;
|
||||||
pathnode->jpath.pathinfo = joinrel->restrictinfo;
|
pathnode->jpath.pathinfo = joinrel->restrictinfo;
|
||||||
pathnode->jpath.path.keys = keys;
|
pathnode->jpath.path.keys = keys;
|
||||||
pathnode->jpath.path.path_order.ordtype = MERGE_ORDER;
|
pathnode->jpath.path.path_order = makeNode(PathOrder);
|
||||||
pathnode->jpath.path.path_order.ord.merge = order;
|
pathnode->jpath.path.path_order->ordtype = MERGE_ORDER;
|
||||||
|
pathnode->jpath.path.path_order->ord.merge = order;
|
||||||
pathnode->path_mergeclauses = mergeclauses;
|
pathnode->path_mergeclauses = mergeclauses;
|
||||||
pathnode->jpath.path.loc_restrictinfo = NIL;
|
pathnode->jpath.path.loc_restrictinfo = NIL;
|
||||||
pathnode->outersortkeys = outersortkeys;
|
pathnode->outersortkeys = outersortkeys;
|
||||||
@ -552,8 +574,9 @@ create_hashjoin_path(RelOptInfo * joinrel,
|
|||||||
pathnode->jpath.pathinfo = joinrel->restrictinfo;
|
pathnode->jpath.pathinfo = joinrel->restrictinfo;
|
||||||
pathnode->jpath.path.loc_restrictinfo = NIL;
|
pathnode->jpath.path.loc_restrictinfo = NIL;
|
||||||
pathnode->jpath.path.keys = keys;
|
pathnode->jpath.path.keys = keys;
|
||||||
pathnode->jpath.path.path_order.ordtype = SORTOP_ORDER;
|
pathnode->jpath.path.path_order = makeNode(PathOrder);
|
||||||
pathnode->jpath.path.path_order.ord.sortop = NULL;
|
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.outerjoincost = (Cost) 0.0;
|
||||||
pathnode->jpath.path.joinid = (Relid) NULL;
|
pathnode->jpath.path.joinid = (Relid) NULL;
|
||||||
/* pathnode->hashjoinoperator = operator; */
|
/* pathnode->hashjoinoperator = operator; */
|
||||||
|
@ -240,7 +240,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -4802,7 +4802,7 @@ static const short yycheck[] = { 3,
|
|||||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, 215
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, 215
|
||||||
};
|
};
|
||||||
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
|
/* -*-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,
|
/* Skeleton output parser for bison,
|
||||||
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
|
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
|
||||||
@ -4951,13 +4951,9 @@ int yydebug; /* nonzero means print parse trace */
|
|||||||
#define YYMAXDEPTH 10000
|
#define YYMAXDEPTH 10000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef YYPARSE_RETURN_TYPE
|
|
||||||
#define YYPARSE_RETURN_TYPE int
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Prevent warning if -Wstrict-prototypes. */
|
/* Prevent warning if -Wstrict-prototypes. */
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
YYPARSE_RETURN_TYPE yyparse (void);
|
int yyparse (void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
|
#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
|
||||||
@ -4999,7 +4995,7 @@ __yy_memcpy (char *to, char *from, int count)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#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
|
/* The user can define YYPARSE_PARAM as the name of an argument to be passed
|
||||||
into yyparse. The argument should have type void *.
|
into yyparse. The argument should have type void *.
|
||||||
@ -5020,7 +5016,7 @@ __yy_memcpy (char *to, char *from, int count)
|
|||||||
#define YYPARSE_PARAM_DECL
|
#define YYPARSE_PARAM_DECL
|
||||||
#endif /* not YYPARSE_PARAM */
|
#endif /* not YYPARSE_PARAM */
|
||||||
|
|
||||||
YYPARSE_RETURN_TYPE
|
int
|
||||||
yyparse(YYPARSE_PARAM_ARG)
|
yyparse(YYPARSE_PARAM_ARG)
|
||||||
YYPARSE_PARAM_DECL
|
YYPARSE_PARAM_DECL
|
||||||
{
|
{
|
||||||
@ -11126,7 +11122,7 @@ case 969:
|
|||||||
break;}
|
break;}
|
||||||
}
|
}
|
||||||
/* the action file gets copied in in place of this dollarsign */
|
/* the action file gets copied in in place of this dollarsign */
|
||||||
#line 498 "/usr/share/bison.simple"
|
#line 498 "/usr/local/bison/bison.simple"
|
||||||
|
|
||||||
yyvsp -= yylen;
|
yyvsp -= yylen;
|
||||||
yyssp -= yylen;
|
yyssp -= yylen;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* A lexical scanner generated by flex */
|
/* A lexical scanner generated by flex */
|
||||||
|
|
||||||
/* Scanner skeleton version:
|
/* 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
|
#define FLEX_SCANNER
|
||||||
@ -556,7 +556,7 @@ char *yytext;
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -71,6 +71,7 @@ typedef enum NodeTag
|
|||||||
*---------------------
|
*---------------------
|
||||||
*/
|
*/
|
||||||
T_RelOptInfo = 200,
|
T_RelOptInfo = 200,
|
||||||
|
T_PathOrder,
|
||||||
T_Path,
|
T_Path,
|
||||||
T_IndexPath,
|
T_IndexPath,
|
||||||
T_JoinPath,
|
T_JoinPath,
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -127,6 +127,8 @@ typedef enum OrderType
|
|||||||
|
|
||||||
typedef struct PathOrder
|
typedef struct PathOrder
|
||||||
{
|
{
|
||||||
|
NodeTag type;
|
||||||
|
|
||||||
OrderType ordtype;
|
OrderType ordtype;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
@ -144,9 +146,9 @@ typedef struct Path
|
|||||||
|
|
||||||
NodeTag pathtype;
|
NodeTag pathtype;
|
||||||
|
|
||||||
PathOrder path_order;
|
PathOrder *path_order;
|
||||||
|
|
||||||
List *keys;
|
List *keys; /* this is a List of List of keys */
|
||||||
Cost outerjoincost;
|
Cost outerjoincost;
|
||||||
Relid joinid;
|
Relid joinid;
|
||||||
List *loc_restrictinfo;
|
List *loc_restrictinfo;
|
||||||
|
Reference in New Issue
Block a user