📄 gram.y
字号:
%{/********************************************************************** * gram.y - Parser for the PL/pgSQL * procedural language * * IDENTIFICATION * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.48 2003/10/30 17:18:55 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * * The author hereby grants permission to use, copy, modify, * distribute, and license this software and its documentation * for any purpose, provided that existing copyright notices are * retained in all copies and that this notice is included * verbatim in any distributions. No written agreement, license, * or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their * author and need not follow the licensing terms described * here, provided that the new terms are clearly indicated on * the first page of each file where they apply. * * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, * ENHANCEMENTS, OR MODIFICATIONS. * **********************************************************************/#include "plpgsql.h"static PLpgSQL_expr *read_sql_construct(int until, const char *expected, bool isexpression, const char *sqlstart);static PLpgSQL_expr *read_sql_stmt(const char *sqlstart);static PLpgSQL_type *read_datatype(int tok);static PLpgSQL_stmt *make_select_stmt(void);static PLpgSQL_stmt *make_fetch_stmt(void);static void check_assignable(PLpgSQL_datum *datum);%}%union { int32 ival; char *str; struct { char *name; int lineno; } varname; struct { int nalloc; int nused; int *nums; } intlist; struct { int nalloc; int nused; PLpgSQL_diag_item *dtitems; } dtlist; struct { int reverse; PLpgSQL_expr *expr; } forilow; struct { char *label; int n_initvars; int *initvarnos; } declhdr; PLpgSQL_type *dtype; PLpgSQL_datum *variable; /* a VAR, RECFIELD, or TRIGARG */ PLpgSQL_var *var; PLpgSQL_row *row; PLpgSQL_rec *rec; PLpgSQL_expr *expr; PLpgSQL_stmt *stmt; PLpgSQL_stmts *stmts; PLpgSQL_stmt_block *program; PLpgSQL_nsitem *nsitem;}%type <declhdr> decl_sect%type <varname> decl_varname%type <str> decl_renname%type <ival> decl_const decl_notnull%type <expr> decl_defval decl_cursor_query%type <dtype> decl_datatype%type <row> decl_rowtype decl_cursor_args decl_cursor_arglist%type <nsitem> decl_aliasitem%type <str> decl_stmts decl_stmt%type <expr> expr_until_semi expr_until_rightbracket%type <expr> expr_until_then expr_until_loop%type <expr> opt_exitcond%type <ival> assign_var cursor_variable%type <var> fori_var cursor_varptr decl_cursor_arg%type <varname> fori_varname%type <forilow> fori_lower%type <rec> fors_target%type <str> opt_lblname opt_label%type <str> opt_exitlabel%type <str> execsql_start%type <stmts> proc_sect proc_stmts stmt_else loop_body%type <stmt> proc_stmt pl_block%type <stmt> stmt_assign stmt_if stmt_loop stmt_while stmt_exit%type <stmt> stmt_return stmt_return_next stmt_raise stmt_execsql%type <stmt> stmt_fori stmt_fors stmt_select stmt_perform%type <stmt> stmt_dynexecute stmt_dynfors stmt_getdiag%type <stmt> stmt_open stmt_fetch stmt_close%type <intlist> raise_params%type <ival> raise_level raise_param%type <str> raise_msg%type <dtlist> getdiag_list%type <ival> getdiag_item getdiag_target%type <ival> lno /* * Keyword tokens */%token K_ALIAS%token K_ASSIGN%token K_BEGIN%token K_CLOSE%token K_CONSTANT%token K_CURSOR%token K_DEBUG%token K_DECLARE%token K_DEFAULT%token K_DIAGNOSTICS%token K_DOTDOT%token K_ELSE%token K_ELSIF%token K_END%token K_EXCEPTION%token K_EXECUTE%token K_EXIT%token K_FOR%token K_FETCH%token K_FROM%token K_GET%token K_IF%token K_IN%token K_INFO%token K_INTO%token K_IS%token K_LOG%token K_LOOP%token K_NEXT%token K_NOT%token K_NOTICE%token K_NULL%token K_OPEN%token K_PERFORM%token K_ROW_COUNT%token K_RAISE%token K_RECORD%token K_RENAME%token K_RESULT_OID%token K_RETURN%token K_RETURN_NEXT%token K_REVERSE%token K_SELECT%token K_THEN%token K_TO%token K_TYPE%token K_WARNING%token K_WHEN%token K_WHILE /* * Other tokens */%token T_FUNCTION%token T_TRIGGER%token T_STRING%token T_NUMBER%token T_VARIABLE /* a VAR, RECFIELD, or TRIGARG */%token T_ROW%token T_RECORD%token T_DTYPE%token T_LABEL%token T_WORD%token T_ERROR%token O_OPTION%token O_DUMP%%pl_function : T_FUNCTION comp_optsect pl_block opt_semi { yylval.program = (PLpgSQL_stmt_block *)$3; } | T_TRIGGER comp_optsect pl_block opt_semi { yylval.program = (PLpgSQL_stmt_block *)$3; } ;comp_optsect : | comp_options ;comp_options : comp_options comp_option | comp_option ;comp_option : O_OPTION O_DUMP { plpgsql_DumpExecTree = 1; } ;opt_semi : | ';' ;pl_block : decl_sect K_BEGIN lno proc_sect K_END { PLpgSQL_stmt_block *new; new = malloc(sizeof(PLpgSQL_stmt_block)); memset(new, 0, sizeof(PLpgSQL_stmt_block)); new->cmd_type = PLPGSQL_STMT_BLOCK; new->lineno = $3; new->label = $1.label; new->n_initvars = $1.n_initvars; new->initvarnos = $1.initvarnos; new->body = $4; plpgsql_ns_pop(); $$ = (PLpgSQL_stmt *)new; } ;decl_sect : opt_label { plpgsql_ns_setlocal(false); $$.label = $1; $$.n_initvars = 0; $$.initvarnos = NULL; plpgsql_add_initdatums(NULL); } | opt_label decl_start { plpgsql_ns_setlocal(false); $$.label = $1; $$.n_initvars = 0; $$.initvarnos = NULL; plpgsql_add_initdatums(NULL); } | opt_label decl_start decl_stmts { plpgsql_ns_setlocal(false); if ($3 != NULL) $$.label = $3; else $$.label = $1; $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos)); } ;decl_start : K_DECLARE { plpgsql_ns_setlocal(true); } ;decl_stmts : decl_stmts decl_stmt { $$ = $2; } | decl_stmt { $$ = $1; } ;decl_stmt : '<' '<' opt_lblname '>' '>' { $$ = $3; } | K_DECLARE { $$ = NULL; } | decl_statement { $$ = NULL; } ;decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval { if (!OidIsValid($3->typrelid)) { /* Ordinary scalar datatype */ PLpgSQL_var *var; var = malloc(sizeof(PLpgSQL_var)); memset(var, 0, sizeof(PLpgSQL_var)); var->dtype = PLPGSQL_DTYPE_VAR; var->refname = $1.name; var->lineno = $1.lineno; var->datatype = $3; var->isconst = $2; var->notnull = $4; var->default_val = $5; plpgsql_adddatum((PLpgSQL_datum *)var); plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, $1.name); } else { /* Composite type --- treat as rowtype */ PLpgSQL_row *row; row = plpgsql_build_rowtype($3->typrelid); row->dtype = PLPGSQL_DTYPE_ROW; row->refname = $1.name; row->lineno = $1.lineno; if ($2) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("rowtype variable cannot be CONSTANT"))); if ($4) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("rowtype variable cannot be NOT NULL"))); if ($5 != NULL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("default value for rowtype variable is not supported"))); plpgsql_adddatum((PLpgSQL_datum *)row); plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, row->rowno, $1.name); } } | decl_varname K_RECORD ';' { PLpgSQL_rec *var; var = malloc(sizeof(PLpgSQL_rec)); var->dtype = PLPGSQL_DTYPE_REC; var->refname = $1.name; var->lineno = $1.lineno; plpgsql_adddatum((PLpgSQL_datum *)var); plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, var->recno, $1.name); } | decl_varname decl_rowtype ';' { $2->dtype = PLPGSQL_DTYPE_ROW; $2->refname = $1.name; $2->lineno = $1.lineno; plpgsql_adddatum((PLpgSQL_datum *)$2); plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno, $1.name); } | decl_varname K_ALIAS K_FOR decl_aliasitem ';' { plpgsql_ns_additem($4->itemtype, $4->itemno, $1.name); } | K_RENAME decl_renname K_TO decl_renname ';' { plpgsql_ns_rename($2, $4); } | decl_varname K_CURSOR { plpgsql_ns_push(NULL); } decl_cursor_args decl_is_from decl_cursor_query { PLpgSQL_var *new; PLpgSQL_expr *curname_def; char buf[1024]; char *cp1; char *cp2; /* pop local namespace for cursor args */ plpgsql_ns_pop(); new = malloc(sizeof(PLpgSQL_var)); memset(new, 0, sizeof(PLpgSQL_var)); curname_def = malloc(sizeof(PLpgSQL_expr)); memset(curname_def, 0, sizeof(PLpgSQL_expr)); new->dtype = PLPGSQL_DTYPE_VAR; new->refname = $1.name; new->lineno = $1.lineno; curname_def->dtype = PLPGSQL_DTYPE_EXPR; strcpy(buf, "SELECT '"); cp1 = new->refname; cp2 = buf + strlen(buf); while (*cp1 != '\0') { if (*cp1 == '\\' || *cp1 == '\'') *cp2++ = '\\'; *cp2++ = *cp1++; } strcpy(cp2, "'::refcursor"); curname_def->query = strdup(buf); new->default_val = curname_def; new->datatype = plpgsql_parse_datatype("refcursor"); new->cursor_explicit_expr = $6; if ($4 == NULL) new->cursor_explicit_argrow = -1; else new->cursor_explicit_argrow = $4->rowno; plpgsql_adddatum((PLpgSQL_datum *)new); plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno, $1.name); } ;decl_cursor_query : { PLpgSQL_expr *query; plpgsql_ns_setlocal(false); query = read_sql_stmt(""); plpgsql_ns_setlocal(true); $$ = query; } ;decl_cursor_args : { $$ = NULL; } | '(' decl_cursor_arglist ')' { /* Copy the temp arrays to malloc'd storage */ int nfields = $2->nfields; char **ftmp; int *vtmp; ftmp = malloc(nfields * sizeof(char *)); vtmp = malloc(nfields * sizeof(int)); memcpy(ftmp, $2->fieldnames, nfields * sizeof(char *)); memcpy(vtmp, $2->varnos, nfields * sizeof(int)); pfree((char *)($2->fieldnames)); pfree((char *)($2->varnos)); $2->fieldnames = ftmp; $2->varnos = vtmp; plpgsql_adddatum((PLpgSQL_datum *)$2); $$ = $2; } ;decl_cursor_arglist : decl_cursor_arg { PLpgSQL_row *new; new = malloc(sizeof(PLpgSQL_row)); memset(new, 0, sizeof(PLpgSQL_row)); new->dtype = PLPGSQL_DTYPE_ROW; new->refname = strdup("*internal*"); new->lineno = plpgsql_scanner_lineno(); new->rowtupdesc = NULL; /* * We make temporary fieldnames/varnos arrays that * are much bigger than necessary. We will resize * them to just the needed size in the * decl_cursor_args production. */ new->fieldnames = palloc(1024 * sizeof(char *)); new->varnos = palloc(1024 * sizeof(int)); new->nfields = 1; new->fieldnames[0] = $1->refname; new->varnos[0] = $1->varno; $$ = new; } | decl_cursor_arglist ',' decl_cursor_arg { int i = $1->nfields++; $1->fieldnames[i] = $3->refname; $1->varnos[i] = $3->varno; $$ = $1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -