Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 04c8785

Browse files
committed
Restructure planning of nestloop inner indexscans so that the set of usable
joinclauses is determined accurately for each join. Formerly, the code only considered joinclauses that used all of the rels from the outer side of the join; thus for example FROM (a CROSS JOIN b) JOIN c ON (c.f1 = a.x AND c.f2 = b.y) could not exploit a two-column index on c(f1,f2), since neither of the qual clauses would be in the joininfo list it looked in. The new code does this correctly, and also is able to eliminate redundant clauses, thus fixing the problem noted 24-Oct-02 by Hans-Jürgen Schönig.
1 parent 6bfc09b commit 04c8785

File tree

19 files changed

+742
-579
lines changed

19 files changed

+742
-579
lines changed

src/backend/nodes/copyfuncs.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.220 2002/11/23 03:59:07 momjian Exp $
18+
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.221 2002/11/24 21:52:13 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1148,7 +1148,9 @@ _copyRelOptInfo(RelOptInfo *from)
11481148
newnode->baserestrictcost = from->baserestrictcost;
11491149
newnode->outerjoinset = listCopy(from->outerjoinset);
11501150
Node_Copy(from, newnode, joininfo);
1151-
Node_Copy(from, newnode, innerjoin);
1151+
1152+
newnode->index_outer_relids = listCopy(from->index_outer_relids);
1153+
Node_Copy(from, newnode, index_inner_paths);
11521154

11531155
return newnode;
11541156
}
@@ -1200,6 +1202,9 @@ _copyIndexOptInfo(IndexOptInfo *from)
12001202
Node_Copy(from, newnode, indpred);
12011203
newnode->unique = from->unique;
12021204

1205+
newnode->outer_relids = listCopy(from->outer_relids);
1206+
Node_Copy(from, newnode, inner_paths);
1207+
12031208
return newnode;
12041209
}
12051210

@@ -1262,8 +1267,6 @@ _copyIndexPath(IndexPath *from)
12621267
Node_Copy(from, newnode, indexinfo);
12631268
Node_Copy(from, newnode, indexqual);
12641269
newnode->indexscandir = from->indexscandir;
1265-
newnode->joinrelids = listCopy(from->joinrelids);
1266-
newnode->alljoinquals = from->alljoinquals;
12671270
newnode->rows = from->rows;
12681271

12691272
return newnode;
@@ -1491,6 +1494,25 @@ _copyJoinInfo(JoinInfo *from)
14911494
return newnode;
14921495
}
14931496

1497+
/* ----------------
1498+
* _copyInnerIndexscanInfo
1499+
* ----------------
1500+
*/
1501+
static InnerIndexscanInfo *
1502+
_copyInnerIndexscanInfo(InnerIndexscanInfo *from)
1503+
{
1504+
InnerIndexscanInfo *newnode = makeNode(InnerIndexscanInfo);
1505+
1506+
/*
1507+
* copy remainder of node
1508+
*/
1509+
newnode->other_relids = listCopy(from->other_relids);
1510+
newnode->isouterjoin = from->isouterjoin;
1511+
Node_Copy(from, newnode, best_innerpath);
1512+
1513+
return newnode;
1514+
}
1515+
14941516
/* ****************************************************************
14951517
* parsenodes.h copy functions
14961518
* ****************************************************************
@@ -2952,6 +2974,9 @@ copyObject(void *from)
29522974
case T_IndexOptInfo:
29532975
retval = _copyIndexOptInfo(from);
29542976
break;
2977+
case T_InnerIndexscanInfo:
2978+
retval = _copyInnerIndexscanInfo(from);
2979+
break;
29552980

29562981
/*
29572982
* VALUE NODES

src/backend/nodes/equalfuncs.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
* Portions Copyright (c) 1994, Regents of the University of California
2121
*
2222
* IDENTIFICATION
23-
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.166 2002/11/23 03:59:07 momjian Exp $
23+
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.167 2002/11/24 21:52:13 tgl Exp $
2424
*
2525
*-------------------------------------------------------------------------
2626
*/
@@ -429,10 +429,6 @@ _equalIndexPath(IndexPath *a, IndexPath *b)
429429
return false;
430430
if (a->indexscandir != b->indexscandir)
431431
return false;
432-
if (!equali(a->joinrelids, b->joinrelids))
433-
return false;
434-
if (a->alljoinquals != b->alljoinquals)
435-
return false;
436432

437433
/*
438434
* Skip 'rows' because of possibility of floating-point roundoff
@@ -548,13 +544,11 @@ _equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
548544
return false;
549545

550546
/*
551-
* We ignore eval_cost, this_selec, left/right_pathkey, and
552-
* left/right_bucketsize, since they may not be set yet, and should be
553-
* derivable from the clause anyway. Probably it's not really
554-
* necessary to compare any of these remaining fields ...
547+
* We ignore subclauseindices, eval_cost, this_selec, left/right_pathkey,
548+
* and left/right_bucketsize, since they may not be set yet, and should be
549+
* derivable from the clause anyway. Probably it's not really necessary
550+
* to compare any of these remaining fields ...
555551
*/
556-
if (!equal(a->subclauseindices, b->subclauseindices))
557-
return false;
558552
if (a->mergejoinoperator != b->mergejoinoperator)
559553
return false;
560554
if (a->left_sortop != b->left_sortop)
@@ -576,6 +570,18 @@ _equalJoinInfo(JoinInfo *a, JoinInfo *b)
576570
return true;
577571
}
578572

573+
static bool
574+
_equalInnerIndexscanInfo(InnerIndexscanInfo *a, InnerIndexscanInfo *b)
575+
{
576+
if (!equali(a->other_relids, b->other_relids))
577+
return false;
578+
if (a->isouterjoin != b->isouterjoin)
579+
return false;
580+
if (!equal(a->best_innerpath, b->best_innerpath))
581+
return false;
582+
return true;
583+
}
584+
579585
/*
580586
* Stuff from parsenodes.h
581587
*/
@@ -2120,6 +2126,9 @@ equal(void *a, void *b)
21202126
case T_JoinInfo:
21212127
retval = _equalJoinInfo(a, b);
21222128
break;
2129+
case T_InnerIndexscanInfo:
2130+
retval = _equalInnerIndexscanInfo(a, b);
2131+
break;
21232132
case T_TidPath:
21242133
retval = _equalTidPath(a, b);
21252134
break;

src/backend/nodes/list.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.41 2002/06/20 20:29:29 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.42 2002/11/24 21:52:13 tgl Exp $
1212
*
1313
* NOTES
1414
* XXX a few of the following functions are duplicated to handle
@@ -372,6 +372,46 @@ set_unioni(List *l1, List *l2)
372372
return retval;
373373
}
374374

375+
/*
376+
* Generate the intersection of two lists,
377+
* ie, all members of both l1 and l2.
378+
*
379+
* NOTE: if there are duplicates in l1 they will still be duplicate in the
380+
* result; but duplicates in l2 are discarded.
381+
*
382+
* The result is a fresh List, but it points to the same member nodes
383+
* as were in the inputs.
384+
*/
385+
#ifdef NOT_USED
386+
List *
387+
set_intersect(List *l1, List *l2)
388+
{
389+
List *retval = NIL;
390+
List *i;
391+
392+
foreach(i, l1)
393+
{
394+
if (member(lfirst(i), l2))
395+
retval = lappend(retval, lfirst(i));
396+
}
397+
return retval;
398+
}
399+
#endif
400+
401+
List *
402+
set_intersecti(List *l1, List *l2)
403+
{
404+
List *retval = NIL;
405+
List *i;
406+
407+
foreach(i, l1)
408+
{
409+
if (intMember(lfirsti(i), l2))
410+
retval = lappendi(retval, lfirsti(i));
411+
}
412+
return retval;
413+
}
414+
375415
/*
376416
* member()
377417
* nondestructive, returns t iff l1 is a member of the list l2

src/backend/nodes/outfuncs.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
66
* Portions Copyright (c) 1994, Regents of the University of California
77
*
8-
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.180 2002/11/15 02:50:07 momjian Exp $
8+
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.181 2002/11/24 21:52:13 tgl Exp $
99
*
1010
* NOTES
1111
* Every (plan) node in POSTGRES has an associated "out" routine which
@@ -1067,12 +1067,8 @@ _outIndexPath(StringInfo str, IndexPath *node)
10671067
appendStringInfo(str, " :indexqual ");
10681068
_outNode(str, node->indexqual);
10691069

1070-
appendStringInfo(str, " :indexscandir %d :joinrelids ",
1071-
(int) node->indexscandir);
1072-
_outIntList(str, node->joinrelids);
1073-
1074-
appendStringInfo(str, " :alljoinquals %s :rows %.2f ",
1075-
booltostr(node->alljoinquals),
1070+
appendStringInfo(str, " :indexscandir %d :rows %.2f ",
1071+
(int) node->indexscandir,
10761072
node->rows);
10771073
}
10781074

src/backend/nodes/readfuncs.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.137 2002/11/15 02:50:07 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.138 2002/11/24 21:52:13 tgl Exp $
1212
*
1313
* NOTES
1414
* Most of the read functions for plan nodes are tested. (In fact, they
@@ -1824,13 +1824,6 @@ _readIndexPath(void)
18241824
token = pg_strtok(&length); /* now read it */
18251825
local_node->indexscandir = (ScanDirection) atoi(token);
18261826

1827-
token = pg_strtok(&length); /* get :joinrelids */
1828-
local_node->joinrelids = toIntList(nodeRead(true));
1829-
1830-
token = pg_strtok(&length); /* get :alljoinquals */
1831-
token = pg_strtok(&length); /* now read it */
1832-
local_node->alljoinquals = strtobool(token);
1833-
18341827
token = pg_strtok(&length); /* get :rows */
18351828
token = pg_strtok(&length); /* now read it */
18361829
local_node->rows = atof(token);

0 commit comments

Comments
 (0)