-/**********************************************************************
+/*-------------------------------------------------------------------------
+ *
* 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
PLPGSQL_NSTYPE_LABEL,
PLPGSQL_NSTYPE_VAR,
PLPGSQL_NSTYPE_ROW,
- PLPGSQL_NSTYPE_REC,
- PLPGSQL_NSTYPE_RECFIELD
+ PLPGSQL_NSTYPE_REC
};
/* ----------
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,
PLPGSQL_STMT_GETDIAG,
PLPGSQL_STMT_OPEN,
PLPGSQL_STMT_FETCH,
- PLPGSQL_STMT_CLOSE
+ PLPGSQL_STMT_CLOSE,
+ PLPGSQL_STMT_PERFORM
};
{
PLPGSQL_RC_OK,
PLPGSQL_RC_EXIT,
- PLPGSQL_RC_RETURN
+ PLPGSQL_RC_RETURN,
+ PLPGSQL_RC_CONTINUE,
+ PLPGSQL_RC_RERAISE
};
/* ----------
PLPGSQL_GETDIAG_RESULT_OID
};
+/* --------
+ * RAISE statement options
+ * --------
+ */
+enum
+{
+ PLPGSQL_RAISEOPTION_ERRCODE,
+ PLPGSQL_RAISEOPTION_MESSAGE,
+ PLPGSQL_RAISEOPTION_DETAIL,
+ PLPGSQL_RAISEOPTION_HINT
+};
+
/**********************************************************************
* Node and structure definitions
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;
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;
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
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
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
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
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
int cmd_type;
int lineno;
char *label;
- PLpgSQL_stmts *body;
-} PLpgSQL_stmt_loop;
+ List *body; /* List of statements */
+} PLpgSQL_stmt_loop;
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
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
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
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
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
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
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;
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 */
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;
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
* 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);
/* ----------
* ----------
*/
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
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 */