Add hooks to allow debugging and performance measurement plugins
to instrument PL/pgSQL. Korry Douglas
This commit is contained in:
parent
abc3120e9b
commit
355865c5a7
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.175 2006/08/14 21:14:41 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.176 2006/08/15 19:01:17 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -252,6 +252,12 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo)
|
|||
*/
|
||||
exec_set_found(&estate, false);
|
||||
|
||||
/*
|
||||
* Let the instrumentation plugin peek at this function
|
||||
*/
|
||||
if (*plugin_ptr && (*plugin_ptr)->func_beg)
|
||||
((*plugin_ptr)->func_beg)(&estate, func);
|
||||
|
||||
/*
|
||||
* Now call the toplevel block of statements
|
||||
*/
|
||||
|
@ -387,6 +393,12 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Let the instrumentation plugin peek at this function
|
||||
*/
|
||||
if (*plugin_ptr && (*plugin_ptr)->func_end)
|
||||
((*plugin_ptr)->func_end)(&estate, func);
|
||||
|
||||
/* Clean up any leftover temporary memory */
|
||||
FreeExprContext(estate.eval_econtext);
|
||||
estate.eval_econtext = NULL;
|
||||
|
@ -580,6 +592,12 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
|
|||
*/
|
||||
exec_set_found(&estate, false);
|
||||
|
||||
/*
|
||||
* Let the instrumentation plugin peek at this function
|
||||
*/
|
||||
if (*plugin_ptr && (*plugin_ptr)->func_beg)
|
||||
((*plugin_ptr)->func_beg)(&estate, func);
|
||||
|
||||
/*
|
||||
* Now call the toplevel block of statements
|
||||
*/
|
||||
|
@ -633,6 +651,12 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
|
|||
rettup = SPI_copytuple((HeapTuple) (estate.retval));
|
||||
}
|
||||
|
||||
/*
|
||||
* Let the instrumentation plugin peek at this function
|
||||
*/
|
||||
if (*plugin_ptr && (*plugin_ptr)->func_end)
|
||||
((*plugin_ptr)->func_end)(&estate, func);
|
||||
|
||||
/* Clean up any leftover temporary memory */
|
||||
FreeExprContext(estate.eval_econtext);
|
||||
estate.eval_econtext = NULL;
|
||||
|
@ -1037,6 +1061,10 @@ exec_stmt(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
|
|||
save_estmt = estate->err_stmt;
|
||||
estate->err_stmt = stmt;
|
||||
|
||||
/* Let the plugin know that we are about to execute this statement */
|
||||
if (*plugin_ptr && (*plugin_ptr)->stmt_beg)
|
||||
((*plugin_ptr)->stmt_beg)(estate, stmt);
|
||||
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
|
||||
switch (stmt->cmd_type)
|
||||
|
@ -1122,6 +1150,10 @@ exec_stmt(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
|
|||
elog(ERROR, "unrecognized cmdtype: %d", stmt->cmd_type);
|
||||
}
|
||||
|
||||
/* Let the plugin know that we have finished executing this statement */
|
||||
if (*plugin_ptr && (*plugin_ptr)->stmt_end)
|
||||
((*plugin_ptr)->stmt_end)(estate, stmt);
|
||||
|
||||
estate->err_stmt = save_estmt;
|
||||
|
||||
return rc;
|
||||
|
@ -2123,6 +2155,21 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
|
|||
* child of simple_eval_estate.
|
||||
*/
|
||||
estate->eval_econtext = CreateExprContext(simple_eval_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
|
||||
*/
|
||||
if (*plugin_ptr)
|
||||
{
|
||||
(*plugin_ptr)->error_callback = plpgsql_exec_error_callback;
|
||||
(*plugin_ptr)->assign_expr = exec_assign_expr;
|
||||
|
||||
if ((*plugin_ptr)->func_setup)
|
||||
((*plugin_ptr)->func_setup)(estate, func);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.30 2006/08/08 19:15:09 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.31 2006/08/15 19:01:17 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -28,6 +28,8 @@ extern DLLIMPORT bool check_function_bodies;
|
|||
|
||||
PG_MODULE_MAGIC;
|
||||
|
||||
PLpgSQL_plugin **plugin_ptr = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* _PG_init() - library load-time initialization
|
||||
|
@ -46,6 +48,9 @@ _PG_init(void)
|
|||
plpgsql_HashTableInit();
|
||||
RegisterXactCallback(plpgsql_xact_cb, NULL);
|
||||
|
||||
/* Set up a rendezvous point with optional instrumentation plugin */
|
||||
plugin_ptr = (PLpgSQL_plugin **) find_rendezvous_variable("PLpgSQL_plugin");
|
||||
|
||||
inited = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.79 2006/08/14 21:14:41 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.80 2006/08/15 19:01:17 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -617,9 +617,57 @@ typedef struct
|
|||
PLpgSQL_function *err_func; /* current func */
|
||||
PLpgSQL_stmt *err_stmt; /* current stmt */
|
||||
const char *err_text; /* additional state info */
|
||||
void *plugin_info; /* reserved for use by optional plugin */
|
||||
} PLpgSQL_execstate;
|
||||
|
||||
|
||||
/*
|
||||
* A PLpgSQL_plugin structure represents an instrumentation plugin.
|
||||
* To instrument PL/pgSQL, a plugin library must access the rendezvous
|
||||
* variable "PLpgSQL_plugin" and set it to point to a PLpgSQL_plugin struct.
|
||||
* Typically the struct could just be static data in the plugin library.
|
||||
* We expect that a plugin would do this at library load time (_PG_init()).
|
||||
* It must also be careful to set the rendezvous variable back to NULL
|
||||
* if it is unloaded (_PG_fini()).
|
||||
*
|
||||
* This structure is basically a collection of function pointers --- at
|
||||
* various interesting points in pl_exec.c, we call these functions
|
||||
* (if the pointers are non-NULL) to give the plugin a chance to watch
|
||||
* what we are doing.
|
||||
*
|
||||
* func_setup is called when we start a function, before we've initialized
|
||||
* the local variables defined by the function.
|
||||
*
|
||||
* func_beg is called when we start a function, after we've initialized
|
||||
* the local variables.
|
||||
*
|
||||
* func_end is called at the end of a function.
|
||||
*
|
||||
* stmt_beg and stmt_end are called before and after (respectively) each
|
||||
* 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.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Function pointers set up by the plugin */
|
||||
void (*func_setup) (PLpgSQL_execstate *estate, PLpgSQL_function *func);
|
||||
void (*func_beg) (PLpgSQL_execstate *estate, PLpgSQL_function *func);
|
||||
void (*func_end) (PLpgSQL_execstate *estate, PLpgSQL_function *func);
|
||||
void (*stmt_beg) (PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt);
|
||||
void (*stmt_end) (PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt);
|
||||
|
||||
/* Function pointers set by PL/pgSQL itself */
|
||||
void (*error_callback) (void *arg);
|
||||
void (*assign_expr) (PLpgSQL_execstate *estate, PLpgSQL_datum *target,
|
||||
PLpgSQL_expr *expr);
|
||||
} PLpgSQL_plugin;
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Global variable declarations
|
||||
**********************************************************************/
|
||||
|
@ -641,6 +689,8 @@ extern PLpgSQL_function *plpgsql_curr_compile;
|
|||
extern bool plpgsql_check_syntax;
|
||||
extern MemoryContext compile_tmp_cxt;
|
||||
|
||||
extern PLpgSQL_plugin **plugin_ptr;
|
||||
|
||||
/**********************************************************************
|
||||
* Function declarations
|
||||
**********************************************************************/
|
||||
|
|
Loading…
Reference in New Issue