PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
plpgsql.h File Reference
#include "access/xact.h"
#include "commands/event_trigger.h"
#include "commands/trigger.h"
#include "executor/spi.h"
#include "utils/expandedrecord.h"
#include "utils/typcache.h"
Include dependency graph for plpgsql.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PLpgSQL_type
 
struct  PLpgSQL_expr
 
struct  PLpgSQL_datum
 
struct  PLpgSQL_variable
 
struct  PLpgSQL_var
 
struct  PLpgSQL_row
 
struct  PLpgSQL_rec
 
struct  PLpgSQL_recfield
 
struct  PLpgSQL_nsitem
 
struct  PLpgSQL_stmt
 
struct  PLpgSQL_condition
 
struct  PLpgSQL_exception_block
 
struct  PLpgSQL_exception
 
struct  PLpgSQL_stmt_block
 
struct  PLpgSQL_stmt_assign
 
struct  PLpgSQL_stmt_perform
 
struct  PLpgSQL_stmt_call
 
struct  PLpgSQL_stmt_commit
 
struct  PLpgSQL_stmt_rollback
 
struct  PLpgSQL_diag_item
 
struct  PLpgSQL_stmt_getdiag
 
struct  PLpgSQL_stmt_if
 
struct  PLpgSQL_if_elsif
 
struct  PLpgSQL_stmt_case
 
struct  PLpgSQL_case_when
 
struct  PLpgSQL_stmt_loop
 
struct  PLpgSQL_stmt_while
 
struct  PLpgSQL_stmt_fori
 
struct  PLpgSQL_stmt_forq
 
struct  PLpgSQL_stmt_fors
 
struct  PLpgSQL_stmt_forc
 
struct  PLpgSQL_stmt_dynfors
 
struct  PLpgSQL_stmt_foreach_a
 
struct  PLpgSQL_stmt_open
 
struct  PLpgSQL_stmt_fetch
 
struct  PLpgSQL_stmt_close
 
struct  PLpgSQL_stmt_exit
 
struct  PLpgSQL_stmt_return
 
struct  PLpgSQL_stmt_return_next
 
struct  PLpgSQL_stmt_return_query
 
struct  PLpgSQL_stmt_raise
 
struct  PLpgSQL_raise_option
 
struct  PLpgSQL_stmt_assert
 
struct  PLpgSQL_stmt_execsql
 
struct  PLpgSQL_stmt_dynexecute
 
struct  PLpgSQL_func_hashkey
 
struct  PLpgSQL_function
 
struct  PLpgSQL_execstate
 
struct  PLpgSQL_plugin
 
struct  PLword
 
struct  PLcword
 
struct  PLwdatum
 

Macros

#define TEXTDOMAIN   PG_TEXTDOMAIN("plpgsql")
 
#define _(x)   dgettext(TEXTDOMAIN, x)
 
#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)
 

Typedefs

typedef enum PLpgSQL_nsitem_type PLpgSQL_nsitem_type
 
typedef enum PLpgSQL_label_type PLpgSQL_label_type
 
typedef enum PLpgSQL_datum_type PLpgSQL_datum_type
 
typedef enum PLpgSQL_promise_type PLpgSQL_promise_type
 
typedef enum PLpgSQL_type_type PLpgSQL_type_type
 
typedef enum PLpgSQL_stmt_type PLpgSQL_stmt_type
 
typedef enum PLpgSQL_getdiag_kind PLpgSQL_getdiag_kind
 
typedef enum PLpgSQL_raise_option_type PLpgSQL_raise_option_type
 
typedef enum PLpgSQL_resolve_option PLpgSQL_resolve_option
 
typedef struct PLpgSQL_type PLpgSQL_type
 
typedef struct PLpgSQL_expr PLpgSQL_expr
 
typedef struct PLpgSQL_datum PLpgSQL_datum
 
typedef struct PLpgSQL_variable PLpgSQL_variable
 
typedef struct PLpgSQL_var PLpgSQL_var
 
typedef struct PLpgSQL_row PLpgSQL_row
 
typedef struct PLpgSQL_rec PLpgSQL_rec
 
typedef struct PLpgSQL_recfield PLpgSQL_recfield
 
typedef struct PLpgSQL_nsitem PLpgSQL_nsitem
 
typedef struct PLpgSQL_stmt PLpgSQL_stmt
 
typedef struct PLpgSQL_condition PLpgSQL_condition
 
typedef struct PLpgSQL_exception_block PLpgSQL_exception_block
 
typedef struct PLpgSQL_exception PLpgSQL_exception
 
typedef struct PLpgSQL_stmt_block PLpgSQL_stmt_block
 
typedef struct PLpgSQL_stmt_assign PLpgSQL_stmt_assign
 
typedef struct PLpgSQL_stmt_perform PLpgSQL_stmt_perform
 
typedef struct PLpgSQL_stmt_call PLpgSQL_stmt_call
 
typedef struct PLpgSQL_stmt_commit PLpgSQL_stmt_commit
 
typedef struct PLpgSQL_stmt_rollback PLpgSQL_stmt_rollback
 
typedef struct PLpgSQL_diag_item PLpgSQL_diag_item
 
typedef struct PLpgSQL_stmt_getdiag PLpgSQL_stmt_getdiag
 
typedef struct PLpgSQL_stmt_if PLpgSQL_stmt_if
 
typedef struct PLpgSQL_if_elsif PLpgSQL_if_elsif
 
typedef struct PLpgSQL_stmt_case PLpgSQL_stmt_case
 
typedef struct PLpgSQL_case_when PLpgSQL_case_when
 
typedef struct PLpgSQL_stmt_loop PLpgSQL_stmt_loop
 
typedef struct PLpgSQL_stmt_while PLpgSQL_stmt_while
 
typedef struct PLpgSQL_stmt_fori PLpgSQL_stmt_fori
 
typedef struct PLpgSQL_stmt_forq PLpgSQL_stmt_forq
 
typedef struct PLpgSQL_stmt_fors PLpgSQL_stmt_fors
 
typedef struct PLpgSQL_stmt_forc PLpgSQL_stmt_forc
 
typedef struct PLpgSQL_stmt_dynfors PLpgSQL_stmt_dynfors
 
typedef struct PLpgSQL_stmt_foreach_a PLpgSQL_stmt_foreach_a
 
typedef struct PLpgSQL_stmt_open PLpgSQL_stmt_open
 
typedef struct PLpgSQL_stmt_fetch PLpgSQL_stmt_fetch
 
typedef struct PLpgSQL_stmt_close PLpgSQL_stmt_close
 
typedef struct PLpgSQL_stmt_exit PLpgSQL_stmt_exit
 
typedef struct PLpgSQL_stmt_return PLpgSQL_stmt_return
 
typedef struct PLpgSQL_stmt_return_next PLpgSQL_stmt_return_next
 
typedef struct PLpgSQL_stmt_return_query PLpgSQL_stmt_return_query
 
typedef struct PLpgSQL_stmt_raise PLpgSQL_stmt_raise
 
typedef struct PLpgSQL_raise_option PLpgSQL_raise_option
 
typedef struct PLpgSQL_stmt_assert PLpgSQL_stmt_assert
 
typedef struct PLpgSQL_stmt_execsql PLpgSQL_stmt_execsql
 
typedef struct PLpgSQL_stmt_dynexecute PLpgSQL_stmt_dynexecute
 
typedef struct PLpgSQL_func_hashkey PLpgSQL_func_hashkey
 
typedef enum PLpgSQL_trigtype PLpgSQL_trigtype
 
typedef struct PLpgSQL_function PLpgSQL_function
 
typedef struct PLpgSQL_execstate PLpgSQL_execstate
 
typedef struct PLpgSQL_plugin PLpgSQL_plugin
 
typedef struct PLword PLword
 
typedef struct PLcword PLcword
 
typedef struct PLwdatum PLwdatum
 

Enumerations

enum  PLpgSQL_nsitem_type { PLPGSQL_NSTYPE_LABEL , PLPGSQL_NSTYPE_VAR , PLPGSQL_NSTYPE_REC }
 
enum  PLpgSQL_label_type { PLPGSQL_LABEL_BLOCK , PLPGSQL_LABEL_LOOP , PLPGSQL_LABEL_OTHER }
 
enum  PLpgSQL_datum_type {
  PLPGSQL_DTYPE_VAR , PLPGSQL_DTYPE_ROW , PLPGSQL_DTYPE_REC , PLPGSQL_DTYPE_RECFIELD ,
  PLPGSQL_DTYPE_PROMISE
}
 
enum  PLpgSQL_promise_type {
  PLPGSQL_PROMISE_NONE = 0 , 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
}
 
enum  PLpgSQL_type_type { PLPGSQL_TTYPE_SCALAR , PLPGSQL_TTYPE_REC , PLPGSQL_TTYPE_PSEUDO }
 
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
}
 
enum  { PLPGSQL_RC_OK , PLPGSQL_RC_EXIT , PLPGSQL_RC_RETURN , PLPGSQL_RC_CONTINUE }
 
enum  PLpgSQL_getdiag_kind {
  PLPGSQL_GETDIAG_ROW_COUNT , PLPGSQL_GETDIAG_ROUTINE_OID , 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
}
 
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
}
 
enum  PLpgSQL_resolve_option { PLPGSQL_RESOLVE_ERROR , PLPGSQL_RESOLVE_VARIABLE , PLPGSQL_RESOLVE_COLUMN }
 
enum  PLpgSQL_trigtype { PLPGSQL_DML_TRIGGER , PLPGSQL_EVENT_TRIGGER , PLPGSQL_NOT_TRIGGER }
 
enum  IdentifierLookup { IDENTIFIER_LOOKUP_NORMAL , IDENTIFIER_LOOKUP_DECLARE , IDENTIFIER_LOOKUP_EXPR }
 

Functions

PGDLLEXPORT PLpgSQL_functionplpgsql_compile (FunctionCallInfo fcinfo, bool forValidator)
 
PLpgSQL_functionplpgsql_compile_inline (char *proc_source)
 
PGDLLEXPORT void plpgsql_parser_setup (struct ParseState *pstate, PLpgSQL_expr *expr)
 
bool plpgsql_parse_word (char *word1, const char *yytxt, bool lookup, PLwdatum *wdatum, PLword *word)
 
bool plpgsql_parse_dblword (char *word1, char *word2, PLwdatum *wdatum, PLcword *cword)
 
bool plpgsql_parse_tripword (char *word1, char *word2, char *word3, PLwdatum *wdatum, PLcword *cword)
 
PLpgSQL_typeplpgsql_parse_wordtype (char *ident)
 
PLpgSQL_typeplpgsql_parse_cwordtype (List *idents)
 
PLpgSQL_typeplpgsql_parse_wordrowtype (char *ident)
 
PLpgSQL_typeplpgsql_parse_cwordrowtype (List *idents)
 
PGDLLEXPORT PLpgSQL_typeplpgsql_build_datatype (Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
 
PLpgSQL_typeplpgsql_build_datatype_arrayof (PLpgSQL_type *dtype)
 
PLpgSQL_variableplpgsql_build_variable (const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
 
PLpgSQL_recplpgsql_build_record (const char *refname, int lineno, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
 
PLpgSQL_recfieldplpgsql_build_recfield (PLpgSQL_rec *rec, const char *fldname)
 
PGDLLEXPORT int plpgsql_recognize_err_condition (const char *condname, bool allow_sqlstate)
 
PLpgSQL_conditionplpgsql_parse_err_condition (char *condname)
 
void plpgsql_adddatum (PLpgSQL_datum *newdatum)
 
int plpgsql_add_initdatums (int **varnos)
 
void plpgsql_HashTableInit (void)
 
Datum plpgsql_exec_function (PLpgSQL_function *func, FunctionCallInfo fcinfo, EState *simple_eval_estate, ResourceOwner simple_eval_resowner, ResourceOwner procedure_resowner, bool atomic)
 
HeapTuple plpgsql_exec_trigger (PLpgSQL_function *func, TriggerData *trigdata)
 
void plpgsql_exec_event_trigger (PLpgSQL_function *func, EventTriggerData *trigdata)
 
void plpgsql_xact_cb (XactEvent event, void *arg)
 
void plpgsql_subxact_cb (SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg)
 
PGDLLEXPORT Oid plpgsql_exec_get_datum_type (PLpgSQL_execstate *estate, PLpgSQL_datum *datum)
 
void plpgsql_exec_get_datum_type_info (PLpgSQL_execstate *estate, PLpgSQL_datum *datum, Oid *typeId, int32 *typMod, Oid *collation)
 
void plpgsql_ns_init (void)
 
void plpgsql_ns_push (const char *label, PLpgSQL_label_type label_type)
 
void plpgsql_ns_pop (void)
 
PLpgSQL_nsitemplpgsql_ns_top (void)
 
void plpgsql_ns_additem (PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
 
PGDLLEXPORT PLpgSQL_nsitemplpgsql_ns_lookup (PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
 
PLpgSQL_nsitemplpgsql_ns_lookup_label (PLpgSQL_nsitem *ns_cur, const char *name)
 
PLpgSQL_nsitemplpgsql_ns_find_nearest_loop (PLpgSQL_nsitem *ns_cur)
 
PGDLLEXPORT const char * plpgsql_stmt_typename (PLpgSQL_stmt *stmt)
 
const char * plpgsql_getdiag_kindname (PLpgSQL_getdiag_kind kind)
 
void plpgsql_free_function_memory (PLpgSQL_function *func)
 
void plpgsql_dumptree (PLpgSQL_function *func)
 
int plpgsql_base_yylex (void)
 
int plpgsql_yylex (void)
 
int plpgsql_token_length (void)
 
void plpgsql_push_back_token (int token)
 
bool plpgsql_token_is_unreserved_keyword (int token)
 
void plpgsql_append_source_text (StringInfo buf, int startlocation, int endlocation)
 
int plpgsql_peek (void)
 
void plpgsql_peek2 (int *tok1_p, int *tok2_p, int *tok1_loc, int *tok2_loc)
 
int plpgsql_scanner_errposition (int location)
 
void plpgsql_yyerror (const char *message) pg_attribute_noreturn()
 
int plpgsql_location_to_lineno (int location)
 
int plpgsql_latest_lineno (void)
 
void plpgsql_scanner_init (const char *str)
 
void plpgsql_scanner_finish (void)
 
int plpgsql_yyparse (void)
 

Variables

IdentifierLookup plpgsql_IdentifierLookup
 
int plpgsql_variable_conflict
 
bool plpgsql_print_strict_params
 
bool plpgsql_check_asserts
 
int plpgsql_extra_warnings
 
int plpgsql_extra_errors
 
bool plpgsql_check_syntax
 
bool plpgsql_DumpExecTree
 
PLpgSQL_stmt_blockplpgsql_parse_result
 
int plpgsql_nDatums
 
PLpgSQL_datum ** plpgsql_Datums
 
char * plpgsql_error_funcname
 
PLpgSQL_functionplpgsql_curr_compile
 
MemoryContext plpgsql_compile_tmp_cxt
 
PLpgSQL_plugin ** plpgsql_plugin_ptr
 

Macro Definition Documentation

◆ _

#define _ (   x)    dgettext(TEXTDOMAIN, x)

Definition at line 36 of file plpgsql.h.

◆ PLPGSQL_XCHECK_ALL

#define PLPGSQL_XCHECK_ALL   ((int) ~0)

Definition at line 1207 of file plpgsql.h.

◆ PLPGSQL_XCHECK_NONE

#define PLPGSQL_XCHECK_NONE   0

Definition at line 1203 of file plpgsql.h.

◆ PLPGSQL_XCHECK_SHADOWVAR

#define PLPGSQL_XCHECK_SHADOWVAR   (1 << 1)

Definition at line 1204 of file plpgsql.h.

◆ PLPGSQL_XCHECK_STRICTMULTIASSIGNMENT

#define PLPGSQL_XCHECK_STRICTMULTIASSIGNMENT   (1 << 3)

Definition at line 1206 of file plpgsql.h.

◆ PLPGSQL_XCHECK_TOOMANYROWS

#define PLPGSQL_XCHECK_TOOMANYROWS   (1 << 2)

Definition at line 1205 of file plpgsql.h.

◆ TEXTDOMAIN

#define TEXTDOMAIN   PG_TEXTDOMAIN("plpgsql")

Definition at line 33 of file plpgsql.h.

Typedef Documentation

◆ PLcword

typedef struct PLcword PLcword

◆ PLpgSQL_case_when

◆ PLpgSQL_condition

◆ PLpgSQL_datum

typedef struct PLpgSQL_datum PLpgSQL_datum

◆ PLpgSQL_datum_type

◆ PLpgSQL_diag_item

◆ PLpgSQL_exception

◆ PLpgSQL_exception_block

◆ PLpgSQL_execstate

◆ PLpgSQL_expr

typedef struct PLpgSQL_expr PLpgSQL_expr

◆ PLpgSQL_func_hashkey

◆ PLpgSQL_function

◆ PLpgSQL_getdiag_kind

◆ PLpgSQL_if_elsif

◆ PLpgSQL_label_type

◆ PLpgSQL_nsitem

◆ PLpgSQL_nsitem_type

◆ PLpgSQL_plugin

◆ PLpgSQL_promise_type

◆ PLpgSQL_raise_option

◆ PLpgSQL_raise_option_type

◆ PLpgSQL_rec

typedef struct PLpgSQL_rec PLpgSQL_rec

◆ PLpgSQL_recfield

◆ PLpgSQL_resolve_option

◆ PLpgSQL_row

typedef struct PLpgSQL_row PLpgSQL_row

◆ PLpgSQL_stmt

typedef struct PLpgSQL_stmt PLpgSQL_stmt

◆ PLpgSQL_stmt_assert

◆ PLpgSQL_stmt_assign

◆ PLpgSQL_stmt_block

◆ PLpgSQL_stmt_call

◆ PLpgSQL_stmt_case

◆ PLpgSQL_stmt_close

◆ PLpgSQL_stmt_commit

◆ PLpgSQL_stmt_dynexecute

◆ PLpgSQL_stmt_dynfors

◆ PLpgSQL_stmt_execsql

◆ PLpgSQL_stmt_exit

◆ PLpgSQL_stmt_fetch

◆ PLpgSQL_stmt_forc

◆ PLpgSQL_stmt_foreach_a

◆ PLpgSQL_stmt_fori

◆ PLpgSQL_stmt_forq

◆ PLpgSQL_stmt_fors

◆ PLpgSQL_stmt_getdiag

◆ PLpgSQL_stmt_if

◆ PLpgSQL_stmt_loop

◆ PLpgSQL_stmt_open

◆ PLpgSQL_stmt_perform

◆ PLpgSQL_stmt_raise

◆ PLpgSQL_stmt_return

◆ PLpgSQL_stmt_return_next

◆ PLpgSQL_stmt_return_query

◆ PLpgSQL_stmt_rollback

◆ PLpgSQL_stmt_type

◆ PLpgSQL_stmt_while

◆ PLpgSQL_trigtype

◆ PLpgSQL_type

typedef struct PLpgSQL_type PLpgSQL_type

◆ PLpgSQL_type_type

◆ PLpgSQL_var

typedef struct PLpgSQL_var PLpgSQL_var

◆ PLpgSQL_variable

◆ PLwdatum

typedef struct PLwdatum PLwdatum

◆ PLword

typedef struct PLword PLword

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
PLPGSQL_RC_OK 
PLPGSQL_RC_EXIT 
PLPGSQL_RC_RETURN 
PLPGSQL_RC_CONTINUE 

Definition at line 136 of file plpgsql.h.

137 {
142 };
@ PLPGSQL_RC_RETURN
Definition: plpgsql.h:140
@ PLPGSQL_RC_EXIT
Definition: plpgsql.h:139
@ PLPGSQL_RC_OK
Definition: plpgsql.h:138
@ PLPGSQL_RC_CONTINUE
Definition: plpgsql.h:141

◆ IdentifierLookup

Enumerator
IDENTIFIER_LOOKUP_NORMAL 
IDENTIFIER_LOOKUP_DECLARE 
IDENTIFIER_LOOKUP_EXPR 

Definition at line 1187 of file plpgsql.h.

1188 {
1189  IDENTIFIER_LOOKUP_NORMAL, /* normal processing of var names */
1190  IDENTIFIER_LOOKUP_DECLARE, /* In DECLARE --- don't look up names */
1191  IDENTIFIER_LOOKUP_EXPR, /* In SQL expression --- special case */
IdentifierLookup
Definition: plpgsql.h:1188
@ IDENTIFIER_LOOKUP_DECLARE
Definition: plpgsql.h:1190
@ IDENTIFIER_LOOKUP_NORMAL
Definition: plpgsql.h:1189
@ IDENTIFIER_LOOKUP_EXPR
Definition: plpgsql.h:1191

◆ PLpgSQL_datum_type

Enumerator
PLPGSQL_DTYPE_VAR 
PLPGSQL_DTYPE_ROW 
PLPGSQL_DTYPE_REC 
PLPGSQL_DTYPE_RECFIELD 
PLPGSQL_DTYPE_PROMISE 

Definition at line 61 of file plpgsql.h.

62 {
PLpgSQL_datum_type
Definition: plpgsql.h:62
@ PLPGSQL_DTYPE_ROW
Definition: plpgsql.h:64
@ PLPGSQL_DTYPE_PROMISE
Definition: plpgsql.h:67
@ PLPGSQL_DTYPE_RECFIELD
Definition: plpgsql.h:66
@ PLPGSQL_DTYPE_REC
Definition: plpgsql.h:65
@ PLPGSQL_DTYPE_VAR
Definition: plpgsql.h:63

◆ PLpgSQL_getdiag_kind

Enumerator
PLPGSQL_GETDIAG_ROW_COUNT 
PLPGSQL_GETDIAG_ROUTINE_OID 
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 

Definition at line 147 of file plpgsql.h.

148 {
PLpgSQL_getdiag_kind
Definition: plpgsql.h:148
@ PLPGSQL_GETDIAG_ERROR_DETAIL
Definition: plpgsql.h:153
@ PLPGSQL_GETDIAG_SCHEMA_NAME
Definition: plpgsql.h:161
@ PLPGSQL_GETDIAG_MESSAGE_TEXT
Definition: plpgsql.h:159
@ PLPGSQL_GETDIAG_DATATYPE_NAME
Definition: plpgsql.h:158
@ PLPGSQL_GETDIAG_TABLE_NAME
Definition: plpgsql.h:160
@ PLPGSQL_GETDIAG_CONSTRAINT_NAME
Definition: plpgsql.h:157
@ PLPGSQL_GETDIAG_COLUMN_NAME
Definition: plpgsql.h:156
@ PLPGSQL_GETDIAG_ROW_COUNT
Definition: plpgsql.h:149
@ PLPGSQL_GETDIAG_RETURNED_SQLSTATE
Definition: plpgsql.h:155
@ PLPGSQL_GETDIAG_CONTEXT
Definition: plpgsql.h:151
@ PLPGSQL_GETDIAG_ERROR_HINT
Definition: plpgsql.h:154
@ PLPGSQL_GETDIAG_ERROR_CONTEXT
Definition: plpgsql.h:152
@ PLPGSQL_GETDIAG_ROUTINE_OID
Definition: plpgsql.h:150

◆ PLpgSQL_label_type

Enumerator
PLPGSQL_LABEL_BLOCK 
PLPGSQL_LABEL_LOOP 
PLPGSQL_LABEL_OTHER 

Definition at line 51 of file plpgsql.h.

52 {
53  PLPGSQL_LABEL_BLOCK, /* DECLARE/BEGIN block */
54  PLPGSQL_LABEL_LOOP, /* looping construct */
55  PLPGSQL_LABEL_OTHER, /* anything else */
PLpgSQL_label_type
Definition: plpgsql.h:52
@ PLPGSQL_LABEL_LOOP
Definition: plpgsql.h:54
@ PLPGSQL_LABEL_OTHER
Definition: plpgsql.h:55
@ PLPGSQL_LABEL_BLOCK
Definition: plpgsql.h:53

◆ PLpgSQL_nsitem_type

Enumerator
PLPGSQL_NSTYPE_LABEL 
PLPGSQL_NSTYPE_VAR 
PLPGSQL_NSTYPE_REC 

Definition at line 41 of file plpgsql.h.

42 {
43  PLPGSQL_NSTYPE_LABEL, /* block label */
44  PLPGSQL_NSTYPE_VAR, /* scalar variable */
45  PLPGSQL_NSTYPE_REC, /* composite variable */
PLpgSQL_nsitem_type
Definition: plpgsql.h:42
@ PLPGSQL_NSTYPE_VAR
Definition: plpgsql.h:44
@ PLPGSQL_NSTYPE_REC
Definition: plpgsql.h:45
@ PLPGSQL_NSTYPE_LABEL
Definition: plpgsql.h:43

◆ PLpgSQL_promise_type

Enumerator
PLPGSQL_PROMISE_NONE 
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 

Definition at line 73 of file plpgsql.h.

74 {
75  PLPGSQL_PROMISE_NONE = 0, /* not a promise, or promise satisfied */
PLpgSQL_promise_type
Definition: plpgsql.h:74
@ PLPGSQL_PROMISE_TG_RELID
Definition: plpgsql.h:80
@ PLPGSQL_PROMISE_NONE
Definition: plpgsql.h:75
@ PLPGSQL_PROMISE_TG_WHEN
Definition: plpgsql.h:77
@ PLPGSQL_PROMISE_TG_ARGV
Definition: plpgsql.h:84
@ PLPGSQL_PROMISE_TG_TABLE_SCHEMA
Definition: plpgsql.h:82
@ PLPGSQL_PROMISE_TG_EVENT
Definition: plpgsql.h:85
@ PLPGSQL_PROMISE_TG_TABLE_NAME
Definition: plpgsql.h:81
@ PLPGSQL_PROMISE_TG_TAG
Definition: plpgsql.h:86
@ PLPGSQL_PROMISE_TG_OP
Definition: plpgsql.h:79
@ PLPGSQL_PROMISE_TG_LEVEL
Definition: plpgsql.h:78
@ PLPGSQL_PROMISE_TG_NARGS
Definition: plpgsql.h:83
@ PLPGSQL_PROMISE_TG_NAME
Definition: plpgsql.h:76

◆ PLpgSQL_raise_option_type

Enumerator
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 

Definition at line 167 of file plpgsql.h.

168 {
PLpgSQL_raise_option_type
Definition: plpgsql.h:168
@ PLPGSQL_RAISEOPTION_COLUMN
Definition: plpgsql.h:173
@ PLPGSQL_RAISEOPTION_TABLE
Definition: plpgsql.h:176
@ PLPGSQL_RAISEOPTION_SCHEMA
Definition: plpgsql.h:177
@ PLPGSQL_RAISEOPTION_CONSTRAINT
Definition: plpgsql.h:174
@ PLPGSQL_RAISEOPTION_DETAIL
Definition: plpgsql.h:171
@ PLPGSQL_RAISEOPTION_MESSAGE
Definition: plpgsql.h:170
@ PLPGSQL_RAISEOPTION_HINT
Definition: plpgsql.h:172
@ PLPGSQL_RAISEOPTION_ERRCODE
Definition: plpgsql.h:169
@ PLPGSQL_RAISEOPTION_DATATYPE
Definition: plpgsql.h:175

◆ PLpgSQL_resolve_option

Enumerator
PLPGSQL_RESOLVE_ERROR 
PLPGSQL_RESOLVE_VARIABLE 
PLPGSQL_RESOLVE_COLUMN 

Definition at line 183 of file plpgsql.h.

184 {
185  PLPGSQL_RESOLVE_ERROR, /* throw error if ambiguous */
186  PLPGSQL_RESOLVE_VARIABLE, /* prefer plpgsql var to table column */
187  PLPGSQL_RESOLVE_COLUMN, /* prefer table column to plpgsql var */
PLpgSQL_resolve_option
Definition: plpgsql.h:184
@ PLPGSQL_RESOLVE_COLUMN
Definition: plpgsql.h:187
@ PLPGSQL_RESOLVE_ERROR
Definition: plpgsql.h:185
@ PLPGSQL_RESOLVE_VARIABLE
Definition: plpgsql.h:186

◆ PLpgSQL_stmt_type

Enumerator
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 

Definition at line 102 of file plpgsql.h.

103 {
PLpgSQL_stmt_type
Definition: plpgsql.h:103
@ PLPGSQL_STMT_DYNFORS
Definition: plpgsql.h:122
@ PLPGSQL_STMT_FORI
Definition: plpgsql.h:110
@ PLPGSQL_STMT_FETCH
Definition: plpgsql.h:125
@ PLPGSQL_STMT_CASE
Definition: plpgsql.h:107
@ PLPGSQL_STMT_OPEN
Definition: plpgsql.h:124
@ PLPGSQL_STMT_ROLLBACK
Definition: plpgsql.h:130
@ PLPGSQL_STMT_COMMIT
Definition: plpgsql.h:129
@ PLPGSQL_STMT_RETURN_QUERY
Definition: plpgsql.h:117
@ PLPGSQL_STMT_RETURN
Definition: plpgsql.h:115
@ PLPGSQL_STMT_CLOSE
Definition: plpgsql.h:126
@ PLPGSQL_STMT_WHILE
Definition: plpgsql.h:109
@ PLPGSQL_STMT_BLOCK
Definition: plpgsql.h:104
@ PLPGSQL_STMT_FORS
Definition: plpgsql.h:111
@ PLPGSQL_STMT_FORC
Definition: plpgsql.h:112
@ PLPGSQL_STMT_IF
Definition: plpgsql.h:106
@ PLPGSQL_STMT_PERFORM
Definition: plpgsql.h:127
@ PLPGSQL_STMT_LOOP
Definition: plpgsql.h:108
@ PLPGSQL_STMT_ASSERT
Definition: plpgsql.h:119
@ PLPGSQL_STMT_FOREACH_A
Definition: plpgsql.h:113
@ PLPGSQL_STMT_GETDIAG
Definition: plpgsql.h:123
@ PLPGSQL_STMT_RETURN_NEXT
Definition: plpgsql.h:116
@ PLPGSQL_STMT_ASSIGN
Definition: plpgsql.h:105
@ PLPGSQL_STMT_EXIT
Definition: plpgsql.h:114
@ PLPGSQL_STMT_EXECSQL
Definition: plpgsql.h:120
@ PLPGSQL_STMT_RAISE
Definition: plpgsql.h:118
@ PLPGSQL_STMT_CALL
Definition: plpgsql.h:128
@ PLPGSQL_STMT_DYNEXECUTE
Definition: plpgsql.h:121

◆ PLpgSQL_trigtype

Enumerator
PLPGSQL_DML_TRIGGER 
PLPGSQL_EVENT_TRIGGER 
PLPGSQL_NOT_TRIGGER 

Definition at line 956 of file plpgsql.h.

957 {
PLpgSQL_trigtype
Definition: plpgsql.h:957
@ PLPGSQL_DML_TRIGGER
Definition: plpgsql.h:958
@ PLPGSQL_NOT_TRIGGER
Definition: plpgsql.h:960
@ PLPGSQL_EVENT_TRIGGER
Definition: plpgsql.h:959

◆ PLpgSQL_type_type

Enumerator
PLPGSQL_TTYPE_SCALAR 
PLPGSQL_TTYPE_REC 
PLPGSQL_TTYPE_PSEUDO 

Definition at line 92 of file plpgsql.h.

93 {
94  PLPGSQL_TTYPE_SCALAR, /* scalar types and domains */
95  PLPGSQL_TTYPE_REC, /* composite types, including RECORD */
96  PLPGSQL_TTYPE_PSEUDO, /* pseudotypes */
PLpgSQL_type_type
Definition: plpgsql.h:93
@ PLPGSQL_TTYPE_PSEUDO
Definition: plpgsql.h:96
@ PLPGSQL_TTYPE_REC
Definition: plpgsql.h:95
@ PLPGSQL_TTYPE_SCALAR
Definition: plpgsql.h:94

Function Documentation

◆ plpgsql_add_initdatums()

int plpgsql_add_initdatums ( int **  varnos)

Definition at line 2373 of file pl_comp.c.

2374 {
2375  int i;
2376  int n = 0;
2377 
2378  /*
2379  * The set of dtypes recognized here must match what exec_stmt_block()
2380  * cares about (re)initializing at block entry.
2381  */
2382  for (i = datums_last; i < plpgsql_nDatums; i++)
2383  {
2384  switch (plpgsql_Datums[i]->dtype)
2385  {
2386  case PLPGSQL_DTYPE_VAR:
2387  case PLPGSQL_DTYPE_REC:
2388  n++;
2389  break;
2390 
2391  default:
2392  break;
2393  }
2394  }
2395 
2396  if (varnos != NULL)
2397  {
2398  if (n > 0)
2399  {
2400  *varnos = (int *) palloc(sizeof(int) * n);
2401 
2402  n = 0;
2403  for (i = datums_last; i < plpgsql_nDatums; i++)
2404  {
2405  switch (plpgsql_Datums[i]->dtype)
2406  {
2407  case PLPGSQL_DTYPE_VAR:
2408  case PLPGSQL_DTYPE_REC:
2409  (*varnos)[n++] = plpgsql_Datums[i]->dno;
2410 
2411  default:
2412  break;
2413  }
2414  }
2415  }
2416  else
2417  *varnos = NULL;
2418  }
2419 
2421  return n;
2422 }
int i
Definition: isn.c:72
void * palloc(Size size)
Definition: mcxt.c:1317
PLpgSQL_datum ** plpgsql_Datums
Definition: pl_comp.c:45
static int datums_last
Definition: pl_comp.c:46
int plpgsql_nDatums
Definition: pl_comp.c:44

References datums_last, PLpgSQL_datum::dno, i, palloc(), plpgsql_Datums, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_VAR, and plpgsql_nDatums.

◆ plpgsql_adddatum()

void plpgsql_adddatum ( PLpgSQL_datum newdatum)

Definition at line 2312 of file pl_comp.c.

2313 {
2315  {
2316  datums_alloc *= 2;
2318  }
2319 
2320  newdatum->dno = plpgsql_nDatums;
2321  plpgsql_Datums[plpgsql_nDatums++] = newdatum;
2322 }
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
static int datums_alloc
Definition: pl_comp.c:43

References datums_alloc, PLpgSQL_datum::dno, plpgsql_Datums, plpgsql_nDatums, and repalloc().

Referenced by do_compile(), plpgsql_build_recfield(), plpgsql_build_record(), and plpgsql_build_variable().

◆ plpgsql_append_source_text()

void plpgsql_append_source_text ( StringInfo  buf,
int  startlocation,
int  endlocation 
)

Definition at line 421 of file pl_scanner.c.

423 {
424  Assert(startlocation <= endlocation);
425  appendBinaryStringInfo(buf, scanorig + startlocation,
426  endlocation - startlocation);
427 }
#define Assert(condition)
Definition: c.h:863
static char * buf
Definition: pg_test_fsync.c:72
static const char * scanorig
Definition: pl_scanner.c:110
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:230

References appendBinaryStringInfo(), Assert, buf, and scanorig.

◆ plpgsql_base_yylex()

int plpgsql_base_yylex ( void  )

◆ plpgsql_build_datatype()

PGDLLEXPORT PLpgSQL_type* plpgsql_build_datatype ( Oid  typeOid,
int32  typmod,
Oid  collation,
TypeName origtypname 
)

Definition at line 2043 of file pl_comp.c.

2045 {
2046  HeapTuple typeTup;
2047  PLpgSQL_type *typ;
2048 
2049  typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
2050  if (!HeapTupleIsValid(typeTup))
2051  elog(ERROR, "cache lookup failed for type %u", typeOid);
2052 
2053  typ = build_datatype(typeTup, typmod, collation, origtypname);
2054 
2055  ReleaseSysCache(typeTup);
2056 
2057  return typ;
2058 }
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static PLpgSQL_type * build_datatype(HeapTuple typeTup, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2065
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221

References build_datatype(), elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), and SearchSysCache1().

Referenced by do_compile(), exec_stmt_case(), plpgsql_build_datatype_arrayof(), plpgsql_compile_inline(), plpgsql_parse_cwordrowtype(), and plpgsql_parse_wordrowtype().

◆ plpgsql_build_datatype_arrayof()

PLpgSQL_type* plpgsql_build_datatype_arrayof ( PLpgSQL_type dtype)

Definition at line 2177 of file pl_comp.c.

2178 {
2179  Oid array_typeid;
2180 
2181  /*
2182  * If it's already an array type, use it as-is: Postgres doesn't do nested
2183  * arrays.
2184  */
2185  if (dtype->typisarray)
2186  return dtype;
2187 
2188  array_typeid = get_array_type(dtype->typoid);
2189  if (!OidIsValid(array_typeid))
2190  ereport(ERROR,
2191  (errcode(ERRCODE_UNDEFINED_OBJECT),
2192  errmsg("could not find array type for data type %s",
2193  format_type_be(dtype->typoid))));
2194 
2195  /* Note we inherit typmod and collation, if any, from the element type */
2196  return plpgsql_build_datatype(array_typeid, dtype->atttypmod,
2197  dtype->collation, NULL);
2198 }
#define OidIsValid(objectId)
Definition: c.h:780
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereport(elevel,...)
Definition: elog.h:149
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
Oid get_array_type(Oid typid)
Definition: lsyscache.c:2787
PLpgSQL_type * plpgsql_build_datatype(Oid typeOid, int32 typmod, Oid collation, TypeName *origtypname)
Definition: pl_comp.c:2043
unsigned int Oid
Definition: postgres_ext.h:31
bool typisarray
Definition: plpgsql.h:207
Oid collation
Definition: plpgsql.h:206
Oid typoid
Definition: plpgsql.h:201
int32 atttypmod
Definition: plpgsql.h:208

References PLpgSQL_type::atttypmod, PLpgSQL_type::collation, ereport, errcode(), errmsg(), ERROR, format_type_be(), get_array_type(), OidIsValid, plpgsql_build_datatype(), PLpgSQL_type::typisarray, and PLpgSQL_type::typoid.

◆ plpgsql_build_recfield()

PLpgSQL_recfield* plpgsql_build_recfield ( PLpgSQL_rec rec,
const char *  fldname 
)

Definition at line 1996 of file pl_comp.c.

1997 {
1998  PLpgSQL_recfield *recfield;
1999  int i;
2000 
2001  /* search for an existing datum referencing this field */
2002  i = rec->firstfield;
2003  while (i >= 0)
2004  {
2006 
2008  fld->recparentno == rec->dno);
2009  if (strcmp(fld->fieldname, fldname) == 0)
2010  return fld;
2011  i = fld->nextfield;
2012  }
2013 
2014  /* nope, so make a new one */
2015  recfield = palloc0(sizeof(PLpgSQL_recfield));
2016  recfield->dtype = PLPGSQL_DTYPE_RECFIELD;
2017  recfield->fieldname = pstrdup(fldname);
2018  recfield->recparentno = rec->dno;
2020 
2021  plpgsql_adddatum((PLpgSQL_datum *) recfield);
2022 
2023  /* now we can link it into the parent's chain */
2024  recfield->nextfield = rec->firstfield;
2025  rec->firstfield = recfield->dno;
2026 
2027  return recfield;
2028 }
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void * palloc0(Size size)
Definition: mcxt.c:1347
void plpgsql_adddatum(PLpgSQL_datum *newdatum)
Definition: pl_comp.c:2312
int firstfield
Definition: plpgsql.h:409
uint64 rectupledescid
Definition: plpgsql.h:429
PLpgSQL_datum_type dtype
Definition: plpgsql.h:422
char * fieldname
Definition: plpgsql.h:426
#define INVALID_TUPLEDESC_IDENTIFIER
Definition: typcache.h:156

References Assert, PLpgSQL_rec::dno, PLpgSQL_recfield::dno, PLpgSQL_recfield::dtype, PLpgSQL_recfield::fieldname, PLpgSQL_rec::firstfield, i, INVALID_TUPLEDESC_IDENTIFIER, PLpgSQL_recfield::nextfield, palloc0(), plpgsql_adddatum(), plpgsql_Datums, PLPGSQL_DTYPE_RECFIELD, pstrdup(), PLpgSQL_recfield::recparentno, and PLpgSQL_recfield::rectupledescid.

Referenced by plpgsql_parse_dblword(), and plpgsql_parse_tripword().

◆ plpgsql_build_record()

PLpgSQL_rec* plpgsql_build_record ( const char *  refname,
int  lineno,
PLpgSQL_type dtype,
Oid  rectypeid,
bool  add2namespace 
)

Definition at line 1902 of file pl_comp.c.

1905 {
1906  PLpgSQL_rec *rec;
1907 
1908  rec = palloc0(sizeof(PLpgSQL_rec));
1909  rec->dtype = PLPGSQL_DTYPE_REC;
1910  rec->refname = pstrdup(refname);
1911  rec->lineno = lineno;
1912  /* other fields are left as 0, might be changed by caller */
1913  rec->datatype = dtype;
1914  rec->rectypeid = rectypeid;
1915  rec->firstfield = -1;
1916  rec->erh = NULL;
1918  if (add2namespace)
1920 
1921  return rec;
1922 }
void plpgsql_ns_additem(PLpgSQL_nsitem_type itemtype, int itemno, const char *name)
Definition: pl_funcs.c:92
ExpandedRecordHeader * erh
Definition: plpgsql.h:414
PLpgSQL_type * datatype
Definition: plpgsql.h:406
PLpgSQL_datum_type dtype
Definition: plpgsql.h:391
Oid rectypeid
Definition: plpgsql.h:407
int lineno
Definition: plpgsql.h:394
char * refname
Definition: plpgsql.h:393

References PLpgSQL_rec::datatype, PLpgSQL_rec::dno, PLpgSQL_rec::dtype, PLpgSQL_rec::erh, PLpgSQL_rec::firstfield, PLpgSQL_rec::lineno, palloc0(), plpgsql_adddatum(), PLPGSQL_DTYPE_REC, plpgsql_ns_additem(), PLPGSQL_NSTYPE_REC, pstrdup(), PLpgSQL_rec::rectypeid, and PLpgSQL_rec::refname.

Referenced by do_compile(), and plpgsql_build_variable().

◆ plpgsql_build_variable()

PLpgSQL_variable* plpgsql_build_variable ( const char *  refname,
int  lineno,
PLpgSQL_type dtype,
bool  add2namespace 
)

Definition at line 1839 of file pl_comp.c.

1841 {
1842  PLpgSQL_variable *result;
1843 
1844  switch (dtype->ttype)
1845  {
1846  case PLPGSQL_TTYPE_SCALAR:
1847  {
1848  /* Ordinary scalar datatype */
1849  PLpgSQL_var *var;
1850 
1851  var = palloc0(sizeof(PLpgSQL_var));
1852  var->dtype = PLPGSQL_DTYPE_VAR;
1853  var->refname = pstrdup(refname);
1854  var->lineno = lineno;
1855  var->datatype = dtype;
1856  /* other fields are left as 0, might be changed by caller */
1857 
1858  /* preset to NULL */
1859  var->value = 0;
1860  var->isnull = true;
1861  var->freeval = false;
1862 
1864  if (add2namespace)
1866  var->dno,
1867  refname);
1868  result = (PLpgSQL_variable *) var;
1869  break;
1870  }
1871  case PLPGSQL_TTYPE_REC:
1872  {
1873  /* Composite type -- build a record variable */
1874  PLpgSQL_rec *rec;
1875 
1876  rec = plpgsql_build_record(refname, lineno,
1877  dtype, dtype->typoid,
1878  add2namespace);
1879  result = (PLpgSQL_variable *) rec;
1880  break;
1881  }
1882  case PLPGSQL_TTYPE_PSEUDO:
1883  ereport(ERROR,
1884  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1885  errmsg("variable \"%s\" has pseudo-type %s",
1886  refname, format_type_be(dtype->typoid))));
1887  result = NULL; /* keep compiler quiet */
1888  break;
1889  default:
1890  elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
1891  result = NULL; /* keep compiler quiet */
1892  break;
1893  }
1894 
1895  return result;
1896 }
PLpgSQL_rec * plpgsql_build_record(const char *refname, int lineno, PLpgSQL_type *dtype, Oid rectypeid, bool add2namespace)
Definition: pl_comp.c:1902
PLpgSQL_type_type ttype
Definition: plpgsql.h:202
int lineno
Definition: plpgsql.h:314
PLpgSQL_datum_type dtype
Definition: plpgsql.h:311
bool freeval
Definition: plpgsql.h:335
bool isnull
Definition: plpgsql.h:334
PLpgSQL_type * datatype
Definition: plpgsql.h:320
char * refname
Definition: plpgsql.h:313
Datum value
Definition: plpgsql.h:333

References PLpgSQL_var::datatype, PLpgSQL_var::dno, PLpgSQL_var::dtype, elog, ereport, errcode(), errmsg(), ERROR, format_type_be(), PLpgSQL_var::freeval, PLpgSQL_var::isnull, PLpgSQL_var::lineno, palloc0(), plpgsql_adddatum(), plpgsql_build_record(), PLPGSQL_DTYPE_VAR, plpgsql_ns_additem(), PLPGSQL_NSTYPE_VAR, PLPGSQL_TTYPE_PSEUDO, PLPGSQL_TTYPE_REC, PLPGSQL_TTYPE_SCALAR, pstrdup(), PLpgSQL_var::refname, PLpgSQL_type::ttype, PLpgSQL_type::typoid, and PLpgSQL_var::value.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_compile()

PGDLLEXPORT PLpgSQL_function* plpgsql_compile ( FunctionCallInfo  fcinfo,
bool  forValidator 
)

Definition at line 135 of file pl_comp.c.

136 {
137  Oid funcOid = fcinfo->flinfo->fn_oid;
138  HeapTuple procTup;
139  Form_pg_proc procStruct;
140  PLpgSQL_function *function;
141  PLpgSQL_func_hashkey hashkey;
142  bool function_valid = false;
143  bool hashkey_valid = false;
144 
145  /*
146  * Lookup the pg_proc tuple by Oid; we'll need it in any case
147  */
148  procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid));
149  if (!HeapTupleIsValid(procTup))
150  elog(ERROR, "cache lookup failed for function %u", funcOid);
151  procStruct = (Form_pg_proc) GETSTRUCT(procTup);
152 
153  /*
154  * See if there's already a cache entry for the current FmgrInfo. If not,
155  * try to find one in the hash table.
156  */
157  function = (PLpgSQL_function *) fcinfo->flinfo->fn_extra;
158 
159 recheck:
160  if (!function)
161  {
162  /* Compute hashkey using function signature and actual arg types */
163  compute_function_hashkey(fcinfo, procStruct, &hashkey, forValidator);
164  hashkey_valid = true;
165 
166  /* And do the lookup */
167  function = plpgsql_HashTableLookup(&hashkey);
168  }
169 
170  if (function)
171  {
172  /* We have a compiled function, but is it still valid? */
173  if (function->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) &&
174  ItemPointerEquals(&function->fn_tid, &procTup->t_self))
175  function_valid = true;
176  else
177  {
178  /*
179  * Nope, so remove it from hashtable and try to drop associated
180  * storage (if not done already).
181  */
182  delete_function(function);
183 
184  /*
185  * If the function isn't in active use then we can overwrite the
186  * func struct with new data, allowing any other existing fn_extra
187  * pointers to make use of the new definition on their next use.
188  * If it is in use then just leave it alone and make a new one.
189  * (The active invocations will run to completion using the
190  * previous definition, and then the cache entry will just be
191  * leaked; doesn't seem worth adding code to clean it up, given
192  * what a corner case this is.)
193  *
194  * If we found the function struct via fn_extra then it's possible
195  * a replacement has already been made, so go back and recheck the
196  * hashtable.
197  */
198  if (function->use_count != 0)
199  {
200  function = NULL;
201  if (!hashkey_valid)
202  goto recheck;
203  }
204  }
205  }
206 
207  /*
208  * If the function wasn't found or was out-of-date, we have to compile it
209  */
210  if (!function_valid)
211  {
212  /*
213  * Calculate hashkey if we didn't already; we'll need it to store the
214  * completed function.
215  */
216  if (!hashkey_valid)
217  compute_function_hashkey(fcinfo, procStruct, &hashkey,
218  forValidator);
219 
220  /*
221  * Do the hard part.
222  */
223  function = do_compile(fcinfo, procTup, function,
224  &hashkey, forValidator);
225  }
226 
227  ReleaseSysCache(procTup);
228 
229  /*
230  * Save pointer in FmgrInfo to avoid search on subsequent calls
231  */
232  fcinfo->flinfo->fn_extra = (void *) function;
233 
234  /*
235  * Finally return the compiled function
236  */
237  return function;
238 }
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:304
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:35
on_exit_nicely_callback function
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
static void compute_function_hashkey(FunctionCallInfo fcinfo, Form_pg_proc procStruct, PLpgSQL_func_hashkey *hashkey, bool forValidator)
Definition: pl_comp.c:2431
static PLpgSQL_function * plpgsql_HashTableLookup(PLpgSQL_func_hashkey *func_key)
Definition: pl_comp.c:2610
static PLpgSQL_function * do_compile(FunctionCallInfo fcinfo, HeapTuple procTup, PLpgSQL_function *function, PLpgSQL_func_hashkey *hashkey, bool forValidator)
Definition: pl_comp.c:263
static void delete_function(PLpgSQL_function *func)
Definition: pl_comp.c:2582
void * fn_extra
Definition: fmgr.h:64
Oid fn_oid
Definition: fmgr.h:59
FmgrInfo * flinfo
Definition: fmgr.h:87
ItemPointerData t_self
Definition: htup.h:65
HeapTupleHeader t_data
Definition: htup.h:68

References compute_function_hashkey(), delete_function(), do_compile(), elog, ERROR, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_extra, FmgrInfo::fn_oid, function, GETSTRUCT, HeapTupleHeaderGetRawXmin, HeapTupleIsValid, if(), ItemPointerEquals(), ObjectIdGetDatum(), plpgsql_HashTableLookup(), ReleaseSysCache(), SearchSysCache1(), HeapTupleData::t_data, and HeapTupleData::t_self.

Referenced by plpgsql_call_handler(), and plpgsql_validator().

◆ plpgsql_compile_inline()

PLpgSQL_function* plpgsql_compile_inline ( char *  proc_source)

Definition at line 842 of file pl_comp.c.

843 {
844  char *func_name = "inline_code_block";
845  PLpgSQL_function *function;
846  ErrorContextCallback plerrcontext;
847  PLpgSQL_variable *var;
848  int parse_rc;
849  MemoryContext func_cxt;
850 
851  /*
852  * Setup the scanner input and error info. We assume that this function
853  * cannot be invoked recursively, so there's no need to save and restore
854  * the static variables used here.
855  */
856  plpgsql_scanner_init(proc_source);
857 
858  plpgsql_error_funcname = func_name;
859 
860  /*
861  * Setup error traceback support for ereport()
862  */
864  plerrcontext.arg = proc_source;
865  plerrcontext.previous = error_context_stack;
866  error_context_stack = &plerrcontext;
867 
868  /* Do extra syntax checking if check_function_bodies is on */
870 
871  /* Function struct does not live past current statement */
872  function = (PLpgSQL_function *) palloc0(sizeof(PLpgSQL_function));
873 
874  plpgsql_curr_compile = function;
875 
876  /*
877  * All the rest of the compile-time storage (e.g. parse tree) is kept in
878  * its own memory context, so it can be reclaimed easily.
879  */
881  "PL/pgSQL inline code context",
884 
885  function->fn_signature = pstrdup(func_name);
886  function->fn_is_trigger = PLPGSQL_NOT_TRIGGER;
887  function->fn_input_collation = InvalidOid;
888  function->fn_cxt = func_cxt;
889  function->out_param_varno = -1; /* set up for no OUT param */
890  function->resolve_option = plpgsql_variable_conflict;
891  function->print_strict_params = plpgsql_print_strict_params;
892 
893  /*
894  * don't do extra validation for inline code as we don't want to add spam
895  * at runtime
896  */
897  function->extra_warnings = 0;
898  function->extra_errors = 0;
899 
900  function->nstatements = 0;
901  function->requires_procedure_resowner = false;
902 
903  plpgsql_ns_init();
905  plpgsql_DumpExecTree = false;
907 
908  /* Set up as though in a function returning VOID */
909  function->fn_rettype = VOIDOID;
910  function->fn_retset = false;
911  function->fn_retistuple = false;
912  function->fn_retisdomain = false;
913  function->fn_prokind = PROKIND_FUNCTION;
914  /* a bit of hardwired knowledge about type VOID here */
915  function->fn_retbyval = true;
916  function->fn_rettyplen = sizeof(int32);
917 
918  /*
919  * Remember if function is STABLE/IMMUTABLE. XXX would it be better to
920  * set this true inside a read-only transaction? Not clear.
921  */
922  function->fn_readonly = false;
923 
924  /*
925  * Create the magic FOUND variable.
926  */
927  var = plpgsql_build_variable("found", 0,
928  plpgsql_build_datatype(BOOLOID,
929  -1,
930  InvalidOid,
931  NULL),
932  true);
933  function->found_varno = var->dno;
934 
935  /*
936  * Now parse the function's text
937  */
938  parse_rc = plpgsql_yyparse();
939  if (parse_rc != 0)
940  elog(ERROR, "plpgsql parser returned %d", parse_rc);
941  function->action = plpgsql_parse_result;
942 
944 
945  /*
946  * If it returns VOID (always true at the moment), we allow control to
947  * fall off the end without an explicit RETURN statement.
948  */
949  if (function->fn_rettype == VOIDOID)
950  add_dummy_return(function);
951 
952  /*
953  * Complete the function's info
954  */
955  function->fn_nargs = 0;
956 
957  plpgsql_finish_datums(function);
958 
959  /*
960  * Pop the error context stack
961  */
962  error_context_stack = plerrcontext.previous;
963  plpgsql_error_funcname = NULL;
964 
965  plpgsql_check_syntax = false;
966 
969  return function;
970 }
signed int int32
Definition: c.h:508
ErrorContextCallback * error_context_stack
Definition: elog.c:94
bool check_function_bodies
Definition: guc_tables.c:511
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
static void add_dummy_return(PLpgSQL_function *function)
Definition: pl_comp.c:1031
MemoryContext plpgsql_compile_tmp_cxt
Definition: pl_comp.c:55
static void plpgsql_compile_error_callback(void *arg)
Definition: pl_comp.c:979
PLpgSQL_variable * plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype, bool add2namespace)
Definition: pl_comp.c:1839
static void plpgsql_start_datums(void)
Definition: pl_comp.c:2295
char * plpgsql_error_funcname
Definition: pl_comp.c:48
PLpgSQL_stmt_block * plpgsql_parse_result
Definition: pl_comp.c:41
bool plpgsql_check_syntax
Definition: pl_comp.c:50
static void plpgsql_finish_datums(PLpgSQL_function *function)
Definition: pl_comp.c:2329
PLpgSQL_function * plpgsql_curr_compile
Definition: pl_comp.c:52
bool plpgsql_DumpExecTree
Definition: pl_comp.c:49
void plpgsql_ns_init(void)
Definition: pl_funcs.c:43
void plpgsql_ns_push(const char *label, PLpgSQL_label_type label_type)
Definition: pl_funcs.c:54
int plpgsql_variable_conflict
Definition: pl_handler.c:44
bool plpgsql_print_strict_params
Definition: pl_handler.c:46
void plpgsql_scanner_finish(void)
Definition: pl_scanner.c:630
void plpgsql_scanner_init(const char *str)
Definition: pl_scanner.c:603
int plpgsql_yyparse(void)
#define InvalidOid
Definition: postgres_ext.h:36
MemoryContextSwitchTo(old_ctx)
struct ErrorContextCallback * previous
Definition: elog.h:296
void(* callback)(void *arg)
Definition: elog.h:297

References add_dummy_return(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, ErrorContextCallback::arg, ErrorContextCallback::callback, check_function_bodies, CurrentMemoryContext, PLpgSQL_variable::dno, elog, ERROR, error_context_stack, function, InvalidOid, MemoryContextSwitchTo(), palloc0(), plpgsql_build_datatype(), plpgsql_build_variable(), plpgsql_check_syntax, plpgsql_compile_error_callback(), plpgsql_compile_tmp_cxt, plpgsql_curr_compile, plpgsql_DumpExecTree, plpgsql_error_funcname, plpgsql_finish_datums(), PLPGSQL_LABEL_BLOCK, PLPGSQL_NOT_TRIGGER, plpgsql_ns_init(), plpgsql_ns_push(), plpgsql_parse_result, plpgsql_print_strict_params, plpgsql_scanner_finish(), plpgsql_scanner_init(), plpgsql_start_datums(), plpgsql_variable_conflict, plpgsql_yyparse(), ErrorContextCallback::previous, and pstrdup().

Referenced by plpgsql_inline_handler().

◆ plpgsql_dumptree()

void plpgsql_dumptree ( PLpgSQL_function func)

Definition at line 1600 of file pl_funcs.c.

1601 {
1602  int i;
1603  PLpgSQL_datum *d;
1604 
1605  printf("\nExecution tree of successfully compiled PL/pgSQL function %s:\n",
1606  func->fn_signature);
1607 
1608  printf("\nFunction's data area:\n");
1609  for (i = 0; i < func->ndatums; i++)
1610  {
1611  d = func->datums[i];
1612 
1613  printf(" entry %d: ", i);
1614  switch (d->dtype)
1615  {
1616  case PLPGSQL_DTYPE_VAR:
1617  case PLPGSQL_DTYPE_PROMISE:
1618  {
1619  PLpgSQL_var *var = (PLpgSQL_var *) d;
1620 
1621  printf("VAR %-16s type %s (typoid %u) atttypmod %d\n",
1622  var->refname, var->datatype->typname,
1623  var->datatype->typoid,
1624  var->datatype->atttypmod);
1625  if (var->isconst)
1626  printf(" CONSTANT\n");
1627  if (var->notnull)
1628  printf(" NOT NULL\n");
1629  if (var->default_val != NULL)
1630  {
1631  printf(" DEFAULT ");
1632  dump_expr(var->default_val);
1633  printf("\n");
1634  }
1635  if (var->cursor_explicit_expr != NULL)
1636  {
1637  if (var->cursor_explicit_argrow >= 0)
1638  printf(" CURSOR argument row %d\n", var->cursor_explicit_argrow);
1639 
1640  printf(" CURSOR IS ");
1642  printf("\n");
1643  }
1644  if (var->promise != PLPGSQL_PROMISE_NONE)
1645  printf(" PROMISE %d\n",
1646  (int) var->promise);
1647  }
1648  break;
1649  case PLPGSQL_DTYPE_ROW:
1650  {
1651  PLpgSQL_row *row = (PLpgSQL_row *) d;
1652 
1653  printf("ROW %-16s fields", row->refname);
1654  for (int j = 0; j < row->nfields; j++)
1655  {
1656  printf(" %s=var %d", row->fieldnames[j],
1657  row->varnos[j]);
1658  }
1659  printf("\n");
1660  }
1661  break;
1662  case PLPGSQL_DTYPE_REC:
1663  printf("REC %-16s typoid %u\n",
1664  ((PLpgSQL_rec *) d)->refname,
1665  ((PLpgSQL_rec *) d)->rectypeid);
1666  if (((PLpgSQL_rec *) d)->isconst)
1667  printf(" CONSTANT\n");
1668  if (((PLpgSQL_rec *) d)->notnull)
1669  printf(" NOT NULL\n");
1670  if (((PLpgSQL_rec *) d)->default_val != NULL)
1671  {
1672  printf(" DEFAULT ");
1673  dump_expr(((PLpgSQL_rec *) d)->default_val);
1674  printf("\n");
1675  }
1676  break;
1678  printf("RECFIELD %-16s of REC %d\n",
1679  ((PLpgSQL_recfield *) d)->fieldname,
1680  ((PLpgSQL_recfield *) d)->recparentno);
1681  break;
1682  default:
1683  printf("??? unknown data type %d\n", d->dtype);
1684  }
1685  }
1686  printf("\nFunction's statements:\n");
1687 
1688  dump_indent = 0;
1689  printf("%3d:", func->action->lineno);
1690  dump_block(func->action);
1691  printf("\nEnd of execution tree of function %s\n\n", func->fn_signature);
1692  fflush(stdout);
1693 }
int j
Definition: isn.c:73
static void const char fflush(stdout)
static int dump_indent
Definition: pl_funcs.c:786
static void dump_expr(PLpgSQL_expr *expr)
Definition: pl_funcs.c:1594
static void dump_block(PLpgSQL_stmt_block *block)
Definition: pl_funcs.c:935
#define printf(...)
Definition: port.h:244
PLpgSQL_datum_type dtype
Definition: plpgsql.h:277
PLpgSQL_stmt_block * action
Definition: plpgsql.h:1007
PLpgSQL_datum ** datums
Definition: plpgsql.h:1003
char * fn_signature
Definition: plpgsql.h:968
int * varnos
Definition: plpgsql.h:383
char * refname
Definition: plpgsql.h:367
char ** fieldnames
Definition: plpgsql.h:382
int nfields
Definition: plpgsql.h:381
char * typname
Definition: plpgsql.h:200
PLpgSQL_promise_type promise
Definition: plpgsql.h:342
int cursor_explicit_argrow
Definition: plpgsql.h:328
bool notnull
Definition: plpgsql.h:316
bool isconst
Definition: plpgsql.h:315
PLpgSQL_expr * cursor_explicit_expr
Definition: plpgsql.h:327
PLpgSQL_expr * default_val
Definition: plpgsql.h:317

References PLpgSQL_function::action, PLpgSQL_type::atttypmod, PLpgSQL_var::cursor_explicit_argrow, PLpgSQL_var::cursor_explicit_expr, PLpgSQL_var::datatype, PLpgSQL_function::datums, PLpgSQL_var::default_val, PLpgSQL_datum::dtype, PLpgSQL_rec::dtype, dump_block(), dump_expr(), dump_indent, fflush(), PLpgSQL_row::fieldnames, PLpgSQL_function::fn_signature, i, PLpgSQL_var::isconst, j, PLpgSQL_stmt_block::lineno, PLpgSQL_function::ndatums, PLpgSQL_row::nfields, PLpgSQL_var::notnull, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_ROW, PLPGSQL_DTYPE_VAR, PLPGSQL_PROMISE_NONE, printf, PLpgSQL_var::promise, PLpgSQL_var::refname, PLpgSQL_row::refname, generate_unaccent_rules::stdout, PLpgSQL_type::typname, PLpgSQL_type::typoid, and PLpgSQL_row::varnos.

Referenced by do_compile().

◆ plpgsql_exec_event_trigger()

void plpgsql_exec_event_trigger ( PLpgSQL_function func,
EventTriggerData trigdata 
)

Definition at line 1159 of file pl_exec.c.

1160 {
1161  PLpgSQL_execstate estate;
1162  ErrorContextCallback plerrcontext;
1163  int rc;
1164 
1165  /*
1166  * Setup the execution state
1167  */
1168  plpgsql_estate_setup(&estate, func, NULL, NULL, NULL);
1169  estate.evtrigdata = trigdata;
1170 
1171  /*
1172  * Setup error traceback support for ereport()
1173  */
1174  plerrcontext.callback = plpgsql_exec_error_callback;
1175  plerrcontext.arg = &estate;
1176  plerrcontext.previous = error_context_stack;
1177  error_context_stack = &plerrcontext;
1178 
1179  /*
1180  * Make local execution copies of all the datums
1181  */
1182  estate.err_text = gettext_noop("during initialization of execution state");
1183  copy_plpgsql_datums(&estate, func);
1184 
1185  /*
1186  * Let the instrumentation plugin peek at this function
1187  */
1188  if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
1189  ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
1190 
1191  /*
1192  * Now call the toplevel block of statements
1193  */
1194  estate.err_text = NULL;
1195  rc = exec_toplevel_block(&estate, func->action);
1196  if (rc != PLPGSQL_RC_RETURN)
1197  {
1198  estate.err_text = NULL;
1199  ereport(ERROR,
1200  (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
1201  errmsg("control reached end of trigger procedure without RETURN")));
1202  }
1203 
1204  estate.err_text = gettext_noop("during function exit");
1205 
1206  /*
1207  * Let the instrumentation plugin peek at this function
1208  */
1209  if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
1210  ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
1211 
1212  /* Clean up any leftover temporary memory */
1213  plpgsql_destroy_econtext(&estate);
1214  exec_eval_cleanup(&estate);
1215  /* stmt_mcontext will be destroyed when function's main context is */
1216 
1217  /*
1218  * Pop the error context stack
1219  */
1220  error_context_stack = plerrcontext.previous;
1221 }
#define gettext_noop(x)
Definition: c.h:1201
static void exec_eval_cleanup(PLpgSQL_execstate *estate)
Definition: pl_exec.c:4134
static void plpgsql_exec_error_callback(void *arg)
Definition: pl_exec.c:1227
static void plpgsql_estate_setup(PLpgSQL_execstate *estate, PLpgSQL_function *func, ReturnSetInfo *rsi, EState *simple_eval_estate, ResourceOwner simple_eval_resowner)
Definition: pl_exec.c:3977
static int exec_toplevel_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
Definition: pl_exec.c:1618
static void plpgsql_destroy_econtext(PLpgSQL_execstate *estate)
Definition: pl_exec.c:8460
static void copy_plpgsql_datums(PLpgSQL_execstate *estate, PLpgSQL_function *func)
Definition: pl_exec.c:1294
PLpgSQL_plugin ** plpgsql_plugin_ptr
Definition: pl_handler.c:56
const char * err_text
Definition: plpgsql.h:1092
EventTriggerData * evtrigdata
Definition: plpgsql.h:1026
void(* func_beg)(PLpgSQL_execstate *estate, PLpgSQL_function *func)
Definition: plpgsql.h:1137
void(* func_end)(PLpgSQL_execstate *estate, PLpgSQL_function *func)
Definition: plpgsql.h:1138

References PLpgSQL_function::action, ErrorContextCallback::arg, ErrorContextCallback::callback, copy_plpgsql_datums(), ereport, PLpgSQL_execstate::err_text, errcode(), errmsg(), ERROR, error_context_stack, PLpgSQL_execstate::evtrigdata, exec_eval_cleanup(), exec_toplevel_block(), PLpgSQL_plugin::func_beg, PLpgSQL_plugin::func_end, gettext_noop, plpgsql_destroy_econtext(), plpgsql_estate_setup(), plpgsql_exec_error_callback(), plpgsql_plugin_ptr, PLPGSQL_RC_RETURN, and ErrorContextCallback::previous.

Referenced by plpgsql_call_handler().

◆ plpgsql_exec_function()

Datum plpgsql_exec_function ( PLpgSQL_function func,
FunctionCallInfo  fcinfo,
EState simple_eval_estate,
ResourceOwner  simple_eval_resowner,
ResourceOwner  procedure_resowner,
bool  atomic 
)

Definition at line 477 of file pl_exec.c.

482 {
483  PLpgSQL_execstate estate;
484  ErrorContextCallback plerrcontext;
485  int i;
486  int rc;
487 
488  /*
489  * Setup the execution state
490  */
491  plpgsql_estate_setup(&estate, func, (ReturnSetInfo *) fcinfo->resultinfo,
492  simple_eval_estate, simple_eval_resowner);
493  estate.procedure_resowner = procedure_resowner;
494  estate.atomic = atomic;
495 
496  /*
497  * Setup error traceback support for ereport()
498  */
499  plerrcontext.callback = plpgsql_exec_error_callback;
500  plerrcontext.arg = &estate;
501  plerrcontext.previous = error_context_stack;
502  error_context_stack = &plerrcontext;
503 
504  /*
505  * Make local execution copies of all the datums
506  */
507  estate.err_text = gettext_noop("during initialization of execution state");
508  copy_plpgsql_datums(&estate, func);
509 
510  /*
511  * Store the actual call argument values into the appropriate variables
512  */
513  estate.err_text = gettext_noop("while storing call arguments into local variables");
514  for (i = 0; i < func->fn_nargs; i++)
515  {
516  int n = func->fn_argvarnos[i];
517 
518  switch (estate.datums[n]->dtype)
519  {
520  case PLPGSQL_DTYPE_VAR:
521  {
522  PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[n];
523 
524  assign_simple_var(&estate, var,
525  fcinfo->args[i].value,
526  fcinfo->args[i].isnull,
527  false);
528 
529  /*
530  * If it's a varlena type, check to see if we received a
531  * R/W expanded-object pointer. If so, we can commandeer
532  * the object rather than having to copy it. If passed a
533  * R/O expanded pointer, just keep it as the value of the
534  * variable for the moment. (We can change it to R/W if
535  * the variable gets modified, but that may very well
536  * never happen.)
537  *
538  * Also, force any flat array value to be stored in
539  * expanded form in our local variable, in hopes of
540  * improving efficiency of uses of the variable. (This is
541  * a hack, really: why only arrays? Need more thought
542  * about which cases are likely to win. See also
543  * typisarray-specific heuristic in exec_assign_value.)
544  */
545  if (!var->isnull && var->datatype->typlen == -1)
546  {
548  {
549  /* take ownership of R/W object */
550  assign_simple_var(&estate, var,
552  estate.datum_context),
553  false,
554  true);
555  }
557  {
558  /* R/O pointer, keep it as-is until assigned to */
559  }
560  else if (var->datatype->typisarray)
561  {
562  /* flat array, so force to expanded form */
563  assign_simple_var(&estate, var,
564  expand_array(var->value,
565  estate.datum_context,
566  NULL),
567  false,
568  true);
569  }
570  }
571  }
572  break;
573 
574  case PLPGSQL_DTYPE_REC:
575  {
576  PLpgSQL_rec *rec = (PLpgSQL_rec *) estate.datums[n];
577 
578  if (!fcinfo->args[i].isnull)
579  {
580  /* Assign row value from composite datum */
581  exec_move_row_from_datum(&estate,
582  (PLpgSQL_variable *) rec,
583  fcinfo->args[i].value);
584  }
585  else
586  {
587  /* If arg is null, set variable to null */
588  exec_move_row(&estate, (PLpgSQL_variable *) rec,
589  NULL, NULL);
590  }
591  /* clean up after exec_move_row() */
592  exec_eval_cleanup(&estate);
593  }
594  break;
595 
596  default:
597  /* Anything else should not be an argument variable */
598  elog(ERROR, "unrecognized dtype: %d", func->datums[i]->dtype);
599  }
600  }
601 
602  estate.err_text = gettext_noop("during function entry");
603 
604  /*
605  * Set the magic variable FOUND to false
606  */
607  exec_set_found(&estate, false);
608 
609  /*
610  * Let the instrumentation plugin peek at this function
611  */
612  if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
613  ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
614 
615  /*
616  * Now call the toplevel block of statements
617  */
618  estate.err_text = NULL;
619  rc = exec_toplevel_block(&estate, func->action);
620  if (rc != PLPGSQL_RC_RETURN)
621  {
622  estate.err_text = NULL;
623  ereport(ERROR,
624  (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
625  errmsg("control reached end of function without RETURN")));
626  }
627 
628  /*
629  * We got a return value - process it
630  */
631  estate.err_text = gettext_noop("while casting return value to function's return type");
632 
633  fcinfo->isnull = estate.retisnull;
634 
635  if (estate.retisset)
636  {
637  ReturnSetInfo *rsi = estate.rsi;
638 
639  /* Check caller can handle a set result */
640  if (!rsi || !IsA(rsi, ReturnSetInfo))
641  ereport(ERROR,
642  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
643  errmsg("set-valued function called in context that cannot accept a set")));
644 
645  if (!(rsi->allowedModes & SFRM_Materialize))
646  ereport(ERROR,
647  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
648  errmsg("materialize mode required, but it is not allowed in this context")));
649 
651 
652  /* If we produced any tuples, send back the result */
653  if (estate.tuple_store)
654  {
655  MemoryContext oldcxt;
656 
657  rsi->setResult = estate.tuple_store;
658  oldcxt = MemoryContextSwitchTo(estate.tuple_store_cxt);
660  MemoryContextSwitchTo(oldcxt);
661  }
662  estate.retval = (Datum) 0;
663  fcinfo->isnull = true;
664  }
665  else if (!estate.retisnull)
666  {
667  /*
668  * Cast result value to function's declared result type, and copy it
669  * out to the upper executor memory context. We must treat tuple
670  * results specially in order to deal with cases like rowtypes
671  * involving dropped columns.
672  */
673  if (estate.retistuple)
674  {
675  /* Don't need coercion if rowtype is known to match */
676  if (func->fn_rettype == estate.rettype &&
677  func->fn_rettype != RECORDOID)
678  {
679  /*
680  * Copy the tuple result into upper executor memory context.
681  * However, if we have a R/W expanded datum, we can just
682  * transfer its ownership out to the upper context.
683  */
684  estate.retval = SPI_datumTransfer(estate.retval,
685  false,
686  -1);
687  }
688  else
689  {
690  /*
691  * Need to look up the expected result type. XXX would be
692  * better to cache the tupdesc instead of repeating
693  * get_call_result_type(), but the only easy place to save it
694  * is in the PLpgSQL_function struct, and that's too
695  * long-lived: composite types could change during the
696  * existence of a PLpgSQL_function.
697  */
698  Oid resultTypeId;
699  TupleDesc tupdesc;
700 
701  switch (get_call_result_type(fcinfo, &resultTypeId, &tupdesc))
702  {
703  case TYPEFUNC_COMPOSITE:
704  /* got the expected result rowtype, now coerce it */
705  coerce_function_result_tuple(&estate, tupdesc);
706  break;
708  /* got the expected result rowtype, now coerce it */
709  coerce_function_result_tuple(&estate, tupdesc);
710  /* and check domain constraints */
711  /* XXX allowing caching here would be good, too */
712  domain_check(estate.retval, false, resultTypeId,
713  NULL, NULL);
714  break;
715  case TYPEFUNC_RECORD:
716 
717  /*
718  * Failed to determine actual type of RECORD. We
719  * could raise an error here, but what this means in
720  * practice is that the caller is expecting any old
721  * generic rowtype, so we don't really need to be
722  * restrictive. Pass back the generated result as-is.
723  */
724  estate.retval = SPI_datumTransfer(estate.retval,
725  false,
726  -1);
727  break;
728  default:
729  /* shouldn't get here if retistuple is true ... */
730  elog(ERROR, "return type must be a row type");
731  break;
732  }
733  }
734  }
735  else
736  {
737  /* Scalar case: use exec_cast_value */
738  estate.retval = exec_cast_value(&estate,
739  estate.retval,
740  &fcinfo->isnull,
741  estate.rettype,
742  -1,
743  func->fn_rettype,
744  -1);
745 
746  /*
747  * If the function's return type isn't by value, copy the value
748  * into upper executor memory context. However, if we have a R/W
749  * expanded datum, we can just transfer its ownership out to the
750  * upper executor context.
751  */
752  if (!fcinfo->isnull && !func->fn_retbyval)
753  estate.retval = SPI_datumTransfer(estate.retval,
754  false,
755  func->fn_rettyplen);
756  }
757  }
758  else
759  {
760  /*
761  * We're returning a NULL, which normally requires no conversion work
762  * regardless of datatypes. But, if we are casting it to a domain
763  * return type, we'd better check that the domain's constraints pass.
764  */
765  if (func->fn_retisdomain)
766  estate.retval = exec_cast_value(&estate,
767  estate.retval,
768  &fcinfo->isnull,
769  estate.rettype,
770  -1,
771  func->fn_rettype,
772  -1);
773  }
774 
775  estate.err_text = gettext_noop("during function exit");
776 
777  /*
778  * Let the instrumentation plugin peek at this function
779  */
780  if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
781  ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
782 
783  /* Clean up any leftover temporary memory */
784  plpgsql_destroy_econtext(&estate);
785  exec_eval_cleanup(&estate);
786  /* stmt_mcontext will be destroyed when function's main context is */
787 
788  /*
789  * Pop the error context stack
790  */
791  error_context_stack = plerrcontext.previous;
792 
793  /*
794  * Return the function's result
795  */
796  return estate.retval;
797 }
Datum expand_array(Datum arraydatum, MemoryContext parentcontext, ArrayMetaState *metacache)
void domain_check(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt)
Definition: domains.c:346
@ SFRM_Materialize
Definition: execnodes.h:320
Datum TransferExpandedObject(Datum d, MemoryContext new_parent)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:276
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
@ TYPEFUNC_RECORD
Definition: funcapi.h:151
@ TYPEFUNC_COMPOSITE_DOMAIN
Definition: funcapi.h:150
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
static void coerce_function_result_tuple(PLpgSQL_execstate *estate, TupleDesc tupdesc)
Definition: pl_exec.c:808
static void exec_move_row_from_datum(PLpgSQL_execstate *estate, PLpgSQL_variable *target, Datum value)
Definition: pl_exec.c:7423
static Datum exec_cast_value(PLpgSQL_execstate *estate, Datum value, bool *isnull, Oid valtype, int32 valtypmod, Oid reqtype, int32 reqtypmod)
Definition: pl_exec.c:7720
static void exec_set_found(PLpgSQL_execstate *estate, bool state)
Definition: pl_exec.c:8375
static void assign_simple_var(PLpgSQL_execstate *estate, PLpgSQL_var *var, Datum newvalue, bool isnull, bool freeable)
Definition: pl_exec.c:8551
static void exec_move_row(PLpgSQL_execstate *estate, PLpgSQL_variable *target, HeapTuple tup, TupleDesc tupdesc)
Definition: pl_exec.c:6749
uintptr_t Datum
Definition: postgres.h:64
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
Datum SPI_datumTransfer(Datum value, bool typByVal, int typLen)
Definition: spi.c:1361
fmNodePtr resultinfo
Definition: fmgr.h:89
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
Datum value
Definition: postgres.h:75
bool isnull
Definition: postgres.h:77
PLpgSQL_datum ** datums
Definition: plpgsql.h:1058
ResourceOwner procedure_resowner
Definition: plpgsql.h:1075
Tuplestorestate * tuple_store
Definition: plpgsql.h:1043
MemoryContext tuple_store_cxt
Definition: plpgsql.h:1045
TupleDesc tuple_store_desc
Definition: plpgsql.h:1044
MemoryContext datum_context
Definition: plpgsql.h:1060
ReturnSetInfo * rsi
Definition: plpgsql.h:1047
bool fn_retbyval
Definition: plpgsql.h:979
bool fn_retisdomain
Definition: plpgsql.h:981
int fn_argvarnos[FUNC_MAX_ARGS]
Definition: plpgsql.h:987
int16 typlen
Definition: plpgsql.h:203
SetFunctionReturnMode returnMode
Definition: execnodes.h:339
TupleDesc setDesc
Definition: execnodes.h:343
Tuplestorestate * setResult
Definition: execnodes.h:342
int allowedModes
Definition: execnodes.h:337
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:133
#define VARATT_IS_EXTERNAL_EXPANDED_RO(PTR)
Definition: varatt.h:294
#define VARATT_IS_EXTERNAL_EXPANDED_RW(PTR)
Definition: varatt.h:296

References PLpgSQL_function::action, ReturnSetInfo::allowedModes, ErrorContextCallback::arg, FunctionCallInfoBaseData::args, assign_simple_var(), PLpgSQL_execstate::atomic, ErrorContextCallback::callback, coerce_function_result_tuple(), copy_plpgsql_datums(), CreateTupleDescCopy(), PLpgSQL_var::datatype, PLpgSQL_execstate::datum_context, DatumGetPointer(), PLpgSQL_function::datums, PLpgSQL_execstate::datums, domain_check(), PLpgSQL_datum::dtype, elog, ereport, PLpgSQL_execstate::err_text, errcode(), errmsg(), ERROR, error_context_stack, exec_cast_value(), exec_eval_cleanup(), exec_move_row(), exec_move_row_from_datum(), exec_set_found(), exec_toplevel_block(), expand_array(), PLpgSQL_function::fn_argvarnos, PLpgSQL_function::fn_nargs, PLpgSQL_function::fn_retbyval, PLpgSQL_function::fn_retisdomain, PLpgSQL_function::fn_rettype, PLpgSQL_function::fn_rettyplen, PLpgSQL_plugin::func_beg, PLpgSQL_plugin::func_end, get_call_result_type(), gettext_noop, i, if(), IsA, FunctionCallInfoBaseData::isnull, NullableDatum::isnull, PLpgSQL_var::isnull, MemoryContextSwitchTo(), plpgsql_destroy_econtext(), PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_VAR, plpgsql_estate_setup(), plpgsql_exec_error_callback(), plpgsql_plugin_ptr, PLPGSQL_RC_RETURN, ErrorContextCallback::previous, PLpgSQL_execstate::procedure_resowner, FunctionCallInfoBaseData::resultinfo, PLpgSQL_execstate::retisnull, PLpgSQL_execstate::retisset, PLpgSQL_execstate::retistuple, PLpgSQL_execstate::rettype, ReturnSetInfo::returnMode, PLpgSQL_execstate::retval, PLpgSQL_execstate::rsi, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SPI_datumTransfer(), TransferExpandedObject(), PLpgSQL_execstate::tuple_store, PLpgSQL_execstate::tuple_store_cxt, PLpgSQL_execstate::tuple_store_desc, TYPEFUNC_COMPOSITE, TYPEFUNC_COMPOSITE_DOMAIN, TYPEFUNC_RECORD, PLpgSQL_type::typisarray, PLpgSQL_type::typlen, NullableDatum::value, PLpgSQL_var::value, VARATT_IS_EXTERNAL_EXPANDED_RO, and VARATT_IS_EXTERNAL_EXPANDED_RW.

Referenced by plpgsql_call_handler(), and plpgsql_inline_handler().

◆ plpgsql_exec_get_datum_type()

PGDLLEXPORT Oid plpgsql_exec_get_datum_type ( PLpgSQL_execstate estate,
PLpgSQL_datum datum 
)

Definition at line 5457 of file pl_exec.c.

5459 {
5460  Oid typeid;
5461 
5462  switch (datum->dtype)
5463  {
5464  case PLPGSQL_DTYPE_VAR:
5465  case PLPGSQL_DTYPE_PROMISE:
5466  {
5467  PLpgSQL_var *var = (PLpgSQL_var *) datum;
5468 
5469  typeid = var->datatype->typoid;
5470  break;
5471  }
5472 
5473  case PLPGSQL_DTYPE_REC:
5474  {
5475  PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
5476 
5477  if (rec->erh == NULL || rec->rectypeid != RECORDOID)
5478  {
5479  /* Report variable's declared type */
5480  typeid = rec->rectypeid;
5481  }
5482  else
5483  {
5484  /* Report record's actual type if declared RECORD */
5485  typeid = rec->erh->er_typeid;
5486  }
5487  break;
5488  }
5489 
5491  {
5492  PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
5493  PLpgSQL_rec *rec;
5494 
5495  rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5496 
5497  /*
5498  * If record variable is NULL, instantiate it if it has a
5499  * named composite type, else complain. (This won't change
5500  * the logical state of the record: it's still NULL.)
5501  */
5502  if (rec->erh == NULL)
5503  instantiate_empty_record_variable(estate, rec);
5504 
5505  /*
5506  * Look up the field's properties if we have not already, or
5507  * if the tuple descriptor ID changed since last time.
5508  */
5509  if (unlikely(recfield->rectupledescid != rec->erh->er_tupdesc_id))
5510  {
5512  recfield->fieldname,
5513  &recfield->finfo))
5514  ereport(ERROR,
5515  (errcode(ERRCODE_UNDEFINED_COLUMN),
5516  errmsg("record \"%s\" has no field \"%s\"",
5517  rec->refname, recfield->fieldname)));
5518  recfield->rectupledescid = rec->erh->er_tupdesc_id;
5519  }
5520 
5521  typeid = recfield->finfo.ftypeid;
5522  break;
5523  }
5524 
5525  default:
5526  elog(ERROR, "unrecognized dtype: %d", datum->dtype);
5527  typeid = InvalidOid; /* keep compiler quiet */
5528  break;
5529  }
5530 
5531  return typeid;
5532 }
#define unlikely(x)
Definition: c.h:326
bool expanded_record_lookup_field(ExpandedRecordHeader *erh, const char *fieldname, ExpandedRecordFieldInfo *finfo)
static void instantiate_empty_record_variable(PLpgSQL_execstate *estate, PLpgSQL_rec *rec)
Definition: pl_exec.c:7656
ExpandedRecordFieldInfo finfo
Definition: plpgsql.h:430

References PLpgSQL_var::datatype, PLpgSQL_execstate::datums, PLpgSQL_datum::dtype, elog, ExpandedRecordHeader::er_tupdesc_id, ExpandedRecordHeader::er_typeid, ereport, PLpgSQL_rec::erh, errcode(), errmsg(), ERROR, expanded_record_lookup_field(), PLpgSQL_recfield::fieldname, PLpgSQL_recfield::finfo, ExpandedRecordFieldInfo::ftypeid, instantiate_empty_record_variable(), InvalidOid, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_VAR, PLpgSQL_recfield::recparentno, PLpgSQL_recfield::rectupledescid, PLpgSQL_rec::rectypeid, PLpgSQL_rec::refname, PLpgSQL_type::typoid, and unlikely.

Referenced by exec_stmt_foreach_a().

◆ plpgsql_exec_get_datum_type_info()

void plpgsql_exec_get_datum_type_info ( PLpgSQL_execstate estate,
PLpgSQL_datum datum,
Oid typeId,
int32 typMod,
Oid collation 
)

Definition at line 5542 of file pl_exec.c.

5545 {
5546  switch (datum->dtype)
5547  {
5548  case PLPGSQL_DTYPE_VAR:
5549  case PLPGSQL_DTYPE_PROMISE:
5550  {
5551  PLpgSQL_var *var = (PLpgSQL_var *) datum;
5552 
5553  *typeId = var->datatype->typoid;
5554  *typMod = var->datatype->atttypmod;
5555  *collation = var->datatype->collation;
5556  break;
5557  }
5558 
5559  case PLPGSQL_DTYPE_REC:
5560  {
5561  PLpgSQL_rec *rec = (PLpgSQL_rec *) datum;
5562 
5563  if (rec->erh == NULL || rec->rectypeid != RECORDOID)
5564  {
5565  /* Report variable's declared type */
5566  *typeId = rec->rectypeid;
5567  *typMod = -1;
5568  }
5569  else
5570  {
5571  /* Report record's actual type if declared RECORD */
5572  *typeId = rec->erh->er_typeid;
5573  /* do NOT return the mutable typmod of a RECORD variable */
5574  *typMod = -1;
5575  }
5576  /* composite types are never collatable */
5577  *collation = InvalidOid;
5578  break;
5579  }
5580 
5582  {
5583  PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum;
5584  PLpgSQL_rec *rec;
5585 
5586  rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]);
5587 
5588  /*
5589  * If record variable is NULL, instantiate it if it has a
5590  * named composite type, else complain. (This won't change
5591  * the logical state of the record: it's still NULL.)
5592  */
5593  if (rec->erh == NULL)
5594  instantiate_empty_record_variable(estate, rec);
5595 
5596  /*
5597  * Look up the field's properties if we have not already, or
5598  * if the tuple descriptor ID changed since last time.
5599  */
5600  if (unlikely(recfield->rectupledescid != rec->erh->er_tupdesc_id))
5601  {
5603  recfield->fieldname,
5604  &recfield->finfo))
5605  ereport(ERROR,
5606  (errcode(ERRCODE_UNDEFINED_COLUMN),
5607  errmsg("record \"%s\" has no field \"%s\"",
5608  rec->refname, recfield->fieldname)));
5609  recfield->rectupledescid = rec->erh->er_tupdesc_id;
5610  }
5611 
5612  *typeId = recfield->finfo.ftypeid;
5613  *typMod = recfield->finfo.ftypmod;
5614  *collation = recfield->finfo.fcollation;
5615  break;
5616  }
5617 
5618  default:
5619  elog(ERROR, "unrecognized dtype: %d", datum->dtype);
5620  *typeId = InvalidOid; /* keep compiler quiet */
5621  *typMod = -1;
5622  *collation = InvalidOid;
5623  break;
5624  }
5625 }

References PLpgSQL_type::atttypmod, PLpgSQL_type::collation, PLpgSQL_var::datatype, PLpgSQL_execstate::datums, PLpgSQL_datum::dtype, elog, ExpandedRecordHeader::er_tupdesc_id, ExpandedRecordHeader::er_typeid, ereport, PLpgSQL_rec::erh, errcode(), errmsg(), ERROR, expanded_record_lookup_field(), ExpandedRecordFieldInfo::fcollation, PLpgSQL_recfield::fieldname, PLpgSQL_recfield::finfo, ExpandedRecordFieldInfo::ftypeid, ExpandedRecordFieldInfo::ftypmod, instantiate_empty_record_variable(), InvalidOid, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_VAR, PLpgSQL_recfield::recparentno, PLpgSQL_recfield::rectupledescid, PLpgSQL_rec::rectypeid, PLpgSQL_rec::refname, PLpgSQL_type::typoid, and unlikely.

Referenced by make_datum_param().

◆ plpgsql_exec_trigger()

HeapTuple plpgsql_exec_trigger ( PLpgSQL_function func,
TriggerData trigdata 
)

Definition at line 919 of file pl_exec.c.

921 {
922  PLpgSQL_execstate estate;
923  ErrorContextCallback plerrcontext;
924  int rc;
925  TupleDesc tupdesc;
926  PLpgSQL_rec *rec_new,
927  *rec_old;
928  HeapTuple rettup;
929 
930  /*
931  * Setup the execution state
932  */
933  plpgsql_estate_setup(&estate, func, NULL, NULL, NULL);
934  estate.trigdata = trigdata;
935 
936  /*
937  * Setup error traceback support for ereport()
938  */
939  plerrcontext.callback = plpgsql_exec_error_callback;
940  plerrcontext.arg = &estate;
941  plerrcontext.previous = error_context_stack;
942  error_context_stack = &plerrcontext;
943 
944  /*
945  * Make local execution copies of all the datums
946  */
947  estate.err_text = gettext_noop("during initialization of execution state");
948  copy_plpgsql_datums(&estate, func);
949 
950  /*
951  * Put the OLD and NEW tuples into record variables
952  *
953  * We set up expanded records for both variables even though only one may
954  * have a value. This allows record references to succeed in functions
955  * that are used for multiple trigger types. For example, we might have a
956  * test like "if (TG_OP = 'INSERT' and NEW.foo = 'xyz')", which should
957  * work regardless of the current trigger type. If a value is actually
958  * fetched from an unsupplied tuple, it will read as NULL.
959  */
960  tupdesc = RelationGetDescr(trigdata->tg_relation);
961 
962  rec_new = (PLpgSQL_rec *) (estate.datums[func->new_varno]);
963  rec_old = (PLpgSQL_rec *) (estate.datums[func->old_varno]);
964 
965  rec_new->erh = make_expanded_record_from_tupdesc(tupdesc,
966  estate.datum_context);
967  rec_old->erh = make_expanded_record_from_exprecord(rec_new->erh,
968  estate.datum_context);
969 
970  if (!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
971  {
972  /*
973  * Per-statement triggers don't use OLD/NEW variables
974  */
975  }
976  else if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
977  {
978  expanded_record_set_tuple(rec_new->erh, trigdata->tg_trigtuple,
979  false, false);
980  }
981  else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
982  {
983  expanded_record_set_tuple(rec_new->erh, trigdata->tg_newtuple,
984  false, false);
985  expanded_record_set_tuple(rec_old->erh, trigdata->tg_trigtuple,
986  false, false);
987 
988  /*
989  * In BEFORE trigger, stored generated columns are not computed yet,
990  * so make them null in the NEW row. (Only needed in UPDATE branch;
991  * in the INSERT case, they are already null, but in UPDATE, the field
992  * still contains the old value.) Alternatively, we could construct a
993  * whole new row structure without the generated columns, but this way
994  * seems more efficient and potentially less confusing.
995  */
996  if (tupdesc->constr && tupdesc->constr->has_generated_stored &&
997  TRIGGER_FIRED_BEFORE(trigdata->tg_event))
998  {
999  for (int i = 0; i < tupdesc->natts; i++)
1000  if (TupleDescAttr(tupdesc, i)->attgenerated == ATTRIBUTE_GENERATED_STORED)
1002  i + 1,
1003  (Datum) 0,
1004  true, /* isnull */
1005  false, false);
1006  }
1007  }
1008  else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
1009  {
1010  expanded_record_set_tuple(rec_old->erh, trigdata->tg_trigtuple,
1011  false, false);
1012  }
1013  else
1014  elog(ERROR, "unrecognized trigger action: not INSERT, DELETE, or UPDATE");
1015 
1016  /* Make transition tables visible to this SPI connection */
1017  rc = SPI_register_trigger_data(trigdata);
1018  Assert(rc >= 0);
1019 
1020  estate.err_text = gettext_noop("during function entry");
1021 
1022  /*
1023  * Set the magic variable FOUND to false
1024  */
1025  exec_set_found(&estate, false);
1026 
1027  /*
1028  * Let the instrumentation plugin peek at this function
1029  */
1030  if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_beg)
1031  ((*plpgsql_plugin_ptr)->func_beg) (&estate, func);
1032 
1033  /*
1034  * Now call the toplevel block of statements
1035  */
1036  estate.err_text = NULL;
1037  rc = exec_toplevel_block(&estate, func->action);
1038  if (rc != PLPGSQL_RC_RETURN)
1039  {
1040  estate.err_text = NULL;
1041  ereport(ERROR,
1042  (errcode(ERRCODE_S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT),
1043  errmsg("control reached end of trigger procedure without RETURN")));
1044  }
1045 
1046  estate.err_text = gettext_noop("during function exit");
1047 
1048  if (estate.retisset)
1049  ereport(ERROR,
1050  (errcode(ERRCODE_DATATYPE_MISMATCH),
1051  errmsg("trigger procedure cannot return a set")));
1052 
1053  /*
1054  * Check that the returned tuple structure has the same attributes, the
1055  * relation that fired the trigger has. A per-statement trigger always
1056  * needs to return NULL, so we ignore any return value the function itself
1057  * produces (XXX: is this a good idea?)
1058  *
1059  * XXX This way it is possible, that the trigger returns a tuple where
1060  * attributes don't have the correct atttypmod's length. It's up to the
1061  * trigger's programmer to ensure that this doesn't happen. Jan
1062  */
1063  if (estate.retisnull || !TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
1064  rettup = NULL;
1065  else
1066  {
1067  TupleDesc retdesc;
1068  TupleConversionMap *tupmap;
1069 
1070  /* We assume exec_stmt_return verified that result is composite */
1071  Assert(type_is_rowtype(estate.rettype));
1072 
1073  /* We can special-case expanded records for speed */
1075  {
1077 
1078  Assert(erh->er_magic == ER_MAGIC);
1079 
1080  /* Extract HeapTuple and TupleDesc */
1081  rettup = expanded_record_get_tuple(erh);
1082  Assert(rettup);
1083  retdesc = expanded_record_get_tupdesc(erh);
1084 
1085  if (retdesc != RelationGetDescr(trigdata->tg_relation))
1086  {
1087  /* check rowtype compatibility */
1088  tupmap = convert_tuples_by_position(retdesc,
1089  RelationGetDescr(trigdata->tg_relation),
1090  gettext_noop("returned row structure does not match the structure of the triggering table"));
1091  /* it might need conversion */
1092  if (tupmap)
1093  rettup = execute_attr_map_tuple(rettup, tupmap);
1094  /* no need to free map, we're about to return anyway */
1095  }
1096 
1097  /*
1098  * Copy tuple to upper executor memory. But if user just did
1099  * "return new" or "return old" without changing anything, there's
1100  * no need to copy; we can return the original tuple (which will
1101  * save a few cycles in trigger.c as well as here).
1102  */
1103  if (rettup != trigdata->tg_newtuple &&
1104  rettup != trigdata->tg_trigtuple)
1105  rettup = SPI_copytuple(rettup);
1106  }
1107  else
1108  {
1109  /* Convert composite datum to a HeapTuple and TupleDesc */
1110  HeapTupleData tmptup;
1111 
1112  retdesc = deconstruct_composite_datum(estate.retval, &tmptup);
1113  rettup = &tmptup;
1114 
1115  /* check rowtype compatibility */
1116  tupmap = convert_tuples_by_position(retdesc,
1117  RelationGetDescr(trigdata->tg_relation),
1118  gettext_noop("returned row structure does not match the structure of the triggering table"));
1119  /* it might need conversion */
1120  if (tupmap)
1121  rettup = execute_attr_map_tuple(rettup, tupmap);
1122 
1123  ReleaseTupleDesc(retdesc);
1124  /* no need to free map, we're about to return anyway */
1125 
1126  /* Copy tuple to upper executor memory */
1127  rettup = SPI_copytuple(rettup);
1128  }
1129  }
1130 
1131  /*
1132  * Let the instrumentation plugin peek at this function
1133  */
1134  if (*plpgsql_plugin_ptr && (*plpgsql_plugin_ptr)->func_end)
1135  ((*plpgsql_plugin_ptr)->func_end) (&estate, func);
1136 
1137  /* Clean up any leftover temporary memory */
1138  plpgsql_destroy_econtext(&estate);
1139  exec_eval_cleanup(&estate);
1140  /* stmt_mcontext will be destroyed when function's main context is */
1141 
1142  /*
1143  * Pop the error context stack
1144  */
1145  error_context_stack = plerrcontext.previous;
1146 
1147  /*
1148  * Return the trigger's result
1149  */
1150  return rettup;
1151 }
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
ExpandedRecordHeader * make_expanded_record_from_tupdesc(TupleDesc tupdesc, MemoryContext parentcontext)
void expanded_record_set_field_internal(ExpandedRecordHeader *erh, int fnumber, Datum newValue, bool isnull, bool expand_external, bool check_constraints)
ExpandedRecordHeader * make_expanded_record_from_exprecord(ExpandedRecordHeader *olderh, MemoryContext parentcontext)
void expanded_record_set_tuple(ExpandedRecordHeader *erh, HeapTuple tuple, bool copy, bool expand_external)
HeapTuple expanded_record_get_tuple(ExpandedRecordHeader *erh)
#define ER_MAGIC
static TupleDesc expanded_record_get_tupdesc(ExpandedRecordHeader *erh)
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2655
static TupleDesc deconstruct_composite_datum(Datum value, HeapTupleData *tmptup)
Definition: pl_exec.c:7392
#define RelationGetDescr(relation)
Definition: rel.h:531
int SPI_register_trigger_data(TriggerData *tdata)
Definition: spi.c:3364
HeapTuple SPI_copytuple(HeapTuple tuple)
Definition: spi.c:1047
TriggerData * trigdata
Definition: plpgsql.h:1025
Relation tg_relation
Definition: trigger.h:35
TriggerEvent tg_event
Definition: trigger.h:34
HeapTuple tg_newtuple
Definition: trigger.h:37
HeapTuple tg_trigtuple
Definition: trigger.h:36
bool has_generated_stored
Definition: tupdesc.h:45
TupleConstr * constr
Definition: tupdesc.h:85
#define TRIGGER_FIRED_BY_DELETE(event)
Definition: trigger.h:113
#define TRIGGER_FIRED_BEFORE(event)
Definition: trigger.h:128
#define TRIGGER_FIRED_FOR_ROW(event)
Definition: trigger.h:122
#define TRIGGER_FIRED_BY_INSERT(event)
Definition: trigger.h:110
#define TRIGGER_FIRED_BY_UPDATE(event)
Definition: trigger.h:116
TupleConversionMap * convert_tuples_by_position(TupleDesc indesc, TupleDesc outdesc, const char *msg)
Definition: tupconvert.c:59
HeapTuple execute_attr_map_tuple(HeapTuple tuple, TupleConversionMap *map)
Definition: tupconvert.c:154
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:122
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define VARATT_IS_EXTERNAL_EXPANDED(PTR)
Definition: varatt.h:298

References PLpgSQL_function::action, ErrorContextCallback::arg, Assert, ErrorContextCallback::callback, TupleDescData::constr, convert_tuples_by_position(), copy_plpgsql_datums(), PLpgSQL_execstate::datum_context, DatumGetEOHP(), DatumGetPointer(), PLpgSQL_execstate::datums, deconstruct_composite_datum(), elog, ER_MAGIC, ExpandedRecordHeader::er_magic, ereport, PLpgSQL_rec::erh, PLpgSQL_execstate::err_text, errcode(), errmsg(), ERROR, error_context_stack, exec_eval_cleanup(), exec_set_found(), exec_toplevel_block(), execute_attr_map_tuple(), expanded_record_get_tupdesc(), expanded_record_get_tuple(), expanded_record_set_field_internal(), expanded_record_set_tuple(), PLpgSQL_plugin::func_beg, PLpgSQL_plugin::func_end, gettext_noop, TupleConstr::has_generated_stored, i, make_expanded_record_from_exprecord(), make_expanded_record_from_tupdesc(), TupleDescData::natts, PLpgSQL_function::new_varno, PLpgSQL_function::old_varno, plpgsql_destroy_econtext(), plpgsql_estate_setup(), plpgsql_exec_error_callback(), plpgsql_plugin_ptr, PLPGSQL_RC_RETURN, ErrorContextCallback::previous, RelationGetDescr, ReleaseTupleDesc, PLpgSQL_execstate::retisnull, PLpgSQL_execstate::retisset, PLpgSQL_execstate::rettype, PLpgSQL_execstate::retval, SPI_copytuple(), SPI_register_trigger_data(), TriggerData::tg_event, TriggerData::tg_newtuple, TriggerData::tg_relation, TriggerData::tg_trigtuple, PLpgSQL_execstate::trigdata, TRIGGER_FIRED_BEFORE, TRIGGER_FIRED_BY_DELETE, TRIGGER_FIRED_BY_INSERT, TRIGGER_FIRED_BY_UPDATE, TRIGGER_FIRED_FOR_ROW, TupleDescAttr, type_is_rowtype(), and VARATT_IS_EXTERNAL_EXPANDED.

Referenced by plpgsql_call_handler().

◆ plpgsql_free_function_memory()

void plpgsql_free_function_memory ( PLpgSQL_function func)

Definition at line 727 of file pl_funcs.c.

728 {
729  int i;
730 
731  /* Better not call this on an in-use function */
732  Assert(func->use_count == 0);
733 
734  /* Release plans associated with variable declarations */
735  for (i = 0; i < func->ndatums; i++)
736  {
737  PLpgSQL_datum *d = func->datums[i];
738 
739  switch (d->dtype)
740  {
741  case PLPGSQL_DTYPE_VAR:
743  {
744  PLpgSQL_var *var = (PLpgSQL_var *) d;
745 
746  free_expr(var->default_val);
748  }
749  break;
750  case PLPGSQL_DTYPE_ROW:
751  break;
752  case PLPGSQL_DTYPE_REC:
753  {
754  PLpgSQL_rec *rec = (PLpgSQL_rec *) d;
755 
756  free_expr(rec->default_val);
757  }
758  break;
760  break;
761  default:
762  elog(ERROR, "unrecognized data type: %d", d->dtype);
763  }
764  }
765  func->ndatums = 0;
766 
767  /* Release plans in statement tree */
768  if (func->action)
769  free_block(func->action);
770  func->action = NULL;
771 
772  /*
773  * And finally, release all memory except the PLpgSQL_function struct
774  * itself (which has to be kept around because there may be multiple
775  * fn_extra pointers to it).
776  */
777  if (func->fn_cxt)
779  func->fn_cxt = NULL;
780 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
static void free_block(PLpgSQL_stmt_block *block)
Definition: pl_funcs.c:480
static void free_expr(PLpgSQL_expr *expr)
Definition: pl_funcs.c:717
unsigned long use_count
Definition: plpgsql.h:1015
MemoryContext fn_cxt
Definition: plpgsql.h:975
PLpgSQL_expr * default_val
Definition: plpgsql.h:397

References PLpgSQL_function::action, Assert, PLpgSQL_var::cursor_explicit_expr, PLpgSQL_function::datums, PLpgSQL_var::default_val, PLpgSQL_rec::default_val, PLpgSQL_datum::dtype, elog, ERROR, PLpgSQL_function::fn_cxt, free_block(), free_expr(), i, MemoryContextDelete(), PLpgSQL_function::ndatums, PLPGSQL_DTYPE_PROMISE, PLPGSQL_DTYPE_REC, PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_ROW, PLPGSQL_DTYPE_VAR, and PLpgSQL_function::use_count.

Referenced by delete_function(), and plpgsql_inline_handler().

◆ plpgsql_getdiag_kindname()

const char* plpgsql_getdiag_kindname ( PLpgSQL_getdiag_kind  kind)

Definition at line 300 of file pl_funcs.c.

301 {
302  switch (kind)
303  {
305  return "ROW_COUNT";
307  return "PG_ROUTINE_OID";
309  return "PG_CONTEXT";
311  return "PG_EXCEPTION_CONTEXT";
313  return "PG_EXCEPTION_DETAIL";
315  return "PG_EXCEPTION_HINT";
317  return "RETURNED_SQLSTATE";
319  return "COLUMN_NAME";
321  return "CONSTRAINT_NAME";
323  return "PG_DATATYPE_NAME";
325  return "MESSAGE_TEXT";
327  return "TABLE_NAME";
329  return "SCHEMA_NAME";
330  }
331 
332  return "unknown";
333 }

References PLPGSQL_GETDIAG_COLUMN_NAME, PLPGSQL_GETDIAG_CONSTRAINT_NAME, PLPGSQL_GETDIAG_CONTEXT, PLPGSQL_GETDIAG_DATATYPE_NAME, PLPGSQL_GETDIAG_ERROR_CONTEXT, PLPGSQL_GETDIAG_ERROR_DETAIL, PLPGSQL_GETDIAG_ERROR_HINT, PLPGSQL_GETDIAG_MESSAGE_TEXT, PLPGSQL_GETDIAG_RETURNED_SQLSTATE, PLPGSQL_GETDIAG_ROUTINE_OID, PLPGSQL_GETDIAG_ROW_COUNT, PLPGSQL_GETDIAG_SCHEMA_NAME, and PLPGSQL_GETDIAG_TABLE_NAME.

Referenced by dump_getdiag().

◆ plpgsql_HashTableInit()

void plpgsql_HashTableInit ( void  )

Definition at line 2594 of file pl_comp.c.

2595 {
2596  HASHCTL ctl;
2597 
2598  /* don't allow double-initialization */
2599  Assert(plpgsql_HashTable == NULL);
2600 
2601  ctl.keysize = sizeof(PLpgSQL_func_hashkey);
2602  ctl.entrysize = sizeof(plpgsql_HashEnt);
2603  plpgsql_HashTable = hash_create("PLpgSQL function hash",
2605  &ctl,
2606  HASH_ELEM | HASH_BLOBS);
2607 }
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
#define FUNCS_PER_USER
Definition: pl_comp.c:69
struct plpgsql_hashent plpgsql_HashEnt
static HTAB * plpgsql_HashTable
Definition: pl_comp.c:61
struct PLpgSQL_func_hashkey PLpgSQL_func_hashkey
tree ctl
Definition: radixtree.h:1853

References Assert, ctl, FUNCS_PER_USER, HASH_BLOBS, hash_create(), HASH_ELEM, and plpgsql_HashTable.

Referenced by _PG_init().

◆ plpgsql_latest_lineno()

int plpgsql_latest_lineno ( void  )

Definition at line 589 of file pl_scanner.c.

590 {
591  return cur_line_num;
592 }
static int cur_line_num
Definition: pl_scanner.c:128

References cur_line_num.

Referenced by plpgsql_compile_error_callback().

◆ plpgsql_location_to_lineno()

int plpgsql_location_to_lineno ( int  location)

Definition at line 555 of file pl_scanner.c.

556 {
557  const char *loc;
558 
559  if (location < 0 || scanorig == NULL)
560  return 0; /* garbage in, garbage out */
561  loc = scanorig + location;
562 
563  /* be correct, but not fast, if input location goes backwards */
564  if (loc < cur_line_start)
566 
567  while (cur_line_end != NULL && loc > cur_line_end)
568  {
570  cur_line_num++;
571  cur_line_end = strchr(cur_line_start, '\n');
572  }
573 
574  return cur_line_num;
575 }
static const char * cur_line_end
Definition: pl_scanner.c:127
static void location_lineno_init(void)
Definition: pl_scanner.c:579
static const char * cur_line_start
Definition: pl_scanner.c:126

References cur_line_end, cur_line_num, cur_line_start, location_lineno_init(), and scanorig.

◆ plpgsql_ns_additem()

void plpgsql_ns_additem ( PLpgSQL_nsitem_type  itemtype,
int  itemno,
const char *  name 
)

Definition at line 92 of file pl_funcs.c.

93 {
94  PLpgSQL_nsitem *nse;
95 
96  Assert(name != NULL);
97  /* first item added must be a label */
98  Assert(ns_top != NULL || itemtype == PLPGSQL_NSTYPE_LABEL);
99 
100  nse = palloc(offsetof(PLpgSQL_nsitem, name) + strlen(name) + 1);
101  nse->itemtype = itemtype;
102  nse->itemno = itemno;
103  nse->prev = ns_top;
104  strcpy(nse->name, name);
105  ns_top = nse;
106 }
static PLpgSQL_nsitem * ns_top
Definition: pl_funcs.c:35
char name[FLEXIBLE_ARRAY_MEMBER]
Definition: plpgsql.h:447
struct PLpgSQL_nsitem * prev
Definition: plpgsql.h:446
PLpgSQL_nsitem_type itemtype
Definition: plpgsql.h:439
const char * name

References Assert, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, name, PLpgSQL_nsitem::name, ns_top, palloc(), PLPGSQL_NSTYPE_LABEL, and PLpgSQL_nsitem::prev.

Referenced by add_parameter_name(), plpgsql_build_record(), plpgsql_build_variable(), and plpgsql_ns_push().

◆ plpgsql_ns_find_nearest_loop()

PLpgSQL_nsitem* plpgsql_ns_find_nearest_loop ( PLpgSQL_nsitem ns_cur)

Definition at line 214 of file pl_funcs.c.

215 {
216  while (ns_cur != NULL)
217  {
218  if (ns_cur->itemtype == PLPGSQL_NSTYPE_LABEL &&
219  ns_cur->itemno == PLPGSQL_LABEL_LOOP)
220  return ns_cur;
221  ns_cur = ns_cur->prev;
222  }
223 
224  return NULL; /* no loop found */
225 }

References PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, PLPGSQL_LABEL_LOOP, PLPGSQL_NSTYPE_LABEL, and PLpgSQL_nsitem::prev.

◆ plpgsql_ns_init()

void plpgsql_ns_init ( void  )

Definition at line 43 of file pl_funcs.c.

44 {
45  ns_top = NULL;
46 }

References ns_top.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_ns_lookup()

PGDLLEXPORT PLpgSQL_nsitem* plpgsql_ns_lookup ( PLpgSQL_nsitem ns_cur,
bool  localmode,
const char *  name1,
const char *  name2,
const char *  name3,
int *  names_used 
)

Definition at line 130 of file pl_funcs.c.

133 {
134  /* Outer loop iterates once per block level in the namespace chain */
135  while (ns_cur != NULL)
136  {
137  PLpgSQL_nsitem *nsitem;
138 
139  /* Check this level for unqualified match to variable name */
140  for (nsitem = ns_cur;
141  nsitem->itemtype != PLPGSQL_NSTYPE_LABEL;
142  nsitem = nsitem->prev)
143  {
144  if (strcmp(nsitem->name, name1) == 0)
145  {
146  if (name2 == NULL ||
147  nsitem->itemtype != PLPGSQL_NSTYPE_VAR)
148  {
149  if (names_used)
150  *names_used = 1;
151  return nsitem;
152  }
153  }
154  }
155 
156  /* Check this level for qualified match to variable name */
157  if (name2 != NULL &&
158  strcmp(nsitem->name, name1) == 0)
159  {
160  for (nsitem = ns_cur;
161  nsitem->itemtype != PLPGSQL_NSTYPE_LABEL;
162  nsitem = nsitem->prev)
163  {
164  if (strcmp(nsitem->name, name2) == 0)
165  {
166  if (name3 == NULL ||
167  nsitem->itemtype != PLPGSQL_NSTYPE_VAR)
168  {
169  if (names_used)
170  *names_used = 2;
171  return nsitem;
172  }
173  }
174  }
175  }
176 
177  if (localmode)
178  break; /* do not look into upper levels */
179 
180  ns_cur = nsitem->prev;
181  }
182 
183  /* This is just to suppress possibly-uninitialized-variable warnings */
184  if (names_used)
185  *names_used = 0;
186  return NULL; /* No match found */
187 }

References PLpgSQL_nsitem::itemtype, PLpgSQL_nsitem::name, PLPGSQL_NSTYPE_LABEL, PLPGSQL_NSTYPE_VAR, and PLpgSQL_nsitem::prev.

Referenced by add_parameter_name(), plpgsql_param_ref(), plpgsql_parse_cwordtype(), plpgsql_parse_dblword(), plpgsql_parse_tripword(), plpgsql_parse_word(), plpgsql_parse_wordtype(), and resolve_column_ref().

◆ plpgsql_ns_lookup_label()

PLpgSQL_nsitem* plpgsql_ns_lookup_label ( PLpgSQL_nsitem ns_cur,
const char *  name 
)

Definition at line 195 of file pl_funcs.c.

196 {
197  while (ns_cur != NULL)
198  {
199  if (ns_cur->itemtype == PLPGSQL_NSTYPE_LABEL &&
200  strcmp(ns_cur->name, name) == 0)
201  return ns_cur;
202  ns_cur = ns_cur->prev;
203  }
204 
205  return NULL; /* label not found */
206 }

References PLpgSQL_nsitem::itemtype, name, PLpgSQL_nsitem::name, PLPGSQL_NSTYPE_LABEL, and PLpgSQL_nsitem::prev.

◆ plpgsql_ns_pop()

void plpgsql_ns_pop ( void  )

Definition at line 67 of file pl_funcs.c.

68 {
69  Assert(ns_top != NULL);
71  ns_top = ns_top->prev;
72  ns_top = ns_top->prev;
73 }

References Assert, PLpgSQL_nsitem::itemtype, ns_top, PLPGSQL_NSTYPE_LABEL, and PLpgSQL_nsitem::prev.

◆ plpgsql_ns_push()

void plpgsql_ns_push ( const char *  label,
PLpgSQL_label_type  label_type 
)

Definition at line 54 of file pl_funcs.c.

55 {
56  if (label == NULL)
57  label = "";
58  plpgsql_ns_additem(PLPGSQL_NSTYPE_LABEL, (int) label_type, label);
59 }
static char * label

References label, plpgsql_ns_additem(), and PLPGSQL_NSTYPE_LABEL.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_ns_top()

PLpgSQL_nsitem* plpgsql_ns_top ( void  )

◆ plpgsql_parse_cwordrowtype()

PLpgSQL_type* plpgsql_parse_cwordrowtype ( List idents)

Definition at line 1795 of file pl_comp.c.

1796 {
1797  Oid classOid;
1798  Oid typOid;
1799  RangeVar *relvar;
1800  MemoryContext oldCxt;
1801 
1802  /*
1803  * As above, this is a relation lookup but could be a type lookup if we
1804  * weren't being backwards-compatible about error wording.
1805  */
1806 
1807  /* Avoid memory leaks in long-term function context */
1809 
1810  /* Look up relation name. Can't lock it - we might not have privileges. */
1811  relvar = makeRangeVarFromNameList(idents);
1812  classOid = RangeVarGetRelid(relvar, NoLock, false);
1813 
1814  /* Some relkinds lack type OIDs */
1815  typOid = get_rel_type_id(classOid);
1816  if (!OidIsValid(typOid))
1817  ereport(ERROR,
1818  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1819  errmsg("relation \"%s\" does not have a composite type",
1820  relvar->relname)));
1821 
1822  MemoryContextSwitchTo(oldCxt);
1823 
1824  /* Build and return the row type struct */
1825  return plpgsql_build_datatype(typOid, -1, InvalidOid,
1826  makeTypeNameFromNameList(idents));
1827 }
#define NoLock
Definition: lockdefs.h:34
Oid get_rel_type_id(Oid relid)
Definition: lsyscache.c:1979
TypeName * makeTypeNameFromNameList(List *names)
Definition: makefuncs.c:481
RangeVar * makeRangeVarFromNameList(const List *names)
Definition: namespace.c:3554
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:80
char * relname
Definition: primnodes.h:82

References ereport, errcode(), errmsg(), ERROR, get_rel_type_id(), InvalidOid, makeRangeVarFromNameList(), makeTypeNameFromNameList(), MemoryContextSwitchTo(), NoLock, OidIsValid, plpgsql_build_datatype(), plpgsql_compile_tmp_cxt, RangeVarGetRelid, and RangeVar::relname.

◆ plpgsql_parse_cwordtype()

PLpgSQL_type* plpgsql_parse_cwordtype ( List idents)

Definition at line 1646 of file pl_comp.c.

1647 {
1648  PLpgSQL_type *dtype = NULL;
1649  PLpgSQL_nsitem *nse;
1650  int nnames;
1651  RangeVar *relvar = NULL;
1652  const char *fldname = NULL;
1653  Oid classOid;
1654  HeapTuple attrtup = NULL;
1655  HeapTuple typetup = NULL;
1656  Form_pg_attribute attrStruct;
1657  MemoryContext oldCxt;
1658 
1659  /* Avoid memory leaks in the long-term function context */
1661 
1662  if (list_length(idents) == 2)
1663  {
1664  /*
1665  * Do a lookup in the current namespace stack
1666  */
1667  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1668  strVal(linitial(idents)),
1669  strVal(lsecond(idents)),
1670  NULL,
1671  &nnames);
1672 
1673  if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)
1674  {
1675  /* Block-qualified reference to scalar variable. */
1676  dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1677  goto done;
1678  }
1679  else if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_REC &&
1680  nnames == 2)
1681  {
1682  /* Block-qualified reference to record variable. */
1683  dtype = ((PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]))->datatype;
1684  goto done;
1685  }
1686 
1687  /*
1688  * First word could also be a table name
1689  */
1690  relvar = makeRangeVar(NULL,
1691  strVal(linitial(idents)),
1692  -1);
1693  fldname = strVal(lsecond(idents));
1694  }
1695  else
1696  {
1697  /*
1698  * We could check for a block-qualified reference to a field of a
1699  * record variable, but %TYPE is documented as applying to variables,
1700  * not fields of variables. Things would get rather ambiguous if we
1701  * allowed either interpretation.
1702  */
1703  List *rvnames;
1704 
1705  Assert(list_length(idents) > 2);
1706  rvnames = list_delete_last(list_copy(idents));
1707  relvar = makeRangeVarFromNameList(rvnames);
1708  fldname = strVal(llast(idents));
1709  }
1710 
1711  /* Look up relation name. Can't lock it - we might not have privileges. */
1712  classOid = RangeVarGetRelid(relvar, NoLock, false);
1713 
1714  /*
1715  * Fetch the named table field and its type
1716  */
1717  attrtup = SearchSysCacheAttName(classOid, fldname);
1718  if (!HeapTupleIsValid(attrtup))
1719  ereport(ERROR,
1720  (errcode(ERRCODE_UNDEFINED_COLUMN),
1721  errmsg("column \"%s\" of relation \"%s\" does not exist",
1722  fldname, relvar->relname)));
1723  attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
1724 
1725  typetup = SearchSysCache1(TYPEOID,
1726  ObjectIdGetDatum(attrStruct->atttypid));
1727  if (!HeapTupleIsValid(typetup))
1728  elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);
1729 
1730  /*
1731  * Found that - build a compiler type struct in the caller's cxt and
1732  * return it. Note that we treat the type as being found-by-OID; no
1733  * attempt to re-look-up the type name will happen during invalidations.
1734  */
1735  MemoryContextSwitchTo(oldCxt);
1736  dtype = build_datatype(typetup,
1737  attrStruct->atttypmod,
1738  attrStruct->attcollation,
1739  NULL);
1741 
1742 done:
1743  if (HeapTupleIsValid(attrtup))
1744  ReleaseSysCache(attrtup);
1745  if (HeapTupleIsValid(typetup))
1746  ReleaseSysCache(typetup);
1747 
1748  MemoryContextSwitchTo(oldCxt);
1749  return dtype;
1750 }
List * list_copy(const List *oldlist)
Definition: list.c:1573
List * list_delete_last(List *list)
Definition: list.c:957
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
Definition: makefuncs.c:424
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209
#define llast(l)
Definition: pg_list.h:198
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
PLpgSQL_nsitem * plpgsql_ns_top(void)
Definition: pl_funcs.c:81
PLpgSQL_nsitem * plpgsql_ns_lookup(PLpgSQL_nsitem *ns_cur, bool localmode, const char *name1, const char *name2, const char *name3, int *names_used)
Definition: pl_funcs.c:130
Definition: pg_list.h:54
HeapTuple SearchSysCacheAttName(Oid relid, const char *attname)
Definition: syscache.c:480
#define strVal(v)
Definition: value.h:82

References Assert, build_datatype(), elog, ereport, errcode(), errmsg(), ERROR, GETSTRUCT, HeapTupleIsValid, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, linitial, list_copy(), list_delete_last(), list_length(), llast, lsecond, makeRangeVar(), makeRangeVarFromNameList(), MemoryContextSwitchTo(), NoLock, ObjectIdGetDatum(), plpgsql_compile_tmp_cxt, plpgsql_Datums, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_VAR, RangeVarGetRelid, ReleaseSysCache(), RangeVar::relname, SearchSysCache1(), SearchSysCacheAttName(), and strVal.

◆ plpgsql_parse_dblword()

bool plpgsql_parse_dblword ( char *  word1,
char *  word2,
PLwdatum wdatum,
PLcword cword 
)

Definition at line 1440 of file pl_comp.c.

1442 {
1443  PLpgSQL_nsitem *ns;
1444  List *idents;
1445  int nnames;
1446 
1447  idents = list_make2(makeString(word1),
1448  makeString(word2));
1449 
1450  /*
1451  * We should do nothing in DECLARE sections. In SQL expressions, we
1452  * really only need to make sure that RECFIELD datums are created when
1453  * needed. In all the cases handled by this function, returning a T_DATUM
1454  * with a two-word idents string is the right thing.
1455  */
1457  {
1458  /*
1459  * Do a lookup in the current namespace stack
1460  */
1461  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1462  word1, word2, NULL,
1463  &nnames);
1464  if (ns != NULL)
1465  {
1466  switch (ns->itemtype)
1467  {
1468  case PLPGSQL_NSTYPE_VAR:
1469  /* Block-qualified reference to scalar variable. */
1470  wdatum->datum = plpgsql_Datums[ns->itemno];
1471  wdatum->ident = NULL;
1472  wdatum->quoted = false; /* not used */
1473  wdatum->idents = idents;
1474  return true;
1475 
1476  case PLPGSQL_NSTYPE_REC:
1477  if (nnames == 1)
1478  {
1479  /*
1480  * First word is a record name, so second word could
1481  * be a field in this record. We build a RECFIELD
1482  * datum whether it is or not --- any error will be
1483  * detected later.
1484  */
1485  PLpgSQL_rec *rec;
1486  PLpgSQL_recfield *new;
1487 
1488  rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1489  new = plpgsql_build_recfield(rec, word2);
1490 
1491  wdatum->datum = (PLpgSQL_datum *) new;
1492  }
1493  else
1494  {
1495  /* Block-qualified reference to record variable. */
1496  wdatum->datum = plpgsql_Datums[ns->itemno];
1497  }
1498  wdatum->ident = NULL;
1499  wdatum->quoted = false; /* not used */
1500  wdatum->idents = idents;
1501  return true;
1502 
1503  default:
1504  break;
1505  }
1506  }
1507  }
1508 
1509  /* Nothing found */
1510  cword->idents = idents;
1511  return false;
1512 }
#define list_make2(x1, x2)
Definition: pg_list.h:214
PLpgSQL_recfield * plpgsql_build_recfield(PLpgSQL_rec *rec, const char *fldname)
Definition: pl_comp.c:1996
IdentifierLookup plpgsql_IdentifierLookup
Definition: pl_scanner.c:26
List * idents
Definition: plpgsql.h:1172
List * idents
Definition: plpgsql.h:1180
char * ident
Definition: plpgsql.h:1178
PLpgSQL_datum * datum
Definition: plpgsql.h:1177
bool quoted
Definition: plpgsql.h:1179
String * makeString(char *str)
Definition: value.c:63

References PLwdatum::datum, PLwdatum::ident, IDENTIFIER_LOOKUP_DECLARE, PLcword::idents, PLwdatum::idents, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, list_make2, makeString(), plpgsql_build_recfield(), plpgsql_Datums, plpgsql_IdentifierLookup, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_VAR, and PLwdatum::quoted.

Referenced by plpgsql_yylex().

◆ plpgsql_parse_err_condition()

PLpgSQL_condition* plpgsql_parse_err_condition ( char *  condname)

Definition at line 2244 of file pl_comp.c.

2245 {
2246  int i;
2247  PLpgSQL_condition *new;
2248  PLpgSQL_condition *prev;
2249 
2250  /*
2251  * XXX Eventually we will want to look for user-defined exception names
2252  * here.
2253  */
2254 
2255  /*
2256  * OTHERS is represented as code 0 (which would map to '00000', but we
2257  * have no need to represent that as an exception condition).
2258  */
2259  if (strcmp(condname, "others") == 0)
2260  {
2261  new = palloc(sizeof(PLpgSQL_condition));
2262  new->sqlerrstate = 0;
2263  new->condname = condname;
2264  new->next = NULL;
2265  return new;
2266  }
2267 
2268  prev = NULL;
2269  for (i = 0; exception_label_map[i].label != NULL; i++)
2270  {
2271  if (strcmp(condname, exception_label_map[i].label) == 0)
2272  {
2273  new = palloc(sizeof(PLpgSQL_condition));
2274  new->sqlerrstate = exception_label_map[i].sqlerrstate;
2275  new->condname = condname;
2276  new->next = prev;
2277  prev = new;
2278  }
2279  }
2280 
2281  if (!prev)
2282  ereport(ERROR,
2283  (errcode(ERRCODE_UNDEFINED_OBJECT),
2284  errmsg("unrecognized exception condition \"%s\"",
2285  condname)));
2286 
2287  return prev;
2288 }
static const ExceptionLabelMap exception_label_map[]
Definition: pl_comp.c:81
const char * label
Definition: pl_comp.c:77

References ereport, errcode(), errmsg(), ERROR, exception_label_map, i, label, ExceptionLabelMap::label, palloc(), and ExceptionLabelMap::sqlerrstate.

◆ plpgsql_parse_tripword()

bool plpgsql_parse_tripword ( char *  word1,
char *  word2,
char *  word3,
PLwdatum wdatum,
PLcword cword 
)

Definition at line 1521 of file pl_comp.c.

1523 {
1524  PLpgSQL_nsitem *ns;
1525  List *idents;
1526  int nnames;
1527 
1528  /*
1529  * We should do nothing in DECLARE sections. In SQL expressions, we need
1530  * to make sure that RECFIELD datums are created when needed, and we need
1531  * to be careful about how many names are reported as belonging to the
1532  * T_DATUM: the third word could be a sub-field reference, which we don't
1533  * care about here.
1534  */
1536  {
1537  /*
1538  * Do a lookup in the current namespace stack. Must find a record
1539  * reference, else ignore.
1540  */
1541  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1542  word1, word2, word3,
1543  &nnames);
1544  if (ns != NULL)
1545  {
1546  switch (ns->itemtype)
1547  {
1548  case PLPGSQL_NSTYPE_REC:
1549  {
1550  PLpgSQL_rec *rec;
1551  PLpgSQL_recfield *new;
1552 
1553  rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
1554  if (nnames == 1)
1555  {
1556  /*
1557  * First word is a record name, so second word
1558  * could be a field in this record (and the third,
1559  * a sub-field). We build a RECFIELD datum
1560  * whether it is or not --- any error will be
1561  * detected later.
1562  */
1563  new = plpgsql_build_recfield(rec, word2);
1564  idents = list_make2(makeString(word1),
1565  makeString(word2));
1566  }
1567  else
1568  {
1569  /* Block-qualified reference to record variable. */
1570  new = plpgsql_build_recfield(rec, word3);
1571  idents = list_make3(makeString(word1),
1572  makeString(word2),
1573  makeString(word3));
1574  }
1575  wdatum->datum = (PLpgSQL_datum *) new;
1576  wdatum->ident = NULL;
1577  wdatum->quoted = false; /* not used */
1578  wdatum->idents = idents;
1579  return true;
1580  }
1581 
1582  default:
1583  break;
1584  }
1585  }
1586  }
1587 
1588  /* Nothing found */
1589  idents = list_make3(makeString(word1),
1590  makeString(word2),
1591  makeString(word3));
1592  cword->idents = idents;
1593  return false;
1594 }
#define list_make3(x1, x2, x3)
Definition: pg_list.h:216

References PLwdatum::datum, PLwdatum::ident, IDENTIFIER_LOOKUP_DECLARE, PLcword::idents, PLwdatum::idents, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, list_make2, list_make3, makeString(), plpgsql_build_recfield(), plpgsql_Datums, plpgsql_IdentifierLookup, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, and PLwdatum::quoted.

Referenced by plpgsql_yylex().

◆ plpgsql_parse_word()

bool plpgsql_parse_word ( char *  word1,
const char *  yytxt,
bool  lookup,
PLwdatum wdatum,
PLword word 
)

Definition at line 1385 of file pl_comp.c.

1387 {
1388  PLpgSQL_nsitem *ns;
1389 
1390  /*
1391  * We should not lookup variables in DECLARE sections. In SQL
1392  * expressions, there's no need to do so either --- lookup will happen
1393  * when the expression is compiled.
1394  */
1396  {
1397  /*
1398  * Do a lookup in the current namespace stack
1399  */
1400  ns = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1401  word1, NULL, NULL,
1402  NULL);
1403 
1404  if (ns != NULL)
1405  {
1406  switch (ns->itemtype)
1407  {
1408  case PLPGSQL_NSTYPE_VAR:
1409  case PLPGSQL_NSTYPE_REC:
1410  wdatum->datum = plpgsql_Datums[ns->itemno];
1411  wdatum->ident = word1;
1412  wdatum->quoted = (yytxt[0] == '"');
1413  wdatum->idents = NIL;
1414  return true;
1415 
1416  default:
1417  /* plpgsql_ns_lookup should never return anything else */
1418  elog(ERROR, "unrecognized plpgsql itemtype: %d",
1419  ns->itemtype);
1420  }
1421  }
1422  }
1423 
1424  /*
1425  * Nothing found - up to now it's a word without any special meaning for
1426  * us.
1427  */
1428  word->ident = word1;
1429  word->quoted = (yytxt[0] == '"');
1430  return false;
1431 }
#define NIL
Definition: pg_list.h:68
static void word(struct vars *v, int dir, struct state *lp, struct state *rp)
Definition: regcomp.c:1476
Definition: zic.c:304

References PLwdatum::datum, elog, ERROR, PLwdatum::ident, IDENTIFIER_LOOKUP_NORMAL, PLwdatum::idents, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, NIL, plpgsql_Datums, plpgsql_IdentifierLookup, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, PLPGSQL_NSTYPE_VAR, PLwdatum::quoted, and word().

Referenced by plpgsql_yylex().

◆ plpgsql_parse_wordrowtype()

PLpgSQL_type* plpgsql_parse_wordrowtype ( char *  ident)

Definition at line 1758 of file pl_comp.c.

1759 {
1760  Oid classOid;
1761  Oid typOid;
1762 
1763  /*
1764  * Look up the relation. Note that because relation rowtypes have the
1765  * same names as their relations, this could be handled as a type lookup
1766  * equally well; we use the relation lookup code path only because the
1767  * errors thrown here have traditionally referred to relations not types.
1768  * But we'll make a TypeName in case we have to do re-look-up of the type.
1769  */
1770  classOid = RelnameGetRelid(ident);
1771  if (!OidIsValid(classOid))
1772  ereport(ERROR,
1774  errmsg("relation \"%s\" does not exist", ident)));
1775 
1776  /* Some relkinds lack type OIDs */
1777  typOid = get_rel_type_id(classOid);
1778  if (!OidIsValid(typOid))
1779  ereport(ERROR,
1780  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1781  errmsg("relation \"%s\" does not have a composite type",
1782  ident)));
1783 
1784  /* Build and return the row type struct */
1785  return plpgsql_build_datatype(typOid, -1, InvalidOid,
1786  makeTypeName(ident));
1787 }
#define ident
Definition: indent_codes.h:47
TypeName * makeTypeName(char *typnam)
Definition: makefuncs.c:469
Oid RelnameGetRelid(const char *relname)
Definition: namespace.c:885
#define ERRCODE_UNDEFINED_TABLE
Definition: pgbench.c:78

References ereport, errcode(), ERRCODE_UNDEFINED_TABLE, errmsg(), ERROR, get_rel_type_id(), ident, InvalidOid, makeTypeName(), OidIsValid, plpgsql_build_datatype(), and RelnameGetRelid().

◆ plpgsql_parse_wordtype()

PLpgSQL_type* plpgsql_parse_wordtype ( char *  ident)

Definition at line 1605 of file pl_comp.c.

1606 {
1607  PLpgSQL_nsitem *nse;
1608 
1609  /*
1610  * Do a lookup in the current namespace stack
1611  */
1612  nse = plpgsql_ns_lookup(plpgsql_ns_top(), false,
1613  ident, NULL, NULL,
1614  NULL);
1615 
1616  if (nse != NULL)
1617  {
1618  switch (nse->itemtype)
1619  {
1620  case PLPGSQL_NSTYPE_VAR:
1621  return ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
1622  case PLPGSQL_NSTYPE_REC:
1623  return ((PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]))->datatype;
1624  default:
1625  break;
1626  }
1627  }
1628 
1629  /* No match, complain */
1630  ereport(ERROR,
1631  (errcode(ERRCODE_UNDEFINED_OBJECT),
1632  errmsg("variable \"%s\" does not exist", ident)));
1633  return NULL; /* keep compiler quiet */
1634 }

References ereport, errcode(), errmsg(), ERROR, ident, PLpgSQL_nsitem::itemno, PLpgSQL_nsitem::itemtype, plpgsql_Datums, plpgsql_ns_lookup(), plpgsql_ns_top(), PLPGSQL_NSTYPE_REC, and PLPGSQL_NSTYPE_VAR.

◆ plpgsql_parser_setup()

PGDLLEXPORT void plpgsql_parser_setup ( struct ParseState pstate,
PLpgSQL_expr expr 
)

Definition at line 1076 of file pl_comp.c.

1077 {
1081  /* no need to use p_coerce_param_hook */
1082  pstate->p_ref_hook_state = (void *) expr;
1083 }
static Node * plpgsql_param_ref(ParseState *pstate, ParamRef *pref)
Definition: pl_comp.c:1147
static Node * plpgsql_pre_column_ref(ParseState *pstate, ColumnRef *cref)
Definition: pl_comp.c:1089
static Node * plpgsql_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)
Definition: pl_comp.c:1103
void * p_ref_hook_state
Definition: parse_node.h:258
ParseParamRefHook p_paramref_hook
Definition: parse_node.h:256
PreParseColumnRefHook p_pre_columnref_hook
Definition: parse_node.h:254
PostParseColumnRefHook p_post_columnref_hook
Definition: parse_node.h:255

References ParseState::p_paramref_hook, ParseState::p_post_columnref_hook, ParseState::p_pre_columnref_hook, ParseState::p_ref_hook_state, plpgsql_param_ref(), plpgsql_post_column_ref(), and plpgsql_pre_column_ref().

Referenced by exec_prepare_plan(), and plpgsql_estate_setup().

◆ plpgsql_peek()

int plpgsql_peek ( void  )

Definition at line 437 of file pl_scanner.c.

438 {
439  int tok1;
440  TokenAuxData aux1;
441 
442  tok1 = internal_yylex(&aux1);
443  push_back_token(tok1, &aux1);
444  return tok1;
445 }
static void push_back_token(int token, TokenAuxData *auxdata)
Definition: pl_scanner.c:371
static int internal_yylex(TokenAuxData *auxdata)
Definition: pl_scanner.c:325

References internal_yylex(), and push_back_token().

◆ plpgsql_peek2()

void plpgsql_peek2 ( int *  tok1_p,
int *  tok2_p,
int *  tok1_loc,
int *  tok2_loc 
)

Definition at line 456 of file pl_scanner.c.

457 {
458  int tok1,
459  tok2;
460  TokenAuxData aux1,
461  aux2;
462 
463  tok1 = internal_yylex(&aux1);
464  tok2 = internal_yylex(&aux2);
465 
466  *tok1_p = tok1;
467  if (tok1_loc)
468  *tok1_loc = aux1.lloc;
469  *tok2_p = tok2;
470  if (tok2_loc)
471  *tok2_loc = aux2.lloc;
472 
473  push_back_token(tok2, &aux2);
474  push_back_token(tok1, &aux1);
475 }
YYLTYPE lloc
Definition: pl_scanner.c:94

References internal_yylex(), TokenAuxData::lloc, and push_back_token().

◆ plpgsql_push_back_token()

void plpgsql_push_back_token ( int  token)

Definition at line 387 of file pl_scanner.c.

388 {
389  TokenAuxData auxdata;
390 
391  auxdata.lval = plpgsql_yylval;
392  auxdata.lloc = plpgsql_yylloc;
393  auxdata.leng = plpgsql_yyleng;
394  push_back_token(token, &auxdata);
395 }
#define token
Definition: indent_globs.h:126
static int plpgsql_yyleng
Definition: pl_scanner.c:113
YYSTYPE lval
Definition: pl_scanner.c:93

References TokenAuxData::leng, TokenAuxData::lloc, TokenAuxData::lval, plpgsql_yyleng, push_back_token(), and token.

◆ plpgsql_recognize_err_condition()

PGDLLEXPORT int plpgsql_recognize_err_condition ( const char *  condname,
bool  allow_sqlstate 
)

Definition at line 2208 of file pl_comp.c.

2209 {
2210  int i;
2211 
2212  if (allow_sqlstate)
2213  {
2214  if (strlen(condname) == 5 &&
2215  strspn(condname, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
2216  return MAKE_SQLSTATE(condname[0],
2217  condname[1],
2218  condname[2],
2219  condname[3],
2220  condname[4]);
2221  }
2222 
2223  for (i = 0; exception_label_map[i].label != NULL; i++)
2224  {
2225  if (strcmp(condname, exception_label_map[i].label) == 0)
2227  }
2228 
2229  ereport(ERROR,
2230  (errcode(ERRCODE_UNDEFINED_OBJECT),
2231  errmsg("unrecognized exception condition \"%s\"",
2232  condname)));
2233  return 0; /* keep compiler quiet */
2234 }
#define MAKE_SQLSTATE(ch1, ch2, ch3, ch4, ch5)
Definition: elog.h:56

References ereport, errcode(), errmsg(), ERROR, exception_label_map, i, label, ExceptionLabelMap::label, MAKE_SQLSTATE, and ExceptionLabelMap::sqlerrstate.

Referenced by exec_stmt_raise().

◆ plpgsql_scanner_errposition()

int plpgsql_scanner_errposition ( int  location)

Definition at line 489 of file pl_scanner.c.

490 {
491  int pos;
492 
493  if (location < 0 || scanorig == NULL)
494  return 0; /* no-op if location is unknown */
495 
496  /* Convert byte offset to character number */
497  pos = pg_mbstrlen_with_len(scanorig, location) + 1;
498  /* And pass it to the ereport mechanism */
499  (void) internalerrposition(pos);
500  /* Also pass the function body string */
501  return internalerrquery(scanorig);
502 }
int internalerrquery(const char *query)
Definition: elog.c:1482
int internalerrposition(int cursorpos)
Definition: elog.c:1462
int pg_mbstrlen_with_len(const char *mbstr, int limit)
Definition: mbutils.c:1057

References internalerrposition(), internalerrquery(), pg_mbstrlen_with_len(), and scanorig.

Referenced by plpgsql_yyerror().

◆ plpgsql_scanner_finish()

void plpgsql_scanner_finish ( void  )

Definition at line 630 of file pl_scanner.c.

631 {
632  /* release storage */
634  /* avoid leaving any dangling pointers */
635  yyscanner = NULL;
636  scanorig = NULL;
637 }
static core_yyscan_t yyscanner
Definition: pl_scanner.c:106
void scanner_finish(core_yyscan_t yyscanner)

References scanner_finish(), scanorig, and yyscanner.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_scanner_init()

void plpgsql_scanner_init ( const char *  str)

Definition at line 603 of file pl_scanner.c.

604 {
605  /* Start up the core scanner */
607  &ReservedPLKeywords, ReservedPLKeywordTokens);
608 
609  /*
610  * scanorig points to the original string, which unlike the scanner's
611  * scanbuf won't be modified on-the-fly by flex. Notice that although
612  * yytext points into scanbuf, we rely on being able to apply locations
613  * (offsets from string start) to scanorig as well.
614  */
615  scanorig = str;
616 
617  /* Other setup */
619  plpgsql_yytoken = 0;
620 
621  num_pushbacks = 0;
622 
624 }
const char * str
static int num_pushbacks
Definition: pl_scanner.c:121
static int plpgsql_yytoken
Definition: pl_scanner.c:116
static const uint16 ReservedPLKeywordTokens[]
Definition: pl_scanner.c:66
static core_yy_extra_type core_yy
Definition: pl_scanner.c:107
core_yyscan_t scanner_init(const char *str, core_yy_extra_type *yyext, const ScanKeywordList *keywordlist, const uint16 *keyword_tokens)

References core_yy, IDENTIFIER_LOOKUP_NORMAL, location_lineno_init(), num_pushbacks, plpgsql_IdentifierLookup, plpgsql_yytoken, ReservedPLKeywordTokens, scanner_init(), scanorig, str, and yyscanner.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_stmt_typename()

PGDLLEXPORT const char* plpgsql_stmt_typename ( PLpgSQL_stmt stmt)

Definition at line 232 of file pl_funcs.c.

233 {
234  switch (stmt->cmd_type)
235  {
236  case PLPGSQL_STMT_BLOCK:
237  return _("statement block");
238  case PLPGSQL_STMT_ASSIGN:
239  return _("assignment");
240  case PLPGSQL_STMT_IF:
241  return "IF";
242  case PLPGSQL_STMT_CASE:
243  return "CASE";
244  case PLPGSQL_STMT_LOOP:
245  return "LOOP";
246  case PLPGSQL_STMT_WHILE:
247  return "WHILE";
248  case PLPGSQL_STMT_FORI:
249  return _("FOR with integer loop variable");
250  case PLPGSQL_STMT_FORS:
251  return _("FOR over SELECT rows");
252  case PLPGSQL_STMT_FORC:
253  return _("FOR over cursor");
255  return _("FOREACH over array");
256  case PLPGSQL_STMT_EXIT:
257  return ((PLpgSQL_stmt_exit *) stmt)->is_exit ? "EXIT" : "CONTINUE";
258  case PLPGSQL_STMT_RETURN:
259  return "RETURN";
261  return "RETURN NEXT";
263  return "RETURN QUERY";
264  case PLPGSQL_STMT_RAISE:
265  return "RAISE";
266  case PLPGSQL_STMT_ASSERT:
267  return "ASSERT";
269  return _("SQL statement");
271  return "EXECUTE";
273  return _("FOR over EXECUTE statement");
275  return ((PLpgSQL_stmt_getdiag *) stmt)->is_stacked ?
276  "GET STACKED DIAGNOSTICS" : "GET DIAGNOSTICS";
277  case PLPGSQL_STMT_OPEN:
278  return "OPEN";
279  case PLPGSQL_STMT_FETCH:
280  return ((PLpgSQL_stmt_fetch *) stmt)->is_move ? "MOVE" : "FETCH";
281  case PLPGSQL_STMT_CLOSE:
282  return "CLOSE";
284  return "PERFORM";
285  case PLPGSQL_STMT_CALL:
286  return ((PLpgSQL_stmt_call *) stmt)->is_call ? "CALL" : "DO";
287  case PLPGSQL_STMT_COMMIT:
288  return "COMMIT";
290  return "ROLLBACK";
291  }
292 
293  return "unknown";
294 }
#define _(x)
Definition: elog.c:90
#define stmt
Definition: indent_codes.h:59

References _, PLPGSQL_STMT_ASSERT, PLPGSQL_STMT_ASSIGN, PLPGSQL_STMT_BLOCK, PLPGSQL_STMT_CALL, PLPGSQL_STMT_CASE, PLPGSQL_STMT_CLOSE, PLPGSQL_STMT_COMMIT, PLPGSQL_STMT_DYNEXECUTE, PLPGSQL_STMT_DYNFORS, PLPGSQL_STMT_EXECSQL, PLPGSQL_STMT_EXIT, PLPGSQL_STMT_FETCH, PLPGSQL_STMT_FORC, PLPGSQL_STMT_FOREACH_A, PLPGSQL_STMT_FORI, PLPGSQL_STMT_FORS, PLPGSQL_STMT_GETDIAG, PLPGSQL_STMT_IF, PLPGSQL_STMT_LOOP, PLPGSQL_STMT_OPEN, PLPGSQL_STMT_PERFORM, PLPGSQL_STMT_RAISE, PLPGSQL_STMT_RETURN, PLPGSQL_STMT_RETURN_NEXT, PLPGSQL_STMT_RETURN_QUERY, PLPGSQL_STMT_ROLLBACK, PLPGSQL_STMT_WHILE, and stmt.

Referenced by plpgsql_exec_error_callback().

◆ plpgsql_subxact_cb()

void plpgsql_subxact_cb ( SubXactEvent  event,
SubTransactionId  mySubid,
SubTransactionId  parentSubid,
void *  arg 
)

Definition at line 8524 of file pl_exec.c.

8526 {
8527  if (event == SUBXACT_EVENT_COMMIT_SUB || event == SUBXACT_EVENT_ABORT_SUB)
8528  {
8529  while (simple_econtext_stack != NULL &&
8530  simple_econtext_stack->xact_subxid == mySubid)
8531  {
8533 
8535  (event == SUBXACT_EVENT_COMMIT_SUB));
8539  }
8540  }
8541 }
static int32 next
Definition: blutils.c:219
void FreeExprContext(ExprContext *econtext, bool isCommit)
Definition: execUtils.c:416
void pfree(void *pointer)
Definition: mcxt.c:1521
static SimpleEcontextStackEntry * simple_econtext_stack
Definition: pl_exec.c:91
struct SimpleEcontextStackEntry * next
Definition: pl_exec.c:87
ExprContext * stack_econtext
Definition: pl_exec.c:85
SubTransactionId xact_subxid
Definition: pl_exec.c:86
@ SUBXACT_EVENT_ABORT_SUB
Definition: xact.h:144
@ SUBXACT_EVENT_COMMIT_SUB
Definition: xact.h:143

References FreeExprContext(), next, SimpleEcontextStackEntry::next, pfree(), simple_econtext_stack, SimpleEcontextStackEntry::stack_econtext, SUBXACT_EVENT_ABORT_SUB, SUBXACT_EVENT_COMMIT_SUB, and SimpleEcontextStackEntry::xact_subxid.

Referenced by _PG_init(), and plpgsql_inline_handler().

◆ plpgsql_token_is_unreserved_keyword()

bool plpgsql_token_is_unreserved_keyword ( int  token)

Definition at line 404 of file pl_scanner.c.

405 {
406  int i;
407 
408  for (i = 0; i < lengthof(UnreservedPLKeywordTokens); i++)
409  {
411  return true;
412  }
413  return false;
414 }
#define lengthof(array)
Definition: c.h:793
static const uint16 UnreservedPLKeywordTokens[]
Definition: pl_scanner.c:70

References i, lengthof, token, and UnreservedPLKeywordTokens.

◆ plpgsql_token_length()

int plpgsql_token_length ( void  )

Definition at line 313 of file pl_scanner.c.

314 {
315  return plpgsql_yyleng;
316 }

References plpgsql_yyleng.

◆ plpgsql_xact_cb()

void plpgsql_xact_cb ( XactEvent  event,
void *  arg 
)

Definition at line 8482 of file pl_exec.c.

8483 {
8484  /*
8485  * If we are doing a clean transaction shutdown, free the EState and tell
8486  * the resowner to release whatever plancache references it has, so that
8487  * all remaining resources will be released correctly. (We don't need to
8488  * actually delete the resowner here; deletion of the
8489  * TopTransactionResourceOwner will take care of that.)
8490  *
8491  * In an abort, we expect the regular abort recovery procedures to release
8492  * everything of interest, so just clear our pointers.
8493  */
8494  if (event == XACT_EVENT_COMMIT ||
8495  event == XACT_EVENT_PARALLEL_COMMIT ||
8496  event == XACT_EVENT_PREPARE)
8497  {
8498  simple_econtext_stack = NULL;
8499 
8506  }
8507  else if (event == XACT_EVENT_ABORT ||
8508  event == XACT_EVENT_PARALLEL_ABORT)
8509  {
8510  simple_econtext_stack = NULL;
8513  }
8514 }
void FreeExecutorState(EState *estate)
Definition: execUtils.c:191
static ResourceOwner shared_simple_eval_resowner
Definition: pl_exec.c:101
static EState * shared_simple_eval_estate
Definition: pl_exec.c:90
void ReleaseAllPlanCacheRefsInOwner(ResourceOwner owner)
Definition: plancache.c:2234
@ XACT_EVENT_COMMIT
Definition: xact.h:128
@ XACT_EVENT_PARALLEL_COMMIT
Definition: xact.h:129
@ XACT_EVENT_ABORT
Definition: xact.h:130
@ XACT_EVENT_PARALLEL_ABORT
Definition: xact.h:131
@ XACT_EVENT_PREPARE
Definition: xact.h:132

References FreeExecutorState(), ReleaseAllPlanCacheRefsInOwner(), shared_simple_eval_estate, shared_simple_eval_resowner, simple_econtext_stack, XACT_EVENT_ABORT, XACT_EVENT_COMMIT, XACT_EVENT_PARALLEL_ABORT, XACT_EVENT_PARALLEL_COMMIT, and XACT_EVENT_PREPARE.

Referenced by _PG_init().

◆ plpgsql_yyerror()

void plpgsql_yyerror ( const char *  message)

Definition at line 516 of file pl_scanner.c.

517 {
518  char *yytext = core_yy.scanbuf + plpgsql_yylloc;
519 
520  if (*yytext == '\0')
521  {
522  ereport(ERROR,
523  (errcode(ERRCODE_SYNTAX_ERROR),
524  /* translator: %s is typically the translation of "syntax error" */
525  errmsg("%s at end of input", _(message)),
526  plpgsql_scanner_errposition(plpgsql_yylloc)));
527  }
528  else
529  {
530  /*
531  * If we have done any lookahead then flex will have restored the
532  * character after the end-of-token. Zap it again so that we report
533  * only the single token here. This modifies scanbuf but we no longer
534  * care about that.
535  */
536  yytext[plpgsql_yyleng] = '\0';
537 
538  ereport(ERROR,
539  (errcode(ERRCODE_SYNTAX_ERROR),
540  /* translator: first %s is typically the translation of "syntax error" */
541  errmsg("%s at or near \"%s\"", _(message), yytext),
542  plpgsql_scanner_errposition(plpgsql_yylloc)));
543  }
544 }
int plpgsql_scanner_errposition(int location)
Definition: pl_scanner.c:489
char * scanbuf
Definition: scanner.h:72

References _, core_yy, ereport, errcode(), errmsg(), ERROR, plpgsql_scanner_errposition(), plpgsql_yyleng, and core_yy_extra_type::scanbuf.

◆ plpgsql_yylex()

int plpgsql_yylex ( void  )

Definition at line 146 of file pl_scanner.c.

147 {
148  int tok1;
149  TokenAuxData aux1;
150  int kwnum;
151 
152  tok1 = internal_yylex(&aux1);
153  if (tok1 == IDENT || tok1 == PARAM)
154  {
155  int tok2;
156  TokenAuxData aux2;
157 
158  tok2 = internal_yylex(&aux2);
159  if (tok2 == '.')
160  {
161  int tok3;
162  TokenAuxData aux3;
163 
164  tok3 = internal_yylex(&aux3);
165  if (tok3 == IDENT)
166  {
167  int tok4;
168  TokenAuxData aux4;
169 
170  tok4 = internal_yylex(&aux4);
171  if (tok4 == '.')
172  {
173  int tok5;
174  TokenAuxData aux5;
175 
176  tok5 = internal_yylex(&aux5);
177  if (tok5 == IDENT)
178  {
179  if (plpgsql_parse_tripword(aux1.lval.str,
180  aux3.lval.str,
181  aux5.lval.str,
182  &aux1.lval.wdatum,
183  &aux1.lval.cword))
184  tok1 = T_DATUM;
185  else
186  tok1 = T_CWORD;
187  /* Adjust token length to include A.B.C */
188  aux1.leng = aux5.lloc - aux1.lloc + aux5.leng;
189  }
190  else
191  {
192  /* not A.B.C, so just process A.B */
193  push_back_token(tok5, &aux5);
194  push_back_token(tok4, &aux4);
195  if (plpgsql_parse_dblword(aux1.lval.str,
196  aux3.lval.str,
197  &aux1.lval.wdatum,
198  &aux1.lval.cword))
199  tok1 = T_DATUM;
200  else
201  tok1 = T_CWORD;
202  /* Adjust token length to include A.B */
203  aux1.leng = aux3.lloc - aux1.lloc + aux3.leng;
204  }
205  }
206  else
207  {
208  /* not A.B.C, so just process A.B */
209  push_back_token(tok4, &aux4);
210  if (plpgsql_parse_dblword(aux1.lval.str,
211  aux3.lval.str,
212  &aux1.lval.wdatum,
213  &aux1.lval.cword))
214  tok1 = T_DATUM;
215  else
216  tok1 = T_CWORD;
217  /* Adjust token length to include A.B */
218  aux1.leng = aux3.lloc - aux1.lloc + aux3.leng;
219  }
220  }
221  else
222  {
223  /* not A.B, so just process A */
224  push_back_token(tok3, &aux3);
225  push_back_token(tok2, &aux2);
226  if (plpgsql_parse_word(aux1.lval.str,
227  core_yy.scanbuf + aux1.lloc,
228  true,
229  &aux1.lval.wdatum,
230  &aux1.lval.word))
231  tok1 = T_DATUM;
232  else if (!aux1.lval.word.quoted &&
233  (kwnum = ScanKeywordLookup(aux1.lval.word.ident,
234  &UnreservedPLKeywords)) >= 0)
235  {
236  aux1.lval.keyword = GetScanKeyword(kwnum,
237  &UnreservedPLKeywords);
238  tok1 = UnreservedPLKeywordTokens[kwnum];
239  }
240  else
241  tok1 = T_WORD;
242  }
243  }
244  else
245  {
246  /* not A.B, so just process A */
247  push_back_token(tok2, &aux2);
248 
249  /*
250  * See if it matches a variable name, except in the context where
251  * we are at start of statement and the next token isn't
252  * assignment or '['. In that case, it couldn't validly be a
253  * variable name, and skipping the lookup allows variable names to
254  * be used that would conflict with plpgsql or core keywords that
255  * introduce statements (e.g., "comment"). Without this special
256  * logic, every statement-introducing keyword would effectively be
257  * reserved in PL/pgSQL, which would be unpleasant.
258  *
259  * If it isn't a variable name, try to match against unreserved
260  * plpgsql keywords. If not one of those either, it's T_WORD.
261  *
262  * Note: we must call plpgsql_parse_word even if we don't want to
263  * do variable lookup, because it sets up aux1.lval.word for the
264  * non-variable cases.
265  */
266  if (plpgsql_parse_word(aux1.lval.str,
267  core_yy.scanbuf + aux1.lloc,
269  (tok2 == '=' || tok2 == COLON_EQUALS ||
270  tok2 == '[')),
271  &aux1.lval.wdatum,
272  &aux1.lval.word))
273  tok1 = T_DATUM;
274  else if (!aux1.lval.word.quoted &&
275  (kwnum = ScanKeywordLookup(aux1.lval.word.ident,
276  &UnreservedPLKeywords)) >= 0)
277  {
278  aux1.lval.keyword = GetScanKeyword(kwnum,
279  &UnreservedPLKeywords);
280  tok1 = UnreservedPLKeywordTokens[kwnum];
281  }
282  else
283  tok1 = T_WORD;
284  }
285  }
286  else
287  {
288  /*
289  * Not a potential plpgsql variable name, just return the data.
290  *
291  * Note that we also come through here if the grammar pushed back a
292  * T_DATUM, T_CWORD, T_WORD, or unreserved-keyword token returned by a
293  * previous lookup cycle; thus, pushbacks do not incur extra lookup
294  * work, since we'll never do the above code twice for the same token.
295  * This property also makes it safe to rely on the old value of
296  * plpgsql_yytoken in the is-this-start-of-statement test above.
297  */
298  }
299 
300  plpgsql_yylval = aux1.lval;
301  plpgsql_yylloc = aux1.lloc;
302  plpgsql_yyleng = aux1.leng;
303  plpgsql_yytoken = tok1;
304  return tok1;
305 }
int ScanKeywordLookup(const char *str, const ScanKeywordList *keywords)
Definition: kwlookup.c:38
static const char * GetScanKeyword(int n, const ScanKeywordList *keywords)
Definition: kwlookup.h:39
bool plpgsql_parse_dblword(char *word1, char *word2, PLwdatum *wdatum, PLcword *cword)
Definition: pl_comp.c:1440
bool plpgsql_parse_word(char *word1, const char *yytxt, bool lookup, PLwdatum *wdatum, PLword *word)
Definition: pl_comp.c:1385
bool plpgsql_parse_tripword(char *word1, char *word2, char *word3, PLwdatum *wdatum, PLcword *cword)
Definition: pl_comp.c:1521
#define AT_STMT_START(prev_token)
Definition: pl_scanner.c:82

References AT_STMT_START, core_yy, GetScanKeyword(), internal_yylex(), TokenAuxData::leng, TokenAuxData::lloc, TokenAuxData::lval, plpgsql_parse_dblword(), plpgsql_parse_tripword(), plpgsql_parse_word(), plpgsql_yyleng, plpgsql_yytoken, push_back_token(), core_yy_extra_type::scanbuf, ScanKeywordLookup(), and UnreservedPLKeywordTokens.

◆ plpgsql_yyparse()

int plpgsql_yyparse ( void  )

Variable Documentation

◆ plpgsql_check_asserts

bool plpgsql_check_asserts
extern

Definition at line 48 of file pl_handler.c.

Referenced by _PG_init(), and exec_stmt_assert().

◆ plpgsql_check_syntax

bool plpgsql_check_syntax
extern

Definition at line 50 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_compile_tmp_cxt

MemoryContext plpgsql_compile_tmp_cxt
extern

◆ plpgsql_curr_compile

PLpgSQL_function* plpgsql_curr_compile
extern

Definition at line 52 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_Datums

◆ plpgsql_DumpExecTree

bool plpgsql_DumpExecTree
extern

Definition at line 49 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_error_funcname

char* plpgsql_error_funcname
extern

Definition at line 48 of file pl_comp.c.

Referenced by do_compile(), plpgsql_compile_error_callback(), and plpgsql_compile_inline().

◆ plpgsql_extra_errors

int plpgsql_extra_errors
extern

◆ plpgsql_extra_warnings

int plpgsql_extra_warnings
extern

◆ plpgsql_IdentifierLookup

IdentifierLookup plpgsql_IdentifierLookup
extern

◆ plpgsql_nDatums

int plpgsql_nDatums
extern

◆ plpgsql_parse_result

PLpgSQL_stmt_block* plpgsql_parse_result
extern

Definition at line 41 of file pl_comp.c.

Referenced by do_compile(), and plpgsql_compile_inline().

◆ plpgsql_plugin_ptr

◆ plpgsql_print_strict_params

bool plpgsql_print_strict_params
extern

Definition at line 46 of file pl_handler.c.

Referenced by _PG_init(), do_compile(), and plpgsql_compile_inline().

◆ plpgsql_variable_conflict

int plpgsql_variable_conflict
extern

Definition at line 44 of file pl_handler.c.

Referenced by _PG_init(), do_compile(), and plpgsql_compile_inline().