gram.y
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:30k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. %{
  2. /**********************************************************************
  3.  * gram.y - Parser for the PL/pgSQL
  4.  *   procedural language
  5.  *
  6.  * IDENTIFICATION
  7.  *    $Header: /usr/local/cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.4.2.1 1999/08/16 19:55:46 momjian Exp $
  8.  *
  9.  *    This software is copyrighted by Jan Wieck - Hamburg.
  10.  *
  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.
  21.  *
  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
  27.  *    DAMAGE.
  28.  *
  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.
  36.  *
  37.  **********************************************************************/
  38. #include "stdio.h"
  39. #include "string.h"
  40. #include "plpgsql.h"
  41. #ifdef YYBISON
  42. #include "pl_scan.c" /* GNU bison wants it here */
  43. #endif
  44. static PLpgSQL_expr *read_sqlstmt(int until, char *s, char *sqlstart);
  45. static PLpgSQL_stmt *make_select_stmt(void);
  46. static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
  47. %}
  48. %union {
  49. int32 ival;
  50. char *str;
  51. struct {
  52.     char *name;
  53.     int  lineno;
  54. } varname;
  55. struct {
  56.     int  nalloc;
  57.     int  nused;
  58.     int  *dtnums;
  59. } dtlist;
  60. struct {
  61.     int  reverse;
  62.     PLpgSQL_expr *expr;
  63. } forilow;
  64. struct {
  65.     char *label;
  66.     int  n_initvars;
  67.     int  *initvarnos;
  68. } declhdr;
  69. PLpgSQL_type *dtype;
  70. PLpgSQL_var *var;
  71. PLpgSQL_row *row;
  72. PLpgSQL_rec *rec;
  73. PLpgSQL_recfield *recfield;
  74. PLpgSQL_trigarg *trigarg;
  75. PLpgSQL_expr *expr;
  76. PLpgSQL_stmt *stmt;
  77. PLpgSQL_stmts *stmts;
  78. PLpgSQL_stmt_block *program;
  79. PLpgSQL_nsitem *nsitem;
  80. }
  81. %type <declhdr> decl_sect
  82. %type <varname> decl_varname
  83. %type <str> decl_renname
  84. %type <ival> decl_const, decl_notnull, decl_atttypmod, decl_atttypmodval
  85. %type <expr> decl_defval
  86. %type <dtype> decl_datatype, decl_dtypename
  87. %type <row> decl_rowtype
  88. %type <nsitem> decl_aliasitem
  89. %type <str> decl_stmts, decl_stmt
  90. %type <expr> expr_until_semi, expr_until_then, expr_until_loop
  91. %type <expr> opt_exitcond
  92. %type <ival> assign_var
  93. %type <var> fori_var
  94. %type <varname> fori_varname
  95. %type <forilow> fori_lower
  96. %type <rec> fors_target
  97. %type <str> opt_lblname, opt_label
  98. %type <str> opt_exitlabel
  99. %type <str> execsql_start
  100. %type <stmts> proc_sect, proc_stmts, stmt_else, loop_body
  101. %type <stmt> proc_stmt, pl_block
  102. %type <stmt> stmt_assign, stmt_if, stmt_loop, stmt_while, stmt_exit
  103. %type <stmt> stmt_return, stmt_raise, stmt_execsql, stmt_fori
  104. %type <stmt> stmt_fors, stmt_select, stmt_perform
  105. %type <dtlist> raise_params
  106. %type <ival> raise_level, raise_param
  107. %type <str> raise_msg
  108. %type <ival> lno
  109. /*
  110.  * Keyword tokens
  111.  */
  112. %token K_ALIAS
  113. %token K_ASSIGN
  114. %token K_BEGIN
  115. %token K_CONSTANT
  116. %token K_DEBUG
  117. %token K_DECLARE
  118. %token K_DEFAULT
  119. %token K_DOTDOT
  120. %token K_ELSE
  121. %token K_END
  122. %token K_EXCEPTION
  123. %token K_EXIT
  124. %token K_FOR
  125. %token K_FROM
  126. %token K_IF
  127. %token K_IN
  128. %token K_INTO
  129. %token K_LOOP
  130. %token K_NOT
  131. %token K_NOTICE
  132. %token K_NULL
  133. %token K_PERFORM
  134. %token K_RAISE
  135. %token K_RECORD
  136. %token K_RENAME
  137. %token K_RETURN
  138. %token K_REVERSE
  139. %token K_SELECT
  140. %token K_THEN
  141. %token K_TO
  142. %token K_TYPE
  143. %token K_WHEN
  144. %token K_WHILE
  145. /*
  146.  * Other tokens
  147.  */
  148. %token T_FUNCTION
  149. %token T_TRIGGER
  150. %token T_CHAR
  151. %token T_BPCHAR
  152. %token T_VARCHAR
  153. %token T_LABEL
  154. %token T_STRING
  155. %token T_VARIABLE
  156. %token T_ROW
  157. %token T_ROWTYPE
  158. %token T_RECORD
  159. %token T_RECFIELD
  160. %token T_TGARGV
  161. %token T_DTYPE
  162. %token T_WORD
  163. %token T_NUMBER
  164. %token T_ERROR
  165. %token O_OPTION
  166. %token O_DUMP
  167. %%
  168. pl_function : T_FUNCTION comp_optsect pl_block
  169.     {
  170. yylval.program = (PLpgSQL_stmt_block *)$3;
  171.     }
  172. | T_TRIGGER comp_optsect pl_block
  173.     {
  174. yylval.program = (PLpgSQL_stmt_block *)$3;
  175.     }
  176. ;
  177. comp_optsect :
  178. | comp_options
  179. ;
  180. comp_options : comp_options comp_option
  181. | comp_option
  182. ;
  183. comp_option : O_OPTION O_DUMP
  184.     {
  185.         plpgsql_DumpExecTree = 1;
  186.     }
  187. ;
  188. pl_block : decl_sect K_BEGIN lno proc_sect K_END ';'
  189.     {
  190.         PLpgSQL_stmt_block *new;
  191. new = malloc(sizeof(PLpgSQL_stmt_block));
  192. memset(new, 0, sizeof(PLpgSQL_stmt_block));
  193. new->cmd_type   = PLPGSQL_STMT_BLOCK;
  194. new->lineno     = $3;
  195. new->label      = $1.label;
  196. new->n_initvars = $1.n_initvars;
  197. new->initvarnos = $1.initvarnos;
  198. new->body       = $4;
  199. plpgsql_ns_pop();
  200. $$ = (PLpgSQL_stmt *)new;
  201.     }
  202. ;
  203. decl_sect : opt_label
  204.     {
  205.         plpgsql_ns_setlocal(false);
  206. $$.label      = $1;
  207. $$.n_initvars = 0;
  208. $$.initvarnos = NULL;
  209. plpgsql_add_initdatums(NULL);
  210.     }
  211. | opt_label decl_start
  212.     {
  213.         plpgsql_ns_setlocal(false);
  214. $$.label      = $1;
  215. $$.n_initvars = 0;
  216. $$.initvarnos = NULL;
  217. plpgsql_add_initdatums(NULL);
  218.     }
  219. | opt_label decl_start decl_stmts
  220.     {
  221.         plpgsql_ns_setlocal(false);
  222. if ($3 != NULL) {
  223.     $$.label = $3;
  224. } else {
  225.     $$.label = $1;
  226. }
  227. $$.n_initvars = plpgsql_add_initdatums(&($$.initvarnos));
  228.     }
  229. ;
  230. decl_start : K_DECLARE
  231.     {
  232.         plpgsql_ns_setlocal(true);
  233.     }
  234. ;
  235. decl_stmts : decl_stmts decl_stmt
  236.     {
  237.         $$ = $2;
  238.     }
  239. | decl_stmt
  240.     {
  241.         $$ = $1;
  242.     }
  243. ;
  244. decl_stmt : '<' '<' opt_lblname '>' '>'
  245.     {
  246. $$ = $3;
  247.     }
  248. | K_DECLARE
  249.     {
  250.         $$ = NULL;
  251.     }
  252. | decl_statement
  253.     {
  254.         $$ = NULL;
  255.     }
  256. ;
  257. decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
  258.     {
  259.         PLpgSQL_var *new;
  260. new = malloc(sizeof(PLpgSQL_var));
  261. new->dtype = PLPGSQL_DTYPE_VAR;
  262. new->refname = $1.name;
  263. new->lineno = $1.lineno;
  264. new->datatype = $3;
  265. new->isconst = $2;
  266. new->notnull = $4;
  267. new->default_val = $5;
  268. plpgsql_adddatum((PLpgSQL_datum *)new);
  269. plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
  270. $1.name);
  271.     }
  272. | decl_varname K_RECORD ';'
  273.     {
  274.         PLpgSQL_rec *new;
  275. new = malloc(sizeof(PLpgSQL_var));
  276. new->dtype = PLPGSQL_DTYPE_REC;
  277. new->refname = $1.name;
  278. new->lineno = $1.lineno;
  279. plpgsql_adddatum((PLpgSQL_datum *)new);
  280. plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, new->recno,
  281. $1.name);
  282.     }
  283. | decl_varname decl_rowtype ';'
  284.     {
  285. $2->dtype = PLPGSQL_DTYPE_ROW;
  286. $2->refname = $1.name;
  287. $2->lineno = $1.lineno;
  288. plpgsql_adddatum((PLpgSQL_datum *)$2);
  289. plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno,
  290. $1.name);
  291.     }
  292. | decl_varname K_ALIAS K_FOR decl_aliasitem ';'
  293.     {
  294.         plpgsql_ns_additem($4->itemtype,
  295. $4->itemno, $1.name);
  296.     }
  297. | K_RENAME decl_renname K_TO decl_renname ';'
  298.     {
  299.         plpgsql_ns_rename($2, $4);
  300.     }
  301. ;
  302. decl_aliasitem : T_WORD
  303.     {
  304.         PLpgSQL_nsitem *nsi;
  305. char *name;
  306. plpgsql_ns_setlocal(false);
  307. name = plpgsql_tolower(yytext);
  308. if (name[0] != '$') {
  309.     elog(ERROR, "can only alias positional parameters");
  310. }
  311. nsi = plpgsql_ns_lookup(name, NULL);
  312. if (nsi == NULL) {
  313.     elog(ERROR, "function has no parameter %s", name);
  314. }
  315. plpgsql_ns_setlocal(true);
  316. $$ = nsi;
  317.     }
  318. ;
  319. decl_rowtype : T_ROW
  320.     {
  321.         $$ = yylval.row;
  322.     }
  323. ;
  324. decl_varname : T_WORD
  325.     {
  326.         $$.name = strdup(yytext);
  327. $$.lineno  = yylineno;
  328.     }
  329. ;
  330. decl_renname : T_WORD
  331.     {
  332.         $$ = plpgsql_tolower(yytext);
  333.     }
  334. ;
  335. decl_const :
  336.     { $$ = 0; }
  337. | K_CONSTANT
  338.     { $$ = 1; }
  339. ;
  340. decl_datatype : decl_dtypename
  341.     {
  342.         $$ = $1;
  343.     }
  344. ;
  345. decl_dtypename : T_DTYPE
  346.     {
  347. $$ = yylval.dtype;
  348.     }
  349. | T_CHAR decl_atttypmod
  350.     {
  351.         if ($2 < 0) {
  352.     plpgsql_parse_word("char");
  353.     $$ = yylval.dtype;
  354. } else {
  355.     plpgsql_parse_word("bpchar");
  356.     $$ = yylval.dtype;
  357.     $$->atttypmod = $2;
  358. }
  359.     }
  360. | T_VARCHAR decl_atttypmod
  361.     {
  362.         plpgsql_parse_word("varchar");
  363. $$ = yylval.dtype;
  364. $$->atttypmod = $2;
  365.     }
  366. | T_BPCHAR '(' decl_atttypmodval ')'
  367.     {
  368.         plpgsql_parse_word("bpchar");
  369. $$ = yylval.dtype;
  370. $$->atttypmod = $3;
  371.     }
  372. ;
  373. decl_atttypmod :
  374.     {
  375.         $$ = -1;
  376.     }
  377. | '(' decl_atttypmodval ')'
  378.     {
  379.         $$ = $2;
  380.     }
  381. ;
  382. decl_atttypmodval : T_NUMBER
  383.     {
  384.         $$ = int2in(yytext) + VARHDRSZ;
  385.     }
  386. ;
  387. decl_notnull :
  388.     { $$ = 0; }
  389. | K_NOT K_NULL
  390.     { $$ = 1; }
  391. ;
  392. decl_defval : ';'
  393.     { $$ = NULL; }
  394. | decl_defkey
  395.     {
  396. int tok;
  397. int lno;
  398.         PLpgSQL_dstring ds;
  399. PLpgSQL_expr *expr;
  400. lno = yylineno;
  401. expr = malloc(sizeof(PLpgSQL_expr));
  402. plpgsql_dstring_init(&ds);
  403. plpgsql_dstring_append(&ds, "SELECT ");
  404. expr->dtype   = PLPGSQL_DTYPE_EXPR;
  405. expr->plan    = NULL;
  406. expr->nparams = 0;
  407. tok = yylex();
  408. switch (tok) {
  409.     case 0:
  410. plpgsql_error_lineno = lno;
  411. plpgsql_comperrinfo();
  412.      elog(ERROR, "unexpected end of file");
  413.     case K_NULL:
  414.         if (yylex() != ';') {
  415.     plpgsql_error_lineno = lno;
  416.     plpgsql_comperrinfo();
  417.     elog(ERROR, "expectec ; after NULL");
  418. }
  419. free(expr);
  420. plpgsql_dstring_free(&ds);
  421. $$ = NULL;
  422. break;
  423.     default:
  424. plpgsql_dstring_append(&ds, yytext);
  425. while ((tok = yylex()) != ';') {
  426.     if (tok == 0) {
  427. plpgsql_error_lineno = lno;
  428. plpgsql_comperrinfo();
  429. elog(ERROR, "unterminated default value");
  430.     }
  431.     if (plpgsql_SpaceScanned) {
  432. plpgsql_dstring_append(&ds, " ");
  433.     }
  434.     plpgsql_dstring_append(&ds, yytext);
  435. }
  436. expr->query = strdup(plpgsql_dstring_get(&ds));
  437. plpgsql_dstring_free(&ds);
  438. $$ = expr;
  439. break;
  440. }
  441.     }
  442. ;
  443. decl_defkey : K_ASSIGN
  444. | K_DEFAULT
  445. proc_sect :
  446. {
  447. PLpgSQL_stmts *new;
  448. new = malloc(sizeof(PLpgSQL_stmts));
  449. memset(new, 0, sizeof(PLpgSQL_stmts));
  450. $$ = new;
  451. }
  452. | proc_stmts
  453. {
  454. $$ = $1;
  455. }
  456. ;
  457. proc_stmts : proc_stmts proc_stmt
  458. {
  459. if ($1->stmts_used == $1->stmts_alloc) {
  460.     $1->stmts_alloc *= 2;
  461.     $1->stmts = realloc($1->stmts, sizeof(PLpgSQL_stmt *) * $1->stmts_alloc);
  462. }
  463. $1->stmts[$1->stmts_used++] = (struct PLpgSQL_stmt *)$2;
  464. $$ = $1;
  465. }
  466. | proc_stmt
  467. {
  468. PLpgSQL_stmts *new;
  469. new = malloc(sizeof(PLpgSQL_stmts));
  470. memset(new, 0, sizeof(PLpgSQL_stmts));
  471. new->stmts_alloc = 64;
  472. new->stmts_used  = 1;
  473. new->stmts = malloc(sizeof(PLpgSQL_stmt *) * new->stmts_alloc);
  474. new->stmts[0] = (struct PLpgSQL_stmt *)$1;
  475. $$ = new;
  476. }
  477. ;
  478. proc_stmt : pl_block
  479. { $$ = $1; }
  480. | stmt_assign
  481. { $$ = $1; }
  482. | stmt_if
  483. { $$ = $1; }
  484. | stmt_loop
  485. { $$ = $1; }
  486. | stmt_while
  487. { $$ = $1; }
  488. | stmt_fori
  489. { $$ = $1; }
  490. | stmt_fors
  491. { $$ = $1; }
  492. | stmt_select
  493. { $$ = $1; }
  494. | stmt_exit
  495. { $$ = $1; }
  496. | stmt_return
  497. { $$ = $1; }
  498. | stmt_raise
  499. { $$ = $1; }
  500. | stmt_execsql
  501. { $$ = $1; }
  502. | stmt_perform
  503. { $$ = $1; }
  504. ;
  505. stmt_perform : K_PERFORM lno expr_until_semi
  506.     {
  507.      PLpgSQL_stmt_assign *new;
  508. new = malloc(sizeof(PLpgSQL_stmt_assign));
  509. memset(new, 0, sizeof(PLpgSQL_stmt_assign));
  510. new->cmd_type = PLPGSQL_STMT_ASSIGN;
  511. new->lineno   = $2;
  512. new->varno = -1;
  513. new->expr  = $3;
  514. $$ = (PLpgSQL_stmt *)new;
  515.     }
  516. ;
  517. stmt_assign : assign_var lno K_ASSIGN expr_until_semi
  518.     {
  519. PLpgSQL_stmt_assign *new;
  520. new = malloc(sizeof(PLpgSQL_stmt_assign));
  521. memset(new, 0, sizeof(PLpgSQL_stmt_assign));
  522. new->cmd_type = PLPGSQL_STMT_ASSIGN;
  523. new->lineno   = $2;
  524. new->varno = $1;
  525. new->expr  = $4;
  526. $$ = (PLpgSQL_stmt *)new;
  527.     }
  528. ;
  529. assign_var : T_VARIABLE
  530.     {
  531. if (yylval.var->isconst) {
  532.     plpgsql_comperrinfo();
  533.     elog(ERROR, "%s is declared CONSTANT", yylval.var->refname);
  534. }
  535.         $$ = yylval.var->varno;
  536.     }
  537. | T_RECFIELD
  538.     {
  539.         $$ = yylval.recfield->rfno;
  540.     }
  541. ;
  542. stmt_if : K_IF lno expr_until_then proc_sect stmt_else K_END K_IF ';'
  543.     {
  544. PLpgSQL_stmt_if *new;
  545. new = malloc(sizeof(PLpgSQL_stmt_if));
  546. memset(new, 0, sizeof(PLpgSQL_stmt_if));
  547. new->cmd_type   = PLPGSQL_STMT_IF;
  548. new->lineno     = $2;
  549. new->cond       = $3;
  550. new->true_body  = $4;
  551. new->false_body = $5;
  552. $$ = (PLpgSQL_stmt *)new;
  553.     }
  554. ;
  555. stmt_else :
  556. {
  557. PLpgSQL_stmts *new;
  558. new = malloc(sizeof(PLpgSQL_stmts));
  559. memset(new, 0, sizeof(PLpgSQL_stmts));
  560. $$ = new;
  561. }
  562. | K_ELSE proc_sect
  563. { $$ = $2; }
  564. ;
  565. stmt_loop : opt_label K_LOOP lno loop_body
  566.     {
  567. PLpgSQL_stmt_loop *new;
  568. new = malloc(sizeof(PLpgSQL_stmt_loop));
  569. memset(new, 0, sizeof(PLpgSQL_stmt_loop));
  570. new->cmd_type = PLPGSQL_STMT_LOOP;
  571. new->lineno   = $3;
  572. new->label    = $1;
  573. new->body     = $4;
  574. plpgsql_ns_pop();
  575. $$ = (PLpgSQL_stmt *)new;
  576.     }
  577. ;
  578. stmt_while : opt_label K_WHILE lno expr_until_loop loop_body
  579.     {
  580. PLpgSQL_stmt_while *new;
  581. new = malloc(sizeof(PLpgSQL_stmt_while));
  582. memset(new, 0, sizeof(PLpgSQL_stmt_while));
  583. new->cmd_type = PLPGSQL_STMT_WHILE;
  584. new->lineno   = $3;
  585. new->label    = $1;
  586. new->cond     = $4;
  587. new->body     = $5;
  588. plpgsql_ns_pop();
  589. $$ = (PLpgSQL_stmt *)new;
  590.     }
  591. ;
  592. stmt_fori : opt_label K_FOR lno fori_var K_IN fori_lower expr_until_loop loop_body
  593.     {
  594. PLpgSQL_stmt_fori *new;
  595. new = malloc(sizeof(PLpgSQL_stmt_fori));
  596. memset(new, 0, sizeof(PLpgSQL_stmt_fori));
  597. new->cmd_type = PLPGSQL_STMT_FORI;
  598. new->lineno   = $3;
  599. new->label    = $1;
  600. new->var      = $4;
  601. new->reverse  = $6.reverse;
  602. new->lower    = $6.expr;
  603. new->upper    = $7;
  604. new->body     = $8;
  605. plpgsql_ns_pop();
  606. $$ = (PLpgSQL_stmt *)new;
  607.     }
  608. ;
  609. fori_var : fori_varname
  610.     {
  611.         PLpgSQL_var *new;
  612. new = malloc(sizeof(PLpgSQL_var));
  613. new->dtype = PLPGSQL_DTYPE_VAR;
  614. new->refname = $1.name;
  615. new->lineno = $1.lineno;
  616. plpgsql_parse_word("integer");
  617. new->datatype = yylval.dtype;
  618. new->isconst = false;
  619. new->notnull = false;
  620. new->default_val = NULL;
  621. plpgsql_adddatum((PLpgSQL_datum *)new);
  622. plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
  623. $1.name);
  624. plpgsql_add_initdatums(NULL);
  625.         $$ = new;
  626.     }
  627. ;
  628. fori_varname : T_VARIABLE
  629.     {
  630.         $$.name = strdup(yytext);
  631. $$.lineno = yylineno;
  632.     }
  633. | T_WORD
  634.     {
  635.         $$.name = strdup(yytext);
  636. $$.lineno = yylineno;
  637.     }
  638. ;
  639. fori_lower :
  640.     {
  641. int tok;
  642. int lno;
  643. PLpgSQL_dstring ds;
  644. int nparams = 0;
  645. int params[1024];
  646. char buf[32];
  647. PLpgSQL_expr *expr;
  648. int firsttok = 1;
  649. lno = yylineno;
  650. plpgsql_dstring_init(&ds);
  651. plpgsql_dstring_append(&ds, "SELECT ");
  652. $$.reverse = 0;
  653. while((tok = yylex()) != K_DOTDOT) {
  654.     if (firsttok) {
  655. firsttok = 0;
  656. if (tok == K_REVERSE) {
  657.     $$.reverse = 1;
  658.     continue;
  659. }
  660.     }
  661.     if (tok == ';') break;
  662.     if (plpgsql_SpaceScanned) {
  663. plpgsql_dstring_append(&ds, " ");
  664.     }
  665.     switch (tok) {
  666. case T_VARIABLE:
  667.     params[nparams] = yylval.var->varno;
  668.     sprintf(buf, "$%d", ++nparams);
  669.     plpgsql_dstring_append(&ds, buf);
  670.     break;
  671.     
  672. case T_RECFIELD:
  673.     params[nparams] = yylval.recfield->rfno;
  674.     sprintf(buf, "$%d", ++nparams);
  675.     plpgsql_dstring_append(&ds, buf);
  676.     break;
  677.     
  678. case T_TGARGV:
  679.     params[nparams] = yylval.trigarg->dno;
  680.     sprintf(buf, "$%d", ++nparams);
  681.     plpgsql_dstring_append(&ds, buf);
  682.     break;
  683.     
  684. default:
  685.     if (tok == 0) {
  686. plpgsql_error_lineno = lno;
  687. plpgsql_comperrinfo();
  688. elog(ERROR, "missing .. to terminate lower bound of for loop");
  689.     }
  690.     plpgsql_dstring_append(&ds, yytext);
  691.     break;
  692.     }
  693. }
  694. expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
  695. expr->dtype = PLPGSQL_DTYPE_EXPR;
  696. expr->query = strdup(plpgsql_dstring_get(&ds));
  697. expr->plan = NULL;
  698. expr->nparams = nparams;
  699. while(nparams-- > 0) {
  700.     expr->params[nparams] = params[nparams];
  701. }
  702. plpgsql_dstring_free(&ds);
  703. $$.expr = expr;
  704.     }
  705. stmt_fors : opt_label K_FOR lno fors_target K_IN K_SELECT expr_until_loop loop_body
  706.     {
  707. PLpgSQL_stmt_fors *new;
  708. new = malloc(sizeof(PLpgSQL_stmt_fors));
  709. memset(new, 0, sizeof(PLpgSQL_stmt_fors));
  710. new->cmd_type = PLPGSQL_STMT_FORS;
  711. new->lineno   = $3;
  712. new->label    = $1;
  713. switch ($4->dtype) {
  714.     case PLPGSQL_DTYPE_REC:
  715.         new->rec = $4;
  716. break;
  717.     case PLPGSQL_DTYPE_ROW:
  718.         new->row = (PLpgSQL_row *)$4;
  719. break;
  720.     default:
  721. plpgsql_comperrinfo();
  722.         elog(ERROR, "unknown dtype %d in stmt_fors", $4->dtype);
  723. }
  724. new->query = $7;
  725. new->body  = $8;
  726. plpgsql_ns_pop();
  727. $$ = (PLpgSQL_stmt *)new;
  728.     }
  729. fors_target : T_RECORD
  730.     {
  731.         $$ = yylval.rec;
  732.     }
  733. | T_ROW
  734.     {
  735.      $$ = (PLpgSQL_rec *)(yylval.row);
  736.     }
  737. ;
  738. stmt_select : K_SELECT lno
  739.     {
  740.      $$ = make_select_stmt();
  741. $$->lineno = $2;
  742.     }
  743. ;
  744. stmt_exit : K_EXIT lno opt_exitlabel opt_exitcond
  745.     {
  746. PLpgSQL_stmt_exit *new;
  747. new = malloc(sizeof(PLpgSQL_stmt_exit));
  748. memset(new, 0, sizeof(PLpgSQL_stmt_exit));
  749. new->cmd_type = PLPGSQL_STMT_EXIT;
  750. new->lineno   = $2;
  751. new->label    = $3;
  752. new->cond     = $4;
  753. $$ = (PLpgSQL_stmt *)new;
  754.     }
  755. ;
  756. stmt_return : K_RETURN lno
  757.     {
  758. PLpgSQL_stmt_return *new;
  759. PLpgSQL_expr *expr = NULL;
  760. int tok;
  761. new = malloc(sizeof(PLpgSQL_stmt_return));
  762. memset(new, 0, sizeof(PLpgSQL_stmt_return));
  763. if (plpgsql_curr_compile->fn_retistuple) {
  764.     new->retistuple = true;
  765.     new->retrecno   = -1;
  766.     switch (tok = yylex()) {
  767.         case K_NULL:
  768.     expr = NULL;
  769.     break;
  770.         case T_ROW:
  771.     expr = make_tupret_expr(yylval.row);
  772.     break;
  773. case T_RECORD:
  774.     new->retrecno = yylval.rec->recno;
  775.     expr = NULL;
  776.     break;
  777. default:
  778.     yyerror("return type mismatch in function returning table row");
  779.     break;
  780.     }
  781.     if (yylex() != ';') {
  782.         yyerror("expected ';'");
  783.     }
  784. } else {
  785.     new->retistuple = false;
  786.     expr = plpgsql_read_expression(';', ";");
  787. }
  788. new->cmd_type = PLPGSQL_STMT_RETURN;
  789. new->lineno   = $2;
  790. new->expr     = expr;
  791. $$ = (PLpgSQL_stmt *)new;
  792.     }
  793. ;
  794. stmt_raise : K_RAISE lno raise_level raise_msg raise_params ';'
  795.     {
  796.         PLpgSQL_stmt_raise *new;
  797. new = malloc(sizeof(PLpgSQL_stmt_raise));
  798. new->cmd_type = PLPGSQL_STMT_RAISE;
  799. new->lineno     = $2;
  800. new->elog_level = $3;
  801. new->message = $4;
  802. new->nparams = $5.nused;
  803. new->params = malloc(sizeof(int) * $5.nused);
  804. memcpy(new->params, $5.dtnums, sizeof(int) * $5.nused);
  805. $$ = (PLpgSQL_stmt *)new;
  806.     }
  807. | K_RAISE lno raise_level raise_msg ';'
  808.     {
  809.         PLpgSQL_stmt_raise *new;
  810. new = malloc(sizeof(PLpgSQL_stmt_raise));
  811. new->cmd_type = PLPGSQL_STMT_RAISE;
  812. new->lineno     = $2;
  813. new->elog_level = $3;
  814. new->message = $4;
  815. new->nparams = 0;
  816. new->params = NULL;
  817. $$ = (PLpgSQL_stmt *)new;
  818.     }
  819. ;
  820. raise_msg : T_STRING
  821.     {
  822.         $$ = strdup(yytext);
  823.     }
  824. ;
  825. raise_level : K_EXCEPTION
  826.     {
  827.         $$ = ERROR;
  828.     }
  829. | K_NOTICE
  830.     {
  831.         $$ = NOTICE;
  832.     }
  833. | K_DEBUG
  834.     {
  835.         $$ = DEBUG;
  836.     }
  837. ;
  838. raise_params : raise_params raise_param
  839.     {
  840.         if ($1.nused == $1.nalloc) {
  841.     $1.nalloc *= 2;
  842.     $1.dtnums = repalloc($1.dtnums, sizeof(int) * $1.nalloc);
  843. }
  844. $1.dtnums[$1.nused++] = $2;
  845. $$.nalloc = $1.nalloc;
  846. $$.nused  = $1.nused;
  847. $$.dtnums = $1.dtnums;
  848.     }
  849. | raise_param
  850.     {
  851.         $$.nalloc = 1;
  852. $$.nused  = 1;
  853. $$.dtnums = palloc(sizeof(int) * $$.nalloc);
  854. $$.dtnums[0] = $1;
  855.     }
  856. ;
  857. raise_param : ',' T_VARIABLE
  858.     {
  859.         $$ = yylval.var->varno;
  860.     }
  861. | ',' T_RECFIELD
  862.     {
  863.         $$ = yylval.recfield->rfno;
  864.     }
  865. | ',' T_TGARGV
  866.     {
  867.         $$ = yylval.trigarg->dno;
  868.     }
  869. ;
  870. loop_body : proc_sect K_END K_LOOP ';'
  871.     { $$ = $1; }
  872. ;
  873. stmt_execsql : execsql_start lno
  874.     {
  875.         PLpgSQL_stmt_execsql *new;
  876. new = malloc(sizeof(PLpgSQL_stmt_execsql));
  877. new->cmd_type = PLPGSQL_STMT_EXECSQL;
  878. new->lineno   = $2;
  879. new->sqlstmt  = read_sqlstmt(';', ";", $1);
  880. $$ = (PLpgSQL_stmt *)new;
  881.     }
  882. ;
  883. execsql_start : T_WORD
  884.     { $$ = strdup(yytext); }
  885. | T_ERROR
  886.     { $$ = strdup(yytext); }
  887. ;
  888. expr_until_semi :
  889.     { $$ = plpgsql_read_expression(';', ";"); }
  890. ;
  891. expr_until_then :
  892.     { $$ = plpgsql_read_expression(K_THEN, "THEN"); }
  893. ;
  894. expr_until_loop :
  895.     { $$ = plpgsql_read_expression(K_LOOP, "LOOP"); }
  896. ;
  897. opt_label :
  898.     {
  899. plpgsql_ns_push(NULL);
  900. $$ = NULL;
  901.     }
  902. | '<' '<' opt_lblname '>' '>'
  903.     {
  904. plpgsql_ns_push($3);
  905. $$ = $3;
  906.     }
  907. ;
  908. opt_exitlabel :
  909.     { $$ = NULL; }
  910. | T_LABEL
  911.     { $$ = strdup(yytext); }
  912. ;
  913. opt_exitcond : ';'
  914.     { $$ = NULL; }
  915. | K_WHEN expr_until_semi
  916.     { $$ = $2; }
  917. ;
  918. opt_lblname : T_WORD
  919.     { $$ = strdup(yytext); }
  920. ;
  921. lno :
  922.     {
  923. plpgsql_error_lineno = yylineno;
  924.         $$ = yylineno;
  925.     }
  926. ;
  927. %%
  928. #ifndef YYBISON
  929. #include "pl_scan.c" /* BSD yacc wants it here */
  930. #endif
  931. PLpgSQL_expr *
  932. plpgsql_read_expression (int until, char *s)
  933. {
  934.     return read_sqlstmt(until, s, "SELECT ");
  935. }
  936. static PLpgSQL_expr *
  937. read_sqlstmt (int until, char *s, char *sqlstart)
  938. {
  939.     int tok;
  940.     int lno;
  941.     PLpgSQL_dstring ds;
  942.     int nparams = 0;
  943.     int params[1024];
  944.     char buf[32];
  945.     PLpgSQL_expr *expr;
  946.     lno = yylineno;
  947.     plpgsql_dstring_init(&ds);
  948.     plpgsql_dstring_append(&ds, sqlstart);
  949.     while((tok = yylex()) != until) {
  950. if (tok == ';') break;
  951. if (plpgsql_SpaceScanned) {
  952.     plpgsql_dstring_append(&ds, " ");
  953. }
  954.         switch (tok) {
  955.     case T_VARIABLE:
  956. params[nparams] = yylval.var->varno;
  957. sprintf(buf, "$%d", ++nparams);
  958. plpgsql_dstring_append(&ds, buf);
  959. break;
  960.         
  961.     case T_RECFIELD:
  962. params[nparams] = yylval.recfield->rfno;
  963. sprintf(buf, "$%d", ++nparams);
  964. plpgsql_dstring_append(&ds, buf);
  965. break;
  966.         
  967.     case T_TGARGV:
  968. params[nparams] = yylval.trigarg->dno;
  969. sprintf(buf, "$%d", ++nparams);
  970. plpgsql_dstring_append(&ds, buf);
  971. break;
  972.         
  973.     default:
  974. if (tok == 0) {
  975.     plpgsql_error_lineno = lno;
  976.     plpgsql_comperrinfo();
  977.     elog(ERROR, "missing %s at end of SQL statement", s);
  978. }
  979. plpgsql_dstring_append(&ds, yytext);
  980. break;
  981.         }
  982.     }
  983.     expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
  984.     expr->dtype = PLPGSQL_DTYPE_EXPR;
  985.     expr->query = strdup(plpgsql_dstring_get(&ds));
  986.     expr->plan = NULL;
  987.     expr->nparams = nparams;
  988.     while(nparams-- > 0) {
  989.         expr->params[nparams] = params[nparams];
  990.     }
  991.     plpgsql_dstring_free(&ds);
  992.     
  993.     return expr;
  994. }
  995. static PLpgSQL_stmt *
  996. make_select_stmt()
  997. {
  998.     int tok;
  999.     int lno;
  1000.     PLpgSQL_dstring ds;
  1001.     int nparams = 0;
  1002.     int params[1024];
  1003.     char buf[32];
  1004.     PLpgSQL_expr *expr;
  1005.     PLpgSQL_row *row = NULL;
  1006.     PLpgSQL_rec *rec = NULL;
  1007.     PLpgSQL_stmt_select *select;
  1008.     int have_nexttok = 0;
  1009.     lno = yylineno;
  1010.     plpgsql_dstring_init(&ds);
  1011.     plpgsql_dstring_append(&ds, "SELECT ");
  1012.     while((tok = yylex()) != K_INTO) {
  1013. if (tok == ';') {
  1014.     PLpgSQL_stmt_execsql *execsql;
  1015.     expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
  1016.     expr->dtype = PLPGSQL_DTYPE_EXPR;
  1017.     expr->query = strdup(plpgsql_dstring_get(&ds));
  1018.     expr->plan = NULL;
  1019.     expr->nparams = nparams;
  1020.     while(nparams-- > 0) {
  1021. expr->params[nparams] = params[nparams];
  1022.     }
  1023.     plpgsql_dstring_free(&ds);
  1024.     execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
  1025.     execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
  1026.     execsql->sqlstmt  = expr;
  1027.     return (PLpgSQL_stmt *)execsql;
  1028. }
  1029. if (plpgsql_SpaceScanned) {
  1030.     plpgsql_dstring_append(&ds, " ");
  1031. }
  1032.         switch (tok) {
  1033.     case T_VARIABLE:
  1034. params[nparams] = yylval.var->varno;
  1035. sprintf(buf, "$%d", ++nparams);
  1036. plpgsql_dstring_append(&ds, buf);
  1037. break;
  1038.         
  1039.     case T_RECFIELD:
  1040. params[nparams] = yylval.recfield->rfno;
  1041. sprintf(buf, "$%d", ++nparams);
  1042. plpgsql_dstring_append(&ds, buf);
  1043. break;
  1044.         
  1045.     case T_TGARGV:
  1046. params[nparams] = yylval.trigarg->dno;
  1047. sprintf(buf, "$%d", ++nparams);
  1048. plpgsql_dstring_append(&ds, buf);
  1049. break;
  1050.         
  1051.     default:
  1052. if (tok == 0) {
  1053.     plpgsql_error_lineno = yylineno;
  1054.     plpgsql_comperrinfo();
  1055.     elog(ERROR, "unexpected end of file");
  1056. }
  1057. plpgsql_dstring_append(&ds, yytext);
  1058. break;
  1059.         }
  1060.     }
  1061.     tok = yylex();
  1062.     switch (tok) {
  1063.         case T_ROW:
  1064.     row = yylval.row;
  1065.     break;
  1066.         case T_RECORD:
  1067.     rec = yylval.rec;
  1068.     break;
  1069. case T_VARIABLE:
  1070. case T_RECFIELD:
  1071.     {
  1072. PLpgSQL_var *var;
  1073. PLpgSQL_recfield *recfield;
  1074. int nfields = 1;
  1075. char *fieldnames[1024];
  1076. int varnos[1024];
  1077. switch (tok) {
  1078.     case T_VARIABLE:
  1079. var = yylval.var;
  1080. fieldnames[0] = strdup(yytext);
  1081. varnos[0]     = var->varno;
  1082. break;
  1083.     
  1084.     case T_RECFIELD:
  1085. recfield = yylval.recfield;
  1086. fieldnames[0] = strdup(yytext);
  1087. varnos[0]     = recfield->rfno;
  1088. break;
  1089. }
  1090. while ((tok = yylex()) == ',') {
  1091.     tok = yylex();
  1092.     switch(tok) {
  1093. case T_VARIABLE:
  1094.     var = yylval.var;
  1095.     fieldnames[nfields] = strdup(yytext);
  1096.     varnos[nfields++]   = var->varno;
  1097.     break;
  1098. case T_RECFIELD:
  1099.     recfield = yylval.recfield;
  1100.     fieldnames[0] = strdup(yytext);
  1101.     varnos[0]     = recfield->rfno;
  1102.     break;
  1103. default:
  1104.     elog(ERROR, "plpgsql: %s is not a variable or record field", yytext);
  1105.     }
  1106. }
  1107. row = malloc(sizeof(PLpgSQL_row));
  1108. row->dtype = PLPGSQL_DTYPE_ROW;
  1109. row->refname = strdup("*internal*");
  1110. row->lineno = yylineno;
  1111. row->rowtypeclass = InvalidOid;
  1112. row->nfields = nfields;
  1113. row->fieldnames = malloc(sizeof(char *) * nfields);
  1114. row->varnos = malloc(sizeof(int) * nfields);
  1115. while (--nfields >= 0) {
  1116.     row->fieldnames[nfields] = fieldnames[nfields];
  1117.     row->varnos[nfields] = varnos[nfields];
  1118. }
  1119. plpgsql_adddatum((PLpgSQL_datum *)row);
  1120. have_nexttok = 1;
  1121.     }
  1122.     break;
  1123.         default:
  1124.     {
  1125. if (plpgsql_SpaceScanned) {
  1126.     plpgsql_dstring_append(&ds, " ");
  1127. }
  1128. plpgsql_dstring_append(&ds, yytext);
  1129. while(1) {
  1130.     tok = yylex();
  1131.     if (tok == ';') {
  1132. PLpgSQL_stmt_execsql *execsql;
  1133. expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - 1);
  1134. expr->dtype = PLPGSQL_DTYPE_EXPR;
  1135. expr->query = strdup(plpgsql_dstring_get(&ds));
  1136. expr->plan = NULL;
  1137. expr->nparams = nparams;
  1138. while(nparams-- > 0) {
  1139.     expr->params[nparams] = params[nparams];
  1140. }
  1141. plpgsql_dstring_free(&ds);
  1142. execsql = malloc(sizeof(PLpgSQL_stmt_execsql));
  1143. execsql->cmd_type = PLPGSQL_STMT_EXECSQL;
  1144. execsql->sqlstmt  = expr;
  1145. return (PLpgSQL_stmt *)execsql;
  1146.     }
  1147.     if (plpgsql_SpaceScanned) {
  1148. plpgsql_dstring_append(&ds, " ");
  1149.     }
  1150.     switch (tok) {
  1151. case T_VARIABLE:
  1152.     params[nparams] = yylval.var->varno;
  1153.     sprintf(buf, "$%d", ++nparams);
  1154.     plpgsql_dstring_append(&ds, buf);
  1155.     break;
  1156.     
  1157. case T_RECFIELD:
  1158.     params[nparams] = yylval.recfield->rfno;
  1159.     sprintf(buf, "$%d", ++nparams);
  1160.     plpgsql_dstring_append(&ds, buf);
  1161.     break;
  1162.     
  1163. case T_TGARGV:
  1164.     params[nparams] = yylval.trigarg->dno;
  1165.     sprintf(buf, "$%d", ++nparams);
  1166.     plpgsql_dstring_append(&ds, buf);
  1167.     break;
  1168.     
  1169. default:
  1170.     if (tok == 0) {
  1171. plpgsql_error_lineno = yylineno;
  1172. plpgsql_comperrinfo();
  1173. elog(ERROR, "unexpected end of file");
  1174.     }
  1175.     plpgsql_dstring_append(&ds, yytext);
  1176.     break;
  1177.     }
  1178. }
  1179.     }
  1180.     }
  1181.     /************************************************************
  1182.      * Eat up the rest of the statement after the target fields
  1183.      ************************************************************/
  1184.     while(1) {
  1185. if (!have_nexttok) {
  1186.     tok = yylex();
  1187. }
  1188. have_nexttok = 0;
  1189. if (tok == ';') {
  1190.     break;
  1191. }
  1192. if (plpgsql_SpaceScanned) {
  1193.     plpgsql_dstring_append(&ds, " ");
  1194. }
  1195. switch (tok) {
  1196.     case T_VARIABLE:
  1197. params[nparams] = yylval.var->varno;
  1198. sprintf(buf, "$%d", ++nparams);
  1199. plpgsql_dstring_append(&ds, buf);
  1200. break;
  1201.     case T_RECFIELD:
  1202. params[nparams] = yylval.recfield->rfno;
  1203. sprintf(buf, "$%d", ++nparams);
  1204. plpgsql_dstring_append(&ds, buf);
  1205. break;
  1206.     case T_TGARGV:
  1207. params[nparams] = yylval.trigarg->dno;
  1208. sprintf(buf, "$%d", ++nparams);
  1209. plpgsql_dstring_append(&ds, buf);
  1210. break;
  1211.     default:
  1212. if (tok == 0) {
  1213.     plpgsql_error_lineno = yylineno;
  1214.     plpgsql_comperrinfo();
  1215.     elog(ERROR, "unexpected end of file");
  1216. }
  1217. plpgsql_dstring_append(&ds, yytext);
  1218. break;
  1219. }
  1220.     }
  1221.     expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (nparams - 1));
  1222.     expr->dtype = PLPGSQL_DTYPE_EXPR;
  1223.     expr->query = strdup(plpgsql_dstring_get(&ds));
  1224.     expr->plan = NULL;
  1225.     expr->nparams = nparams;
  1226.     while(nparams-- > 0) {
  1227.         expr->params[nparams] = params[nparams];
  1228.     }
  1229.     plpgsql_dstring_free(&ds);
  1230.     select = malloc(sizeof(PLpgSQL_stmt_select));
  1231.     memset(select, 0, sizeof(PLpgSQL_stmt_select));
  1232.     select->cmd_type = PLPGSQL_STMT_SELECT;
  1233.     select->rec      = rec;
  1234.     select->row      = row;
  1235.     select->query    = expr;
  1236.     
  1237.     return (PLpgSQL_stmt *)select;
  1238. }
  1239. static PLpgSQL_expr *
  1240. make_tupret_expr(PLpgSQL_row *row)
  1241. {
  1242.     PLpgSQL_dstring ds;
  1243.     PLpgSQL_expr *expr;
  1244.     int i;
  1245.     char buf[16];
  1246.     expr = malloc(sizeof(PLpgSQL_expr) + sizeof(int) * (row->nfields - 1));
  1247.     expr->dtype = PLPGSQL_DTYPE_EXPR;
  1248.     plpgsql_dstring_init(&ds);
  1249.     plpgsql_dstring_append(&ds, "SELECT ");
  1250.     for (i = 0; i < row->nfields; i++) {
  1251.         sprintf(buf, "%s$%d", (i > 0) ? "," : "", i + 1);
  1252. plpgsql_dstring_append(&ds, buf);
  1253. expr->params[i] = row->varnos[i];
  1254.     }
  1255.     expr->query         = strdup(plpgsql_dstring_get(&ds));
  1256.     expr->plan          = NULL;
  1257.     expr->plan_argtypes = NULL;
  1258.     expr->nparams       = row->nfields;
  1259.     plpgsql_dstring_free(&ds);
  1260.     return expr;
  1261. }