%{
/*
* Copyright (c) 1998
*/
#ifndef lint
static char rcsid[] = "@(#)$Id$";
static char copyright[] = "Copyright (c) 1998";
#endif
/***********************************************************************
* OpenROAD GRAMMAR
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
#include <assert.h>
#include "api.h"
#include "private.h"
#define YYSTYPE union yystack
%}
/* types of the non-terminals */
%type <str> com
%type <expr> expr factor opt_expr
%type <variable> variable opt_return
%type <builtin> builtin
%type <arglist> opt_arglist arg_list callproc_parms
%type <dotted> dotted_var var
%type <array_expr> array_expr
%type <args> args
%type <str> semicomma ',' ';'
%type <block> stmt_block opt_block
%type <stmtlist> stmtlist
%type <stmt> stmt
%type <stmt> s_assign s_call s_callsystem s_callframe s_callproc s_close s_commit
%type <stmt> s_continue s_delete s_endloop s_execimm s_execproc s_exit s_fetch
%type <stmt> s_for s_gotoframe s_ifthen s_inquiresql s_insert s_message s_open
%type <stmt> s_openframe s_prompt s_resume s_return s_rollback s_select s_set
%type <stmt> s_update s_while
%type <elseif_list> elseif_part elseif_list elseif
%type <stmtlist> else_part
%type <str> opt_label opt_labelref
%type <val> for_direction opt_work opt_repeated update_mode opt_next
%type <callparmlist> callparmlist callparm
%type <callparm> callparms
%type <framename> frame_name
%type <optlist> optlist attr
%type <str> savepoint opt_corrname cursor
%type <decl> initialize procedure on decl decl_list
%type <declarex> declare locals local_list local
%type <parms> parms parmlist parm
%type <onlist> on_list on_clause
%type <variable> column_name opt_fieldname
%type <str> event
%type <nulldef> nulldef_spec defspec
%type <datatype> datatype basic_type type
%type <val> '(' ')' '='
%type <varcol> varcol_list varcol
%type <val> sortorder selmode
%type <expr> sql_expr search_expr having_clause where_clause
%type <delete> sql_delete
%type <insert> sql_insert
%type <select> sql_select
%type <update> sql_update
%type <updateclause> update_clause
%type <columnlist> column_list columns update_of group_clause
%type <cursorlist> cursor_list
%type <varlist> varlist
%type <tablename> tablename
%type <setclause> set_clause set_expr
%type <fromlist> from_list from_item from_clause
%type <orderspec> orderspec order_list order_clause
%type <sqlexplist> sql_explist
%type <subselect> subselect select_union
/* Definition of returned tokens from the lexical analyzer */
%token <val> ARRAY
%token <val> DOWNTO
%token <val> READONLY
%token <val> DEFERRED
%token <val> RETURNING
%token <val> ALL
%token <val> ALTER
%token <val> AND
%token <val> ANY
%token <val> AS
%token <val> ASC
%token <val> AT
%token <val> BEGIN
%token <val> BETWEEN
%token <val> BY
%token <val> BYREF
%token <val> CALL
%token <val> CALLFRAME
%token <val> CALLPROC
%token <val> CLOSE
%token <val> COMMIT
%token <val> CONTINUE
%token <val> COPY
%token <val> COUNT
%token <val> CURRENT
%token <val> DECLARE
%token <val> DEFAULT
%token <val> DELETE
%token <val> DESC
%token <val> DIRECT
%token <val> DISTINCT
%token <val> DO
%token <val> ELSE
%token <val> ELSEIF
%token <val> END
%token <val> ENDDECLARE
%token <val> ENDFOR
%token <val> ENDIF
%token <val> ENDLOOP
%token <val> ENDWHILE
%token <val> ESCAPE
%token <val> EXECUTE
%token <val> EXIT
%token <val> FETCH
%token <val> FOR
%token <val> FROM
%token <val> GOTOFRAME
%token <val> GROUP
%token <val> HAVING
%token <val> IF
%token <val> IMMEDIATE
%token <val> IN
%token <val> INITIALIZE
%token <val> INQUIRE_INGRES
%token <val> INQUIRE_SQL
%token <val> INSERT
%token <val> INTO
%token <val> IS
%token <val> LIKE
%token <val> MESSAGE
%token <val> NEXT
%token <val> NOT
%token <val> KW_NULL
%token <val> OF
%token <val> ON
%token <val> OPEN
%token <val> OPENFRAME
%token <val> OR
%token <val> ORDER
%token <val> PROCEDURE
%token <val> PROMPT
%token <val> REPEATED
%token <val> RESUME
%token <val> RETURN
%token <val> ROLLBACK
%token <val> SELECT
%token <val> SET
%token <val> SYSTEM
%token <val> THEN
%token <val> TO
%token <val> UNION
%token <val> UPDATE
%token <val> VALUES
%token <val> WHERE
%token <val> WHILE
%token <val> WITH
%token <val> WORK
/*
* Tokens representing operators in expressions
*/
%token LE /* <= */
%token GE /* >= */
%token NE /* <> */
%token EXP /* * */
/*
* Tokens representing literals
*/
%token <str> INTEGER
%token <str> FLOAT
%token <str> STRING
/*
* Tokens representing symbols or identifiers
*/
%token <str> IDENT
/*
* Operators precedence
*/
%left AS
%left OR
%left BETWEEN
%left AND
%left IS IN
%left LIKE
%left ESCAPE
%left '=' NE '<' LE '>' GE
%left '+' '-'
%left '*' '/' '%'
%left EXP
%nonassoc NOT
%nonassoc UNIMINUS
/*
* Union operator precedence
*/
%left UNION ALL
%start program
%%
program : decl_list { G.program = $1; }
;
decl_list : decl { $$ = $1; }
| decl_list decl { $$ = decl_add($1, $2); }
;
decl : initialize opt_semi { $$ = $1; }
| procedure opt_semi { $$ = $1; }
| on opt_semi { $$ = $1; }
;
com : /* empty */ { $$ = CommentGet(); }
;
initialize : INITIALIZE com parms '=' declare stmt_block
{ $$ = decl_initialize($1, $2, $3, $5, $6); }
;
procedure : PROCEDURE com IDENT parms '=' declare stmt_block
{ $$ = decl_procedure($1, $2, $3, $4, $6, $7); }
;
on : on_list '=' com stmt_block { $$ = decl_on($2, $3, $1, $4); }
;
/* ------ on_list -------- */
on_list : on_clause { $$ = $1; }
| on_list ',' on_clause { $$ = onlist_add($1, $3); }
;
on_clause : ON event opt_fieldname { $$ = onlist($2, $3, NULL); }
| ON event STRING { $$ = onlist($2, NULL, $3); }
;
opt_fieldname : variable { $$ = $1; }
| /* empty */ { $$ = NULL; }
;
event : IDENT { $$ = $1; }
| EXIT { $$ = NULL; }
;
/* ------ parms ------ */
parms : '(' parmlist opt_semicomma ')' { $$ = $2; }
| '(' ')' { $$ = NULL; }
| /* empty */ { $$ = NULL; }
;
parmlist : parm { $$ = $1; }
| parmlist semicomma parm { $$ = parms_add($1, $3); }
;
parm : IDENT '=' type { $$ = parms($1, $3); }
;
/* ----- declare ----- */
declare : DECLARE locals enddeclare { $$ = $2; CommentReset(); }
| /* empty */ { $$ = NULL; CommentReset(); }
;
enddeclare : ENDDECLARE
| /* empty */
;
/* ----- locals ----- */
locals : local_list opt_semicomma { $$ = $1; }
| /* empty */ { $$ = NULL; }
;
local_list : local { $$ = $1; }
| local_list semicomma local { $$ = declarex_add($1, $3); }
;
local : IDENT com '=' PROCEDURE { $$ = declarex($2, $1, DX_PROC, NULL); }
| IDENT com '=' PROCEDURE RETURNING type { $$ = declarex($2, $1, DX_PROCRET, $6); }
| IDENT com '=' type { $$ = declarex($2, $1, DX_VAR, $4); }
;
/* ------------- statements ------------------------------------------------- */
stmt : s_assign { $$ = $1; }
| s_call { $$ = $1; }
| s_callsystem { $$ = $1; }
| s_callframe { $$ = $1; }
| s_callproc { $$ = $1; }
| s_close { $$ = $1; }
| s_commit { $$ = $1; }
| s_continue { $$ = $1; }
| s_delete { $$ = $1; }
| s_endloop { $$ = $1; }
| s_execimm { $$ = $1; }
| s_execproc { $$ = $1; }
| s_exit { $$ = $1; }
| s_fetch { $$ = $1; }
| s_for { $$ = $1; }
| s_gotoframe { $$ = $1; }
| s_ifthen { $$ = $1; }
| s_inquiresql { $$ = $1; }
| s_insert { $$ = $1; }
| s_message { $$ = $1; }
| s_open { $$ = $1; }
| s_openframe { $$ = $1; }
| s_prompt { $$ = $1; }
| s_resume { $$ = $1; }
| s_return { $$ = $1; }
| s_rollback { $$ = $1; }
| s_select { $$ = $1; }
| s_set { $$ = $1; }
| s_update { $$ = $1; }
| s_while { $$ = $1; }
| /* empty */ { $$ = mk_empty(); }
;
/* ----- sytactic sugar ----- */
semicomma : ',' { $$ = $1; }
| ';' { $$ = $1; }
;
opt_semicomma : semicomma
| /* empty */
;
opt_semi : ';'
| /* empty */
;
/* ----- type ----- */
type : basic_type { $$ = $1; }
| ARRAY OF basic_type { $$ = datatype_arrayof($3); }
;
basic_type : datatype nulldef_spec { $$ = datatype_nulldef($1, $2); }
;
datatype : IDENT { $$ = datatype($1, NULL); }
| IDENT '(' INTEGER ')' { $$ = datatype($1, $3); }
nulldef_spec : WITH KW_NULL defspec { $$ = nulldef_merge(WITH_NULL, $3); }
| NOT KW_NULL defspec { $$ = nulldef_merge(NOT_NULL, $3); }
| NOT DEFAULT { $$ = nulldef(EMPTY_NULL, NOT_DEFAULT, NULL); }
| WITH DEFAULT opt_expr { $$ = nulldef(EMPTY_NULL, WITH_DEFAULT, $3); }
| DEFAULT expr { $$ = nulldef(EMPTY_NULL, USE_DEFAULT, $2); }
| /* empty */ { $$ = nulldef(EMPTY_NULL, EMPTY_DEFAULT, NULL); }
;
defspec : NOT DEFAULT { $$ = nulldef(EMPTY_NULL, NOT_DEFAULT, NULL); }
| WITH DEFAULT opt_expr { $$ = nulldef(EMPTY_NULL, WITH_DEFAULT, $3); }
| DEFAULT opt_expr { $$ = nulldef(EMPTY_NULL, USE_DEFAULT, $2); }
| /* empty */ { $$ = nulldef(EMPTY_NULL, EMPTY_DEFAULT, NULL); }
;
/* ------ callproc_parms ----- */
callproc_parms : opt_arglist { $$ = $1; }
| /* empty */ { $$ = arglist_empty(0); }
;
/* ------ callparms ----- */
callparms : '(' callparmlist ')' { $$ = callparm(1, $2); }
| '(' ')' { $$ = callparm(1, NULL); }
| /* empty */ { $$ = callparm(0, NULL); }
;
callparmlist : callparm { $$ = $1; }
| callparmlist ',' callparm { $$ = callparmlist_add($1, $3); }
;
callparm : IDENT '=' expr { $$ = callparmlist($1, $3, NULL); }
| BYREF '(' variable ')' { $$ = callparmlist(NULL, NULL, $3); }
;
/***********************************************************************
* EXPRESSIONS
***********************************************************************
*/
expr : expr '+' expr { $$ = expr2(C_ADD, $1, $3); }
| expr '-' expr { $$ = expr2(C_SUB, $1, $3); }
| '-' expr %prec UNIMINUS
{ $$ = expr1(C_NEG, $2); }
| expr '*' expr { $$ = expr2(C_MUL, $1, $3); }
| expr '/' expr { $$ = expr2(C_DIV, $1, $3); }
| expr EXP expr { $$ = expr2(C_EXP, $1, $3); }
| NOT expr { $$ = expr1(C_NOT, $2); }
| expr AND expr { $$ = expr2(C_AND, $1, $3); }
| expr OR expr { $$ = expr2(C_OR, $1, $3); }
| expr '=' expr { $$ = expr2(C_EQ, $1, $3); }
| expr NE expr { $$ = expr2(C_NE, $1, $3); }
| expr '<' expr { $$ = expr2(C_LT, $1, $3); }
| expr LE expr { $$ = expr2(C_LE, $1, $3); }
| expr '>' expr { $$ = expr2(C_GT, $1, $3); }
| expr GE expr { $$ = expr2(C_GE, $1, $3); }
| expr IS KW_NULL %prec IS { $$ = expr2(C_ISNULL, $1, NULL); }
| expr IS NOT KW_NULL %prec IS { $$ = expr2(C_ISNNULL, $1, NULL); }
| expr LIKE expr %prec LIKE { $$ = expr_like(C_LIKE, $1, $3, NULL); }
| expr NOT LIKE expr %prec LIKE { $$ = expr_like(C_NLIKE, $1, $4, NULL); }
| expr LIKE expr ESCAPE STRING %prec ESCAPE
{ $$ = expr_like(C_LIKE, $1, $3, $5); }
| expr NOT LIKE expr ESCAPE STRING %prec ESCAPE
{ $$ = expr_like(C_NLIKE, $1, $4, $6); }
| expr IN arg_list %prec IN { $$ = expr_in(C_IN, $1, $3); }
| expr NOT IN arg_list %prec IN { $$ = expr_in(C_NIN, $1, $4); }
| expr BETWEEN expr { $$ = expr2(C_BETWEEN, $1, $3); }
| expr NOT BETWEEN expr { $$ = expr2(C_NBETWEEN, $1, $4); }
| expr AS IDENT { $$ = expr_as($1, $3); }
| factor { $$ = $1; }
;
factor : '(' expr ')' { $$ = exprE(C_PAREN, $2); }
| variable { $$ = exprV(C_VARIABLE, $1); }
| builtin { $$ = exprB(C_BUILTIN, $1); }
| INTEGER { $$ = exprS(C_INTEGER, $1); }
| FLOAT { $$ = exprS(C_FLOAT, $1); }
| STRING { $$ = exprS(C_STRING, $1); }
| KW_NULL { $$ = exprS(C_NULL, "NULL"); }
;
/* ------ variable ------ */
variable : dotted_var { $$ = variable(0, $1); }
| ':' dotted_var { $$ = variable(1, $2); }
;
dotted_var : var { $$ = $1; }
| dotted_var '.' var { $$ = dotted_add($1, $3); }
;
var : IDENT { $$ = dotted(C_SVAR, $1, NULL, NULL); }
| IDENT '[' array_expr ']' { $$ = dotted(C_AVAR, $1, $3, NULL); }
| IDENT opt_arglist { $$ = dotted(C_PVAR, $1, NULL, $2); }
;
array_expr : expr { $$ = array_expr(0, $1); }
| '*' { $$ = array_expr(1, NULL); }
| /* empty */ { $$ = array_expr(0, NULL); }
;
/* ------ arg_list opt_arglist ----- */
opt_arglist : arg_list { $$ = $1; }
| '(' ')' { $$ = arglist_empty($1); }
;
arg_list : '(' args ')' { $$ = arglist($1, $2); }
;
args : expr { $$ = args($1); }
| args semicomma expr { $$ = args_add($1, $2, args($3)); }
;
/* ----- builtin ----- */
builtin : BYREF arg_list { $$ = builtin_byref($2); }
| COUNT '(' expr ')' { $$ = builtin_count(0, $3); }
| COUNT '(' DISTINCT expr ')' { $$ = builtin_count(1, $4); }
| COUNT '(' '*' ')' { $$ = builtin_count(0, NULL); }
;
/***********************************************************************
* STATEMENTS
***********************************************************************
*/
s_assign : variable '=' com expr { $$ = mk_assign($3, $1, $4); }
| variable com { $$ = mk_assign($2, $1, NULL); }
;
s_call : opt_return CALL com IDENT callparms { $$ = mk_call($2, $3, $1, $4, $5); }
;
s_callsystem : opt_return CALL com SYSTEM expr { $$ = mk_callsystem($2, $3, $1, $5); }
;
s_callframe : opt_return CALLFRAME com frame_name callparms WITH optlist
{ $$ = mk_callframe($2, $3, $1, $4, $5, $7); }
| opt_return CALLFRAME com frame_name callparms
{ $$ = mk_callframe($2, $3, $1, $4, $5, NULL); }
;
s_callproc : opt_return CALLPROC com IDENT callproc_parms
{ $$ = mk_callproc($2, $3, $1, $4, $5); }
;
s_close : CLOSE com expr { $$ = mk_close($1, $2, $3); }
;
s_commit : COMMIT com opt_work { $$ = mk_commit($1, $2, $3); }
;
opt_work : WORK { $$ = 1; }
| /* empty */ { $$ = 0; }
;
s_continue : CONTINUE com opt_labelref { $$ = mk_continue($1, $2, $3); }
;
s_delete : opt_repeated sql_delete { $$ = mk_delete($1, $2); }
;
s_endloop : ENDLOOP com opt_labelref { $$ = mk_endloop($1, $2, $3); }
;
s_execimm : opt_return EXECUTE com IMMEDIATE expr INTO varlist opt_block
{ $$ = mk_execimm($2, $3, $1, $5, $7, $8); }
| opt_return EXECUTE com IMMEDIATE expr opt_block
{ $$ = mk_execimm($2, $3, $1, $5, NULL, $6); }
;
s_execproc : opt_return EXECUTE com PROCEDURE IDENT callparms
{ $$ = mk_execproc($2, $3, $1, $5, $6, NULL); }
| opt_return EXECUTE com PROCEDURE IDENT callparms INTO cursor_list
{ $$ = mk_execproc($2, $3, $1, $5, $6, $8); }
;
s_exit : EXIT com { $$ = mk_exit($1, $2); }
;
s_fetch : FETCH com cursor INTO varcol_list { $$ = mk_fetch($1, $2, $3, $5); }
;
varcol_list : varcol { $$ = $1; }
| varcol_list ',' varcol { $$ = varcol_add($1, $3); }
;
varcol : variable { $$ = varcol($1, NULL); }
| variable '=' column_name { $$ = varcol($1, $3); }
;
s_for : opt_label FOR com variable '=' expr for_direction expr DO stmtlist ENDFOR
{ $$ = mk_for($2, $3, $1, $4, $6, $7, $8, $10); }
;
for_direction : TO { $$ = TO; }
| DOWNTO { $$ = DOWNTO; }
;
s_gotoframe : GOTOFRAME com frame_name callparms WITH optlist
{ $$ = mk_gotoframe($1, $2, $3, $4, $6); }
| GOTOFRAME com frame_name callparms
{ $$ = mk_gotoframe($1, $2, $3, $4, NULL); }
;
s_ifthen : IF com expr THEN stmtlist elseif_part else_part ENDIF
{ $$ = mk_ifthen($1, $2, $3, $5, $6, $7); }
;
elseif_part : elseif_list { $$ = $1; }
| /* empty */ { $$ = NULL; }
;
elseif_list : elseif { $$ = $1; }
| elseif_list elseif { $$ = elseif_add($1, $2); }
;
elseif : ELSEIF expr THEN stmtlist { $$ = mk_elseif($2, $4); }
;
else_part : ELSE stmtlist { $$ = $2; }
| /* empty */ { $$ = NULL; }
;
s_inquiresql : INQUIRE_SQL com callproc_parms { $$ = mk_inquiresql($1, $2, $3); }
;
s_insert : opt_repeated sql_insert { $$ = mk_insert($1, $2); }
;
s_message : MESSAGE com expr { $$ = mk_message($1, $2, $3); }
;
s_open : OPEN com cursor FOR sql_select { $$ = mk_open($1, $2, $3, $5, NULL); }
| OPEN com cursor FOR sql_select FOR update_clause
{ $$ = mk_open($1, $2, $3, $5, $7); }
;
update_clause : update_mode update_of { $$ = updateclause($1, $2); }
;
update_mode : READONLY { $$ = READONLY; }
| DEFERRED { $$ = DEFERRED; }
| DIRECT { $$ = DIRECT; }
| /* empty */ { $$ = 0; }
;
update_of : UPDATE OF column_list { $$ = $3; }
| /* empty */ { $$ = NULL; }
;
s_openframe : opt_return OPENFRAME com frame_name callparms
{ $$ = mk_openframe($2, $3, $1, $4, $5, NULL); }
| opt_return OPENFRAME com frame_name callparms WITH optlist
{ $$ = mk_openframe($2, $3, $1, $4, $5, $7); }
;
s_prompt : variable '=' PROMPT com expr { $$ = mk_prompt($3, $4, $1, $5); }
;
s_resume : RESUME com opt_next { $$ = mk_resume($1, $2, $3); }
;
opt_next : NEXT { $$ = 1; }
| /* empty */ { $$ = 0; }
;
s_return : RETURN com opt_expr { $$ = mk_return($1, $2, $3); }
;
s_rollback : ROLLBACK com opt_work savepoint { $$ = mk_rollback($1, $2, $3, $4); }
;
savepoint : TO IDENT { $$ = $2; }
| /* empty */ { $$ = NULL; }
;
s_select : opt_repeated com sql_select opt_block { $$ = mk_select($1, $2, $3, $4); }
;
s_update : opt_repeated sql_update { $$ = mk_update($1, $2); }
;
s_while : opt_label WHILE com expr DO stmtlist ENDWHILE
{ $$ = mk_while($2, $3, $1, $4, $6); }
;
s_set : SET com IDENT IDENT WHERE expr { $$ = mk_set($1, $2, $3, 0, $4, $6); }
| SET com IDENT ON IDENT WHERE expr { $$ = mk_set($1, $2, $3, 1, $5, $7); }
;
/***********************************************************************
* COMMON STATEMENT RULES
***********************************************************************
*/
stmtlist : stmt { $$ = mk_stmtlist($1); }
| stmtlist ';' stmt { $$ = stmtlist_add($1, mk_stmtlist($3)); }
;
stmt_block : BEGIN stmtlist END { $$ = mk_block($2); }
;
opt_block : stmt_block { $$ = $1; }
| /* empty */ { $$ = NULL; }
;
opt_return : variable '=' { $$ = $1; }
| /* empty */ { $$ = NULL; }
;
optlist : attr { $$ = $1; }
| optlist ',' attr { $$ = optlist_add($1, $3); }
;
attr : IDENT '=' expr { $$ = optlist($1, $3); }
;
opt_labelref : IDENT { $$ = $1; }
| /* empty */ { $$ = NULL; }
;
opt_repeated : REPEATED { $$ = 1; }
| /* empty */ { $$ = 0; }
;
tablename : IDENT { $$ = tablename(0, $1); }
| ':' IDENT { $$ = tablename(1, $2); }
;
opt_corrname : IDENT { $$ = $1; }
| /* empty */ { $$ = NULL; }
;
cursor_list : cursor { $$ = cursorlist($1); }
| cursor_list ',' cursor { $$ = cursorlist_add($1, cursorlist($3)); }
;
cursor : IDENT { $$ = $1; }
;
varlist : variable { $$ = varlist($1); }
| varlist ',' variable { $$ = varlist_add($1, varlist($3)); }
;
column_name : variable { $$ = $1; }
;
opt_label : IDENT ':' { $$ = $1; }
| /* empty */ { $$ = NULL; }
;
frame_name : IDENT { $$ = frame_name(0, $1); }
| ':' IDENT { $$ = frame_name(1, $2); }
;
opt_expr : expr { $$ = $1; }
| /* empty */ { $$ = NULL; }
;
/***********************************************************************
* SQL RULES
***********************************************************************
*/
sql_expr : expr { $$ = $1; }
;
sql_explist : sql_expr { $$ = sqlexplist($1); }
| sql_explist ',' sql_expr { $$ = sqlexplist_add($1, sqlexplist($3)); }
search_expr : expr { $$ = $1; }
;
column_list : column_name { $$ = columnlist($1); }
| column_list ',' column_name { $$ = columnlist_add($1, columnlist($3)); }
;
columns : '(' column_list ')' { $$ = $2; }
| /* empty */ { $$ = NULL; }
;
sql_delete : DELETE com FROM tablename opt_corrname WHERE CURRENT OF cursor
{ $$ = mk_sqldelete($1, $2, $4, $5, $9, NULL); }
| DELETE com FROM tablename opt_corrname where_clause
{ $$ = mk_sqldelete($1, $2, $4, $5, NULL, $6); }
;
sql_insert : INSERT com INTO tablename columns VALUES '(' sql_explist ')'
{ $$ = mk_sqlinsert($1, $2, $4, $5, $8, NULL); }
| INSERT com INTO tablename columns sql_select
{ $$ = mk_sqlinsert($1, $2, $4, $5, NULL, $6); }
;
sql_select : select_union order_clause { $$ = mk_sqlselect($1, $2); }
;
select_union : subselect { $$ = $1; }
| select_union UNION select_union { $$ = subselect_join(1, $1, $3); }
| select_union UNION ALL select_union { $$ = subselect_join(2, $1, $4); }
;
subselect : SELECT selmode sql_explist from_clause where_clause group_clause having_clause
{ $$ = subselect($1, $2, $3, $4, $5, $6, $7); }
;
order_clause : ORDER BY order_list { $$ = $3; }
| /* empty */ { $$ = NULL; }
;
order_list : orderspec { $$ = $1; }
| order_list ',' orderspec { $$ = orderspec_add($1, $3); }
;
orderspec : column_name sortorder { $$ = orderspec($1, NULL, $2); }
| INTEGER sortorder { $$ = orderspec(NULL, $1, $2); }
;
sortorder : ASC { $$ = ASC; }
| DESC { $$ = DESC; }
| /* empty */ { $$ = 0; }
;
selmode : ALL { $$ = ALL; }
| DISTINCT { $$ = DISTINCT; }
| /* empty */ { $$ = 0; }
;
where_clause : WHERE search_expr { $$ = $2; }
| /* empty */ { $$ = NULL; }
;
group_clause : GROUP BY column_list { $$ = $3; }
| /* empty */ { $$ = NULL; }
;
having_clause : HAVING sql_expr { $$ = $2; }
| /* empty */ { $$ = NULL; }
;
sql_update : UPDATE com tablename opt_corrname from_clause SET set_clause where_clause
{ $$ = mk_sqlupdate($1, $2, $3, $4, $5, $7, NULL, $8); }
| UPDATE com tablename opt_corrname from_clause SET set_clause WHERE CURRENT OF cursor
{ $$ = mk_sqlupdate($1, $2, $3, $4, $5, $7, $11, NULL); }
;
from_clause : FROM from_list { $$ = $2; }
| /* empty */ { $$ = NULL; }
;
from_list : from_item { $$ = $1; }
| from_list ',' from_item { $$ = fromlist_add($1, $3); }
;
from_item : tablename opt_corrname { $$ = fromlist($1, $2); }
;
set_clause : set_expr { $$ = $1; }
| set_clause ',' set_expr { $$ = setclause_add($1, $3); }
;
set_expr : column_name '=' sql_expr { $$ = setclause($1, $3); }
;
%%
/* yyerror -
* Call the Parse_Error routine, and exit.
*/
static void yyerror(char *s)
{
Parse_Error(MSG_YACC_SYNTAX, s);
}
