Expose a few more PL/pgSQL functions to debugger plugins.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 31 Mar 2022 21:05:47 +0000 (17:05 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 31 Mar 2022 21:05:47 +0000 (17:05 -0400)
Add exec_assign_value, exec_eval_datum, and exec_cast_value
to the set of functions a PL/pgSQL debugger plugin can
conveniently call.  This allows more convenient manipulation
of the values of PL/pgSQL function variables.

Pavel Stehule, reviewed by Aleksander Alekseev and myself

Discussion: https://postgr.es/m/CAFj8pRD+dBPU0T-KrkP7ef6QNPDEsjYCejEsBe07NDq8TybOkA@mail.gmail.com

src/pl/plpgsql/src/pl_exec.c
src/pl/plpgsql/src/plpgsql.h

index 00328fddcff00e3570cdbd6754a49ee413d3a8b6..ceb011810d30eec2acfff63ceb863eb7bc6cca54 100644 (file)
@@ -4077,15 +4077,18 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
    plpgsql_create_econtext(estate);
 
    /*
-    * Let the plugin see this function before we initialize any local
-    * PL/pgSQL variables - note that we also give the plugin a few function
-    * pointers so it can call back into PL/pgSQL for doing things like
-    * variable assignments and stack traces
+    * Let the plugin, if any, see this function before we initialize local
+    * PL/pgSQL variables.  Note that we also give the plugin a few function
+    * pointers, so it can call back into PL/pgSQL for doing things like
+    * variable assignments and stack traces.
     */
    if (*plpgsql_plugin_ptr)
    {
        (*plpgsql_plugin_ptr)->error_callback = plpgsql_exec_error_callback;
        (*plpgsql_plugin_ptr)->assign_expr = exec_assign_expr;
+       (*plpgsql_plugin_ptr)->assign_value = exec_assign_value;
+       (*plpgsql_plugin_ptr)->eval_datum = exec_eval_datum;
+       (*plpgsql_plugin_ptr)->cast_value = exec_cast_value;
 
        if ((*plpgsql_plugin_ptr)->func_setup)
            ((*plpgsql_plugin_ptr)->func_setup) (estate, func);
index 813c32c70f553908b9053c31023ac407571e5c52..cc8d782217de42624304ff3b2a27a09c286283a5 100644 (file)
@@ -1120,9 +1120,17 @@ typedef struct PLpgSQL_execstate
  * statement.
  *
  * Also, immediately before any call to func_setup, PL/pgSQL fills in the
- * error_callback and assign_expr fields with pointers to its own
- * plpgsql_exec_error_callback and exec_assign_expr functions.  This is
- * a somewhat ad-hoc expedient to simplify life for debugger plugins.
+ * remaining fields with pointers to some of its own functions, allowing the
+ * plugin to invoke those functions conveniently.  The exposed functions are:
+ *     plpgsql_exec_error_callback
+ *     exec_assign_expr
+ *     exec_assign_value
+ *     exec_eval_datum
+ *     exec_cast_value
+ * (plpgsql_exec_error_callback is not actually meant to be called by the
+ * plugin, but rather to allow it to identify PL/pgSQL error context stack
+ * frames.  The others are useful for debugger-like plugins to examine and
+ * set variables.)
  */
 typedef struct PLpgSQL_plugin
 {
@@ -1135,8 +1143,20 @@ typedef struct PLpgSQL_plugin
 
    /* Function pointers set by PL/pgSQL itself */
    void        (*error_callback) (void *arg);
-   void        (*assign_expr) (PLpgSQL_execstate *estate, PLpgSQL_datum *target,
+   void        (*assign_expr) (PLpgSQL_execstate *estate,
+                               PLpgSQL_datum *target,
                                PLpgSQL_expr *expr);
+   void        (*assign_value) (PLpgSQL_execstate *estate,
+                                PLpgSQL_datum *target,
+                                Datum value, bool isNull,
+                                Oid valtype, int32 valtypmod);
+   void        (*eval_datum) (PLpgSQL_execstate *estate, PLpgSQL_datum *datum,
+                              Oid *typeid, int32 *typetypmod,
+                              Datum *value, bool *isnull);
+   Datum       (*cast_value) (PLpgSQL_execstate *estate,
+                              Datum value, bool *isnull,
+                              Oid valtype, int32 valtypmod,
+                              Oid reqtype, int32 reqtypmod);
 } PLpgSQL_plugin;
 
 /*