simplistic; it recognized SELECT * FROM but not SELECT * FROM LIMIT.
Per bug report from Jeff Bohmer.
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
+}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* 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;
}
}
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:
* 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 $
*
*-------------------------------------------------------------------------
*/
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