Skip to content

Commit 7bbd9d9

Browse files
committed
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.
1 parent b95c05c commit 7bbd9d9

File tree

3 files changed

+76
-19
lines changed

3 files changed

+76
-19
lines changed

src/backend/executor/execAmi.c

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.77 2003/12/18 20:21:37 tgl Exp $
9+
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.78 2004/03/02 18:56:15 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -348,3 +348,68 @@ ExecSupportsBackwardScan(Plan *node)
348348
return false;
349349
}
350350
}
351+
352+
/*
353+
* ExecMayReturnRawTuples
354+
* Check whether a plan tree may return "raw" disk tuples (that is,
355+
* pointers to original data in disk buffers, as opposed to temporary
356+
* tuples constructed by projection steps). In the case of Append,
357+
* some subplans may return raw tuples and others projected tuples;
358+
* we return "true" if any of the returned tuples could be raw.
359+
*
360+
* This must be passed an already-initialized planstate tree, because we
361+
* need to look at the results of ExecAssignScanProjectionInfo().
362+
*/
363+
bool
364+
ExecMayReturnRawTuples(PlanState *node)
365+
{
366+
/*
367+
* At a table scan node, we check whether ExecAssignScanProjectionInfo
368+
* decided to do projection or not. Most non-scan nodes always project
369+
* and so we can return "false" immediately. For nodes that don't
370+
* project but just pass up input tuples, we have to recursively
371+
* examine the input plan node.
372+
*
373+
* Note: Hash and Material are listed here because they sometimes
374+
* return an original input tuple, not a copy. But Sort and SetOp
375+
* never return an original tuple, so they can be treated like
376+
* projecting nodes.
377+
*/
378+
switch (nodeTag(node))
379+
{
380+
/* Table scan nodes */
381+
case T_SeqScanState:
382+
case T_IndexScanState:
383+
case T_TidScanState:
384+
case T_SubqueryScanState:
385+
case T_FunctionScanState:
386+
if (node->ps_ProjInfo == NULL)
387+
return true;
388+
break;
389+
390+
/* Non-projecting nodes */
391+
case T_HashState:
392+
case T_MaterialState:
393+
case T_UniqueState:
394+
case T_LimitState:
395+
return ExecMayReturnRawTuples(node->lefttree);
396+
397+
case T_AppendState:
398+
{
399+
AppendState *appendstate = (AppendState *) node;
400+
int j;
401+
402+
for (j = 0; j < appendstate->as_nplans; j++)
403+
{
404+
if (ExecMayReturnRawTuples(appendstate->appendplans[j]))
405+
return true;
406+
}
407+
break;
408+
}
409+
410+
/* All projecting node types come here */
411+
default:
412+
break;
413+
}
414+
return false;
415+
}

src/backend/executor/execMain.c

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.228 2004/01/22 02:23:21 tgl Exp $
29+
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.229 2004/03/02 18:56:15 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -659,10 +659,10 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
659659
/*
660660
* Initialize the junk filter if needed. SELECT and INSERT queries
661661
* need a filter if there are any junk attrs in the tlist. INSERT and
662-
* SELECT INTO also need a filter if the top plan node is a scan node
663-
* that's not doing projection (else we'll be scribbling on the scan
664-
* tuple!) UPDATE and DELETE always need a filter, since there's
665-
* always a junk 'ctid' attribute present --- no need to look first.
662+
* SELECT INTO also need a filter if the plan may return raw disk tuples
663+
* (else heap_insert will be scribbling on the source relation!).
664+
* UPDATE and DELETE always need a filter, since there's always a junk
665+
* 'ctid' attribute present --- no need to look first.
666666
*/
667667
{
668668
bool junk_filter_needed = false;
@@ -683,18 +683,9 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
683683
}
684684
}
685685
if (!junk_filter_needed &&
686-
(operation == CMD_INSERT || do_select_into))
687-
{
688-
if (IsA(planstate, SeqScanState) ||
689-
IsA(planstate, IndexScanState) ||
690-
IsA(planstate, TidScanState) ||
691-
IsA(planstate, SubqueryScanState) ||
692-
IsA(planstate, FunctionScanState))
693-
{
694-
if (planstate->ps_ProjInfo == NULL)
695-
junk_filter_needed = true;
696-
}
697-
}
686+
(operation == CMD_INSERT || do_select_into) &&
687+
ExecMayReturnRawTuples(planstate))
688+
junk_filter_needed = true;
698689
break;
699690
case CMD_UPDATE:
700691
case CMD_DELETE:

src/include/executor/executor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.106 2004/01/22 02:23:21 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.107 2004/03/02 18:56:15 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -36,6 +36,7 @@ extern void ExecMarkPos(PlanState *node);
3636
extern void ExecRestrPos(PlanState *node);
3737
extern bool ExecSupportsMarkRestore(NodeTag plantype);
3838
extern bool ExecSupportsBackwardScan(Plan *node);
39+
extern bool ExecMayReturnRawTuples(PlanState *node);
3940

4041
/*
4142
* prototypes from functions in execGrouping.c

0 commit comments

Comments
 (0)