mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-23 19:39:53 +08:00
Junkfilter logic to force a projection step during SELECT INTO was too
simplistic; it recognized SELECT * FROM but not SELECT * FROM LIMIT. Per bug report from Jeff Bohmer.
This commit is contained in:
parent
b95c05c9c1
commit
7bbd9d93cc
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.77 2003/12/18 20:21:37 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.78 2004/03/02 18:56:15 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -348,3 +348,68 @@ ExecSupportsBackwardScan(Plan *node)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ExecMayReturnRawTuples
|
||||
* Check whether a plan tree may return "raw" disk tuples (that is,
|
||||
* pointers to original data in disk buffers, as opposed to temporary
|
||||
* tuples constructed by projection steps). In the case of Append,
|
||||
* some subplans may return raw tuples and others projected tuples;
|
||||
* we return "true" if any of the returned tuples could be raw.
|
||||
*
|
||||
* This must be passed an already-initialized planstate tree, because we
|
||||
* need to look at the results of ExecAssignScanProjectionInfo().
|
||||
*/
|
||||
bool
|
||||
ExecMayReturnRawTuples(PlanState *node)
|
||||
{
|
||||
/*
|
||||
* At a table scan node, we check whether ExecAssignScanProjectionInfo
|
||||
* decided to do projection or not. Most non-scan nodes always project
|
||||
* and so we can return "false" immediately. For nodes that don't
|
||||
* project but just pass up input tuples, we have to recursively
|
||||
* examine the input plan node.
|
||||
*
|
||||
* Note: Hash and Material are listed here because they sometimes
|
||||
* return an original input tuple, not a copy. But Sort and SetOp
|
||||
* never return an original tuple, so they can be treated like
|
||||
* projecting nodes.
|
||||
*/
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
/* Table scan nodes */
|
||||
case T_SeqScanState:
|
||||
case T_IndexScanState:
|
||||
case T_TidScanState:
|
||||
case T_SubqueryScanState:
|
||||
case T_FunctionScanState:
|
||||
if (node->ps_ProjInfo == NULL)
|
||||
return true;
|
||||
break;
|
||||
|
||||
/* Non-projecting nodes */
|
||||
case T_HashState:
|
||||
case T_MaterialState:
|
||||
case T_UniqueState:
|
||||
case T_LimitState:
|
||||
return ExecMayReturnRawTuples(node->lefttree);
|
||||
|
||||
case T_AppendState:
|
||||
{
|
||||
AppendState *appendstate = (AppendState *) node;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < appendstate->as_nplans; j++)
|
||||
{
|
||||
if (ExecMayReturnRawTuples(appendstate->appendplans[j]))
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* All projecting node types come here */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.228 2004/01/22 02:23:21 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.229 2004/03/02 18:56:15 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -659,10 +659,10 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
|
||||
/*
|
||||
* Initialize the junk filter if needed. SELECT and INSERT queries
|
||||
* need a filter if there are any junk attrs in the tlist. INSERT and
|
||||
* SELECT INTO also need a filter if the top plan node is a scan node
|
||||
* that's not doing projection (else we'll be scribbling on the scan
|
||||
* tuple!) UPDATE and DELETE always need a filter, since there's
|
||||
* always a junk 'ctid' attribute present --- no need to look first.
|
||||
* SELECT INTO also need a filter if the plan may return raw disk tuples
|
||||
* (else heap_insert will be scribbling on the source relation!).
|
||||
* UPDATE and DELETE always need a filter, since there's always a junk
|
||||
* 'ctid' attribute present --- no need to look first.
|
||||
*/
|
||||
{
|
||||
bool junk_filter_needed = false;
|
||||
@ -683,18 +683,9 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
|
||||
}
|
||||
}
|
||||
if (!junk_filter_needed &&
|
||||
(operation == CMD_INSERT || do_select_into))
|
||||
{
|
||||
if (IsA(planstate, SeqScanState) ||
|
||||
IsA(planstate, IndexScanState) ||
|
||||
IsA(planstate, TidScanState) ||
|
||||
IsA(planstate, SubqueryScanState) ||
|
||||
IsA(planstate, FunctionScanState))
|
||||
{
|
||||
if (planstate->ps_ProjInfo == NULL)
|
||||
junk_filter_needed = true;
|
||||
}
|
||||
}
|
||||
(operation == CMD_INSERT || do_select_into) &&
|
||||
ExecMayReturnRawTuples(planstate))
|
||||
junk_filter_needed = true;
|
||||
break;
|
||||
case CMD_UPDATE:
|
||||
case CMD_DELETE:
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.106 2004/01/22 02:23:21 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.107 2004/03/02 18:56:15 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -36,6 +36,7 @@ extern void ExecMarkPos(PlanState *node);
|
||||
extern void ExecRestrPos(PlanState *node);
|
||||
extern bool ExecSupportsMarkRestore(NodeTag plantype);
|
||||
extern bool ExecSupportsBackwardScan(Plan *node);
|
||||
extern bool ExecMayReturnRawTuples(PlanState *node);
|
||||
|
||||
/*
|
||||
* prototypes from functions in execGrouping.c
|
||||
|
Loading…
Reference in New Issue
Block a user