1
0
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:
Tom Lane
2000-09-08 02:11:33 +00:00
parent 4fc8465398
commit 16f1cfcb87
4 changed files with 69 additions and 33 deletions

View File

@ -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;
} }
} }

View File

@ -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

View File

@ -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,

View File

@ -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 */