aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execUtils.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-05-12 20:10:05 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-05-12 20:10:05 +0000
commitf9e4f611a18f64fd9106a72ec9af9e2220075780 (patch)
treebfbc1d3d9fb5a008d8fe3405dce3366659c7e7cc /src/backend/executor/execUtils.c
parent71009354c848964e657e540e24dac6b4c9a81570 (diff)
downloadpostgresql-f9e4f611a18f64fd9106a72ec9af9e2220075780.tar.gz
postgresql-f9e4f611a18f64fd9106a72ec9af9e2220075780.zip
First pass at set-returning-functions in FROM, by Joe Conway with
some kibitzing from Tom Lane. Not everything works yet, and there's no documentation or regression test, but let's commit this so Joe doesn't need to cope with tracking changes in so many files ...
Diffstat (limited to 'src/backend/executor/execUtils.c')
-rw-r--r--src/backend/executor/execUtils.c102
1 files changed, 99 insertions, 3 deletions
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 9b03401e444..a6b5048326b 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.80 2002/04/12 20:38:26 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.81 2002/05/12 20:10:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,6 +20,9 @@
* ExecCloseIndices | referenced by InitPlan, EndPlan,
* ExecInsertIndexTuples / ExecAppend, ExecReplace
*
+ * RegisterExprContextCallback Register function shutdown callback
+ * UnregisterExprContextCallback Deregister function shutdown callback
+ *
* NOTES
* This file has traditionally been the place to stick misc.
* executor support stuff that doesn't really go anyplace else.
@@ -58,6 +61,9 @@ extern int NIndexTupleProcessed; /* have to be defined in the
* access method level so that the
* cinterface.a will link ok. */
+
+static void ShutdownExprContext(ExprContext *econtext);
+
/* ----------------------------------------------------------------
* statistic functions
* ----------------------------------------------------------------
@@ -120,8 +126,6 @@ DisplayTupleCount(FILE *statfp)
/* ----------------------------------------------------------------
* miscellaneous node-init support functions
- *
- * ExecAssignExprContext - assigns the node's expression context
* ----------------------------------------------------------------
*/
@@ -160,6 +164,7 @@ ExecAssignExprContext(EState *estate, CommonState *commonstate)
econtext->ecxt_param_list_info = estate->es_param_list_info;
econtext->ecxt_aggvalues = NULL;
econtext->ecxt_aggnulls = NULL;
+ econtext->ecxt_callbacks = NULL;
commonstate->cs_ExprContext = econtext;
}
@@ -204,6 +209,7 @@ MakeExprContext(TupleTableSlot *slot,
econtext->ecxt_param_list_info = NULL;
econtext->ecxt_aggvalues = NULL;
econtext->ecxt_aggnulls = NULL;
+ econtext->ecxt_callbacks = NULL;
return econtext;
}
@@ -216,6 +222,9 @@ MakeExprContext(TupleTableSlot *slot,
void
FreeExprContext(ExprContext *econtext)
{
+ /* Call any registered callbacks */
+ ShutdownExprContext(econtext);
+ /* And clean up the memory used */
MemoryContextDelete(econtext->ecxt_per_tuple_memory);
pfree(econtext);
}
@@ -370,6 +379,11 @@ ExecFreeExprContext(CommonState *commonstate)
return;
/*
+ * clean up any registered callbacks
+ */
+ ShutdownExprContext(econtext);
+
+ /*
* clean up memory used.
*/
MemoryContextDelete(econtext->ecxt_per_tuple_memory);
@@ -689,3 +703,85 @@ SetChangedParamList(Plan *node, List *newchg)
node->chgParam = lappendi(node->chgParam, paramId);
}
}
+
+/*
+ * Register a shutdown callback in an ExprContext.
+ *
+ * Shutdown callbacks will be called (in reverse order of registration)
+ * when the ExprContext is deleted or rescanned. This provides a hook
+ * for functions called in the context to do any cleanup needed --- it's
+ * particularly useful for functions returning sets. Note that the
+ * callback will *not* be called in the event that execution is aborted
+ * by an error.
+ */
+void
+RegisterExprContextCallback(ExprContext *econtext,
+ ExprContextCallbackFunction function,
+ Datum arg)
+{
+ ExprContext_CB *ecxt_callback;
+
+ /* Save the info in appropriate memory context */
+ ecxt_callback = (ExprContext_CB *)
+ MemoryContextAlloc(econtext->ecxt_per_query_memory,
+ sizeof(ExprContext_CB));
+
+ ecxt_callback->function = function;
+ ecxt_callback->arg = arg;
+
+ /* link to front of list for appropriate execution order */
+ ecxt_callback->next = econtext->ecxt_callbacks;
+ econtext->ecxt_callbacks = ecxt_callback;
+}
+
+/*
+ * Deregister a shutdown callback in an ExprContext.
+ *
+ * Any list entries matching the function and arg will be removed.
+ * This can be used if it's no longer necessary to call the callback.
+ */
+void
+UnregisterExprContextCallback(ExprContext *econtext,
+ ExprContextCallbackFunction function,
+ Datum arg)
+{
+ ExprContext_CB **prev_callback;
+ ExprContext_CB *ecxt_callback;
+
+ prev_callback = &econtext->ecxt_callbacks;
+
+ while ((ecxt_callback = *prev_callback) != NULL)
+ {
+ if (ecxt_callback->function == function && ecxt_callback->arg == arg)
+ {
+ *prev_callback = ecxt_callback->next;
+ pfree(ecxt_callback);
+ }
+ else
+ {
+ prev_callback = &ecxt_callback->next;
+ }
+ }
+}
+
+/*
+ * Call all the shutdown callbacks registered in an ExprContext.
+ *
+ * The callback list is emptied (important in case this is only a rescan
+ * reset, and not deletion of the ExprContext).
+ */
+static void
+ShutdownExprContext(ExprContext *econtext)
+{
+ ExprContext_CB *ecxt_callback;
+
+ /*
+ * Call each callback function in reverse registration order.
+ */
+ while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
+ {
+ econtext->ecxt_callbacks = ecxt_callback->next;
+ (*ecxt_callback->function) (ecxt_callback->arg);
+ pfree(ecxt_callback);
+ }
+}