1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +03:00

IN clauses appearing at top level of WHERE can now be handled as joins.

There are two implementation techniques: the executor understands a new
JOIN_IN jointype, which emits at most one matching row per left-hand row,
or the result of the IN's sub-select can be fed through a DISTINCT filter
and then joined as an ordinary relation.
Along the way, some minor code cleanup in the optimizer; notably, break
out most of the jointree-rearrangement preprocessing in planner.c and
put it in a new file prep/prepjointree.c.
This commit is contained in:
Tom Lane
2003-01-20 18:55:07 +00:00
parent be2b660ecd
commit bdfbfde1b1
47 changed files with 2075 additions and 875 deletions

View File

@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.236 2003/01/15 19:35:35 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.237 2003/01/20 18:54:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1095,6 +1095,21 @@ _copyJoinInfo(JoinInfo *from)
return newnode;
}
/*
* _copyInClauseInfo
*/
static InClauseInfo *
_copyInClauseInfo(InClauseInfo *from)
{
InClauseInfo *newnode = makeNode(InClauseInfo);
COPY_INTLIST_FIELD(lefthand);
COPY_INTLIST_FIELD(righthand);
COPY_NODE_FIELD(sub_targetlist);
return newnode;
}
/* ****************************************************************
* parsenodes.h copy functions
* ****************************************************************
@@ -1424,9 +1439,9 @@ _copyQuery(Query *from)
/*
* We do not copy the planner internal fields: base_rel_list,
* other_rel_list, join_rel_list, equi_key_list, query_pathkeys,
* hasJoinRTEs. That would get us into copying RelOptInfo/Path
* trees, which we don't want to do.
* other_rel_list, join_rel_list, equi_key_list, in_info_list,
* query_pathkeys, hasJoinRTEs. That would get us into copying
* RelOptInfo/Path trees, which we don't want to do.
*/
return newnode;
@@ -2490,6 +2505,9 @@ copyObject(void *from)
case T_JoinInfo:
retval = _copyJoinInfo(from);
break;
case T_InClauseInfo:
retval = _copyInClauseInfo(from);
break;
/*
* VALUE NODES

View File

@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.180 2003/01/15 19:35:37 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.181 2003/01/20 18:54:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -486,6 +486,16 @@ _equalJoinInfo(JoinInfo *a, JoinInfo *b)
return true;
}
static bool
_equalInClauseInfo(InClauseInfo *a, InClauseInfo *b)
{
COMPARE_INTLIST_FIELD(lefthand);
COMPARE_INTLIST_FIELD(righthand);
COMPARE_NODE_FIELD(sub_targetlist);
return true;
}
/*
* Stuff from parsenodes.h
@@ -518,9 +528,9 @@ _equalQuery(Query *a, Query *b)
/*
* We do not check the internal-to-the-planner fields: base_rel_list,
* other_rel_list, join_rel_list, equi_key_list, query_pathkeys,
* hasJoinRTEs. They might not be set yet, and in any case they should
* be derivable from the other fields.
* other_rel_list, join_rel_list, equi_key_list, in_info_list,
* query_pathkeys, hasJoinRTEs. They might not be set yet, and in any
* case they should be derivable from the other fields.
*/
return true;
}
@@ -1618,6 +1628,9 @@ equal(void *a, void *b)
case T_JoinInfo:
retval = _equalJoinInfo(a, b);
break;
case T_InClauseInfo:
retval = _equalInClauseInfo(a, b);
break;
/*
* LIST NODES

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.43 2002/12/17 01:18:18 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.44 2003/01/20 18:54:47 tgl Exp $
*
* NOTES
* XXX a few of the following functions are duplicated to handle
@@ -638,10 +638,10 @@ lreverse(List *l)
}
/*
* Return t if two integer lists have no members in common.
* Return t if two integer lists have any members in common.
*/
bool
nonoverlap_setsi(List *list1, List *list2)
overlap_setsi(List *list1, List *list2)
{
List *x;
@@ -650,9 +650,9 @@ nonoverlap_setsi(List *list1, List *list2)
int e = lfirsti(x);
if (intMember(e, list2))
return false;
return true;
}
return true;
return false;
}
/*

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.193 2003/01/15 19:35:39 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.194 2003/01/20 18:54:47 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
@@ -905,6 +905,18 @@ _outMaterialPath(StringInfo str, MaterialPath *node)
WRITE_NODE_FIELD(subpath);
}
static void
_outUniquePath(StringInfo str, UniquePath *node)
{
WRITE_NODE_TYPE("UNIQUEPATH");
_outPathInfo(str, (Path *) node);
WRITE_NODE_FIELD(subpath);
WRITE_BOOL_FIELD(use_hash);
WRITE_FLOAT_FIELD(rows, "%.0f");
}
static void
_outNestPath(StringInfo str, NestPath *node)
{
@@ -969,6 +981,16 @@ _outJoinInfo(StringInfo str, JoinInfo *node)
WRITE_NODE_FIELD(jinfo_restrictinfo);
}
static void
_outInClauseInfo(StringInfo str, InClauseInfo *node)
{
WRITE_NODE_TYPE("INCLAUSEINFO");
WRITE_INTLIST_FIELD(lefthand);
WRITE_INTLIST_FIELD(righthand);
WRITE_NODE_FIELD(sub_targetlist);
}
/*****************************************************************************
*
* Stuff from parsenodes.h.
@@ -1563,6 +1585,9 @@ _outNode(StringInfo str, void *obj)
case T_MaterialPath:
_outMaterialPath(str, obj);
break;
case T_UniquePath:
_outUniquePath(str, obj);
break;
case T_NestPath:
_outNestPath(str, obj);
break;
@@ -1581,6 +1606,9 @@ _outNode(StringInfo str, void *obj)
case T_JoinInfo:
_outJoinInfo(str, obj);
break;
case T_InClauseInfo:
_outInClauseInfo(str, obj);
break;
case T_CreateStmt:
_outCreateStmt(str, obj);