1321 lines
35 KiB
C
1321 lines
35 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* plpgsql.h - Definitions for the PL/pgSQL
|
|
* procedural language
|
|
*
|
|
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* src/pl/plpgsql/src/plpgsql.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#ifndef PLPGSQL_H
|
|
#define PLPGSQL_H
|
|
|
|
#include "access/xact.h"
|
|
#include "commands/event_trigger.h"
|
|
#include "commands/trigger.h"
|
|
#include "executor/spi.h"
|
|
#include "utils/expandedrecord.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
|
|
*/
|
|
typedef enum PLpgSQL_nsitem_type
|
|
{
|
|
PLPGSQL_NSTYPE_LABEL, /* block label */
|
|
PLPGSQL_NSTYPE_VAR, /* scalar variable */
|
|
PLPGSQL_NSTYPE_REC /* composite variable */
|
|
} PLpgSQL_nsitem_type;
|
|
|
|
/*
|
|
* A PLPGSQL_NSTYPE_LABEL stack entry must be one of these types
|
|
*/
|
|
typedef enum PLpgSQL_label_type
|
|
{
|
|
PLPGSQL_LABEL_BLOCK, /* DECLARE/BEGIN block */
|
|
PLPGSQL_LABEL_LOOP, /* looping construct */
|
|
PLPGSQL_LABEL_OTHER /* anything else */
|
|
} PLpgSQL_label_type;
|
|
|
|
/*
|
|
* Datum array node types
|
|
*/
|
|
typedef enum PLpgSQL_datum_type
|
|
{
|
|
PLPGSQL_DTYPE_VAR,
|
|
PLPGSQL_DTYPE_ROW,
|
|
PLPGSQL_DTYPE_REC,
|
|
PLPGSQL_DTYPE_RECFIELD,
|
|
PLPGSQL_DTYPE_ARRAYELEM,
|
|
PLPGSQL_DTYPE_PROMISE
|
|
} PLpgSQL_datum_type;
|
|
|
|
/*
|
|
* DTYPE_PROMISE datums have these possible ways of computing the promise
|
|
*/
|
|
typedef enum PLpgSQL_promise_type
|
|
{
|
|
PLPGSQL_PROMISE_NONE = 0, /* not a promise, or promise satisfied */
|
|
PLPGSQL_PROMISE_TG_NAME,
|
|
PLPGSQL_PROMISE_TG_WHEN,
|
|
PLPGSQL_PROMISE_TG_LEVEL,
|
|
PLPGSQL_PROMISE_TG_OP,
|
|
PLPGSQL_PROMISE_TG_RELID,
|
|
PLPGSQL_PROMISE_TG_TABLE_NAME,
|
|
PLPGSQL_PROMISE_TG_TABLE_SCHEMA,
|
|
PLPGSQL_PROMISE_TG_NARGS,
|
|
PLPGSQL_PROMISE_TG_ARGV,
|
|
PLPGSQL_PROMISE_TG_EVENT,
|
|
PLPGSQL_PROMISE_TG_TAG
|
|
} PLpgSQL_promise_type;
|
|
|
|
/*
|
|
* Variants distinguished in PLpgSQL_type structs
|
|
*/
|
|
typedef enum PLpgSQL_type_type
|
|
{
|
|
PLPGSQL_TTYPE_SCALAR, /* scalar types and domains */
|
|
PLPGSQL_TTYPE_REC, /* composite types, including RECORD */
|
|
PLPGSQL_TTYPE_PSEUDO /* pseudotypes */
|
|
} PLpgSQL_type_type;
|
|
|
|
/*
|
|
* Execution tree node types
|
|
*/
|
|
typedef enum PLpgSQL_stmt_type
|
|
{
|
|
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_FORC,
|
|
PLPGSQL_STMT_FOREACH_A,
|
|
PLPGSQL_STMT_EXIT,
|
|
PLPGSQL_STMT_RETURN,
|
|
PLPGSQL_STMT_RETURN_NEXT,
|
|
PLPGSQL_STMT_RETURN_QUERY,
|
|
PLPGSQL_STMT_RAISE,
|
|
PLPGSQL_STMT_ASSERT,
|
|
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_CALL,
|
|
PLPGSQL_STMT_COMMIT,
|
|
PLPGSQL_STMT_ROLLBACK,
|
|
PLPGSQL_STMT_SET
|
|
} PLpgSQL_stmt_type;
|
|
|
|
/*
|
|
* Execution node return codes
|
|
*/
|
|
enum
|
|
{
|
|
PLPGSQL_RC_OK,
|
|
PLPGSQL_RC_EXIT,
|
|
PLPGSQL_RC_RETURN,
|
|
PLPGSQL_RC_CONTINUE
|
|
};
|
|
|
|
/*
|
|
* GET DIAGNOSTICS information items
|
|
*/
|
|
typedef enum PLpgSQL_getdiag_kind
|
|
{
|
|
PLPGSQL_GETDIAG_ROW_COUNT,
|
|
PLPGSQL_GETDIAG_CONTEXT,
|
|
PLPGSQL_GETDIAG_ERROR_CONTEXT,
|
|
PLPGSQL_GETDIAG_ERROR_DETAIL,
|
|
PLPGSQL_GETDIAG_ERROR_HINT,
|
|
PLPGSQL_GETDIAG_RETURNED_SQLSTATE,
|
|
PLPGSQL_GETDIAG_COLUMN_NAME,
|
|
PLPGSQL_GETDIAG_CONSTRAINT_NAME,
|
|
PLPGSQL_GETDIAG_DATATYPE_NAME,
|
|
PLPGSQL_GETDIAG_MESSAGE_TEXT,
|
|
PLPGSQL_GETDIAG_TABLE_NAME,
|
|
PLPGSQL_GETDIAG_SCHEMA_NAME
|
|
} PLpgSQL_getdiag_kind;
|
|
|
|
/*
|
|
* RAISE statement options
|
|
*/
|
|
typedef enum PLpgSQL_raise_option_type
|
|
{
|
|
PLPGSQL_RAISEOPTION_ERRCODE,
|
|
PLPGSQL_RAISEOPTION_MESSAGE,
|
|
PLPGSQL_RAISEOPTION_DETAIL,
|
|
PLPGSQL_RAISEOPTION_HINT,
|
|
PLPGSQL_RAISEOPTION_COLUMN,
|
|
PLPGSQL_RAISEOPTION_CONSTRAINT,
|
|
PLPGSQL_RAISEOPTION_DATATYPE,
|
|
PLPGSQL_RAISEOPTION_TABLE,
|
|
PLPGSQL_RAISEOPTION_SCHEMA
|
|
} PLpgSQL_raise_option_type;
|
|
|
|
/*
|
|
* Behavioral modes for plpgsql variable resolution
|
|
*/
|
|
typedef enum PLpgSQL_resolve_option
|
|
{
|
|
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;
|
|
|
|
|
|
/**********************************************************************
|
|
* Node and structure definitions
|
|
**********************************************************************/
|
|
|
|
/*
|
|
* Postgres data type
|
|
*/
|
|
typedef struct PLpgSQL_type
|
|
{
|
|
char *typname; /* (simple) name of the type */
|
|
Oid typoid; /* OID of the data type */
|
|
PLpgSQL_type_type ttype; /* PLPGSQL_TTYPE_ code */
|
|
int16 typlen; /* stuff copied from its pg_type entry */
|
|
bool typbyval;
|
|
char typtype;
|
|
Oid collation; /* from pg_type, but can be overridden */
|
|
bool typisarray; /* is "true" array, or domain over one */
|
|
int32 atttypmod; /* typmod (taken from someplace else) */
|
|
} PLpgSQL_type;
|
|
|
|
/*
|
|
* SQL Query to plan and execute
|
|
*/
|
|
typedef struct PLpgSQL_expr
|
|
{
|
|
char *query;
|
|
SPIPlanPtr plan;
|
|
Bitmapset *paramnos; /* all dnos referenced by this query */
|
|
int rwparam; /* dno of read/write param, or -1 if none */
|
|
|
|
/* 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 */
|
|
int32 expr_simple_typmod; /* result typmod, if simple */
|
|
|
|
/*
|
|
* 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;
|
|
} PLpgSQL_expr;
|
|
|
|
/*
|
|
* Generic datum array item
|
|
*
|
|
* PLpgSQL_datum is the common supertype for PLpgSQL_var, PLpgSQL_row,
|
|
* PLpgSQL_rec, PLpgSQL_recfield, and PLpgSQL_arrayelem.
|
|
*/
|
|
typedef struct PLpgSQL_datum
|
|
{
|
|
PLpgSQL_datum_type dtype;
|
|
int dno;
|
|
} PLpgSQL_datum;
|
|
|
|
/*
|
|
* Scalar or composite variable
|
|
*
|
|
* The variants PLpgSQL_var, PLpgSQL_row, and PLpgSQL_rec share these
|
|
* fields.
|
|
*/
|
|
typedef struct PLpgSQL_variable
|
|
{
|
|
PLpgSQL_datum_type dtype;
|
|
int dno;
|
|
char *refname;
|
|
int lineno;
|
|
bool isconst;
|
|
bool notnull;
|
|
PLpgSQL_expr *default_val;
|
|
} PLpgSQL_variable;
|
|
|
|
/*
|
|
* Scalar variable
|
|
*
|
|
* DTYPE_VAR and DTYPE_PROMISE datums both use this struct type.
|
|
* A PROMISE datum works exactly like a VAR datum for most purposes,
|
|
* but if it is read without having previously been assigned to, then
|
|
* a special "promised" value is computed and assigned to the datum
|
|
* before the read is performed. This technique avoids the overhead of
|
|
* computing the variable's value in cases where we expect that many
|
|
* functions will never read it.
|
|
*/
|
|
typedef struct PLpgSQL_var
|
|
{
|
|
PLpgSQL_datum_type dtype;
|
|
int dno;
|
|
char *refname;
|
|
int lineno;
|
|
bool isconst;
|
|
bool notnull;
|
|
PLpgSQL_expr *default_val;
|
|
/* end of PLpgSQL_variable fields */
|
|
|
|
PLpgSQL_type *datatype;
|
|
|
|
/*
|
|
* Variables declared as CURSOR FOR <query> are mostly like ordinary
|
|
* scalar variables of type refcursor, but they have these additional
|
|
* properties:
|
|
*/
|
|
PLpgSQL_expr *cursor_explicit_expr;
|
|
int cursor_explicit_argrow;
|
|
int cursor_options;
|
|
|
|
/* Fields below here can change at runtime */
|
|
|
|
Datum value;
|
|
bool isnull;
|
|
bool freeval;
|
|
|
|
/*
|
|
* The promise field records which "promised" value to assign if the
|
|
* promise must be honored. If it's a normal variable, or the promise has
|
|
* been fulfilled, this is PLPGSQL_PROMISE_NONE.
|
|
*/
|
|
PLpgSQL_promise_type promise;
|
|
} PLpgSQL_var;
|
|
|
|
/*
|
|
* Row variable - this represents one or more variables that are listed in an
|
|
* INTO clause, FOR-loop targetlist, cursor argument list, etc. We also use
|
|
* a row to represent a function's OUT parameters when there's more than one.
|
|
*
|
|
* Note that there's no way to name the row as such from PL/pgSQL code,
|
|
* so many functions don't need to support these.
|
|
*
|
|
* That also means that there's no real name for the row variable, so we
|
|
* conventionally set refname to "(unnamed row)". We could leave it NULL,
|
|
* but it's too convenient to be able to assume that refname is valid in
|
|
* all variants of PLpgSQL_variable.
|
|
*
|
|
* isconst, notnull, and default_val are unsupported (and hence
|
|
* always zero/null) for a row. The member variables of a row should have
|
|
* been checked to be writable at compile time, so isconst is correctly set
|
|
* to false. notnull and default_val aren't applicable.
|
|
*/
|
|
typedef struct PLpgSQL_row
|
|
{
|
|
PLpgSQL_datum_type dtype;
|
|
int dno;
|
|
char *refname;
|
|
int lineno;
|
|
bool isconst;
|
|
bool notnull;
|
|
PLpgSQL_expr *default_val;
|
|
/* end of PLpgSQL_variable fields */
|
|
|
|
/*
|
|
* rowtupdesc is only set up if we might need to convert the row into a
|
|
* composite datum, which currently only happens for OUT parameters.
|
|
* Otherwise it is NULL.
|
|
*/
|
|
TupleDesc rowtupdesc;
|
|
|
|
int nfields;
|
|
char **fieldnames;
|
|
int *varnos;
|
|
} PLpgSQL_row;
|
|
|
|
/*
|
|
* Record variable (any composite type, including RECORD)
|
|
*/
|
|
typedef struct PLpgSQL_rec
|
|
{
|
|
PLpgSQL_datum_type dtype;
|
|
int dno;
|
|
char *refname;
|
|
int lineno;
|
|
bool isconst;
|
|
bool notnull;
|
|
PLpgSQL_expr *default_val;
|
|
/* end of PLpgSQL_variable fields */
|
|
|
|
PLpgSQL_type *datatype; /* can be NULL, if rectypeid is RECORDOID */
|
|
Oid rectypeid; /* declared type of variable */
|
|
/* RECFIELDs for this record are chained together for easy access */
|
|
int firstfield; /* dno of first RECFIELD, or -1 if none */
|
|
|
|
/* Fields below here can change at runtime */
|
|
|
|
/* We always store record variables as "expanded" records */
|
|
ExpandedRecordHeader *erh;
|
|
} PLpgSQL_rec;
|
|
|
|
/*
|
|
* Field in record
|
|
*/
|
|
typedef struct PLpgSQL_recfield
|
|
{
|
|
PLpgSQL_datum_type dtype;
|
|
int dno;
|
|
/* end of PLpgSQL_datum fields */
|
|
|
|
char *fieldname; /* name of field */
|
|
int recparentno; /* dno of parent record */
|
|
int nextfield; /* dno of next child, or -1 if none */
|
|
uint64 rectupledescid; /* record's tupledesc ID as of last lookup */
|
|
ExpandedRecordFieldInfo finfo; /* field's attnum and type info */
|
|
/* if rectupledescid == INVALID_TUPLEDESC_IDENTIFIER, finfo isn't valid */
|
|
} PLpgSQL_recfield;
|
|
|
|
/*
|
|
* Element of array variable
|
|
*/
|
|
typedef struct PLpgSQL_arrayelem
|
|
{
|
|
PLpgSQL_datum_type dtype;
|
|
int dno;
|
|
/* end of PLpgSQL_datum fields */
|
|
|
|
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;
|
|
|
|
/*
|
|
* Item in the compilers namespace tree
|
|
*/
|
|
typedef struct PLpgSQL_nsitem
|
|
{
|
|
PLpgSQL_nsitem_type itemtype;
|
|
|
|
/*
|
|
* For labels, itemno is a value of enum PLpgSQL_label_type. For other
|
|
* itemtypes, itemno is the associated PLpgSQL_datum's dno.
|
|
*/
|
|
int itemno;
|
|
struct PLpgSQL_nsitem *prev;
|
|
char name[FLEXIBLE_ARRAY_MEMBER]; /* nul-terminated string */
|
|
} PLpgSQL_nsitem;
|
|
|
|
/*
|
|
* Generic execution node
|
|
*/
|
|
typedef struct PLpgSQL_stmt
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
|
|
/*
|
|
* Unique statement ID in this function (starting at 1; 0 is invalid/not
|
|
* set). This can be used by a profiler as the index for an array of
|
|
* per-statement metrics.
|
|
*/
|
|
unsigned int stmtid;
|
|
} PLpgSQL_stmt;
|
|
|
|
/*
|
|
* One EXCEPTION condition name
|
|
*/
|
|
typedef struct PLpgSQL_condition
|
|
{
|
|
int sqlerrstate; /* SQLSTATE code */
|
|
char *condname; /* condition name (for debugging) */
|
|
struct PLpgSQL_condition *next;
|
|
} PLpgSQL_condition;
|
|
|
|
/*
|
|
* EXCEPTION block
|
|
*/
|
|
typedef struct PLpgSQL_exception_block
|
|
{
|
|
int sqlstate_varno;
|
|
int sqlerrm_varno;
|
|
List *exc_list; /* List of WHEN clauses */
|
|
} PLpgSQL_exception_block;
|
|
|
|
/*
|
|
* One EXCEPTION ... WHEN clause
|
|
*/
|
|
typedef struct PLpgSQL_exception
|
|
{
|
|
int lineno;
|
|
PLpgSQL_condition *conditions;
|
|
List *action; /* List of statements */
|
|
} PLpgSQL_exception;
|
|
|
|
/*
|
|
* Block of statements
|
|
*/
|
|
typedef struct PLpgSQL_stmt_block
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
char *label;
|
|
List *body; /* List of statements */
|
|
int n_initvars; /* Length of initvarnos[] */
|
|
int *initvarnos; /* dnos of variables declared in this block */
|
|
PLpgSQL_exception_block *exceptions;
|
|
} PLpgSQL_stmt_block;
|
|
|
|
/*
|
|
* Assign statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_assign
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
int varno;
|
|
PLpgSQL_expr *expr;
|
|
} PLpgSQL_stmt_assign;
|
|
|
|
/*
|
|
* PERFORM statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_perform
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
PLpgSQL_expr *expr;
|
|
} PLpgSQL_stmt_perform;
|
|
|
|
/*
|
|
* CALL statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_call
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
PLpgSQL_expr *expr;
|
|
bool is_call;
|
|
PLpgSQL_variable *target;
|
|
} PLpgSQL_stmt_call;
|
|
|
|
/*
|
|
* COMMIT statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_commit
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
bool chain;
|
|
} PLpgSQL_stmt_commit;
|
|
|
|
/*
|
|
* ROLLBACK statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_rollback
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
bool chain;
|
|
} PLpgSQL_stmt_rollback;
|
|
|
|
/*
|
|
* SET statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_set
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
PLpgSQL_expr *expr;
|
|
} PLpgSQL_stmt_set;
|
|
|
|
/*
|
|
* GET DIAGNOSTICS item
|
|
*/
|
|
typedef struct PLpgSQL_diag_item
|
|
{
|
|
PLpgSQL_getdiag_kind kind; /* id for diagnostic value desired */
|
|
int target; /* where to assign it */
|
|
} PLpgSQL_diag_item;
|
|
|
|
/*
|
|
* GET DIAGNOSTICS statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_getdiag
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
bool is_stacked; /* STACKED or CURRENT diagnostics area? */
|
|
List *diag_items; /* List of PLpgSQL_diag_item */
|
|
} PLpgSQL_stmt_getdiag;
|
|
|
|
/*
|
|
* IF statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_if
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
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;
|
|
|
|
/*
|
|
* one ELSIF arm of IF statement
|
|
*/
|
|
typedef struct PLpgSQL_if_elsif
|
|
{
|
|
int lineno;
|
|
PLpgSQL_expr *cond; /* boolean expression for this case */
|
|
List *stmts; /* List of statements */
|
|
} PLpgSQL_if_elsif;
|
|
|
|
/*
|
|
* CASE statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_case
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
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;
|
|
|
|
/*
|
|
* one arm of CASE statement
|
|
*/
|
|
typedef struct PLpgSQL_case_when
|
|
{
|
|
int lineno;
|
|
PLpgSQL_expr *expr; /* boolean expression for this case */
|
|
List *stmts; /* List of statements */
|
|
} PLpgSQL_case_when;
|
|
|
|
/*
|
|
* Unconditional LOOP statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_loop
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
char *label;
|
|
List *body; /* List of statements */
|
|
} PLpgSQL_stmt_loop;
|
|
|
|
/*
|
|
* WHILE cond LOOP statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_while
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
char *label;
|
|
PLpgSQL_expr *cond;
|
|
List *body; /* List of statements */
|
|
} PLpgSQL_stmt_while;
|
|
|
|
/*
|
|
* FOR statement with integer loopvar
|
|
*/
|
|
typedef struct PLpgSQL_stmt_fori
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
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_stmt_dynfors.
|
|
*/
|
|
typedef struct PLpgSQL_stmt_forq
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
char *label;
|
|
PLpgSQL_variable *var; /* Loop variable (record or row) */
|
|
List *body; /* List of statements */
|
|
} PLpgSQL_stmt_forq;
|
|
|
|
/*
|
|
* FOR statement running over SELECT
|
|
*/
|
|
typedef struct PLpgSQL_stmt_fors
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
char *label;
|
|
PLpgSQL_variable *var; /* Loop variable (record or row) */
|
|
List *body; /* List of statements */
|
|
/* end of fields that must match PLpgSQL_stmt_forq */
|
|
PLpgSQL_expr *query;
|
|
} PLpgSQL_stmt_fors;
|
|
|
|
/*
|
|
* FOR statement running over cursor
|
|
*/
|
|
typedef struct PLpgSQL_stmt_forc
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
char *label;
|
|
PLpgSQL_variable *var; /* Loop variable (record or 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;
|
|
|
|
/*
|
|
* FOR statement running over EXECUTE
|
|
*/
|
|
typedef struct PLpgSQL_stmt_dynfors
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
char *label;
|
|
PLpgSQL_variable *var; /* Loop variable (record or 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;
|
|
|
|
/*
|
|
* FOREACH item in array loop
|
|
*/
|
|
typedef struct PLpgSQL_stmt_foreach_a
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
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;
|
|
|
|
/*
|
|
* OPEN a curvar
|
|
*/
|
|
typedef struct PLpgSQL_stmt_open
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
int curvar;
|
|
int cursor_options;
|
|
PLpgSQL_expr *argquery;
|
|
PLpgSQL_expr *query;
|
|
PLpgSQL_expr *dynquery;
|
|
List *params; /* USING expressions */
|
|
} PLpgSQL_stmt_open;
|
|
|
|
/*
|
|
* FETCH or MOVE statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_fetch
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
PLpgSQL_variable *target; /* target (record or 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;
|
|
|
|
/*
|
|
* CLOSE curvar
|
|
*/
|
|
typedef struct PLpgSQL_stmt_close
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
int curvar;
|
|
} PLpgSQL_stmt_close;
|
|
|
|
/*
|
|
* EXIT or CONTINUE statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_exit
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
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;
|
|
|
|
/*
|
|
* RETURN statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_return
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
PLpgSQL_expr *expr;
|
|
int retvarno;
|
|
} PLpgSQL_stmt_return;
|
|
|
|
/*
|
|
* RETURN NEXT statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_return_next
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
PLpgSQL_expr *expr;
|
|
int retvarno;
|
|
} PLpgSQL_stmt_return_next;
|
|
|
|
/*
|
|
* RETURN QUERY statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_return_query
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
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;
|
|
|
|
/*
|
|
* RAISE statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_raise
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
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;
|
|
|
|
/*
|
|
* RAISE statement option
|
|
*/
|
|
typedef struct PLpgSQL_raise_option
|
|
{
|
|
PLpgSQL_raise_option_type opt_type;
|
|
PLpgSQL_expr *expr;
|
|
} PLpgSQL_raise_option;
|
|
|
|
/*
|
|
* ASSERT statement
|
|
*/
|
|
typedef struct PLpgSQL_stmt_assert
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
PLpgSQL_expr *cond;
|
|
PLpgSQL_expr *message;
|
|
} PLpgSQL_stmt_assert;
|
|
|
|
/*
|
|
* Generic SQL statement to execute
|
|
*/
|
|
typedef struct PLpgSQL_stmt_execsql
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
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_variable *target; /* INTO target (record or row) */
|
|
} PLpgSQL_stmt_execsql;
|
|
|
|
/*
|
|
* Dynamic SQL string to execute
|
|
*/
|
|
typedef struct PLpgSQL_stmt_dynexecute
|
|
{
|
|
PLpgSQL_stmt_type cmd_type;
|
|
int lineno;
|
|
unsigned int stmtid;
|
|
PLpgSQL_expr *query; /* string expression */
|
|
bool into; /* INTO supplied? */
|
|
bool strict; /* INTO STRICT flag */
|
|
PLpgSQL_variable *target; /* INTO target (record or row) */
|
|
List *params; /* USING expressions */
|
|
} PLpgSQL_stmt_dynexecute;
|
|
|
|
/*
|
|
* Hash lookup key for functions
|
|
*/
|
|
typedef struct PLpgSQL_func_hashkey
|
|
{
|
|
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 trigger is part of the hash key
|
|
* --- we want to compile the trigger function separately for each trigger
|
|
* it is used with, in case the rowtype or transition table names are
|
|
* different. Zero if not called as a trigger.
|
|
*/
|
|
Oid trigOid;
|
|
|
|
/*
|
|
* 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;
|
|
|
|
/*
|
|
* Trigger type
|
|
*/
|
|
typedef enum PLpgSQL_trigtype
|
|
{
|
|
PLPGSQL_DML_TRIGGER,
|
|
PLPGSQL_EVENT_TRIGGER,
|
|
PLPGSQL_NOT_TRIGGER
|
|
} PLpgSQL_trigtype;
|
|
|
|
/*
|
|
* Complete compiled function
|
|
*/
|
|
typedef struct PLpgSQL_function
|
|
{
|
|
char *fn_signature;
|
|
Oid fn_oid;
|
|
TransactionId fn_xmin;
|
|
ItemPointerData fn_tid;
|
|
PLpgSQL_trigtype 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;
|
|
bool fn_retistuple;
|
|
bool fn_retisdomain;
|
|
bool fn_retset;
|
|
bool fn_readonly;
|
|
char fn_prokind;
|
|
|
|
int fn_nargs;
|
|
int fn_argvarnos[FUNC_MAX_ARGS];
|
|
int out_param_varno;
|
|
int found_varno;
|
|
int new_varno;
|
|
int old_varno;
|
|
|
|
PLpgSQL_resolve_option resolve_option;
|
|
|
|
bool print_strict_params;
|
|
|
|
/* extra checks */
|
|
int extra_warnings;
|
|
int extra_errors;
|
|
|
|
/* count of statements inside function */
|
|
unsigned int nstatements;
|
|
|
|
/* the datums representing the function's local variables */
|
|
int ndatums;
|
|
PLpgSQL_datum **datums;
|
|
Size copiable_size; /* space for locally instantiated datums */
|
|
|
|
/* function body parsetree */
|
|
PLpgSQL_stmt_block *action;
|
|
|
|
/* these fields change when the function is used */
|
|
struct PLpgSQL_execstate *cur_estate;
|
|
unsigned long use_count;
|
|
} PLpgSQL_function;
|
|
|
|
/*
|
|
* Runtime execution data
|
|
*/
|
|
typedef struct PLpgSQL_execstate
|
|
{
|
|
PLpgSQL_function *func; /* function being executed */
|
|
|
|
TriggerData *trigdata; /* if regular trigger, data about firing */
|
|
EventTriggerData *evtrigdata; /* if event trigger, data about firing */
|
|
|
|
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;
|
|
bool atomic;
|
|
|
|
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 */
|
|
TupleDesc tuple_store_desc; /* descriptor for tuples in tuple_store */
|
|
MemoryContext tuple_store_cxt;
|
|
ResourceOwner tuple_store_owner;
|
|
ReturnSetInfo *rsi;
|
|
|
|
int found_varno;
|
|
|
|
/*
|
|
* The datums representing the function's local variables. Some of these
|
|
* are local storage in this execstate, but some just point to the shared
|
|
* copy belonging to the PLpgSQL_function, depending on whether or not we
|
|
* need any per-execution state for the datum's dtype.
|
|
*/
|
|
int ndatums;
|
|
PLpgSQL_datum **datums;
|
|
/* context containing variable values (same as func's SPI_proc context) */
|
|
MemoryContext datum_context;
|
|
|
|
/*
|
|
* paramLI is what we use to pass local variable values to the executor.
|
|
* It does not have a ParamExternData array; we just dynamically
|
|
* instantiate parameter data as needed. By convention, PARAM_EXTERN
|
|
* Params have paramid equal to the dno of the referenced local variable.
|
|
*/
|
|
ParamListInfo paramLI;
|
|
|
|
/* EState to use for "simple" expression evaluation */
|
|
EState *simple_eval_estate;
|
|
|
|
/* lookup table to use for executing type casts */
|
|
HTAB *cast_hash;
|
|
MemoryContext cast_hash_context;
|
|
|
|
/* memory context for statement-lifespan temporary values */
|
|
MemoryContext stmt_mcontext; /* current stmt context, or NULL if none */
|
|
MemoryContext stmt_mcontext_parent; /* parent of current context */
|
|
|
|
/* temporary state for results from evaluation of query or expr */
|
|
SPITupleTable *eval_tuptable;
|
|
uint64 eval_processed;
|
|
ExprContext *eval_econtext; /* for executing simple expressions */
|
|
|
|
/* 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 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);
|
|
} PLpgSQL_plugin;
|
|
|
|
/*
|
|
* Struct types used during parsing
|
|
*/
|
|
|
|
typedef struct PLword
|
|
{
|
|
char *ident; /* palloc'd converted identifier */
|
|
bool quoted; /* Was it double-quoted? */
|
|
} PLword;
|
|
|
|
typedef struct PLcword
|
|
{
|
|
List *idents; /* composite identifiers (list of String) */
|
|
} PLcword;
|
|
|
|
typedef struct PLwdatum
|
|
{
|
|
PLpgSQL_datum *datum; /* referenced variable */
|
|
char *ident; /* valid if simple name */
|
|
bool quoted;
|
|
List *idents; /* valid if composite name */
|
|
} PLwdatum;
|
|
|
|
/**********************************************************************
|
|
* Global variable declarations
|
|
**********************************************************************/
|
|
|
|
typedef enum
|
|
{
|
|
IDENTIFIER_LOOKUP_NORMAL, /* normal processing of var names */
|
|
IDENTIFIER_LOOKUP_DECLARE, /* In DECLARE --- don't look up names */
|
|
IDENTIFIER_LOOKUP_EXPR /* In SQL expression --- special case */
|
|
} IdentifierLookup;
|
|
|
|
extern IdentifierLookup plpgsql_IdentifierLookup;
|
|
|
|
extern int plpgsql_variable_conflict;
|
|
|
|
extern bool plpgsql_print_strict_params;
|
|
|
|
extern bool plpgsql_check_asserts;
|
|
|
|
/* extra compile-time and run-time checks */
|
|
#define PLPGSQL_XCHECK_NONE 0
|
|
#define PLPGSQL_XCHECK_SHADOWVAR (1 << 1)
|
|
#define PLPGSQL_XCHECK_TOOMANYROWS (1 << 2)
|
|
#define PLPGSQL_XCHECK_STRICTMULTIASSIGNMENT (1 << 3)
|
|
#define PLPGSQL_XCHECK_ALL ((int) ~0)
|
|
|
|
extern int plpgsql_extra_warnings;
|
|
extern int plpgsql_extra_errors;
|
|
|
|
extern bool plpgsql_check_syntax;
|
|
extern bool plpgsql_DumpExecTree;
|
|
|
|
extern PLpgSQL_stmt_block *plpgsql_parse_result;
|
|
|
|
extern int plpgsql_nDatums;
|
|
extern PLpgSQL_datum **plpgsql_Datums;
|
|
|
|
extern char *plpgsql_error_funcname;
|
|
|
|
extern PLpgSQL_function *plpgsql_curr_compile;
|
|
extern MemoryContext plpgsql_compile_tmp_cxt;
|
|
|
|
extern PLpgSQL_plugin **plpgsql_plugin_ptr;
|
|
|
|
/**********************************************************************
|
|
* Function declarations
|
|
**********************************************************************/
|
|
|
|
/*
|
|
* Functions in pl_comp.c
|
|
*/
|
|
extern PLpgSQL_function *plpgsql_compile(FunctionCallInfo fcinfo,
|
|
bool forValidator);
|
|
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, bool lookup,
|
|
PLwdatum *wdatum, PLword *word);
|
|
extern bool plpgsql_parse_dblword(char *word1, char *word2,
|
|
PLwdatum *wdatum, PLcword *cword);
|
|
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);
|
|
extern PLpgSQL_rec *plpgsql_build_record(const char *refname, int lineno,
|
|
PLpgSQL_type *dtype, Oid rectypeid,
|
|
bool add2namespace);
|
|
extern PLpgSQL_recfield *plpgsql_build_recfield(PLpgSQL_rec *rec,
|
|
const char *fldname);
|
|
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 *newdatum);
|
|
extern int plpgsql_add_initdatums(int **varnos);
|
|
extern void plpgsql_HashTableInit(void);
|
|
|
|
/*
|
|
* Functions in pl_handler.c
|
|
*/
|
|
extern void _PG_init(void);
|
|
|
|
/*
|
|
* Functions in pl_exec.c
|
|
*/
|
|
extern Datum plpgsql_exec_function(PLpgSQL_function *func,
|
|
FunctionCallInfo fcinfo,
|
|
EState *simple_eval_estate,
|
|
bool atomic);
|
|
extern HeapTuple plpgsql_exec_trigger(PLpgSQL_function *func,
|
|
TriggerData *trigdata);
|
|
extern void plpgsql_exec_event_trigger(PLpgSQL_function *func,
|
|
EventTriggerData *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 plpgsql_exec_get_datum_type(PLpgSQL_execstate *estate,
|
|
PLpgSQL_datum *datum);
|
|
extern void plpgsql_exec_get_datum_type_info(PLpgSQL_execstate *estate,
|
|
PLpgSQL_datum *datum,
|
|
Oid *typeId, int32 *typMod,
|
|
Oid *collation);
|
|
|
|
/*
|
|
* Functions for namespace handling in pl_funcs.c
|
|
*/
|
|
extern void plpgsql_ns_init(void);
|
|
extern void plpgsql_ns_push(const char *label,
|
|
PLpgSQL_label_type label_type);
|
|
extern void plpgsql_ns_pop(void);
|
|
extern PLpgSQL_nsitem *plpgsql_ns_top(void);
|
|
extern void plpgsql_ns_additem(PLpgSQL_nsitem_type 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);
|
|
extern PLpgSQL_nsitem *plpgsql_ns_find_nearest_loop(PLpgSQL_nsitem *ns_cur);
|
|
|
|
/*
|
|
* Other functions in pl_funcs.c
|
|
*/
|
|
extern const char *plpgsql_stmt_typename(PLpgSQL_stmt *stmt);
|
|
extern const char *plpgsql_getdiag_kindname(PLpgSQL_getdiag_kind kind);
|
|
extern void plpgsql_free_function_memory(PLpgSQL_function *func);
|
|
extern void plpgsql_dumptree(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 bool plpgsql_token_is_unreserved_keyword(int token);
|
|
extern void plpgsql_append_source_text(StringInfo buf,
|
|
int startlocation, int endlocation);
|
|
extern int plpgsql_peek(void);
|
|
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) pg_attribute_noreturn();
|
|
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);
|
|
|
|
#endif /* PLPGSQL_H */
|