X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=src%2Fpl%2Fplpgsql%2Fsrc%2Fplpgsql.h;h=3d0f155a884142d477b8a4fbe55ece44478ad84f;hb=9bedd128d6ed83798004b3c7ddc33f33703ccf23;hp=c81b0a3b1bc99d7b538f1f25b2883f07bec65807;hpb=e107f3a7e3feb7eaef8853ba117465f4f3f8ceed;p=postgresql diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h index c81b0a3b1b..3d0f155a88 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -1,56 +1,43 @@ -/********************************************************************** +/*------------------------------------------------------------------------- + * * plpgsql.h - Definitions for the PL/pgSQL * procedural language * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.26 2002/08/30 00:28:41 tgl Exp $ - * - * This software is copyrighted by Jan Wieck - Hamburg. + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California * - * The author hereby grants permission to use, copy, modify, - * distribute, and license this software and its documentation - * for any purpose, provided that existing copyright notices are - * retained in all copies and that this notice is included - * verbatim in any distributions. No written agreement, license, - * or royalty fee is required for any of the authorized uses. - * Modifications to this software may be copyrighted by their - * author and need not follow the licensing terms described - * here, provided that the new terms are clearly indicated on - * the first page of each file where they apply. * - * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR - * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS - * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN - * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON - * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO - * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, - * ENHANCEMENTS, OR MODIFICATIONS. + * IDENTIFICATION + * $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.118 2009/11/04 22:26:07 tgl Exp $ * - **********************************************************************/ + *------------------------------------------------------------------------- + */ + #ifndef PLPGSQL_H #define PLPGSQL_H #include "postgres.h" +#include "access/xact.h" #include "fmgr.h" -#include "miscadmin.h" -#include "executor/spi.h" #include "commands/trigger.h" +#include "executor/spi.h" +#include "nodes/bitmapset.h" #include "utils/tuplestore.h" /********************************************************************** * Definitions **********************************************************************/ +/* define our text domain for translations */ +#undef TEXTDOMAIN +#define TEXTDOMAIN PG_TEXTDOMAIN("plpgsql") + +#undef _ +#define _(x) dgettext(TEXTDOMAIN, x) + /* ---------- - * Compilers namestack item types + * Compiler's namestack item types * ---------- */ enum @@ -58,8 +45,7 @@ enum PLPGSQL_NSTYPE_LABEL, PLPGSQL_NSTYPE_VAR, PLPGSQL_NSTYPE_ROW, - PLPGSQL_NSTYPE_REC, - PLPGSQL_NSTYPE_RECFIELD + PLPGSQL_NSTYPE_REC }; /* ---------- @@ -72,27 +58,41 @@ enum PLPGSQL_DTYPE_ROW, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, - PLPGSQL_DTYPE_EXPR, - PLPGSQL_DTYPE_TRIGARG + PLPGSQL_DTYPE_ARRAYELEM, + PLPGSQL_DTYPE_EXPR }; /* ---------- - * Execution tree node types + * Variants distinguished in PLpgSQL_type structs * ---------- */ enum +{ + PLPGSQL_TTYPE_SCALAR, /* scalar types and domains */ + PLPGSQL_TTYPE_ROW, /* composite types */ + PLPGSQL_TTYPE_REC, /* RECORD pseudotype */ + PLPGSQL_TTYPE_PSEUDO /* other pseudotypes */ +}; + +/* ---------- + * Execution tree node types + * ---------- + */ +enum PLpgSQL_stmt_types { PLPGSQL_STMT_BLOCK, PLPGSQL_STMT_ASSIGN, PLPGSQL_STMT_IF, + PLPGSQL_STMT_CASE, PLPGSQL_STMT_LOOP, PLPGSQL_STMT_WHILE, PLPGSQL_STMT_FORI, PLPGSQL_STMT_FORS, - PLPGSQL_STMT_SELECT, + PLPGSQL_STMT_FORC, PLPGSQL_STMT_EXIT, PLPGSQL_STMT_RETURN, PLPGSQL_STMT_RETURN_NEXT, + PLPGSQL_STMT_RETURN_QUERY, PLPGSQL_STMT_RAISE, PLPGSQL_STMT_EXECSQL, PLPGSQL_STMT_DYNEXECUTE, @@ -100,7 +100,8 @@ enum PLPGSQL_STMT_GETDIAG, PLPGSQL_STMT_OPEN, PLPGSQL_STMT_FETCH, - PLPGSQL_STMT_CLOSE + PLPGSQL_STMT_CLOSE, + PLPGSQL_STMT_PERFORM }; @@ -112,7 +113,9 @@ enum { PLPGSQL_RC_OK, PLPGSQL_RC_EXIT, - PLPGSQL_RC_RETURN + PLPGSQL_RC_RETURN, + PLPGSQL_RC_CONTINUE, + PLPGSQL_RC_RERAISE }; /* ---------- @@ -125,6 +128,18 @@ enum PLPGSQL_GETDIAG_RESULT_OID }; +/* -------- + * RAISE statement options + * -------- + */ +enum +{ + PLPGSQL_RAISEOPTION_ERRCODE, + PLPGSQL_RAISEOPTION_MESSAGE, + PLPGSQL_RAISEOPTION_DETAIL, + PLPGSQL_RAISEOPTION_HINT +}; + /********************************************************************** * Node and structure definitions @@ -132,50 +147,71 @@ enum typedef struct -{ /* Dynamic string control structure */ - int alloc; - int used; - char *value; -} PLpgSQL_dstring; - - -typedef struct -{ /* Postgres base data type */ - char *typname; - Oid typoid; - FmgrInfo typinput; - Oid typelem; - int16 typlen; +{ /* Postgres data type */ + char *typname; /* (simple) name of the type */ + Oid typoid; /* OID of the data type */ + int ttype; /* PLPGSQL_TTYPE_ code */ + int16 typlen; /* stuff copied from its pg_type entry */ bool typbyval; - int32 atttypmod; -} PLpgSQL_type; + Oid typrelid; + Oid typioparam; + FmgrInfo typinput; /* lookup info for typinput function */ + int32 atttypmod; /* typmod (taken from someplace else) */ +} PLpgSQL_type; +/* + * PLpgSQL_datum is the common supertype for PLpgSQL_expr, PLpgSQL_var, + * PLpgSQL_row, PLpgSQL_rec, PLpgSQL_recfield, and PLpgSQL_arrayelem + */ typedef struct { /* Generic datum array item */ int dtype; int dno; -} PLpgSQL_datum; - +} PLpgSQL_datum; +/* + * The variants PLpgSQL_var, PLpgSQL_row, and PLpgSQL_rec share these + * fields + */ typedef struct +{ /* Scalar or composite variable */ + int dtype; + int dno; + char *refname; + int lineno; +} PLpgSQL_variable; + +typedef struct PLpgSQL_expr { /* SQL Query to plan and execute */ int dtype; - int exprno; + int dno; char *query; - void *plan; - Node *plan_simple_expr; - Oid plan_simple_type; - Oid *plan_argtypes; - int nparams; - int params[1]; -} PLpgSQL_expr; + SPIPlanPtr plan; + Bitmapset *paramnos; /* all dnos referenced by this query */ + + /* function containing this expr (not set until we first parse query) */ + struct PLpgSQL_function *func; + + /* fields for "simple expression" fast-path execution: */ + Expr *expr_simple_expr; /* NULL means not a simple expr */ + int expr_simple_generation; /* plancache generation we checked */ + Oid expr_simple_type; /* result type Oid, if simple */ + + /* + * if expr is simple AND prepared in current transaction, + * expr_simple_state is valid. Test validity by seeing if expr_simple_lxid + * matches current LXID. + */ + ExprState *expr_simple_state; + LocalTransactionId expr_simple_lxid; +} PLpgSQL_expr; typedef struct -{ /* Local variable */ +{ /* Scalar variable */ int dtype; - int varno; + int dno; char *refname; int lineno; @@ -185,31 +221,40 @@ typedef struct PLpgSQL_expr *default_val; PLpgSQL_expr *cursor_explicit_expr; int cursor_explicit_argrow; + int cursor_options; Datum value; bool isnull; bool freeval; -} PLpgSQL_var; +} PLpgSQL_var; typedef struct -{ /* Rowtype */ +{ /* Row variable */ int dtype; - int rowno; + int dno; char *refname; int lineno; - Oid rowtypeclass; + TupleDesc rowtupdesc; + + /* + * Note: TupleDesc is only set up for named rowtypes, else it is NULL. + * + * Note: if the underlying rowtype contains a dropped column, the + * corresponding fieldnames[] entry will be NULL, and there is no + * corresponding var (varnos[] will be -1). + */ int nfields; char **fieldnames; int *varnos; -} PLpgSQL_row; +} PLpgSQL_row; typedef struct -{ /* Record of undefined structure */ +{ /* Record variable (non-fixed structure) */ int dtype; - int recno; + int dno; char *refname; int lineno; @@ -217,24 +262,25 @@ typedef struct TupleDesc tupdesc; bool freetup; bool freetupdesc; -} PLpgSQL_rec; +} PLpgSQL_rec; typedef struct -{ /* Field in record */ +{ /* Field in record */ int dtype; - int rfno; + int dno; char *fieldname; - int recno; -} PLpgSQL_recfield; + int recparentno; /* dno of parent record */ +} PLpgSQL_recfield; typedef struct -{ /* Positional argument to trigger */ +{ /* Element of array variable */ int dtype; int dno; - PLpgSQL_expr *argnum; -} PLpgSQL_trigarg; + PLpgSQL_expr *subscript; + int arrayparentno; /* dno of parent array variable */ +} PLpgSQL_arrayelem; typedef struct @@ -242,31 +288,46 @@ typedef struct int itemtype; int itemno; char name[1]; -} PLpgSQL_nsitem; +} PLpgSQL_nsitem; +/* XXX: consider adapting this to use List */ typedef struct PLpgSQL_ns { /* Compiler namestack level */ int items_alloc; int items_used; PLpgSQL_nsitem **items; struct PLpgSQL_ns *upper; -} PLpgSQL_ns; +} PLpgSQL_ns; typedef struct -{ /* List of execution nodes */ - int stmts_alloc; - int stmts_used; - struct PLpgSQL_stmt **stmts; -} PLpgSQL_stmts; +{ /* Generic execution node */ + int cmd_type; + int lineno; +} PLpgSQL_stmt; +typedef struct PLpgSQL_condition +{ /* One EXCEPTION condition name */ + int sqlerrstate; /* SQLSTATE code */ + char *condname; /* condition name (for debugging) */ + struct PLpgSQL_condition *next; +} PLpgSQL_condition; + typedef struct -{ /* Generic execution node */ - int cmd_type; +{ + int sqlstate_varno; + int sqlerrm_varno; + List *exc_list; /* List of WHEN clauses */ +} PLpgSQL_exception_block; + +typedef struct +{ /* One EXCEPTION ... WHEN clause */ int lineno; -} PLpgSQL_stmt; + PLpgSQL_condition *conditions; + List *action; /* List of statements */ +} PLpgSQL_exception; typedef struct @@ -274,10 +335,11 @@ typedef struct int cmd_type; int lineno; char *label; - PLpgSQL_stmts *body; + List *body; /* List of statements */ int n_initvars; int *initvarnos; -} PLpgSQL_stmt_block; + PLpgSQL_exception_block *exceptions; +} PLpgSQL_stmt_block; typedef struct @@ -286,22 +348,27 @@ typedef struct int lineno; int varno; PLpgSQL_expr *expr; -} PLpgSQL_stmt_assign; +} PLpgSQL_stmt_assign; +typedef struct +{ /* PERFORM statement */ + int cmd_type; + int lineno; + PLpgSQL_expr *expr; +} PLpgSQL_stmt_perform; typedef struct { /* Get Diagnostics item */ - int item; /* id for diagnostic value desired */ + int kind; /* id for diagnostic value desired */ int target; /* where to assign it */ -} PLpgSQL_diag_item; +} PLpgSQL_diag_item; typedef struct { /* Get Diagnostics statement */ int cmd_type; int lineno; - int ndtitems; - PLpgSQL_diag_item *dtitems; -} PLpgSQL_stmt_getdiag; + List *diag_items; /* List of PLpgSQL_diag_item */ +} PLpgSQL_stmt_getdiag; typedef struct @@ -309,9 +376,28 @@ typedef struct int cmd_type; int lineno; PLpgSQL_expr *cond; - PLpgSQL_stmts *true_body; - PLpgSQL_stmts *false_body; -} PLpgSQL_stmt_if; + List *true_body; /* List of statements */ + List *false_body; /* List of statements */ +} PLpgSQL_stmt_if; + + +typedef struct /* CASE statement */ +{ + int cmd_type; + int lineno; + PLpgSQL_expr *t_expr; /* test expression, or NULL if none */ + int t_varno; /* var to store test expression value into */ + List *case_when_list; /* List of PLpgSQL_case_when structs */ + bool have_else; /* flag needed because list could be empty */ + List *else_stmts; /* List of statements */ +} PLpgSQL_stmt_case; + +typedef struct /* one arm of CASE statement */ +{ + int lineno; + PLpgSQL_expr *expr; /* boolean expression for this case */ + List *stmts; /* List of statements */ +} PLpgSQL_case_when; typedef struct @@ -319,8 +405,8 @@ typedef struct int cmd_type; int lineno; char *label; - PLpgSQL_stmts *body; -} PLpgSQL_stmt_loop; + List *body; /* List of statements */ +} PLpgSQL_stmt_loop; typedef struct @@ -329,8 +415,8 @@ typedef struct int lineno; char *label; PLpgSQL_expr *cond; - PLpgSQL_stmts *body; -} PLpgSQL_stmt_while; + List *body; /* List of statements */ +} PLpgSQL_stmt_while; typedef struct @@ -341,43 +427,64 @@ typedef struct PLpgSQL_var *var; PLpgSQL_expr *lower; PLpgSQL_expr *upper; + PLpgSQL_expr *step; /* NULL means default (ie, BY 1) */ int reverse; - PLpgSQL_stmts *body; -} PLpgSQL_stmt_fori; + List *body; /* List of statements */ +} PLpgSQL_stmt_fori; +/* + * PLpgSQL_stmt_forq represents a FOR statement running over a SQL query. + * It is the common supertype of PLpgSQL_stmt_fors, PLpgSQL_stmt_forc + * and PLpgSQL_dynfors. + */ typedef struct -{ /* FOR statement running over SELECT */ +{ int cmd_type; int lineno; char *label; PLpgSQL_rec *rec; PLpgSQL_row *row; - PLpgSQL_expr *query; - PLpgSQL_stmts *body; -} PLpgSQL_stmt_fors; - + List *body; /* List of statements */ +} PLpgSQL_stmt_forq; typedef struct -{ /* FOR statement running over EXECUTE */ +{ /* FOR statement running over SELECT */ int cmd_type; int lineno; char *label; PLpgSQL_rec *rec; PLpgSQL_row *row; + List *body; /* List of statements */ + /* end of fields that must match PLpgSQL_stmt_forq */ PLpgSQL_expr *query; - PLpgSQL_stmts *body; -} PLpgSQL_stmt_dynfors; +} PLpgSQL_stmt_fors; +typedef struct +{ /* FOR statement running over cursor */ + int cmd_type; + int lineno; + char *label; + PLpgSQL_rec *rec; + PLpgSQL_row *row; + List *body; /* List of statements */ + /* end of fields that must match PLpgSQL_stmt_forq */ + int curvar; + PLpgSQL_expr *argquery; /* cursor arguments if any */ +} PLpgSQL_stmt_forc; typedef struct -{ /* SELECT ... INTO statement */ +{ /* FOR statement running over EXECUTE */ int cmd_type; int lineno; + char *label; PLpgSQL_rec *rec; PLpgSQL_row *row; + List *body; /* List of statements */ + /* end of fields that must match PLpgSQL_stmt_forq */ PLpgSQL_expr *query; -} PLpgSQL_stmt_select; + List *params; /* USING expressions */ +} PLpgSQL_stmt_dynfors; typedef struct @@ -385,21 +492,27 @@ typedef struct int cmd_type; int lineno; int curvar; + int cursor_options; PLpgSQL_row *returntype; PLpgSQL_expr *argquery; PLpgSQL_expr *query; PLpgSQL_expr *dynquery; -} PLpgSQL_stmt_open; +} PLpgSQL_stmt_open; typedef struct -{ /* FETCH curvar INTO statement */ +{ /* FETCH or MOVE statement */ int cmd_type; int lineno; - PLpgSQL_rec *rec; + PLpgSQL_rec *rec; /* target, as record or row */ PLpgSQL_row *row; - int curvar; -} PLpgSQL_stmt_fetch; + int curvar; /* cursor variable to fetch from */ + FetchDirection direction; /* fetch direction */ + long how_many; /* count, if constant (expr is NULL) */ + PLpgSQL_expr *expr; /* count, if expression */ + bool is_move; /* is this a fetch or move? */ + bool returns_multiple_rows; /* can return more than one row? */ +} PLpgSQL_stmt_fetch; typedef struct @@ -407,16 +520,17 @@ typedef struct int cmd_type; int lineno; int curvar; -} PLpgSQL_stmt_close; +} PLpgSQL_stmt_close; typedef struct -{ /* EXIT statement */ +{ /* EXIT or CONTINUE statement */ int cmd_type; int lineno; - char *label; + bool is_exit; /* Is this an exit or a continue? */ + char *label; /* NULL if it's an unlabelled EXIT/CONTINUE */ PLpgSQL_expr *cond; -} PLpgSQL_stmt_exit; +} PLpgSQL_stmt_exit; typedef struct @@ -424,27 +538,42 @@ typedef struct int cmd_type; int lineno; PLpgSQL_expr *expr; - int retrecno; -} PLpgSQL_stmt_return; + int retvarno; +} PLpgSQL_stmt_return; typedef struct { /* RETURN NEXT statement */ int cmd_type; int lineno; - PLpgSQL_rec *rec; - PLpgSQL_row *row; PLpgSQL_expr *expr; -} PLpgSQL_stmt_return_next; + int retvarno; +} PLpgSQL_stmt_return_next; + +typedef struct +{ /* RETURN QUERY statement */ + int cmd_type; + int lineno; + PLpgSQL_expr *query; /* if static query */ + PLpgSQL_expr *dynquery; /* if dynamic query (RETURN QUERY EXECUTE) */ + List *params; /* USING arguments for dynamic query */ +} PLpgSQL_stmt_return_query; typedef struct { /* RAISE statement */ int cmd_type; int lineno; int elog_level; - char *message; - int nparams; - int *params; -} PLpgSQL_stmt_raise; + char *condname; /* condition name, SQLSTATE, or NULL */ + char *message; /* old-style message format literal, or NULL */ + List *params; /* list of expressions for old-style message */ + List *options; /* list of PLpgSQL_raise_option */ +} PLpgSQL_stmt_raise; + +typedef struct +{ /* RAISE statement option */ + int opt_type; + PLpgSQL_expr *expr; +} PLpgSQL_raise_option; typedef struct @@ -452,15 +581,50 @@ typedef struct int cmd_type; int lineno; PLpgSQL_expr *sqlstmt; -} PLpgSQL_stmt_execsql; + bool mod_stmt; /* is the stmt INSERT/UPDATE/DELETE? */ + /* note: mod_stmt is set when we plan the query */ + bool into; /* INTO supplied? */ + bool strict; /* INTO STRICT flag */ + PLpgSQL_rec *rec; /* INTO target, if record */ + PLpgSQL_row *row; /* INTO target, if row */ +} PLpgSQL_stmt_execsql; typedef struct { /* Dynamic SQL string to execute */ int cmd_type; int lineno; - PLpgSQL_expr *query; -} PLpgSQL_stmt_dynexecute; + PLpgSQL_expr *query; /* string expression */ + bool into; /* INTO supplied? */ + bool strict; /* INTO STRICT flag */ + PLpgSQL_rec *rec; /* INTO target, if record */ + PLpgSQL_row *row; /* INTO target, if row */ + List *params; /* USING expressions */ +} PLpgSQL_stmt_dynexecute; + + +typedef struct PLpgSQL_func_hashkey +{ /* Hash lookup key for functions */ + Oid funcOid; + + bool isTrigger; /* true if called as a trigger */ + + /* be careful that pad bytes in this struct get zeroed! */ + + /* + * For a trigger function, the OID of the relation triggered on is part of + * the hashkey --- we want to compile the trigger separately for each + * relation it is used with, in case the rowtype is different. Zero if + * not called as a trigger. + */ + Oid trigrelOid; + + /* + * We include actual argument types in the hash key to support polymorphic + * PLpgSQL functions. Be careful that extra positions are zeroed! + */ + Oid argtypes[FUNC_MAX_ARGS]; +} PLpgSQL_func_hashkey; typedef struct PLpgSQL_function @@ -468,19 +632,23 @@ typedef struct PLpgSQL_function char *fn_name; Oid fn_oid; TransactionId fn_xmin; - CommandId fn_cmin; - int fn_functype; + ItemPointerData fn_tid; + bool fn_is_trigger; + PLpgSQL_func_hashkey *fn_hashkey; /* back-link to hashtable key */ + MemoryContext fn_cxt; Oid fn_rettype; int fn_rettyplen; bool fn_retbyval; FmgrInfo fn_retinput; - Oid fn_rettypelem; + Oid fn_rettypioparam; bool fn_retistuple; bool fn_retset; + bool fn_readonly; int fn_nargs; int fn_argvarnos[FUNC_MAX_ARGS]; + int out_param_varno; int found_varno; int new_varno; int old_varno; @@ -490,18 +658,25 @@ typedef struct PLpgSQL_function int tg_op_varno; int tg_relid_varno; int tg_relname_varno; + int tg_table_name_varno; + int tg_table_schema_varno; int tg_nargs_varno; + int tg_argv_varno; int ndatums; PLpgSQL_datum **datums; PLpgSQL_stmt_block *action; - struct PLpgSQL_function *next; /* for chaining list of functions */ -} PLpgSQL_function; + /* these fields change when the function is used */ + struct PLpgSQL_execstate *cur_estate; + unsigned long use_count; +} PLpgSQL_function; -typedef struct +typedef struct PLpgSQL_execstate { /* Runtime execution data */ + PLpgSQL_function *func; /* function being executed */ + Datum retval; bool retisnull; Oid rettype; /* type of current retval */ @@ -510,16 +685,16 @@ typedef struct bool retistuple; bool retisset; + bool readonly_func; + TupleDesc rettupdesc; - char *exitlabel; + char *exitlabel; /* the "target" label of the current EXIT or + * CONTINUE stmt, if any */ Tuplestorestate *tuple_store; /* SRFs accumulate results here */ - MemoryContext tuple_store_cxt; + MemoryContext tuple_store_cxt; ReturnSetInfo *rsi; - int trig_nargs; - Datum *trig_argv; - int found_varno; int ndatums; PLpgSQL_datum **datums; @@ -528,31 +703,86 @@ typedef struct SPITupleTable *eval_tuptable; uint32 eval_processed; Oid eval_lastoid; - ExprContext *eval_econtext; -} PLpgSQL_execstate; + ExprContext *eval_econtext; /* for executing simple expressions */ + PLpgSQL_expr *cur_expr; /* current query/expr being evaluated */ + + /* status information for error context reporting */ + 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 **********************************************************************/ -extern int plpgsql_DumpExecTree; -extern int plpgsql_SpaceScanned; +extern bool plpgsql_DumpExecTree; +extern bool plpgsql_SpaceScanned; extern int plpgsql_nDatums; extern PLpgSQL_datum **plpgsql_Datums; extern int plpgsql_error_lineno; extern char *plpgsql_error_funcname; -/* linkage to the real yytext and yylineno variables */ +/* linkage to the real yytext variable */ extern char *plpgsql_base_yytext; -#define plpgsql_yytext plpgsql_base_yytext -extern int plpgsql_base_yylineno; - -#define plpgsql_yylineno plpgsql_base_yylineno +#define yytext plpgsql_base_yytext extern PLpgSQL_function *plpgsql_curr_compile; +extern bool plpgsql_check_syntax; +extern MemoryContext compile_tmp_cxt; + +extern PLpgSQL_plugin **plugin_ptr; /********************************************************************** * Function declarations @@ -562,53 +792,65 @@ extern PLpgSQL_function *plpgsql_curr_compile; * Functions in pl_comp.c * ---------- */ -extern PLpgSQL_function *plpgsql_compile(Oid fn_oid, int functype); -extern int plpgsql_parse_word(char *word); -extern int plpgsql_parse_dblword(char *word); -extern int plpgsql_parse_tripword(char *word); +extern PLpgSQL_function *plpgsql_compile(FunctionCallInfo fcinfo, + bool forValidator); +extern PLpgSQL_function *plpgsql_compile_inline(char *proc_source); +extern int plpgsql_parse_word(const char *word); +extern int plpgsql_parse_dblword(const char *word); +extern int plpgsql_parse_tripword(const char *word); extern int plpgsql_parse_wordtype(char *word); extern int plpgsql_parse_dblwordtype(char *word); +extern int plpgsql_parse_tripwordtype(char *word); extern int plpgsql_parse_wordrowtype(char *word); -extern PLpgSQL_type *plpgsql_parse_datatype(char *string); -extern void plpgsql_adddatum(PLpgSQL_datum * new); +extern int plpgsql_parse_dblwordrowtype(char *word); +extern PLpgSQL_type *plpgsql_parse_datatype(const char *string); +extern PLpgSQL_type *plpgsql_build_datatype(Oid typeOid, int32 typmod); +extern PLpgSQL_variable *plpgsql_build_variable(const char *refname, int lineno, + PLpgSQL_type *dtype, + bool add2namespace); +extern PLpgSQL_rec *plpgsql_build_record(const char *refname, int lineno, + bool add2namespace); +extern int plpgsql_recognize_err_condition(const char *condname, + bool allow_sqlstate); +extern PLpgSQL_condition *plpgsql_parse_err_condition(char *condname); +extern void plpgsql_adddatum(PLpgSQL_datum *new); extern int plpgsql_add_initdatums(int **varnos); -extern void plpgsql_yyerror(const char *s); +extern void plpgsql_HashTableInit(void); +extern void plpgsql_compile_error_callback(void *arg); /* ---------- * Functions in pl_handler.c * ---------- */ +extern void _PG_init(void); extern Datum plpgsql_call_handler(PG_FUNCTION_ARGS); +extern Datum plpgsql_inline_handler(PG_FUNCTION_ARGS); +extern Datum plpgsql_validator(PG_FUNCTION_ARGS); /* ---------- * Functions in pl_exec.c * ---------- */ -extern Datum plpgsql_exec_function(PLpgSQL_function * func, +extern Datum plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo); -extern HeapTuple plpgsql_exec_trigger(PLpgSQL_function * func, +extern HeapTuple plpgsql_exec_trigger(PLpgSQL_function *func, TriggerData *trigdata); - - -/* ---------- - * Functions for the dynamic string handling in pl_funcs.c - * ---------- - */ -extern void plpgsql_dstring_init(PLpgSQL_dstring * ds); -extern void plpgsql_dstring_free(PLpgSQL_dstring * ds); -extern void plpgsql_dstring_append(PLpgSQL_dstring * ds, char *str); -extern char *plpgsql_dstring_get(PLpgSQL_dstring * ds); +extern void plpgsql_xact_cb(XactEvent event, void *arg); +extern void plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid, + SubTransactionId parentSubid, void *arg); /* ---------- - * Functions for the namestack handling in pl_funcs.c + * Functions for namestack handling in pl_funcs.c * ---------- */ extern void plpgsql_ns_init(void); extern bool plpgsql_ns_setlocal(bool flag); -extern void plpgsql_ns_push(char *label); +extern void plpgsql_ns_push(const char *label); extern void plpgsql_ns_pop(void); -extern void plpgsql_ns_additem(int itemtype, int itemno, char *name); -extern PLpgSQL_nsitem *plpgsql_ns_lookup(char *name, char *nsname); +extern void plpgsql_ns_additem(int itemtype, int itemno, const char *name); +extern PLpgSQL_nsitem *plpgsql_ns_lookup(const char *name1, const char *name2, + const char *name3, int *names_used); +extern PLpgSQL_nsitem *plpgsql_ns_lookup_label(const char *name); extern void plpgsql_ns_rename(char *oldname, char *newname); /* ---------- @@ -616,8 +858,8 @@ extern void plpgsql_ns_rename(char *oldname, char *newname); * ---------- */ extern void plpgsql_convert_ident(const char *s, char **output, int numidents); -extern const char *plpgsql_stmt_typename(PLpgSQL_stmt * stmt); -extern void plpgsql_dumptree(PLpgSQL_function * func); +extern const char *plpgsql_stmt_typename(PLpgSQL_stmt *stmt); +extern void plpgsql_dumptree(PLpgSQL_function *func); /* ---------- * Externs in gram.y and scan.l @@ -628,6 +870,9 @@ extern int plpgsql_yyparse(void); extern int plpgsql_base_yylex(void); extern int plpgsql_yylex(void); extern void plpgsql_push_back_token(int token); -extern void plpgsql_setinput(char *s, int functype); +extern void plpgsql_yyerror(const char *message); +extern int plpgsql_scanner_lineno(void); +extern void plpgsql_scanner_init(const char *str); +extern void plpgsql_scanner_finish(void); #endif /* PLPGSQL_H */