summaryrefslogtreecommitdiffstats
path: root/src/backend/executor/nodeBitmapAnd.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:15:05 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:15:05 +0000
commit46651ce6fe013220ed397add242004d764fc0153 (patch)
tree6e5299f990f88e60174a1d3ae6e48eedd2688b2b /src/backend/executor/nodeBitmapAnd.c
parentInitial commit. (diff)
downloadpostgresql-14-upstream.tar.xz
postgresql-14-upstream.zip
Adding upstream version 14.5.upstream/14.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/backend/executor/nodeBitmapAnd.c')
-rw-r--r--src/backend/executor/nodeBitmapAnd.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/backend/executor/nodeBitmapAnd.c b/src/backend/executor/nodeBitmapAnd.c
new file mode 100644
index 0000000..a8d7b1e
--- /dev/null
+++ b/src/backend/executor/nodeBitmapAnd.c
@@ -0,0 +1,223 @@
+/*-------------------------------------------------------------------------
+ *
+ * nodeBitmapAnd.c
+ * routines to handle BitmapAnd nodes.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/executor/nodeBitmapAnd.c
+ *
+ *-------------------------------------------------------------------------
+ */
+/* INTERFACE ROUTINES
+ * ExecInitBitmapAnd - initialize the BitmapAnd node
+ * MultiExecBitmapAnd - retrieve the result bitmap from the node
+ * ExecEndBitmapAnd - shut down the BitmapAnd node
+ * ExecReScanBitmapAnd - rescan the BitmapAnd node
+ *
+ * NOTES
+ * BitmapAnd nodes don't make use of their left and right
+ * subtrees, rather they maintain a list of subplans,
+ * much like Append nodes. The logic is much simpler than
+ * Append, however, since we needn't cope with forward/backward
+ * execution.
+ */
+
+#include "postgres.h"
+
+#include "executor/execdebug.h"
+#include "executor/nodeBitmapAnd.h"
+
+
+/* ----------------------------------------------------------------
+ * ExecBitmapAnd
+ *
+ * stub for pro forma compliance
+ * ----------------------------------------------------------------
+ */
+static TupleTableSlot *
+ExecBitmapAnd(PlanState *pstate)
+{
+ elog(ERROR, "BitmapAnd node does not support ExecProcNode call convention");
+ return NULL;
+}
+
+/* ----------------------------------------------------------------
+ * ExecInitBitmapAnd
+ *
+ * Begin all of the subscans of the BitmapAnd node.
+ * ----------------------------------------------------------------
+ */
+BitmapAndState *
+ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
+{
+ BitmapAndState *bitmapandstate = makeNode(BitmapAndState);
+ PlanState **bitmapplanstates;
+ int nplans;
+ int i;
+ ListCell *l;
+ Plan *initNode;
+
+ /* check for unsupported flags */
+ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
+
+ /*
+ * Set up empty vector of subplan states
+ */
+ nplans = list_length(node->bitmapplans);
+
+ bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
+
+ /*
+ * create new BitmapAndState for our BitmapAnd node
+ */
+ bitmapandstate->ps.plan = (Plan *) node;
+ bitmapandstate->ps.state = estate;
+ bitmapandstate->ps.ExecProcNode = ExecBitmapAnd;
+ bitmapandstate->bitmapplans = bitmapplanstates;
+ bitmapandstate->nplans = nplans;
+
+ /*
+ * call ExecInitNode on each of the plans to be executed and save the
+ * results into the array "bitmapplanstates".
+ */
+ i = 0;
+ foreach(l, node->bitmapplans)
+ {
+ initNode = (Plan *) lfirst(l);
+ bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
+ i++;
+ }
+
+ /*
+ * Miscellaneous initialization
+ *
+ * BitmapAnd plans don't have expression contexts because they never call
+ * ExecQual or ExecProject. They don't need any tuple slots either.
+ */
+
+ return bitmapandstate;
+}
+
+/* ----------------------------------------------------------------
+ * MultiExecBitmapAnd
+ * ----------------------------------------------------------------
+ */
+Node *
+MultiExecBitmapAnd(BitmapAndState *node)
+{
+ PlanState **bitmapplans;
+ int nplans;
+ int i;
+ TIDBitmap *result = NULL;
+
+ /* must provide our own instrumentation support */
+ if (node->ps.instrument)
+ InstrStartNode(node->ps.instrument);
+
+ /*
+ * get information from the node
+ */
+ bitmapplans = node->bitmapplans;
+ nplans = node->nplans;
+
+ /*
+ * Scan all the subplans and AND their result bitmaps
+ */
+ for (i = 0; i < nplans; i++)
+ {
+ PlanState *subnode = bitmapplans[i];
+ TIDBitmap *subresult;
+
+ subresult = (TIDBitmap *) MultiExecProcNode(subnode);
+
+ if (!subresult || !IsA(subresult, TIDBitmap))
+ elog(ERROR, "unrecognized result from subplan");
+
+ if (result == NULL)
+ result = subresult; /* first subplan */
+ else
+ {
+ tbm_intersect(result, subresult);
+ tbm_free(subresult);
+ }
+
+ /*
+ * If at any stage we have a completely empty bitmap, we can fall out
+ * without evaluating the remaining subplans, since ANDing them can no
+ * longer change the result. (Note: the fact that indxpath.c orders
+ * the subplans by selectivity should make this case more likely to
+ * occur.)
+ */
+ if (tbm_is_empty(result))
+ break;
+ }
+
+ if (result == NULL)
+ elog(ERROR, "BitmapAnd doesn't support zero inputs");
+
+ /* must provide our own instrumentation support */
+ if (node->ps.instrument)
+ InstrStopNode(node->ps.instrument, 0 /* XXX */ );
+
+ return (Node *) result;
+}
+
+/* ----------------------------------------------------------------
+ * ExecEndBitmapAnd
+ *
+ * Shuts down the subscans of the BitmapAnd node.
+ *
+ * Returns nothing of interest.
+ * ----------------------------------------------------------------
+ */
+void
+ExecEndBitmapAnd(BitmapAndState *node)
+{
+ PlanState **bitmapplans;
+ int nplans;
+ int i;
+
+ /*
+ * get information from the node
+ */
+ bitmapplans = node->bitmapplans;
+ nplans = node->nplans;
+
+ /*
+ * shut down each of the subscans (that we've initialized)
+ */
+ for (i = 0; i < nplans; i++)
+ {
+ if (bitmapplans[i])
+ ExecEndNode(bitmapplans[i]);
+ }
+}
+
+void
+ExecReScanBitmapAnd(BitmapAndState *node)
+{
+ int i;
+
+ for (i = 0; i < node->nplans; i++)
+ {
+ PlanState *subnode = node->bitmapplans[i];
+
+ /*
+ * ExecReScan doesn't know about my subplans, so I have to do
+ * changed-parameter signaling myself.
+ */
+ if (node->ps.chgParam != NULL)
+ UpdateChangedParamSet(subnode, node->ps.chgParam);
+
+ /*
+ * If chgParam of subnode is not null then plan will be re-scanned by
+ * first ExecProcNode.
+ */
+ if (subnode->chgParam == NULL)
+ ExecReScan(subnode);
+ }
+}