mirror of
https://github.com/postgres/postgres.git
synced 2025-07-17 06:41:09 +03:00
Back-patch fix for bogus plans involving non-mark/restorable plan
as inner plan of a mergejoin.
This commit is contained in:
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: execAmi.c,v 1.46 2000/04/12 17:15:07 momjian Exp $
|
* $Id: execAmi.c,v 1.46.2.1 2000/09/08 02:11:32 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -424,7 +424,7 @@ ExecMarkPos(Plan *node)
|
|||||||
{
|
{
|
||||||
switch (nodeTag(node))
|
switch (nodeTag(node))
|
||||||
{
|
{
|
||||||
case T_SeqScan:
|
case T_SeqScan:
|
||||||
ExecSeqMarkPos((SeqScan *) node);
|
ExecSeqMarkPos((SeqScan *) node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -432,6 +432,10 @@ ExecMarkPos(Plan *node)
|
|||||||
ExecIndexMarkPos((IndexScan *) node);
|
ExecIndexMarkPos((IndexScan *) node);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_Material:
|
||||||
|
ExecMaterialMarkPos((Material *) node);
|
||||||
|
break;
|
||||||
|
|
||||||
case T_Sort:
|
case T_Sort:
|
||||||
ExecSortMarkPos((Sort *) node);
|
ExecSortMarkPos((Sort *) node);
|
||||||
break;
|
break;
|
||||||
@ -458,7 +462,7 @@ ExecRestrPos(Plan *node)
|
|||||||
{
|
{
|
||||||
switch (nodeTag(node))
|
switch (nodeTag(node))
|
||||||
{
|
{
|
||||||
case T_SeqScan:
|
case T_SeqScan:
|
||||||
ExecSeqRestrPos((SeqScan *) node);
|
ExecSeqRestrPos((SeqScan *) node);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -466,12 +470,16 @@ ExecRestrPos(Plan *node)
|
|||||||
ExecIndexRestrPos((IndexScan *) node);
|
ExecIndexRestrPos((IndexScan *) node);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case T_Material:
|
||||||
|
ExecMaterialRestrPos((Material *) node);
|
||||||
|
break;
|
||||||
|
|
||||||
case T_Sort:
|
case T_Sort:
|
||||||
ExecSortRestrPos((Sort *) node);
|
ExecSortRestrPos((Sort *) node);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
elog(DEBUG, "ExecRestrPos: node type %u not supported", nodeTag(node));
|
elog(ERROR, "ExecRestrPos: node type %u not supported", nodeTag(node));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.30 2000/03/02 04:06:39 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.30.2.1 2000/09/08 02:11:32 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -352,35 +352,30 @@ ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NOT_USED /* not used */
|
|
||||||
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
||||||
* ExecMaterialMarkPos
|
* ExecMaterialMarkPos
|
||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
List /* nothing of interest */
|
void
|
||||||
ExecMaterialMarkPos(Material node)
|
ExecMaterialMarkPos(Material *node)
|
||||||
{
|
{
|
||||||
MaterialState matstate;
|
MaterialState *matstate;
|
||||||
HeapScanDesc scan;
|
HeapScanDesc scan;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* if we haven't materialized yet, just return NIL.
|
* if we haven't materialized yet, just return.
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
matstate = get_matstate(node);
|
matstate = node->matstate;
|
||||||
if (get_mat_Flag(matstate) == false)
|
if (matstate->mat_Flag == false)
|
||||||
return NIL;
|
return;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* XXX access methods don't return positions yet so
|
* mark the scan position
|
||||||
* for now we return NIL. It's possible that
|
|
||||||
* they will never return positions for all I know -cim 10/16/89
|
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
scan = get_css_currentScanDesc((CommonScanState) matstate);
|
scan = matstate->csstate.css_currentScanDesc;
|
||||||
heap_markpos(scan);
|
heap_markpos(scan);
|
||||||
|
|
||||||
return NIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
||||||
@ -388,25 +383,23 @@ ExecMaterialMarkPos(Material node)
|
|||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ExecMaterialRestrPos(Material node)
|
ExecMaterialRestrPos(Material *node)
|
||||||
{
|
{
|
||||||
MaterialState matstate;
|
MaterialState *matstate;
|
||||||
HeapScanDesc scan;
|
HeapScanDesc scan;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* if we haven't materialized yet, just return.
|
* if we haven't materialized yet, just return.
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
matstate = get_matstate(node);
|
matstate = node->matstate;
|
||||||
if (get_mat_Flag(matstate) == false)
|
if (matstate->mat_Flag == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* restore the scan to the previously marked position
|
* restore the scan to the previously marked position
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
scan = get_css_currentScanDesc((CommonScanState) matstate);
|
scan = matstate->csstate.css_currentScanDesc;
|
||||||
heap_restrpos(scan);
|
heap_restrpos(scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.90 2000/05/23 16:56:36 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.90.2.1 2000/09/08 02:11:33 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -639,6 +639,44 @@ create_mergejoin_node(MergePath *best_path,
|
|||||||
best_path->innersortkeys,
|
best_path->innersortkeys,
|
||||||
inner_node);
|
inner_node);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The executor requires the inner side of a mergejoin to support "mark"
|
||||||
|
* and "restore" operations. Not all plan types do, so we must be careful
|
||||||
|
* not to generate an invalid plan. If necessary, an invalid inner plan
|
||||||
|
* can be handled by inserting a Materialize node.
|
||||||
|
*
|
||||||
|
* Since the inner side must be ordered, and only Sorts and IndexScans can
|
||||||
|
* create order to begin with, you might think there's no problem --- but
|
||||||
|
* you'd be wrong. Nestloop and merge joins can *preserve* the order of
|
||||||
|
* their inputs, so they can be selected as the input of a mergejoin,
|
||||||
|
* and that won't work in the present executor.
|
||||||
|
*
|
||||||
|
* Doing this here is a bit of a kluge since the cost of the Materialize
|
||||||
|
* wasn't taken into account in our earlier decisions. But Materialize
|
||||||
|
* is hard to estimate a cost for, and the above consideration shows that
|
||||||
|
* this is a rare case anyway, so this seems an acceptable way to proceed.
|
||||||
|
*
|
||||||
|
* This check must agree with ExecMarkPos/ExecRestrPos in
|
||||||
|
* executor/execAmi.c!
|
||||||
|
*/
|
||||||
|
switch (nodeTag(inner_node))
|
||||||
|
{
|
||||||
|
case T_SeqScan:
|
||||||
|
case T_IndexScan:
|
||||||
|
case T_Material:
|
||||||
|
case T_Sort:
|
||||||
|
/* OK, these inner plans support mark/restore */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Ooops, need to materialize the inner plan */
|
||||||
|
inner_node = (Plan *) make_material(inner_tlist,
|
||||||
|
_NONAME_RELATION_ID_,
|
||||||
|
inner_node,
|
||||||
|
0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
join_node = make_mergejoin(tlist,
|
join_node = make_mergejoin(tlist,
|
||||||
qpqual,
|
qpqual,
|
||||||
mergeclauses,
|
mergeclauses,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: nodeMaterial.h,v 1.12 2000/01/26 05:58:05 momjian Exp $
|
* $Id: nodeMaterial.h,v 1.12.2.1 2000/09/08 02:11:31 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -20,11 +20,8 @@ extern TupleTableSlot *ExecMaterial(Material *node);
|
|||||||
extern bool ExecInitMaterial(Material *node, EState *estate, Plan *parent);
|
extern bool ExecInitMaterial(Material *node, EState *estate, Plan *parent);
|
||||||
extern int ExecCountSlotsMaterial(Material *node);
|
extern int ExecCountSlotsMaterial(Material *node);
|
||||||
extern void ExecEndMaterial(Material *node);
|
extern void ExecEndMaterial(Material *node);
|
||||||
|
extern void ExecMaterialMarkPos(Material *node);
|
||||||
|
extern void ExecMaterialRestrPos(Material *node);
|
||||||
extern void ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent);
|
extern void ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent);
|
||||||
|
|
||||||
#ifdef NOT_USED
|
|
||||||
extern List ExecMaterialMarkPos(Material *node);
|
|
||||||
extern void ExecMaterialRestrPos(Material *node);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif /* NODEMATERIAL_H */
|
#endif /* NODEMATERIAL_H */
|
||||||
|
Reference in New Issue
Block a user