2
/**********************************************************************
3
* gram.y - Parser for the PL/pgSQL
7
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.64.4.3 2005-02-08 18:21:59 tgl Exp $
9
* This software is copyrighted by Jan Wieck - Hamburg.
11
* The author hereby grants permission to use, copy, modify,
12
* distribute, and license this software and its documentation
13
* for any purpose, provided that existing copyright notices are
14
* retained in all copies and that this notice is included
15
* verbatim in any distributions. No written agreement, license,
16
* or royalty fee is required for any of the authorized uses.
17
* Modifications to this software may be copyrighted by their
18
* author and need not follow the licensing terms described
19
* here, provided that the new terms are clearly indicated on
20
* the first page of each file where they apply.
22
* IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
23
* PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
24
* CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
25
* SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
26
* IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
29
* THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
30
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
32
* PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
33
* AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
34
* OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
35
* ENHANCEMENTS, OR MODIFICATIONS.
37
**********************************************************************/
42
static PLpgSQL_expr *read_sql_construct(int until,
48
static PLpgSQL_expr *read_sql_stmt(const char *sqlstart);
49
static PLpgSQL_type *read_datatype(int tok);
50
static PLpgSQL_stmt *make_select_stmt(void);
51
static PLpgSQL_stmt *make_fetch_stmt(void);
52
static void check_assignable(PLpgSQL_datum *datum);
74
PLpgSQL_diag_item *dtitems;
90
PLpgSQL_datum *scalar; /* a VAR, RECFIELD, or TRIGARG */
91
PLpgSQL_variable *variable; /* a VAR, REC, or ROW */
98
PLpgSQL_stmt_block *program;
99
PLpgSQL_condition *condition;
100
PLpgSQL_exception *exception;
101
PLpgSQL_exceptions *exceptions;
102
PLpgSQL_nsitem *nsitem;
105
%type <declhdr> decl_sect
106
%type <varname> decl_varname
107
%type <str> decl_renname
108
%type <ival> decl_const decl_notnull
109
%type <expr> decl_defval decl_cursor_query
110
%type <dtype> decl_datatype
111
%type <row> decl_cursor_args decl_cursor_arglist
112
%type <nsitem> decl_aliasitem
113
%type <str> decl_stmts decl_stmt
115
%type <expr> expr_until_semi expr_until_rightbracket
116
%type <expr> expr_until_then expr_until_loop
117
%type <expr> opt_exitcond
119
%type <ival> assign_var cursor_variable
120
%type <var> cursor_varptr
121
%type <variable> decl_cursor_arg
122
%type <forvariable> for_variable
123
%type <stmt> for_control
125
%type <str> opt_lblname opt_label
126
%type <str> opt_exitlabel
127
%type <str> execsql_start
129
%type <stmts> proc_sect proc_stmts stmt_else loop_body
130
%type <stmt> proc_stmt pl_block
131
%type <stmt> stmt_assign stmt_if stmt_loop stmt_while stmt_exit
132
%type <stmt> stmt_return stmt_return_next stmt_raise stmt_execsql
133
%type <stmt> stmt_for stmt_select stmt_perform
134
%type <stmt> stmt_dynexecute stmt_getdiag
135
%type <stmt> stmt_open stmt_fetch stmt_close stmt_null
137
%type <exceptions> exception_sect proc_exceptions
138
%type <exception> proc_exception
139
%type <condition> proc_conditions
141
%type <intlist> raise_params
142
%type <ival> raise_level raise_param
143
%type <str> raise_msg
145
%type <dtlist> getdiag_list
146
%type <ival> getdiag_item getdiag_target
210
%token T_SCALAR /* a VAR, RECFIELD, or TRIGARG */
223
pl_function : T_FUNCTION comp_optsect pl_block opt_semi
225
yylval.program = (PLpgSQL_stmt_block *)$3;
227
| T_TRIGGER comp_optsect pl_block opt_semi
229
yylval.program = (PLpgSQL_stmt_block *)$3;
237
comp_options : comp_options comp_option
241
comp_option : O_OPTION O_DUMP
243
plpgsql_DumpExecTree = 1;
251
pl_block : decl_sect K_BEGIN lno proc_sect exception_sect K_END
253
PLpgSQL_stmt_block *new;
255
new = malloc(sizeof(PLpgSQL_stmt_block));
256
memset(new, 0, sizeof(PLpgSQL_stmt_block));
258
new->cmd_type = PLPGSQL_STMT_BLOCK;
260
new->label = $1.label;
261
new->n_initvars = $1.n_initvars;
262
new->initvarnos = $1.initvarnos;
264
new->exceptions = $5;
268
$$ = (PLpgSQL_stmt *)new;
273
decl_sect : opt_label
275
plpgsql_ns_setlocal(false);
278
$$.initvarnos = NULL;
279
plpgsql_add_initdatums(NULL);
281
| opt_label decl_start
283
plpgsql_ns_setlocal(false);
286
$$.initvarnos = NULL;
287
plpgsql_add_initdatums(NULL);
289
| opt_label decl_start decl_stmts
291
plpgsql_ns_setlocal(false);
296
$$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
300
decl_start : K_DECLARE
302
plpgsql_ns_setlocal(true);
306
decl_stmts : decl_stmts decl_stmt
312
decl_stmt : '<' '<' opt_lblname '>' '>'
320
decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
322
PLpgSQL_variable *var;
324
var = plpgsql_build_variable($1.name, $1.lineno,
328
if (var->dtype == PLPGSQL_DTYPE_VAR)
329
((PLpgSQL_var *) var)->isconst = $2;
332
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
333
errmsg("row or record variable cannot be CONSTANT")));
337
if (var->dtype == PLPGSQL_DTYPE_VAR)
338
((PLpgSQL_var *) var)->notnull = $4;
341
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
342
errmsg("row or record variable cannot be NOT NULL")));
346
if (var->dtype == PLPGSQL_DTYPE_VAR)
347
((PLpgSQL_var *) var)->default_val = $5;
350
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
351
errmsg("default value for row or record variable is not supported")));
354
| decl_varname K_ALIAS K_FOR decl_aliasitem ';'
356
plpgsql_ns_additem($4->itemtype,
357
$4->itemno, $1.name);
359
| K_RENAME decl_renname K_TO decl_renname ';'
361
plpgsql_ns_rename($2, $4);
363
| decl_varname K_CURSOR
364
{ plpgsql_ns_push(NULL); }
365
decl_cursor_args decl_is_from decl_cursor_query
368
PLpgSQL_expr *curname_def;
373
/* pop local namespace for cursor args */
376
new = (PLpgSQL_var *)
377
plpgsql_build_variable($1.name, $1.lineno,
378
plpgsql_build_datatype(REFCURSOROID,
382
curname_def = malloc(sizeof(PLpgSQL_expr));
383
memset(curname_def, 0, sizeof(PLpgSQL_expr));
385
curname_def->dtype = PLPGSQL_DTYPE_EXPR;
386
strcpy(buf, "SELECT '");
388
cp2 = buf + strlen(buf);
391
if (*cp1 == '\\' || *cp1 == '\'')
395
strcpy(cp2, "'::refcursor");
396
curname_def->query = strdup(buf);
397
new->default_val = curname_def;
399
new->cursor_explicit_expr = $6;
401
new->cursor_explicit_argrow = -1;
403
new->cursor_explicit_argrow = $4->rowno;
411
plpgsql_ns_setlocal(false);
412
query = read_sql_stmt("");
413
plpgsql_ns_setlocal(true);
423
| '(' decl_cursor_arglist ')'
425
/* Copy the temp arrays to malloc'd storage */
426
int nfields = $2->nfields;
430
ftmp = malloc(nfields * sizeof(char *));
431
vtmp = malloc(nfields * sizeof(int));
432
memcpy(ftmp, $2->fieldnames, nfields * sizeof(char *));
433
memcpy(vtmp, $2->varnos, nfields * sizeof(int));
435
pfree($2->fieldnames);
438
$2->fieldnames = ftmp;
441
plpgsql_adddatum((PLpgSQL_datum *)$2);
447
decl_cursor_arglist : decl_cursor_arg
451
new = malloc(sizeof(PLpgSQL_row));
452
memset(new, 0, sizeof(PLpgSQL_row));
454
new->dtype = PLPGSQL_DTYPE_ROW;
455
new->refname = strdup("*internal*");
456
new->lineno = plpgsql_scanner_lineno();
457
new->rowtupdesc = NULL;
459
* We make temporary fieldnames/varnos arrays that
460
* are much bigger than necessary. We will resize
461
* them to just the needed size in the
462
* decl_cursor_args production.
464
new->fieldnames = palloc(1024 * sizeof(char *));
465
new->varnos = palloc(1024 * sizeof(int));
468
new->fieldnames[0] = $1->refname;
469
new->varnos[0] = $1->dno;
473
| decl_cursor_arglist ',' decl_cursor_arg
475
int i = $1->nfields++;
477
/* Guard against overflowing the array on malicious input */
479
yyerror("too many parameters specified for refcursor");
481
$1->fieldnames[i] = $3->refname;
482
$1->varnos[i] = $3->dno;
488
decl_cursor_arg : decl_varname decl_datatype
490
$$ = plpgsql_build_variable($1.name, $1.lineno,
495
decl_is_from : K_IS | /* Oracle */
498
decl_aliasitem : T_WORD
503
plpgsql_convert_ident(yytext, &name, 1);
505
yyerror("only positional parameters may be aliased");
507
plpgsql_ns_setlocal(false);
508
nsi = plpgsql_ns_lookup(name, NULL);
511
plpgsql_error_lineno = plpgsql_scanner_lineno();
513
(errcode(ERRCODE_UNDEFINED_PARAMETER),
514
errmsg("function has no parameter \"%s\"",
518
plpgsql_ns_setlocal(true);
526
decl_varname : T_WORD
530
plpgsql_convert_ident(yytext, &name, 1);
531
/* name should be malloc'd for use as varname */
532
$$.name = strdup(name);
533
$$.lineno = plpgsql_scanner_lineno();
538
decl_renname : T_WORD
542
plpgsql_convert_ident(yytext, &name, 1);
543
/* the result must be palloc'd, see plpgsql_ns_rename */
557
* If there's a lookahead token, read_datatype
560
$$ = read_datatype(yychar);
575
plpgsql_ns_setlocal(false);
576
$$ = plpgsql_read_expression(';', ";");
577
plpgsql_ns_setlocal(true);
581
decl_defkey : K_ASSIGN
589
new = malloc(sizeof(PLpgSQL_stmts));
590
memset(new, 0, sizeof(PLpgSQL_stmts));
597
proc_stmts : proc_stmts proc_stmt
601
if ($1->stmts_used == $1->stmts_alloc)
603
$1->stmts_alloc *= 2;
604
$1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
606
$1->stmts[$1->stmts_used++] = $2;
614
new = malloc(sizeof(PLpgSQL_stmts));
615
memset(new, 0, sizeof(PLpgSQL_stmts));
617
new->stmts_alloc = 32;
618
new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
621
new->stmts[new->stmts_used++] = $1;
627
proc_stmt : pl_block ';'
667
stmt_perform : K_PERFORM lno expr_until_semi
669
PLpgSQL_stmt_perform *new;
671
new = malloc(sizeof(PLpgSQL_stmt_perform));
672
memset(new, 0, sizeof(PLpgSQL_stmt_perform));
674
new->cmd_type = PLPGSQL_STMT_PERFORM;
678
$$ = (PLpgSQL_stmt *)new;
682
stmt_assign : assign_var lno K_ASSIGN expr_until_semi
684
PLpgSQL_stmt_assign *new;
686
new = malloc(sizeof(PLpgSQL_stmt_assign));
687
memset(new, 0, sizeof(PLpgSQL_stmt_assign));
689
new->cmd_type = PLPGSQL_STMT_ASSIGN;
694
$$ = (PLpgSQL_stmt *)new;
698
stmt_getdiag : K_GET K_DIAGNOSTICS lno getdiag_list ';'
700
PLpgSQL_stmt_getdiag *new;
702
new = malloc(sizeof(PLpgSQL_stmt_getdiag));
703
memset(new, 0, sizeof(PLpgSQL_stmt_getdiag));
705
new->cmd_type = PLPGSQL_STMT_GETDIAG;
707
new->ndtitems = $4.nused;
708
new->dtitems = malloc(sizeof(PLpgSQL_diag_item) * $4.nused);
709
memcpy(new->dtitems, $4.dtitems, sizeof(PLpgSQL_diag_item) * $4.nused);
711
$$ = (PLpgSQL_stmt *)new;
715
getdiag_list : getdiag_list ',' getdiag_target K_ASSIGN getdiag_item
717
if ($1.nused == $1.nalloc)
720
$1.dtitems = repalloc($1.dtitems, sizeof(PLpgSQL_diag_item) * $1.nalloc);
722
$1.dtitems[$1.nused].target = $3;
723
$1.dtitems[$1.nused].item = $5;
726
$$.nalloc = $1.nalloc;
728
$$.dtitems = $1.dtitems;
730
| getdiag_target K_ASSIGN getdiag_item
734
$$.dtitems = palloc(sizeof(PLpgSQL_diag_item) * $$.nalloc);
735
$$.dtitems[0].target = $1;
736
$$.dtitems[0].item = $3;
740
getdiag_item : K_ROW_COUNT
742
$$ = PLPGSQL_GETDIAG_ROW_COUNT;
746
$$ = PLPGSQL_GETDIAG_RESULT_OID;
750
getdiag_target : T_SCALAR
752
check_assignable(yylval.scalar);
753
$$ = yylval.scalar->dno;
758
assign_var : T_SCALAR
760
check_assignable(yylval.scalar);
761
$$ = yylval.scalar->dno;
765
check_assignable((PLpgSQL_datum *) yylval.row);
766
$$ = yylval.row->rowno;
770
check_assignable((PLpgSQL_datum *) yylval.rec);
771
$$ = yylval.rec->recno;
773
| assign_var '[' expr_until_rightbracket
775
PLpgSQL_arrayelem *new;
777
new = malloc(sizeof(PLpgSQL_arrayelem));
778
memset(new, 0, sizeof(PLpgSQL_arrayelem));
780
new->dtype = PLPGSQL_DTYPE_ARRAYELEM;
782
new->arrayparentno = $1;
784
plpgsql_adddatum((PLpgSQL_datum *)new);
790
stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
792
PLpgSQL_stmt_if *new;
794
new = malloc(sizeof(PLpgSQL_stmt_if));
795
memset(new, 0, sizeof(PLpgSQL_stmt_if));
797
new->cmd_type = PLPGSQL_STMT_IF;
801
new->false_body = $5;
803
$$ = (PLpgSQL_stmt *)new;
811
new = malloc(sizeof(PLpgSQL_stmts));
812
memset(new, 0, sizeof(PLpgSQL_stmts));
815
| K_ELSIF lno expr_until_then proc_sect stmt_else
818
* Translate the structure: into:
820
* IF c1 THEN IF c1 THEN
833
PLpgSQL_stmt_if *new_if;
835
/* first create a new if-statement */
836
new_if = malloc(sizeof(PLpgSQL_stmt_if));
837
memset(new_if, 0, sizeof(PLpgSQL_stmt_if));
839
new_if->cmd_type = PLPGSQL_STMT_IF;
842
new_if->true_body = $4;
843
new_if->false_body = $5;
845
/* this is a 'container' for the if-statement */
846
new = malloc(sizeof(PLpgSQL_stmts));
847
memset(new, 0, sizeof(PLpgSQL_stmts));
849
new->stmts_alloc = 64;
851
new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
852
new->stmts[0] = (PLpgSQL_stmt *) new_if;
864
stmt_loop : opt_label K_LOOP lno loop_body
866
PLpgSQL_stmt_loop *new;
868
new = malloc(sizeof(PLpgSQL_stmt_loop));
869
memset(new, 0, sizeof(PLpgSQL_stmt_loop));
871
new->cmd_type = PLPGSQL_STMT_LOOP;
878
$$ = (PLpgSQL_stmt *)new;
882
stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
884
PLpgSQL_stmt_while *new;
886
new = malloc(sizeof(PLpgSQL_stmt_while));
887
memset(new, 0, sizeof(PLpgSQL_stmt_while));
889
new->cmd_type = PLPGSQL_STMT_WHILE;
897
$$ = (PLpgSQL_stmt *)new;
901
stmt_for : opt_label K_FOR for_control loop_body
903
/* This runs after we've scanned the loop body */
904
if ($3->cmd_type == PLPGSQL_STMT_FORI)
906
PLpgSQL_stmt_fori *new;
908
new = (PLpgSQL_stmt_fori *) $3;
911
$$ = (PLpgSQL_stmt *) new;
913
else if ($3->cmd_type == PLPGSQL_STMT_FORS)
915
PLpgSQL_stmt_fors *new;
917
new = (PLpgSQL_stmt_fors *) $3;
920
$$ = (PLpgSQL_stmt *) new;
924
PLpgSQL_stmt_dynfors *new;
926
Assert($3->cmd_type == PLPGSQL_STMT_DYNFORS);
927
new = (PLpgSQL_stmt_dynfors *) $3;
930
$$ = (PLpgSQL_stmt *) new;
933
/* close namespace started in opt_label */
938
for_control : lno for_variable K_IN
941
bool reverse = false;
942
bool execute = false;
945
/* check for REVERSE and EXECUTE */
947
if (tok == K_REVERSE)
953
if (tok == K_EXECUTE)
956
plpgsql_push_back_token(tok);
958
/* Collect one or two expressions */
959
expr1 = read_sql_construct(K_DOTDOT,
968
/* Found .., so it must be an integer loop */
969
PLpgSQL_stmt_fori *new;
973
expr2 = plpgsql_read_expression(K_LOOP, "LOOP");
977
plpgsql_error_lineno = $1;
978
yyerror("cannot specify EXECUTE in integer for-loop");
981
/* name should be malloc'd for use as varname */
982
fvar = (PLpgSQL_var *)
983
plpgsql_build_variable(strdup($2.name),
985
plpgsql_build_datatype(INT4OID,
989
/* put the for-variable into the local block */
990
plpgsql_add_initdatums(NULL);
992
new = malloc(sizeof(PLpgSQL_stmt_fori));
993
memset(new, 0, sizeof(PLpgSQL_stmt_fori));
995
new->cmd_type = PLPGSQL_STMT_FORI;
998
new->reverse = reverse;
1002
$$ = (PLpgSQL_stmt *) new;
1006
/* No .., so it must be a loop over rows */
1007
PLpgSQL_stmt_dynfors *new;
1011
plpgsql_error_lineno = $1;
1012
yyerror("cannot specify REVERSE in loop over rows");
1015
new = malloc(sizeof(PLpgSQL_stmt_dynfors));
1016
memset(new, 0, sizeof(PLpgSQL_stmt_dynfors));
1018
new->cmd_type = PLPGSQL_STMT_DYNFORS;
1026
plpgsql_error_lineno = $1;
1027
yyerror("loop variable of loop over rows must be a record or row variable");
1031
$$ = (PLpgSQL_stmt *) new;
1035
/* No .., so it must be a loop over rows */
1036
PLpgSQL_stmt_fors *new;
1041
plpgsql_error_lineno = $1;
1042
yyerror("cannot specify REVERSE in loop over rows");
1045
new = malloc(sizeof(PLpgSQL_stmt_fors));
1046
memset(new, 0, sizeof(PLpgSQL_stmt_fors));
1048
new->cmd_type = PLPGSQL_STMT_FORS;
1056
plpgsql_error_lineno = $1;
1057
yyerror("loop variable of loop over rows must be a record or row variable");
1060
* Must get rid of the "SELECT " we prepended
1063
newquery = strdup(expr1->query + 7);
1065
expr1->query = newquery;
1069
$$ = (PLpgSQL_stmt *) new;
1074
for_variable : T_SCALAR
1078
plpgsql_convert_ident(yytext, &name, 1);
1080
$$.lineno = plpgsql_scanner_lineno();
1088
plpgsql_convert_ident(yytext, &name, 1);
1090
$$.lineno = plpgsql_scanner_lineno();
1098
plpgsql_convert_ident(yytext, &name, 1);
1100
$$.lineno = plpgsql_scanner_lineno();
1101
$$.rec = yylval.rec;
1108
plpgsql_convert_ident(yytext, &name, 1);
1110
$$.lineno = plpgsql_scanner_lineno();
1111
$$.row = yylval.row;
1116
stmt_select : K_SELECT lno
1118
$$ = make_select_stmt();
1123
stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond
1125
PLpgSQL_stmt_exit *new;
1127
new = malloc(sizeof(PLpgSQL_stmt_exit));
1128
memset(new, 0, sizeof(PLpgSQL_stmt_exit));
1130
new->cmd_type = PLPGSQL_STMT_EXIT;
1135
$$ = (PLpgSQL_stmt *)new;
1139
stmt_return : K_RETURN lno
1141
PLpgSQL_stmt_return *new;
1143
new = malloc(sizeof(PLpgSQL_stmt_return));
1144
memset(new, 0, sizeof(PLpgSQL_stmt_return));
1149
if (plpgsql_curr_compile->fn_retset)
1152
yyerror("RETURN cannot have a parameter in function returning set; use RETURN NEXT");
1154
else if (plpgsql_curr_compile->fn_retistuple)
1162
new->retrowno = yylval.row->rowno;
1166
new->retrecno = yylval.rec->recno;
1170
yyerror("RETURN must specify a record or row variable in function returning tuple");
1174
yyerror("RETURN must specify a record or row variable in function returning tuple");
1178
/* ordinary expression case */
1179
new->expr = plpgsql_read_expression(';', ";");
1182
new->cmd_type = PLPGSQL_STMT_RETURN;
1185
$$ = (PLpgSQL_stmt *)new;
1189
stmt_return_next: K_RETURN_NEXT lno
1191
PLpgSQL_stmt_return_next *new;
1193
if (!plpgsql_curr_compile->fn_retset)
1194
yyerror("cannot use RETURN NEXT in a non-SETOF function");
1196
new = malloc(sizeof(PLpgSQL_stmt_return_next));
1197
memset(new, 0, sizeof(PLpgSQL_stmt_return_next));
1199
new->cmd_type = PLPGSQL_STMT_RETURN_NEXT;
1202
if (plpgsql_curr_compile->fn_retistuple)
1206
if (tok == T_RECORD)
1207
new->rec = yylval.rec;
1208
else if (tok == T_ROW)
1209
new->row = yylval.row;
1211
yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");
1214
yyerror("RETURN NEXT must specify a record or row variable in function returning tuple");
1217
new->expr = plpgsql_read_expression(';', ";");
1219
$$ = (PLpgSQL_stmt *)new;
1223
stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';'
1225
PLpgSQL_stmt_raise *new;
1227
new = malloc(sizeof(PLpgSQL_stmt_raise));
1229
new->cmd_type = PLPGSQL_STMT_RAISE;
1231
new->elog_level = $3;
1233
new->nparams = $5.nused;
1234
new->params = malloc(sizeof(int) * $5.nused);
1235
memcpy(new->params, $5.nums, sizeof(int) * $5.nused);
1237
$$ = (PLpgSQL_stmt *)new;
1239
| K_RAISE lno raise_level raise_msg ';'
1241
PLpgSQL_stmt_raise *new;
1243
new = malloc(sizeof(PLpgSQL_stmt_raise));
1245
new->cmd_type = PLPGSQL_STMT_RAISE;
1247
new->elog_level = $3;
1252
$$ = (PLpgSQL_stmt *)new;
1256
raise_msg : T_STRING
1258
$$ = plpgsql_get_string_value();
1262
raise_level : K_EXCEPTION
1288
raise_params : raise_params raise_param
1290
if ($1.nused == $1.nalloc)
1293
$1.nums = repalloc($1.nums, sizeof(int) * $1.nalloc);
1295
$1.nums[$1.nused++] = $2;
1297
$$.nalloc = $1.nalloc;
1298
$$.nused = $1.nused;
1305
$$.nums = palloc(sizeof(int) * $$.nalloc);
1310
raise_param : ',' T_SCALAR
1312
$$ = yylval.scalar->dno;
1316
loop_body : proc_sect K_END K_LOOP ';'
1320
stmt_execsql : execsql_start lno
1322
PLpgSQL_stmt_execsql *new;
1324
new = malloc(sizeof(PLpgSQL_stmt_execsql));
1325
new->cmd_type = PLPGSQL_STMT_EXECSQL;
1327
new->sqlstmt = read_sql_stmt($1);
1329
$$ = (PLpgSQL_stmt *)new;
1333
stmt_dynexecute : K_EXECUTE lno expr_until_semi
1335
PLpgSQL_stmt_dynexecute *new;
1337
new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
1338
new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
1342
$$ = (PLpgSQL_stmt *)new;
1346
stmt_open : K_OPEN lno cursor_varptr
1348
PLpgSQL_stmt_open *new;
1351
new = malloc(sizeof(PLpgSQL_stmt_open));
1352
memset(new, 0, sizeof(PLpgSQL_stmt_open));
1354
new->cmd_type = PLPGSQL_STMT_OPEN;
1356
new->curvar = $3->varno;
1358
if ($3->cursor_explicit_expr == NULL)
1364
plpgsql_error_lineno = $2;
1366
(errcode(ERRCODE_SYNTAX_ERROR),
1367
errmsg("syntax error at \"%s\"",
1369
errdetail("Expected FOR to open a reference cursor.")));
1377
plpgsql_push_back_token(tok);
1378
new->query = read_sql_stmt("");
1382
new->dynquery = read_sql_stmt("SELECT ");
1386
plpgsql_error_lineno = $2;
1388
(errcode(ERRCODE_SYNTAX_ERROR),
1389
errmsg("syntax error at \"%s\"",
1396
if ($3->cursor_explicit_argrow >= 0)
1404
plpgsql_error_lineno = plpgsql_scanner_lineno();
1406
(errcode(ERRCODE_SYNTAX_ERROR),
1407
errmsg("cursor \"%s\" has arguments",
1412
* Push back the '(', else read_sql_stmt
1413
* will complain about unbalanced parens.
1415
plpgsql_push_back_token(tok);
1417
new->argquery = read_sql_stmt("SELECT ");
1420
* Now remove the leading and trailing parens,
1421
* because we want "select 1, 2", not
1424
cp = new->argquery->query;
1426
if (strncmp(cp, "SELECT", 6) != 0)
1428
plpgsql_error_lineno = plpgsql_scanner_lineno();
1429
/* internal error */
1430
elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1431
new->argquery->query);
1434
while (*cp == ' ') /* could be more than 1 space here */
1438
plpgsql_error_lineno = plpgsql_scanner_lineno();
1439
/* internal error */
1440
elog(ERROR, "expected \"SELECT (\", got \"%s\"",
1441
new->argquery->query);
1445
cp += strlen(cp) - 1;
1448
yyerror("expected \")\"");
1457
plpgsql_error_lineno = plpgsql_scanner_lineno();
1459
(errcode(ERRCODE_SYNTAX_ERROR),
1460
errmsg("cursor \"%s\" has no arguments",
1466
plpgsql_error_lineno = plpgsql_scanner_lineno();
1468
(errcode(ERRCODE_SYNTAX_ERROR),
1469
errmsg("syntax error at \"%s\"",
1475
$$ = (PLpgSQL_stmt *)new;
1479
stmt_fetch : K_FETCH lno cursor_variable K_INTO
1481
PLpgSQL_stmt_fetch *new;
1483
new = (PLpgSQL_stmt_fetch *)make_fetch_stmt();
1486
$$ = (PLpgSQL_stmt *)new;
1491
stmt_close : K_CLOSE lno cursor_variable ';'
1493
PLpgSQL_stmt_close *new;
1495
new = malloc(sizeof(PLpgSQL_stmt_close));
1496
new->cmd_type = PLPGSQL_STMT_CLOSE;
1500
$$ = (PLpgSQL_stmt *)new;
1504
stmt_null : K_NULL ';'
1506
/* We do not bother building a node for NULL */
1511
cursor_varptr : T_SCALAR
1513
if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
1514
yyerror("cursor variable must be a simple variable");
1516
if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
1518
plpgsql_error_lineno = plpgsql_scanner_lineno();
1520
(errcode(ERRCODE_DATATYPE_MISMATCH),
1521
errmsg("\"%s\" must be of type cursor or refcursor",
1522
((PLpgSQL_var *) yylval.scalar)->refname)));
1524
$$ = (PLpgSQL_var *) yylval.scalar;
1528
cursor_variable : T_SCALAR
1530
if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
1531
yyerror("cursor variable must be a simple variable");
1533
if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
1535
plpgsql_error_lineno = plpgsql_scanner_lineno();
1537
(errcode(ERRCODE_DATATYPE_MISMATCH),
1538
errmsg("\"%s\" must be of type refcursor",
1539
((PLpgSQL_var *) yylval.scalar)->refname)));
1541
$$ = yylval.scalar->dno;
1545
execsql_start : T_WORD
1546
{ $$ = strdup(yytext); }
1548
{ $$ = strdup(yytext); }
1553
| K_EXCEPTION proc_exceptions
1557
proc_exceptions : proc_exceptions proc_exception
1559
if ($1->exceptions_used == $1->exceptions_alloc)
1561
$1->exceptions_alloc *= 2;
1562
$1->exceptions = realloc($1->exceptions, sizeof(PLpgSQL_exception *) * $1->exceptions_alloc);
1564
$1->exceptions[$1->exceptions_used++] = $2;
1570
PLpgSQL_exceptions *new;
1572
new = malloc(sizeof(PLpgSQL_exceptions));
1573
memset(new, 0, sizeof(PLpgSQL_exceptions));
1575
new->exceptions_alloc = 16;
1576
new->exceptions_used = 1;
1577
new->exceptions = malloc(sizeof(PLpgSQL_exception *) * new->exceptions_alloc);
1578
new->exceptions[0] = $1;
1584
proc_exception : K_WHEN lno proc_conditions K_THEN proc_sect
1586
PLpgSQL_exception *new;
1588
new = malloc(sizeof(PLpgSQL_exception));
1589
memset(new, 0, sizeof(PLpgSQL_exception));
1592
new->conditions = $3;
1599
proc_conditions : proc_conditions K_OR opt_lblname
1601
PLpgSQL_condition *old;
1603
for (old = $1; old->next != NULL; old = old->next)
1605
old->next = plpgsql_parse_err_condition($3);
1611
$$ = plpgsql_parse_err_condition($1);
1616
{ $$ = plpgsql_read_expression(';', ";"); }
1619
expr_until_rightbracket :
1620
{ $$ = plpgsql_read_expression(']', "]"); }
1624
{ $$ = plpgsql_read_expression(K_THEN, "THEN"); }
1628
{ $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
1633
plpgsql_ns_push(NULL);
1636
| '<' '<' opt_lblname '>' '>'
1638
plpgsql_ns_push($3);
1649
plpgsql_convert_ident(yytext, &name, 1);
1655
/* just to give a better error than "syntax error" */
1656
yyerror("no such label");
1662
| K_WHEN expr_until_semi
1666
opt_lblname : T_WORD
1670
plpgsql_convert_ident(yytext, &name, 1);
1678
$$ = plpgsql_error_lineno = plpgsql_scanner_lineno();
1686
plpgsql_read_expression(int until, const char *expected)
1688
return read_sql_construct(until, 0, expected, true, "SELECT ", NULL);
1691
static PLpgSQL_expr *
1692
read_sql_stmt(const char *sqlstart)
1694
return read_sql_construct(';', 0, ";", false, sqlstart, NULL);
1698
* Read a SQL construct and build a PLpgSQL_expr for it.
1700
* until: token code for expected terminator
1701
* until2: token code for alternate terminator (pass 0 if none)
1702
* expected: text to use in complaining that terminator was not found
1703
* isexpression: whether to say we're reading an "expression" or a "statement"
1704
* sqlstart: text to prefix to the accumulated SQL text
1705
* endtoken: if not NULL, ending token is stored at *endtoken
1706
* (this is only interesting if until2 isn't zero)
1708
static PLpgSQL_expr *
1709
read_sql_construct(int until,
1711
const char *expected,
1713
const char *sqlstart,
1725
lno = plpgsql_scanner_lineno();
1726
plpgsql_dstring_init(&ds);
1727
plpgsql_dstring_append(&ds, sqlstart);
1732
if (tok == until && parenlevel == 0)
1734
if (tok == until2 && parenlevel == 0)
1736
if (tok == '(' || tok == '[')
1738
else if (tok == ')' || tok == ']')
1743
(errcode(ERRCODE_SYNTAX_ERROR),
1744
errmsg("mismatched parentheses")));
1747
* End of function definition is an error, and we don't expect to
1748
* hit a semicolon either (unless it's the until symbol, in which
1749
* case we should have fallen out above).
1751
if (tok == 0 || tok == ';')
1753
plpgsql_error_lineno = lno;
1754
if (parenlevel != 0)
1756
(errcode(ERRCODE_SYNTAX_ERROR),
1757
errmsg("mismatched parentheses")));
1760
(errcode(ERRCODE_SYNTAX_ERROR),
1761
errmsg("missing \"%s\" at end of SQL expression",
1765
(errcode(ERRCODE_SYNTAX_ERROR),
1766
errmsg("missing \"%s\" at end of SQL statement",
1770
if (plpgsql_SpaceScanned)
1771
plpgsql_dstring_append(&ds, " ");
1773
/* Check for array overflow */
1774
if (nparams >= 1024)
1776
plpgsql_error_lineno = lno;
1778
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1779
errmsg("too many variables specified in SQL statement")));
1785
params[nparams] = yylval.scalar->dno;
1786
snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1787
plpgsql_dstring_append(&ds, buf);
1791
params[nparams] = yylval.row->rowno;
1792
snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1793
plpgsql_dstring_append(&ds, buf);
1797
params[nparams] = yylval.rec->recno;
1798
snprintf(buf, sizeof(buf), " $%d ", ++nparams);
1799
plpgsql_dstring_append(&ds, buf);
1803
plpgsql_dstring_append(&ds, yytext);
1811
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
1812
expr->dtype = PLPGSQL_DTYPE_EXPR;
1813
expr->query = strdup(plpgsql_dstring_get(&ds));
1815
expr->nparams = nparams;
1816
while(nparams-- > 0)
1817
expr->params[nparams] = params[nparams];
1818
plpgsql_dstring_free(&ds);
1823
static PLpgSQL_type *
1824
read_datatype(int tok)
1828
PLpgSQL_type *result;
1829
bool needspace = false;
1832
lno = plpgsql_scanner_lineno();
1834
/* Often there will be a lookahead token, but if not, get one */
1840
/* lexer found word%TYPE and did its thing already */
1841
return yylval.dtype;
1844
plpgsql_dstring_init(&ds);
1850
plpgsql_error_lineno = lno;
1851
if (parenlevel != 0)
1853
(errcode(ERRCODE_SYNTAX_ERROR),
1854
errmsg("mismatched parentheses")));
1856
(errcode(ERRCODE_SYNTAX_ERROR),
1857
errmsg("incomplete datatype declaration")));
1859
/* Possible followers for datatype in a declaration */
1860
if (tok == K_NOT || tok == K_ASSIGN || tok == K_DEFAULT)
1862
/* Possible followers for datatype in a cursor_arg list */
1863
if ((tok == ',' || tok == ')') && parenlevel == 0)
1867
else if (tok == ')')
1870
plpgsql_dstring_append(&ds, " ");
1872
plpgsql_dstring_append(&ds, yytext);
1877
plpgsql_push_back_token(tok);
1879
plpgsql_error_lineno = lno; /* in case of error in parse_datatype */
1881
result = plpgsql_parse_datatype(plpgsql_dstring_get(&ds));
1883
plpgsql_dstring_free(&ds);
1889
static PLpgSQL_stmt *
1890
make_select_stmt(void)
1897
PLpgSQL_row *row = NULL;
1898
PLpgSQL_rec *rec = NULL;
1900
int have_nexttok = 0;
1903
plpgsql_dstring_init(&ds);
1904
plpgsql_dstring_append(&ds, "SELECT ");
1915
plpgsql_error_lineno = plpgsql_scanner_lineno();
1917
(errcode(ERRCODE_SYNTAX_ERROR),
1918
errmsg("unexpected end of function definition")));
1924
plpgsql_error_lineno = plpgsql_scanner_lineno();
1926
(errcode(ERRCODE_SYNTAX_ERROR),
1927
errmsg("INTO specified more than once")));
1945
char *fieldnames[1024];
1948
check_assignable(yylval.scalar);
1949
fieldnames[0] = strdup(yytext);
1950
varnos[0] = yylval.scalar->dno;
1952
while ((tok = yylex()) == ',')
1954
/* Check for array overflow */
1955
if (nfields >= 1024)
1957
plpgsql_error_lineno = plpgsql_scanner_lineno();
1959
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1960
errmsg("too many INTO variables specified")));
1967
check_assignable(yylval.scalar);
1968
fieldnames[nfields] = strdup(yytext);
1969
varnos[nfields++] = yylval.scalar->dno;
1973
plpgsql_error_lineno = plpgsql_scanner_lineno();
1975
(errcode(ERRCODE_SYNTAX_ERROR),
1976
errmsg("\"%s\" is not a variable",
1982
row = malloc(sizeof(PLpgSQL_row));
1983
row->dtype = PLPGSQL_DTYPE_ROW;
1984
row->refname = strdup("*internal*");
1985
row->lineno = plpgsql_scanner_lineno();
1986
row->rowtupdesc = NULL;
1987
row->nfields = nfields;
1988
row->fieldnames = malloc(sizeof(char *) * nfields);
1989
row->varnos = malloc(sizeof(int) * nfields);
1990
while (--nfields >= 0)
1992
row->fieldnames[nfields] = fieldnames[nfields];
1993
row->varnos[nfields] = varnos[nfields];
1996
plpgsql_adddatum((PLpgSQL_datum *)row);
2003
/* Treat the INTO as non-special */
2004
plpgsql_dstring_append(&ds, " INTO ");
2011
if (plpgsql_SpaceScanned)
2012
plpgsql_dstring_append(&ds, " ");
2014
/* Check for array overflow */
2015
if (nparams >= 1024)
2017
plpgsql_error_lineno = plpgsql_scanner_lineno();
2019
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2020
errmsg("too many variables specified in SQL statement")));
2026
params[nparams] = yylval.scalar->dno;
2027
snprintf(buf, sizeof(buf), " $%d ", ++nparams);
2028
plpgsql_dstring_append(&ds, buf);
2032
params[nparams] = yylval.row->rowno;
2033
snprintf(buf, sizeof(buf), " $%d ", ++nparams);
2034
plpgsql_dstring_append(&ds, buf);
2038
params[nparams] = yylval.rec->recno;
2039
snprintf(buf, sizeof(buf), " $%d ", ++nparams);
2040
plpgsql_dstring_append(&ds, buf);
2044
plpgsql_dstring_append(&ds, yytext);
2049
expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
2050
expr->dtype = PLPGSQL_DTYPE_EXPR;
2051
expr->query = strdup(plpgsql_dstring_get(&ds));
2053
expr->nparams = nparams;
2054
while(nparams-- > 0)
2055
expr->params[nparams] = params[nparams];
2056
plpgsql_dstring_free(&ds);
2060
PLpgSQL_stmt_select *select;
2062
select = malloc(sizeof(PLpgSQL_stmt_select));
2063
memset(select, 0, sizeof(PLpgSQL_stmt_select));
2064
select->cmd_type = PLPGSQL_STMT_SELECT;
2067
select->query = expr;
2069
return (PLpgSQL_stmt *)select;
2073
PLpgSQL_stmt_execsql *execsql;
2075
execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
2076
execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
2077
execsql->sqlstmt = expr;
2079
return (PLpgSQL_stmt *)execsql;
2084
static PLpgSQL_stmt *
2085
make_fetch_stmt(void)
2088
PLpgSQL_row *row = NULL;
2089
PLpgSQL_rec *rec = NULL;
2090
PLpgSQL_stmt_fetch *fetch;
2091
int have_nexttok = 0;
2093
/* We have already parsed everything through the INTO keyword */
2109
char *fieldnames[1024];
2112
check_assignable(yylval.scalar);
2113
fieldnames[0] = strdup(yytext);
2114
varnos[0] = yylval.scalar->dno;
2116
while ((tok = yylex()) == ',')
2118
/* Check for array overflow */
2119
if (nfields >= 1024)
2121
plpgsql_error_lineno = plpgsql_scanner_lineno();
2123
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
2124
errmsg("too many INTO variables specified")));
2131
check_assignable(yylval.scalar);
2132
fieldnames[nfields] = strdup(yytext);
2133
varnos[nfields++] = yylval.scalar->dno;
2137
plpgsql_error_lineno = plpgsql_scanner_lineno();
2139
(errcode(ERRCODE_SYNTAX_ERROR),
2140
errmsg("\"%s\" is not a variable",
2146
row = malloc(sizeof(PLpgSQL_row));
2147
row->dtype = PLPGSQL_DTYPE_ROW;
2148
row->refname = strdup("*internal*");
2149
row->lineno = plpgsql_scanner_lineno();
2150
row->rowtupdesc = NULL;
2151
row->nfields = nfields;
2152
row->fieldnames = malloc(sizeof(char *) * nfields);
2153
row->varnos = malloc(sizeof(int) * nfields);
2154
while (--nfields >= 0)
2156
row->fieldnames[nfields] = fieldnames[nfields];
2157
row->varnos[nfields] = varnos[nfields];
2160
plpgsql_adddatum((PLpgSQL_datum *)row);
2165
yyerror("syntax error");
2172
yyerror("syntax error");
2174
fetch = malloc(sizeof(PLpgSQL_stmt_select));
2175
memset(fetch, 0, sizeof(PLpgSQL_stmt_fetch));
2176
fetch->cmd_type = PLPGSQL_STMT_FETCH;
2180
return (PLpgSQL_stmt *)fetch;
2185
check_assignable(PLpgSQL_datum *datum)
2187
switch (datum->dtype)
2189
case PLPGSQL_DTYPE_VAR:
2190
if (((PLpgSQL_var *) datum)->isconst)
2192
plpgsql_error_lineno = plpgsql_scanner_lineno();
2194
(errcode(ERRCODE_ERROR_IN_ASSIGNMENT),
2195
errmsg("\"%s\" is declared CONSTANT",
2196
((PLpgSQL_var *) datum)->refname)));
2199
case PLPGSQL_DTYPE_ROW:
2200
/* always assignable? */
2202
case PLPGSQL_DTYPE_REC:
2203
/* always assignable? What about NEW/OLD? */
2205
case PLPGSQL_DTYPE_RECFIELD:
2206
/* always assignable? */
2208
case PLPGSQL_DTYPE_ARRAYELEM:
2209
/* always assignable? */
2211
case PLPGSQL_DTYPE_TRIGARG:
2212
yyerror("cannot assign to tg_argv");
2215
elog(ERROR, "unrecognized dtype: %d", datum->dtype);
2220
#include "pl_scan.c"