aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeCustom.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeCustom.c')
-rw-r--r--src/backend/executor/nodeCustom.c126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c
new file mode 100644
index 00000000000..576b295a49a
--- /dev/null
+++ b/src/backend/executor/nodeCustom.c
@@ -0,0 +1,126 @@
+/* ------------------------------------------------------------------------
+ *
+ * nodeCustom.c
+ * Routines to handle execution of custom scan node
+ *
+ * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * ------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "executor/executor.h"
+#include "executor/nodeCustom.h"
+#include "nodes/execnodes.h"
+#include "nodes/plannodes.h"
+#include "parser/parsetree.h"
+#include "utils/hsearch.h"
+#include "utils/memutils.h"
+#include "utils/rel.h"
+
+CustomScanState *
+ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
+{
+ CustomScanState *css;
+ Relation scan_rel;
+
+ /* populate a CustomScanState according to the CustomScan */
+ css = (CustomScanState *) cscan->methods->CreateCustomScanState(cscan);
+ Assert(IsA(css, CustomScanState));
+
+ /* fill up fields of ScanState */
+ css->ss.ps.plan = &cscan->scan.plan;
+ css->ss.ps.state = estate;
+
+ /* create expression context for node */
+ ExecAssignExprContext(estate, &css->ss.ps);
+
+ /* initialize child expressions */
+ css->ss.ps.targetlist = (List *)
+ ExecInitExpr((Expr *) cscan->scan.plan.targetlist,
+ (PlanState *) css);
+ css->ss.ps.qual = (List *)
+ ExecInitExpr((Expr *) cscan->scan.plan.qual,
+ (PlanState *) css);
+
+ /* tuple table initialization */
+ ExecInitScanTupleSlot(estate, &css->ss);
+ ExecInitResultTupleSlot(estate, &css->ss.ps);
+
+ /* initialize scan relation */
+ scan_rel = ExecOpenScanRelation(estate, cscan->scan.scanrelid, eflags);
+ css->ss.ss_currentRelation = scan_rel;
+ css->ss.ss_currentScanDesc = NULL; /* set by provider */
+ ExecAssignScanType(&css->ss, RelationGetDescr(scan_rel));
+
+ css->ss.ps.ps_TupFromTlist = false;
+
+ /*
+ * Initialize result tuple type and projection info.
+ */
+ ExecAssignResultTypeFromTL(&css->ss.ps);
+ ExecAssignScanProjectionInfo(&css->ss);
+
+ /*
+ * The callback of custom-scan provider applies the final initialization
+ * of the custom-scan-state node according to its logic.
+ */
+ css->methods->BeginCustomScan(css, estate, eflags);
+
+ return css;
+}
+
+TupleTableSlot *
+ExecCustomScan(CustomScanState *node)
+{
+ Assert(node->methods->ExecCustomScan != NULL);
+ return node->methods->ExecCustomScan(node);
+}
+
+void
+ExecEndCustomScan(CustomScanState *node)
+{
+ Assert(node->methods->EndCustomScan != NULL);
+ node->methods->EndCustomScan(node);
+
+ /* Free the exprcontext */
+ ExecFreeExprContext(&node->ss.ps);
+
+ /* Clean out the tuple table */
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ if (node->ss.ss_ScanTupleSlot)
+ ExecClearTuple(node->ss.ss_ScanTupleSlot);
+
+ /* Close the heap relation */
+ ExecCloseScanRelation(node->ss.ss_currentRelation);
+}
+
+void
+ExecReScanCustomScan(CustomScanState *node)
+{
+ Assert(node->methods->ReScanCustomScan != NULL);
+ node->methods->ReScanCustomScan(node);
+}
+
+void
+ExecCustomMarkPos(CustomScanState *node)
+{
+ if (!node->methods->MarkPosCustomScan)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("custom-scan \"%s\" does not support MarkPos",
+ node->methods->CustomName)));
+ node->methods->MarkPosCustomScan(node);
+}
+
+void
+ExecCustomRestrPos(CustomScanState *node)
+{
+ if (!node->methods->RestrPosCustomScan)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("custom-scan \"%s\" does not support MarkPos",
+ node->methods->CustomName)));
+ node->methods->RestrPosCustomScan(node);
+}