Files
openGauss-server/src/include/utils/plpgsql.h
2021-03-06 12:39:28 +08:00

1016 lines
31 KiB
C++

/*---------------------------------------------------------------------------------------
*
* plpgsql.h
* Definitions for the PL/pgSQL procedural language
*
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* src/include/utils/plpgsql.h
*
* ---------------------------------------------------------------------------------------
*/
#ifndef PLPGSQL_H
#define PLPGSQL_H
#include "postgres.h"
#include "access/xact.h"
#include "catalog/namespace.h"
#include "commands/trigger.h"
#include "executor/spi.h"
/**********************************************************************
* Definitions
**********************************************************************/
/* define our text domain for translations */
#undef TEXTDOMAIN
#define TEXTDOMAIN PG_TEXTDOMAIN("plpgsql")
#undef _
#define _(x) dgettext(TEXTDOMAIN, x)
/* ----------
* Compiler's namespace item types
* ----------
*/
enum {
PLPGSQL_NSTYPE_LABEL,
PLPGSQL_NSTYPE_VAR,
PLPGSQL_NSTYPE_ROW,
PLPGSQL_NSTYPE_REC,
PLPGSQL_NSTYPE_RECORD,
PLPGSQL_NSTYPE_REFCURSOR,
PLPGSQL_NSTYPE_VARRAY
};
/* ----------
* Datum array node types
* ----------
*/
enum {
PLPGSQL_DTYPE_VAR,
PLPGSQL_DTYPE_ROW,
PLPGSQL_DTYPE_REC,
PLPGSQL_DTYPE_RECORD,
PLPGSQL_DTYPE_RECFIELD,
PLPGSQL_DTYPE_ARRAYELEM,
PLPGSQL_DTYPE_EXPR
};
// enums token flag
enum {
PLPGSQL_TOK_REFCURSOR,
PLPGSQL_TOK_VARRAY,
PLPGSQL_TOK_VARRAY_FIRST,
PLPGSQL_TOK_VARRAY_LAST,
PLPGSQL_TOK_VARRAY_COUNT,
PLPGSQL_TOK_VARRAY_EXTEND,
PLPGSQL_TOK_VARRAY_VAR,
PLPGSQL_TOK_RECORD
};
/* ----------
* 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_RECORD, /* RECORD pseudotype complitable A db */
PLPGSQL_TTYPE_PSEUDO /* other pseudotypes */
};
/* ----------
* Execution tree node types
* ----------
*/
enum PLpgSQL_stmt_types {
PLPGSQL_STMT_BLOCK,
PLPGSQL_STMT_ASSIGN,
PLPGSQL_STMT_IF,
PLPGSQL_STMT_GOTO,
PLPGSQL_STMT_CASE,
PLPGSQL_STMT_LOOP,
PLPGSQL_STMT_WHILE,
PLPGSQL_STMT_FORI,
PLPGSQL_STMT_FORS,
PLPGSQL_STMT_FORC,
PLPGSQL_STMT_FOREACH_A,
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_DYNFORS,
PLPGSQL_STMT_GETDIAG,
PLPGSQL_STMT_OPEN,
PLPGSQL_STMT_FETCH,
PLPGSQL_STMT_CLOSE,
PLPGSQL_STMT_PERFORM,
PLPGSQL_STMT_COMMIT,
PLPGSQL_STMT_ROLLBACK,
PLPGSQL_STMT_NULL
};
/* ----------
* Execution node return codes
* ----------
*/
enum { PLPGSQL_RC_OK, PLPGSQL_RC_EXIT, PLPGSQL_RC_RETURN, PLPGSQL_RC_CONTINUE, PLPGSQL_RC_GOTO_UNRESOLVED };
/* ----------
* GET DIAGNOSTICS information items
* ----------
*/
enum {
PLPGSQL_GETDIAG_ROW_COUNT,
PLPGSQL_GETDIAG_RESULT_OID,
PLPGSQL_GETDIAG_ERROR_CONTEXT,
PLPGSQL_GETDIAG_ERROR_DETAIL,
PLPGSQL_GETDIAG_ERROR_HINT,
PLPGSQL_GETDIAG_RETURNED_SQLSTATE,
PLPGSQL_GETDIAG_MESSAGE_TEXT
};
/* --------
* RAISE statement options
* --------
*/
enum { PLPGSQL_RAISEOPTION_ERRCODE, PLPGSQL_RAISEOPTION_MESSAGE, PLPGSQL_RAISEOPTION_DETAIL, PLPGSQL_RAISEOPTION_HINT };
/* --------
* Behavioral modes for plpgsql variable resolution
* --------
*/
typedef enum {
PLPGSQL_RESOLVE_ERROR, /* throw error if ambiguous */
PLPGSQL_RESOLVE_VARIABLE, /* prefer plpgsql var to table column */
PLPGSQL_RESOLVE_COLUMN /* prefer table column to plpgsql var */
} PLpgSQL_resolve_option;
/* --------
* State of cursor found/notfound variable
* --------
*/
typedef enum { PLPGSQL_TRUE, PLPGSQL_FALSE, PLPGSQL_NULL } PLpgSQL_state;
/**********************************************************************
* Node and structure definitions
**********************************************************************/
/*
* PLpgSQL_datum is the common supertype for PLpgSQL_expr, PLpgSQL_var,
* PLpgSQL_row, PLpgSQL_rec, PLpgSQL_recfield, and PLpgSQL_arrayelem
*/
typedef struct PLpgSQL_datum { /* Generic datum array item */
int dtype;
int dno;
} 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 dno;
char* query;
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;
/* namespace chain visible to this expr */
struct PLpgSQL_nsitem* ns;
/* 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 */
bool expr_simple_need_snapshot; /* true means need snapshot */
/*
* if expr is simple AND prepared in current transaction,
* expr_simple_state and expr_simple_in_use are valid. Test validity by
* seeing if expr_simple_lxid matches current LXID. (If not,
* expr_simple_state probably points at garbage!)
*/
ExprState* expr_simple_state; /* eval tree for expr_simple_expr */
bool expr_simple_in_use; /* true if eval tree is active */
LocalTransactionId expr_simple_lxid;
bool isouttype; /*the parameter will output*/
uint32 idx;
bool is_cachedplan_shared;
} PLpgSQL_expr;
typedef struct { /* Postgres data type */
int dtype;
int dno;
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;
Oid typrelid;
Oid typioparam;
Oid collation; /* from pg_type, but can be overridden */
FmgrInfo typinput; /* lookup info for typinput function */
int32 atttypmod; /* typmod (taken from someplace else) */
} PLpgSQL_type;
typedef struct { /* Scalar variable */
int dtype;
int dno;
char* refname;
int lineno;
PLpgSQL_type* datatype;
int isconst;
int notnull;
PLpgSQL_expr* default_val;
PLpgSQL_expr* cursor_explicit_expr;
int cursor_explicit_argrow;
int cursor_options;
Datum value;
bool isnull;
bool freeval;
bool is_cursor_var;
bool is_cursor_open;
} PLpgSQL_var;
typedef struct { /* Row variable */
int dtype;
int dno;
char* refname;
int lineno;
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;
int customErrorCode; /* only for exception variable. */
int intoplaceholders; /* number of placeholders, for anonymous block in dynamic stmt */
PLpgSQL_datum** intodatums;
} PLpgSQL_row;
typedef struct {
char* attrname;
PLpgSQL_type* type;
bool notnull;
PLpgSQL_expr* defaultvalue;
} PLpgSQL_rec_attr;
typedef struct {
int dtype;
int dno;
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;
Oid typrelid;
Oid typioparam;
Oid collation; /* from pg_type, but can be overridden */
FmgrInfo typinput; /* lookup info for typinput function */
int32 atttypmod; /* typmod (taken from someplace else) */
int attrnum;
char** attrnames;
PLpgSQL_type** types;
bool* notnulls;
PLpgSQL_expr** defaultvalues;
} PLpgSQL_rec_type;
typedef struct { /* Record variable (non-fixed structure) */
int dtype;
int dno;
char* refname;
int lineno;
HeapTuple tup;
TupleDesc tupdesc;
bool freetup;
bool freetupdesc;
} PLpgSQL_rec;
typedef struct { /* Field in record */
int dtype;
int dno;
char* fieldname;
int recparentno; /* dno of parent record */
} PLpgSQL_recfield;
typedef struct { /* Element of array variable */
int dtype;
int dno;
PLpgSQL_expr* subscript;
int arrayparentno; /* dno of parent array variable */
/* Remaining fields are cached info about the array variable's type */
Oid parenttypoid; /* type of array variable; 0 if not yet set */
int32 parenttypmod; /* typmod of array variable */
Oid arraytypoid; /* OID of actual array type */
int32 arraytypmod; /* typmod of array (and its elements too) */
int16 arraytyplen; /* typlen of array type */
Oid elemtypoid; /* OID of array element type */
int16 elemtyplen; /* typlen of element type */
bool elemtypbyval; /* element type is pass-by-value? */
char elemtypalign; /* typalign of element type */
} PLpgSQL_arrayelem;
typedef struct PLpgSQL_nsitem { /* Item in the compilers namespace tree */
int itemtype;
int itemno;
struct PLpgSQL_nsitem* prev;
char name[FLEXIBLE_ARRAY_MEMBER]; /* actually, as long as needed */
} PLpgSQL_nsitem;
typedef struct { /* Generic execution node */
int cmd_type;
int lineno;
} PLpgSQL_stmt;
typedef PLpgSQL_stmt PLpgSQL_stmt_null;
extern THR_LOCAL List* goto_labels;
typedef struct {
char* label;
PLpgSQL_stmt* stmt;
} PLpgSQL_gotoLabel;
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 {
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_condition* conditions;
List* action; /* List of statements */
} PLpgSQL_exception;
typedef struct PLpgSQL_stmt_block { /* Block of statements */
int cmd_type;
int lineno;
char* label;
#ifndef ENABLE_MULTIPLE_NODES
bool autonomous;
#endif
List* body; /* List of statements */
int n_initvars;
int* initvarnos;
PLpgSQL_exception_block* exceptions;
} PLpgSQL_stmt_block;
typedef struct { /* Assign statement */
int cmd_type;
int lineno;
int varno;
PLpgSQL_expr* expr;
} PLpgSQL_stmt_assign;
typedef struct { /* PERFORM statement */
int cmd_type;
int lineno;
PLpgSQL_expr* expr;
} PLpgSQL_stmt_perform;
typedef struct { /* Get Diagnostics item */
int kind; /* id for diagnostic value desired */
int target; /* where to assign it */
} PLpgSQL_diag_item;
typedef struct { /* Get Diagnostics statement */
int cmd_type;
int lineno;
bool is_stacked; /* STACKED or CURRENT diagnostics area? */
List* diag_items; /* List of PLpgSQL_diag_item */
} PLpgSQL_stmt_getdiag;
typedef struct { /* IF statement */
int cmd_type;
int lineno;
PLpgSQL_expr* cond; /* boolean expression for THEN */
List* then_body; /* List of statements */
List* elsif_list; /* List of PLpgSQL_if_elsif structs */
List* else_body; /* List of statements */
} PLpgSQL_stmt_if;
typedef struct { /* GOTO statement */
int cmd_type;
int lineno;
char* label;
} PLpgSQL_stmt_goto;
typedef struct /* one ELSIF arm of IF statement */
{
int lineno;
PLpgSQL_expr* cond; /* boolean expression for this case */
List* stmts; /* List of statements */
} PLpgSQL_if_elsif;
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 { /* Unconditional LOOP statement */
int cmd_type;
int lineno;
char* label;
List* body; /* List of statements */
} PLpgSQL_stmt_loop;
typedef struct { /* WHILE cond LOOP statement */
int cmd_type;
int lineno;
char* label;
PLpgSQL_expr* cond;
List* body; /* List of statements */
} PLpgSQL_stmt_while;
typedef struct { /* FOR statement with integer loopvar */
int cmd_type;
int lineno;
char* label;
PLpgSQL_var* var;
PLpgSQL_expr* lower;
PLpgSQL_expr* upper;
PLpgSQL_expr* step; /* NULL means default (ie, BY 1) */
int reverse;
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 {
int cmd_type;
int lineno;
char* label;
PLpgSQL_rec* rec;
PLpgSQL_row* row;
List* body; /* List of statements */
} PLpgSQL_stmt_forq;
typedef struct { /* 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_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 { /* 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;
List* params; /* USING expressions */
} PLpgSQL_stmt_dynfors;
typedef struct { /* FOREACH item in array loop */
int cmd_type;
int lineno;
char* label;
int varno; /* loop target variable */
int slice; /* slice dimension, or 0 */
PLpgSQL_expr* expr; /* array expression */
List* body; /* List of statements */
} PLpgSQL_stmt_foreach_a;
typedef struct { /* OPEN a curvar */
int cmd_type;
int lineno;
int curvar;
int cursor_options;
PLpgSQL_row* returntype;
PLpgSQL_expr* argquery;
PLpgSQL_expr* query;
PLpgSQL_expr* dynquery;
List* params; /* USING expressions */
} PLpgSQL_stmt_open;
typedef struct { /* FETCH or MOVE statement */
int cmd_type;
int lineno;
PLpgSQL_rec* rec; /* target, as record or row */
PLpgSQL_row* row;
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 { /* CLOSE curvar */
int cmd_type;
int lineno;
int curvar;
} PLpgSQL_stmt_close;
typedef struct { /* EXIT or CONTINUE statement */
int cmd_type;
int lineno;
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;
typedef struct { /* RETURN statement */
int cmd_type;
int lineno;
PLpgSQL_expr* expr;
int retvarno;
} PLpgSQL_stmt_return;
typedef struct { /* RETURN NEXT statement */
int cmd_type;
int lineno;
PLpgSQL_expr* expr;
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* 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 { /* Generic SQL statement to execute */
int cmd_type;
int lineno;
PLpgSQL_expr* sqlstmt;
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 */
// A db function invoke feature
int placeholders;
bool multi_func;
} PLpgSQL_stmt_execsql;
// Added USING IN/OUT/IN OUT for plpgsql
typedef struct { /* Dynamic SQL string to execute */
int cmd_type;
int lineno;
PLpgSQL_expr* query; /* string expression */
bool into; /* INTO supplied? */
bool strict; /* INTO STRICT flag */
PLpgSQL_rec* rec; /* INTO target, if record */
union {
PLpgSQL_row* row; /* INTO target, if row */
PLpgSQL_row* out_row; /* USING output */
};
List* params; /* USING expressions */
bool isinouttype; /* IN OUT parameters, differ from INTO statment */
bool isanonymousblock; /* check if it is anonymous block */
void* ppd; /* IN or IN OUT parameters */
} 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 hash key --- 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 must include the input collation as part of the hash key too,
* because we have to generate different plans (with different Param
* collations) for different collation settings.
*/
Oid inputCollation;
/*
* 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 { /* Complete compiled function */
char* fn_signature;
Oid fn_oid;
OverrideSearchPath* fn_searchpath;
Oid fn_owner;
TransactionId fn_xmin;
ItemPointerData fn_tid;
bool fn_is_trigger;
Oid fn_input_collation;
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_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;
// magic variables' varno for implicit cursor attributes
int sql_cursor_found_varno;
int sql_notfound_varno;
int sql_isopen_varno;
int sql_rowcount_varno;
// the magic sqlcode no
int sqlcode_varno;
int new_varno;
int old_varno;
int tg_name_varno;
int tg_when_varno;
int tg_level_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;
PLpgSQL_resolve_option resolve_option;
int ndatums;
PLpgSQL_datum** datums;
PLpgSQL_stmt_block* action;
List* goto_labels;
/* these fields change when the function is used */
struct PLpgSQL_execstate* cur_estate;
unsigned long use_count;
/* these fields are used during trigger pre-parsing */
bool pre_parse_trig;
Relation tg_relation;
} PLpgSQL_function;
class AutonomousSession;
typedef struct PLpgSQL_execstate { /* Runtime execution data */
PLpgSQL_function* func; /* function being executed */
Datum retval;
bool retisnull;
Oid rettype; /* type of current retval */
Oid fn_rettype; /* info about declared function rettype */
bool retistuple;
bool retisset;
bool readonly_func;
TupleDesc rettupdesc;
char* exitlabel; /* the "target" label of the current EXIT or
* CONTINUE stmt, if any */
ErrorData* cur_error; /* current exception handler's error */
Tuplestorestate* tuple_store; /* SRFs accumulate results here */
MemoryContext tuple_store_cxt;
ResourceOwner tuple_store_owner;
ReturnSetInfo* rsi;
#ifndef ENABLE_MULTIPLE_NODES
AutonomousSession *autonomous_session;
#endif
int found_varno;
/*
* The execute state variable estate->rowcount keeps
* the current rowcount while executing store procedure
*/
int32 rowcount;
/* magic variables' varno for implicit cursor attributes */
int sql_cursor_found_varno;
int sql_notfound_varno;
int sql_isopen_varno;
int sql_rowcount_varno;
int sqlcode_varno;
int ndatums;
PLpgSQL_datum** datums;
/* temporary state for results from evaluation of query or expr */
SPITupleTable* eval_tuptable;
uint32 eval_processed;
Oid eval_lastoid;
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 */
/* support GOTO */
List* goto_labels;
char* goto_target_label;
PLpgSQL_stmt* goto_target_stmt; /* current GOTO */
int block_level; /* block level, 0 for topmost */
Cursor_Data* cursor_return_data;
} 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 PLpgSQL_plugin {
/* 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);
Datum (*eval_expr)(PLpgSQL_execstate* estate, PLpgSQL_expr* expr, bool* isNull, Oid* rettype);
void (*assign_value)(PLpgSQL_execstate* estate, PLpgSQL_datum* target, Datum value, Oid valtype, bool* isNull);
void (*eval_cleanup)(PLpgSQL_execstate* estate);
int (*validate_line)(PLpgSQL_stmt_block* block, int linenum);
} PLpgSQL_plugin;
/* Struct types used during parsing */
typedef struct {
char* ident; /* palloc'd converted identifier */
bool quoted; /* Was it double-quoted? */
} PLword;
typedef struct {
List* idents; /* composite identifiers (list of String) */
} PLcword;
typedef struct {
PLpgSQL_datum* datum; /* referenced variable */
char* ident; /* valid if simple name */
bool quoted;
List* idents; /* valid if composite name */
} PLwdatum;
/**********************************************************************
* Function declarations
**********************************************************************/
/* ----------
* Functions in pl_comp.c
* ----------
*/
typedef struct plpgsql_hashent {
PLpgSQL_func_hashkey key;
PLpgSQL_function* function;
DListCell* cell; /* Dlist cell for delete function compile results. */
} plpgsql_HashEnt;
extern PLpgSQL_function* plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator);
extern PLpgSQL_function* plpgsql_compile_nohashkey(FunctionCallInfo fcinfo); /* parse trigger func */
extern PLpgSQL_function* plpgsql_compile_inline(char* proc_source);
extern void plpgsql_parser_setup(struct ParseState* pstate, PLpgSQL_expr* expr);
extern bool plpgsql_parse_word(char* word1, const char* yytxt, PLwdatum* wdatum, PLword* word, int* tok_flag);
extern bool plpgsql_parse_dblword(char* word1, char* word2, PLwdatum* wdatum, PLcword* cword, int* nsflag);
extern bool plpgsql_parse_tripword(char* word1, char* word2, char* word3, PLwdatum* wdatum, PLcword* cword);
extern PLpgSQL_type* plpgsql_parse_wordtype(char* ident);
extern PLpgSQL_type* plpgsql_parse_cwordtype(List* idents);
extern PLpgSQL_type* plpgsql_parse_wordrowtype(char* ident);
extern PLpgSQL_type* plpgsql_parse_cwordrowtype(List* idents);
extern PLpgSQL_type* plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation);
extern PLpgSQL_variable* plpgsql_build_variable(
const char* refname, int lineno, PLpgSQL_type* dtype, bool add2namespace, const char* varname = NULL);
PLpgSQL_variable* plpgsql_build_varrayType(const char* refname, int lineno, PLpgSQL_type* dtype, bool add2namespace);
extern PLpgSQL_rec_type* plpgsql_build_rec_type(const char* typname, int lineno, List* list, 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* newm);
extern int plpgsql_add_initdatums(int** varnos);
extern void plpgsql_HashTableInit(void);
extern PLpgSQL_row* build_row_from_rec_type(const char* rowname, int lineno, PLpgSQL_rec_type* type);
extern bool plpgsql_check_colocate(Query* query, RangeTblEntry* rte, void* plpgsql_func);
extern void plpgsql_HashTableDeleteAll();
extern void plpgsql_HashTableDeleteFunc(Oid func_oid);
extern void plpgsql_HashTableDelete(PLpgSQL_function* func);
/* ----------
* Functions in pl_handler.c
* ----------
*/
extern "C" void _PG_init(void);
extern "C" Datum plpgsql_call_handler(PG_FUNCTION_ARGS);
extern "C" Datum plpgsql_inline_handler(PG_FUNCTION_ARGS);
extern "C" Datum plpgsql_validator(PG_FUNCTION_ARGS);
/* --- --- ---
* Functions in plsql_packages.c
* --- ---
*/
extern "C" {
Datum regexp_substr(PG_FUNCTION_ARGS);
Datum intervaltonum(PG_FUNCTION_ARGS);
Datum rawtohex(PG_FUNCTION_ARGS);
Datum report_application_error(PG_FUNCTION_ARGS);
}
extern THR_LOCAL PLpgSQL_execstate* plpgsql_estate;
/* ----------
* Functions in pl_exec.c
* ----------
*/
extern Datum plpgsql_exec_function(PLpgSQL_function* func, FunctionCallInfo fcinfo, bool dynexec_anonymous_block);
extern HeapTuple plpgsql_exec_trigger(PLpgSQL_function* func, TriggerData* trigdata);
extern void plpgsql_xact_cb(XactEvent event, void* arg);
extern void plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void* arg);
extern Oid exec_get_datum_type(PLpgSQL_execstate* estate, PLpgSQL_datum* datum);
extern void exec_get_datum_type_info(PLpgSQL_execstate* estate, PLpgSQL_datum* datum, Oid* typid, int32* typmod,
Oid* collation, PLpgSQL_function* func = NULL);
extern Datum exec_simple_cast_datum(
PLpgSQL_execstate* estate, Datum value, Oid valtype, Oid reqtype, int32 reqtypmod, bool isnull);
extern void ResetCursorOption(Portal portal, bool reset);
extern void exec_assign_value(PLpgSQL_execstate *estate,
PLpgSQL_datum *target,
Datum value, Oid valtype, bool *isNull);
extern void exec_eval_datum(PLpgSQL_execstate *estate,
PLpgSQL_datum *datum,
Oid *typeId,
int32 *typetypmod,
Datum *value,
bool *isnull,
bool isretry);
extern void exec_eval_cleanup(PLpgSQL_execstate *estate);
/* ----------
* Functions for namespace handling in pl_funcs.c
* ----------
*/
extern void plpgsql_ns_init(void);
extern void plpgsql_ns_push(const char* label);
extern void plpgsql_ns_pop(void);
extern PLpgSQL_nsitem* plpgsql_ns_top(void);
extern void plpgsql_ns_additem(int itemtype, int itemno, const char* name);
extern PLpgSQL_nsitem* plpgsql_ns_lookup(
PLpgSQL_nsitem* ns_cur, bool localmode, const char* name1, const char* name2, const char* name3, int* names_used);
extern PLpgSQL_nsitem* plpgsql_ns_lookup_label(PLpgSQL_nsitem* ns_cur, const char* name);
/* ----------
* Other functions in pl_funcs.c
* ----------
*/
extern const char* plpgsql_stmt_typename(PLpgSQL_stmt* stmt);
extern const char* plpgsql_getdiag_kindname(int kind);
extern void plpgsql_free_function_memory(PLpgSQL_function* func);
extern void plpgsql_dumptree(PLpgSQL_function* func);
extern bool plpgsql_is_trigger_shippable(PLpgSQL_function* func);
/* ----------
* Scanner functions in pl_scanner.c
* ----------
*/
extern int plpgsql_base_yylex(void);
extern int plpgsql_yylex(void);
extern void plpgsql_push_back_token(int token);
extern void plpgsql_append_source_text(StringInfo buf, int startlocation, int endlocation);
extern void plpgsql_peek2(int* tok1_p, int* tok2_p, int* tok1_loc, int* tok2_loc);
extern int plpgsql_scanner_errposition(int location);
extern void plpgsql_yyerror(const char* message);
extern int plpgsql_location_to_lineno(int location);
extern int plpgsql_latest_lineno(void);
extern void plpgsql_scanner_init(const char* str);
extern void plpgsql_scanner_finish(void);
/* ----------
* Externs in gram.y
* ----------
*/
extern int plpgsql_yyparse(void);
extern bool plpgsql_is_token_match2(int token, int token_next);
extern bool plpgsql_is_token_match(int token);
#endif /* PLPGSQL_H */