1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-26 01:22:12 +03:00

Another round of planner/optimizer work. This is just restructuring and

code cleanup; no major improvements yet.  However, EXPLAIN does produce
more intuitive outputs for nested loops with indexscans now...
This commit is contained in:
Tom Lane
2000-01-09 00:26:47 +00:00
parent 69d4299e3e
commit 166b5c1def
35 changed files with 1239 additions and 1448 deletions

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.98 1999/12/13 01:26:53 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.99 2000/01/09 00:26:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -75,9 +75,9 @@ static void
CopyPlanFields(Plan *from, Plan *newnode)
{
newnode->cost = from->cost;
newnode->plan_size = from->plan_size;
newnode->plan_rows = from->plan_rows;
newnode->plan_width = from->plan_width;
newnode->plan_tupperpage = from->plan_tupperpage;
/* state is NOT copied */
newnode->targetlist = copyObject(from->targetlist);
newnode->qual = copyObject(from->qual);
newnode->lefttree = copyObject(from->lefttree);
@ -962,24 +962,43 @@ static RelOptInfo *
_copyRelOptInfo(RelOptInfo *from)
{
RelOptInfo *newnode = makeNode(RelOptInfo);
int i,
len;
/* ----------------
* copy remainder of node
* ----------------
*/
newnode->relids = listCopy(from->relids);
newnode->rows = from->rows;
newnode->width = from->width;
Node_Copy(from, newnode, targetlist);
Node_Copy(from, newnode, pathlist);
/* XXX cheapestpath should point to a member of pathlist? */
Node_Copy(from, newnode, cheapestpath);
newnode->pruneable = from->pruneable;
newnode->indexed = from->indexed;
newnode->pages = from->pages;
newnode->tuples = from->tuples;
newnode->size = from->size;
newnode->width = from->width;
Node_Copy(from, newnode, targetlist);
Node_Copy(from, newnode, pathlist);
Node_Copy(from, newnode, cheapestpath);
newnode->pruneable = from->pruneable;
Node_Copy(from, newnode, restrictinfo);
Node_Copy(from, newnode, joininfo);
Node_Copy(from, newnode, innerjoin);
return newnode;
}
/* ----------------
* _copyIndexOptInfo
* ----------------
*/
static IndexOptInfo *
_copyIndexOptInfo(IndexOptInfo *from)
{
IndexOptInfo *newnode = makeNode(IndexOptInfo);
int i,
len;
newnode->indexoid = from->indexoid;
newnode->pages = from->pages;
newnode->tuples = from->tuples;
if (from->classlist)
{
@ -1015,10 +1034,6 @@ _copyRelOptInfo(RelOptInfo *from)
newnode->indproc = from->indproc;
Node_Copy(from, newnode, indpred);
Node_Copy(from, newnode, restrictinfo);
Node_Copy(from, newnode, joininfo);
Node_Copy(from, newnode, innerjoin);
return newnode;
}
@ -1120,7 +1135,6 @@ _copyTidPath(TidPath *from)
static void
CopyJoinPathFields(JoinPath *from, JoinPath *newnode)
{
Node_Copy(from, newnode, pathinfo);
Node_Copy(from, newnode, outerjoinpath);
Node_Copy(from, newnode, innerjoinpath);
}
@ -1229,7 +1243,6 @@ _copyRestrictInfo(RestrictInfo *from)
* ----------------
*/
Node_Copy(from, newnode, clause);
newnode->selectivity = from->selectivity;
Node_Copy(from, newnode, subclauseindices);
newnode->mergejoinoperator = from->mergejoinoperator;
newnode->left_sortop = from->left_sortop;
@ -1617,6 +1630,9 @@ copyObject(void *from)
case T_Stream:
retval = _copyStream(from);
break;
case T_IndexOptInfo:
retval = _copyIndexOptInfo(from);
break;
/*
* PARSE NODES

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.54 1999/12/24 06:43:32 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.55 2000/01/09 00:26:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -302,6 +302,17 @@ _equalRelOptInfo(RelOptInfo *a, RelOptInfo *b)
return equali(a->relids, b->relids);
}
static bool
_equalIndexOptInfo(IndexOptInfo *a, IndexOptInfo *b)
{
/* We treat IndexOptInfos as equal if they refer to the same index.
* Is this sufficient?
*/
if (a->indexoid != b->indexoid)
return false;
return true;
}
static bool
_equalPathKeyItem(PathKeyItem *a, PathKeyItem *b)
{
@ -358,8 +369,6 @@ _equalJoinPath(JoinPath *a, JoinPath *b)
{
if (!_equalPath((Path *) a, (Path *) b))
return false;
if (!equal(a->pathinfo, b->pathinfo))
return false;
if (!equal(a->outerjoinpath, b->outerjoinpath))
return false;
if (!equal(a->innerjoinpath, b->innerjoinpath))
@ -469,7 +478,6 @@ _equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
{
if (!equal(a->clause, b->clause))
return false;
/* do not check selectivity because of roundoff error worries */
if (!equal(a->subclauseindices, b->subclauseindices))
return false;
if (a->mergejoinoperator != b->mergejoinoperator)
@ -792,6 +800,9 @@ equal(void *a, void *b)
case T_RelOptInfo:
retval = _equalRelOptInfo(a, b);
break;
case T_IndexOptInfo:
retval = _equalIndexOptInfo(a, b);
break;
case T_PathKeyItem:
retval = _equalPathKeyItem(a, b);
break;

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.29 1999/12/16 22:19:47 wieck Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.30 2000/01/09 00:26:23 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -730,11 +730,29 @@ _freeRelOptInfo(RelOptInfo *node)
freeObject(node->targetlist);
freeObject(node->pathlist);
/* is this right? cheapestpath will typically be a pointer into
/* XXX is this right? cheapestpath will typically be a pointer into
* pathlist, won't it?
*/
freeObject(node->cheapestpath);
freeObject(node->restrictinfo);
freeObject(node->joininfo);
freeObject(node->innerjoin);
pfree(node);
}
/* ----------------
* _freeIndexOptInfo
* ----------------
*/
static void
_freeIndexOptInfo(IndexOptInfo *node)
{
/* ----------------
* free remainder of node
* ----------------
*/
if (node->classlist)
pfree(node->classlist);
@ -746,10 +764,6 @@ _freeRelOptInfo(RelOptInfo *node)
freeObject(node->indpred);
freeObject(node->restrictinfo);
freeObject(node->joininfo);
freeObject(node->innerjoin);
pfree(node);
}
@ -837,7 +851,6 @@ _freeTidPath(TidPath *node)
static void
FreeJoinPathFields(JoinPath *node)
{
freeObject(node->pathinfo);
freeObject(node->outerjoinpath);
freeObject(node->innerjoinpath);
}
@ -936,7 +949,7 @@ _freeRestrictInfo(RestrictInfo *node)
* ----------------
*/
freeObject(node->clause);
/* this is certainly wrong? index RelOptInfos don't belong to
/* this is certainly wrong? IndexOptInfos don't belong to
* RestrictInfo...
*/
freeObject(node->subclauseindices);
@ -1253,6 +1266,9 @@ freeObject(void *node)
case T_Stream:
_freeStream(node);
break;
case T_IndexOptInfo:
_freeIndexOptInfo(node);
break;
/*
* PARSE NODES

View File

@ -5,7 +5,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: outfuncs.c,v 1.100 1999/12/13 01:26:53 tgl Exp $
* $Id: outfuncs.c,v 1.101 2000/01/09 00:26:23 tgl Exp $
*
* NOTES
* Every (plan) node in POSTGRES has an associated "out" routine which
@ -265,9 +265,9 @@ static void
_outPlanInfo(StringInfo str, Plan *node)
{
appendStringInfo(str,
":cost %g :size %d :width %d :state %s :qptargetlist ",
":cost %g :rows %.0f :width %d :state %s :qptargetlist ",
node->cost,
node->plan_size,
node->plan_rows,
node->plan_width,
node->state ? "not-NULL" : "<>");
_outNode(str, node->targetlist);
@ -834,6 +834,7 @@ _outEState(StringInfo str, EState *node)
/*
* Stuff from relation.h
*/
static void
_outRelOptInfo(StringInfo str, RelOptInfo *node)
{
@ -841,12 +842,12 @@ _outRelOptInfo(StringInfo str, RelOptInfo *node)
_outIntList(str, node->relids);
appendStringInfo(str,
" :indexed %s :pages %u :tuples %u :size %u :width %u :targetlist ",
" :rows %.0f :width %d :indexed %s :pages %ld :tuples %.0f :targetlist ",
node->rows,
node->width,
node->indexed ? "true" : "false",
node->pages,
node->tuples,
node->size,
node->width);
node->tuples);
_outNode(str, node->targetlist);
appendStringInfo(str, " :pathlist ");
@ -871,6 +872,15 @@ _outRelOptInfo(StringInfo str, RelOptInfo *node)
_outNode(str, node->innerjoin);
}
static void
_outIndexOptInfo(StringInfo str, IndexOptInfo *node)
{
appendStringInfo(str, " INDEXOPTINFO :indexoid %u :pages %ld :tuples %g ",
node->indexoid,
node->pages,
node->tuples);
}
/*
* TargetEntry is a subclass of Node.
*/
@ -910,7 +920,7 @@ _outRowMark(StringInfo str, RowMark *node)
static void
_outPath(StringInfo str, Path *node)
{
appendStringInfo(str, " PATH :pathtype %d :cost %f :pathkeys ",
appendStringInfo(str, " PATH :pathtype %d :cost %.2f :pathkeys ",
node->pathtype,
node->path_cost);
_outNode(str, node->pathkeys);
@ -923,7 +933,7 @@ static void
_outIndexPath(StringInfo str, IndexPath *node)
{
appendStringInfo(str,
" INDEXPATH :pathtype %d :cost %f :pathkeys ",
" INDEXPATH :pathtype %d :cost %.2f :pathkeys ",
node->path.pathtype,
node->path.path_cost);
_outNode(str, node->path.pathkeys);
@ -945,7 +955,7 @@ static void
_outTidPath(StringInfo str, TidPath *node)
{
appendStringInfo(str,
" TIDPATH :pathtype %d :cost %f :pathkeys ",
" TIDPATH :pathtype %d :cost %.2f :pathkeys ",
node->path.pathtype,
node->path.path_cost);
_outNode(str, node->path.pathkeys);
@ -964,14 +974,11 @@ static void
_outNestPath(StringInfo str, NestPath *node)
{
appendStringInfo(str,
" NESTPATH :pathtype %d :cost %f :pathkeys ",
" NESTPATH :pathtype %d :cost %.2f :pathkeys ",
node->path.pathtype,
node->path.path_cost);
_outNode(str, node->path.pathkeys);
appendStringInfo(str, " :pathinfo ");
_outNode(str, node->pathinfo);
/*
* Not sure if these are nodes; they're declared as "struct path *".
* For now, i'll just print the addresses.
@ -990,14 +997,11 @@ static void
_outMergePath(StringInfo str, MergePath *node)
{
appendStringInfo(str,
" MERGEPATH :pathtype %d :cost %f :pathkeys ",
" MERGEPATH :pathtype %d :cost %.2f :pathkeys ",
node->jpath.path.pathtype,
node->jpath.path.path_cost);
_outNode(str, node->jpath.path.pathkeys);
appendStringInfo(str, " :pathinfo ");
_outNode(str, node->jpath.pathinfo);
/*
* Not sure if these are nodes; they're declared as "struct path *".
* For now, i'll just print the addresses.
@ -1025,14 +1029,11 @@ static void
_outHashPath(StringInfo str, HashPath *node)
{
appendStringInfo(str,
" HASHPATH :pathtype %d :cost %f :pathkeys ",
" HASHPATH :pathtype %d :cost %.2f :pathkeys ",
node->jpath.path.pathtype,
node->jpath.path.path_cost);
_outNode(str, node->jpath.path.pathkeys);
appendStringInfo(str, " :pathinfo ");
_outNode(str, node->jpath.pathinfo);
/*
* Not sure if these are nodes; they're declared as "struct path *".
* For now, i'll just print the addresses.
@ -1067,9 +1068,7 @@ _outRestrictInfo(StringInfo str, RestrictInfo *node)
appendStringInfo(str, " RESTRICTINFO :clause ");
_outNode(str, node->clause);
appendStringInfo(str,
" :selectivity %f :subclauseindices ",
node->selectivity);
appendStringInfo(str, " :subclauseindices ");
_outNode(str, node->subclauseindices);
appendStringInfo(str, " :mergejoinoperator %u ", node->mergejoinoperator);
@ -1466,6 +1465,9 @@ _outNode(StringInfo str, void *obj)
case T_RelOptInfo:
_outRelOptInfo(str, obj);
break;
case T_IndexOptInfo:
_outIndexOptInfo(str, obj);
break;
case T_TargetEntry:
_outTargetEntry(str, obj);
break;

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.33 1999/11/23 20:06:53 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.34 2000/01/09 00:26:24 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -364,8 +364,8 @@ print_plan_recursive(Plan *p, Query *parsetree, int indentLevel, char *label)
return;
for (i = 0; i < indentLevel; i++)
printf(" ");
printf("%s%s :c=%.4f :s=%d :w=%d ", label, plannode_type(p),
p->cost, p->plan_size, p->plan_width);
printf("%s%s :c=%.4f :r=%.0f :w=%d ", label, plannode_type(p),
p->cost, p->plan_rows, p->plan_width);
if (IsA(p, Scan) ||IsA(p, SeqScan))
{
RangeTblEntry *rte;

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.76 1999/12/13 01:26:54 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.77 2000/01/09 00:26:24 tgl Exp $
*
* NOTES
* Most of the read functions for plan nodes are tested. (In fact, they
@ -233,9 +233,9 @@ _getPlan(Plan *node)
token = lsptok(NULL, &length); /* next is the actual cost */
node->cost = (Cost) atof(token);
token = lsptok(NULL, &length); /* skip the :size */
token = lsptok(NULL, &length); /* get the plan_size */
node->plan_size = atoi(token);
token = lsptok(NULL, &length); /* skip the :rows */
token = lsptok(NULL, &length); /* get the plan_rows */
node->plan_rows = atof(token);
token = lsptok(NULL, &length); /* skip the :width */
token = lsptok(NULL, &length); /* get the plan_width */
@ -1293,6 +1293,14 @@ _readRelOptInfo()
token = lsptok(NULL, &length); /* get :relids */
local_node->relids = toIntList(nodeRead(true)); /* now read it */
token = lsptok(NULL, &length); /* get :rows */
token = lsptok(NULL, &length); /* now read it */
local_node->rows = atof(token);
token = lsptok(NULL, &length); /* get :width */
token = lsptok(NULL, &length); /* now read it */
local_node->width = atoi(token);
token = lsptok(NULL, &length); /* get :indexed */
token = lsptok(NULL, &length); /* now read it */
@ -1303,19 +1311,11 @@ _readRelOptInfo()
token = lsptok(NULL, &length); /* get :pages */
token = lsptok(NULL, &length); /* now read it */
local_node->pages = (unsigned int) atoi(token);
local_node->pages = atol(token);
token = lsptok(NULL, &length); /* get :tuples */
token = lsptok(NULL, &length); /* now read it */
local_node->tuples = (unsigned int) atoi(token);
token = lsptok(NULL, &length); /* get :size */
token = lsptok(NULL, &length); /* now read it */
local_node->size = (unsigned int) atoi(token);
token = lsptok(NULL, &length); /* get :width */
token = lsptok(NULL, &length); /* now read it */
local_node->width = (unsigned int) atoi(token);
local_node->tuples = atof(token);
token = lsptok(NULL, &length); /* get :targetlist */
local_node->targetlist = nodeRead(true); /* now read it */
@ -1348,6 +1348,34 @@ _readRelOptInfo()
return local_node;
}
/* ----------------
* _readIndexOptInfo
* ----------------
*/
static IndexOptInfo *
_readIndexOptInfo()
{
IndexOptInfo *local_node;
char *token;
int length;
local_node = makeNode(IndexOptInfo);
token = lsptok(NULL, &length); /* get :indexoid */
token = lsptok(NULL, &length); /* now read it */
local_node->indexoid = (Oid) atoi(token);
token = lsptok(NULL, &length); /* get :pages */
token = lsptok(NULL, &length); /* now read it */
local_node->pages = atol(token);
token = lsptok(NULL, &length); /* get :tuples */
token = lsptok(NULL, &length); /* now read it */
local_node->tuples = atof(token);
return local_node;
}
/* ----------------
* _readTargetEntry
* ----------------
@ -1572,9 +1600,6 @@ _readNestPath()
token = lsptok(NULL, &length); /* get :pathkeys */
local_node->path.pathkeys = nodeRead(true); /* now read it */
token = lsptok(NULL, &length); /* get :pathinfo */
local_node->pathinfo = nodeRead(true); /* now read it */
/*
* Not sure if these are nodes; they're declared as "struct path *".
* For now, i'll just print the addresses.
@ -1626,9 +1651,6 @@ _readMergePath()
token = lsptok(NULL, &length); /* get :pathkeys */
local_node->jpath.path.pathkeys = nodeRead(true); /* now read it */
token = lsptok(NULL, &length); /* get :pathinfo */
local_node->jpath.pathinfo = nodeRead(true); /* now read it */
/*
* Not sure if these are nodes; they're declared as "struct path *".
* For now, i'll just print the addresses.
@ -1689,9 +1711,6 @@ _readHashPath()
token = lsptok(NULL, &length); /* get :pathkeys */
local_node->jpath.path.pathkeys = nodeRead(true); /* now read it */
token = lsptok(NULL, &length); /* get :pathinfo */
local_node->jpath.pathinfo = nodeRead(true); /* now read it */
/*
* Not sure if these are nodes; they're declared as "struct path *".
* For now, i'll just print the addresses.
@ -1762,10 +1781,6 @@ _readRestrictInfo()
token = lsptok(NULL, &length); /* get :clause */
local_node->clause = nodeRead(true); /* now read it */
token = lsptok(NULL, &length); /* get :selectivity */
token = lsptok(NULL, &length); /* now read it */
local_node->selectivity = atof(token);
token = lsptok(NULL, &length); /* get :subclauseindices */
local_node->subclauseindices = nodeRead(true); /* now read it */
@ -1909,6 +1924,8 @@ parsePlanString(void)
return_value = _readEState();
else if (!strncmp(token, "RELOPTINFO", length))
return_value = _readRelOptInfo();
else if (!strncmp(token, "INDEXOPTINFO", length))
return_value = _readIndexOptInfo();
else if (!strncmp(token, "TARGETENTRY", length))
return_value = _readTargetEntry();
else if (!strncmp(token, "RTE", length))