]> granicus.if.org Git - postgresql/blob - src/interfaces/ecpg/preproc/preproc.y
- Synced preproc.y with gram.y
[postgresql] / src / interfaces / ecpg / preproc / preproc.y
1 /* Copyright comment */
2 %{
3 #include "postgres_fe.h"
4
5 #include "extern.h"
6
7 /*
8  * Variables containing simple states.
9  */
10 int struct_level = 0;
11 int braces_open; /* brace level counter */
12 char    errortext[128];
13 char    *connection = NULL;
14 char    *input_filename = NULL;
15
16 static int      QueryIsRule = 0, FoundInto = 0;
17 static int      initializer = 0;
18 static struct this_type actual_type[STRUCT_DEPTH];
19 static char *actual_storage[STRUCT_DEPTH];
20 static char *actual_startline[STRUCT_DEPTH];
21
22 /* temporarily store struct members while creating the data structure */
23 struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL };
24
25 /* also store struct type so we can do a sizeof() later */
26 static char *ECPGstruct_sizeof = NULL;
27
28 struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, NULL, {NULL}};
29 struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
30
31 struct ECPGtype ecpg_query = {ECPGt_char_variable, 0L, NULL, {NULL}};
32
33 /*
34  * Handle parsing errors and warnings
35  */
36 void
37 mmerror(int error_code, enum errortype type, char * error)
38 {
39         switch(type)
40         {
41                 case ET_WARNING:
42                         fprintf(stderr, "%s:%d: WARNING: %s\n", input_filename, yylineno, error);
43                         break;
44                 case ET_ERROR:
45                         fprintf(stderr, "%s:%d: ERROR: %s\n", input_filename, yylineno, error);
46                         ret_value = error_code;
47                         break;
48                 case ET_FATAL:
49                         fprintf(stderr, "%s:%d: ERROR: %s\n", input_filename, yylineno, error);
50                         exit(error_code);
51         }
52 }
53
54 /*
55  * string concatenation
56  */
57
58 static char *
59 cat2_str(char *str1, char *str2)
60 {
61         char * res_str  = (char *)mm_alloc(strlen(str1) + strlen(str2) + 2);
62
63         strcpy(res_str, str1);
64         strcat(res_str, " ");
65         strcat(res_str, str2);
66         free(str1);
67         free(str2);
68         return(res_str);
69 }
70
71 static char *
72 cat_str(int count, ...)
73 {
74         va_list         args;
75         int                     i;
76         char            *res_str;
77
78         va_start(args, count);
79
80         res_str = va_arg(args, char *);
81
82         /* now add all other strings */
83         for (i = 1; i < count; i++)
84                 res_str = cat2_str(res_str, va_arg(args, char *));
85
86         va_end(args);
87
88         return(res_str);
89 }
90
91 char *
92 make_str(const char *str)
93 {
94         char * res_str = (char *)mm_alloc(strlen(str) + 1);
95
96         strcpy(res_str, str);
97         return res_str;
98 }
99
100 static char *
101 make2_str(char *str1, char *str2)
102 {
103         char * res_str  = (char *)mm_alloc(strlen(str1) + strlen(str2) + 1);
104
105         strcpy(res_str, str1);
106         strcat(res_str, str2);
107         free(str1);
108         free(str2);
109         return(res_str);
110 }
111
112 static char *
113 make3_str(char *str1, char *str2, char *str3)
114 {
115         char * res_str  = (char *)mm_alloc(strlen(str1) + strlen(str2) +strlen(str3) + 1);
116
117         strcpy(res_str, str1);
118         strcat(res_str, str2);
119         strcat(res_str, str3);
120         free(str1);
121         free(str2);
122         free(str3);
123         return(res_str);
124 }
125
126 static char *
127 make_name(void)
128 {
129         char * name = (char *)mm_alloc(yyleng + 1);
130
131         strncpy(name, yytext, yyleng);
132         name[yyleng] = '\0';
133         return(name);
134 }
135
136 %}
137
138 %union {
139         double  dval;
140         int             ival;
141         char    *str;
142         struct  when            action;
143         struct  index           index;
144         int             tagname;
145         struct  this_type       type;
146         enum    ECPGttype       type_enum;
147         enum    ECPGdtype       dtype_enum;
148         struct  fetch_desc      descriptor;
149 }
150
151 /* special embedded SQL token */
152 %token  SQL_ALLOCATE SQL_AUTOCOMMIT SQL_BOOL SQL_BREAK
153                 SQL_CALL SQL_CARDINALITY SQL_CONNECT SQL_CONNECTION
154                 SQL_CONTINUE SQL_COUNT SQL_DATA
155                 SQL_DATETIME_INTERVAL_CODE
156                 SQL_DATETIME_INTERVAL_PRECISION SQL_DEALLOCATE
157                 SQL_DESCRIPTOR SQL_DISCONNECT SQL_ENUM SQL_FOUND
158                 SQL_FREE SQL_GET SQL_GO SQL_GOTO SQL_IDENTIFIED
159                 SQL_INDICATOR SQL_INT SQL_KEY_MEMBER SQL_LENGTH
160                 SQL_LONG SQL_NAME SQL_NULLABLE SQL_OCTET_LENGTH
161                 SQL_OPEN SQL_PREPARE SQL_RELEASE SQL_REFERENCE
162                 SQL_RETURNED_LENGTH SQL_RETURNED_OCTET_LENGTH SQL_SCALE
163                 SQL_SECTION SQL_SHORT SQL_SIGNED SQL_SQL SQL_SQLERROR
164                 SQL_SQLPRINT SQL_SQLWARNING SQL_START SQL_STOP
165                 SQL_STRUCT SQL_UNSIGNED SQL_VALUE SQL_VAR SQL_WHENEVER
166
167 /* C token */
168 %token  S_ADD S_AND S_ANYTHING S_AUTO S_CONST S_DEC S_DIV
169                 S_DOTPOINT S_EQUAL S_EXTERN S_INC S_LSHIFT S_MEMPOINT
170                 S_MEMBER S_MOD S_MUL S_NEQUAL S_OR S_REGISTER S_RSHIFT
171                 S_STATIC S_SUB S_VOLATILE
172                 S_TYPEDEF
173
174 /* I need this and don't know where it is defined inside the backend */
175 %token  TYPECAST
176
177 /* Keywords (in SQL92 reserved words) */
178 %token  ABSOLUTE, ACTION, ADD, ALL, ALTER, AND, ANY, AS, ASC,
179                 AT, AUTHORIZATION, BEGIN_TRANS, BETWEEN, BOTH, BY,
180                 CASCADE, CASE, CAST, CHAIN, CHAR, CHARACTER,
181                 CHARACTERISTICS, CHECK, CLOSE, COALESCE, COLLATE,
182                 COLUMN, COMMIT, CONSTRAINT, CONSTRAINTS, CREATE, CROSS,
183                 CURRENT, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP,
184                 CURRENT_USER, CURSOR, DAY_P, DEC, DECIMAL, DECLARE,
185                 DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP, ELSE,
186                 ENCRYPTED, END_TRANS, EXCEPT, EXECUTE, EXISTS, EXTRACT,
187                 FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL,
188                 GLOBAL, GRANT, GROUP, HAVING, HOUR_P, IN, INNER_P,
189                 INOUT, INSENSITIVE, INSERT, INTERSECT, INTERVAL, INTO,
190                 IS, ISOLATION, JOIN, KEY, LANGUAGE, LEADING, LEFT,
191                 LEVEL, LIKE, LOCAL, MATCH, MINUTE_P, MONTH_P, NAMES,
192                 NATIONAL, NATURAL, NCHAR, NEXT, NO, NOT, NULLIF,
193                 NULL_P, NUMERIC, OF, OFF, OLD, ON, ONLY, OPTION, OR,
194                 ORDER, OUT, OUTER_P, OVERLAPS, PARTIAL, PATH_P,
195                 POSITION, PRECISION, PRIMARY, PRIOR, PRIVILEGES,
196                 PROCEDURE, PUBLIC, READ, REFERENCES, RELATIVE, REVOKE,
197                 RIGHT, ROLLBACK, SCHEMA, SCROLL, SECOND_P, SELECT,
198                 SESSION, SESSION_USER, SET, SOME, SUBSTRING, TABLE,
199                 TEMPORARY, THEN, TIME, TIMESTAMP TO, TRAILING,
200                 TRANSACTION, TRIM, TRUE_P, UNENCRYPTED, UNION, UNIQUE,
201                 UNKNOWN, UPDATE, USAGE, USER, USING, VALUES, VARCHAR,
202                 VARYING, VIEW, WHEN, WHERE, WITH, WITHOUT, WORK,
203                 YEAR_P, ZONE
204
205 /* Keywords (in SQL3 reserved words) */
206 %token  DEFERRABLE, DEFERRED, IMMEDIATE, INITIALLY, PENDANT,
207                 REPLACE, RESTRICT, TRIGGER
208
209 /* Keywords (in SQL92 non-reserved words) */
210 %token  COMMITTED, SERIALIZABLE, TYPE_P, DOMAIN_P
211
212 /* Keywords for Postgres support (not in SQL92 reserved words)
213  *
214  * The CREATEDB and CREATEUSER tokens should go away
215  * when some sort of pg_privileges relation is introduced.
216  * - Todd A. Brandys 1998-01-01?
217  */
218 %token  ABORT_TRANS, ACCESS, AFTER, AGGREGATE, ANALYSE, ANALYZE,
219                 BACKWARD, BEFORE, BINARY, BIT, CACHE, CHECKPOINT,
220                 CLUSTER, COMMENT, COPY, CREATEDB, CREATEUSER, CYCLE,
221                 DATABASE, DELIMITERS, DO, EACH, ENCODING, EXCLUSIVE,
222                 EXPLAIN, FORCE, FORWARD, FREEZE, FUNCTION, HANDLER,
223                 INCREMENT, INDEX, INHERITS, INSTEAD, ISNULL,
224                 LANCOMPILER, LIMIT, LISTEN, UNLISTEN, LOAD, LOCATION,
225                 LOCK_P, MAXVALUE, MINVALUE, MODE, MOVE, NEW,
226                 NOCREATEDB, NOCREATEUSER, NONE, NOTHING, NOTIFY,
227                 NOTNULL, OFFSET, OIDS, OPERATOR, OWNER, PASSWORD,
228                 PROCEDURAL, REINDEX, RENAME, RESET, RETURNS, ROW, RULE,
229                 SEQUENCE, SETOF, SHARE, SHOW, START, STATEMENT,
230                 STATISTICS, STDIN, STDOUT, STORAGE, SYSID, TEMP,
231                 TEMPLATE, TOAST, TRUNCATE, TRUSTED, UNLISTEN, UNTIL,
232                 VACUUM, VALID, VERBOSE, VERSION
233
234 /* The grammar thinks these are keywords, but they are not in the keywords.c
235  * list and so can never be entered directly.  The filter in parser.c
236  * creates these tokens when required.
237  */
238 %token  UNIONJOIN
239
240 /* Special keywords, not in the query language - see the "lex" file */
241 %token <str>    IDENT SCONST Op CSTRING CVARIABLE CPP_LINE IP BITCONST
242 %token <ival>   ICONST PARAM
243 %token <dval>   FCONST
244
245 /* these are not real. they are here so that they get generated as #define's*/
246 %token                                  OP
247
248 /* precedence: lowest to highest */
249 %left           UNION EXCEPT
250 %left           INTERSECT
251 %left           JOIN UNIONJOIN CROSS LEFT FULL RIGHT INNER_P NATURAL
252 %left           OR
253 %left           AND
254 %right          NOT
255 %right          '='
256 %nonassoc       '<' '>'
257 %nonassoc       LIKE ILIKE
258 %nonassoc       ESCAPE
259 %nonassoc       OVERLAPS
260 %nonassoc       BETWEEN
261 %nonassoc       IN
262 %left                   POSTFIXOP                                       /* dummy for postfix Op rules */
263 %left           Op                              /* multi-character ops and user-defined operators */
264 %nonassoc       NOTNULL
265 %nonassoc       ISNULL
266 %nonassoc       IS NULL_P TRUE_P FALSE_P UNKNOWN
267 %left           '+' '-'
268 %left           '*' '/' '%'
269 %left           '^'
270 /* Unary Operators */
271 %left           AT ZONE
272 %right          UMINUS
273 %left           '[' ']'
274 %left           '(' ')'
275 %left           TYPECAST
276 %left           '.'
277
278 %type  <str>    Iconst Fconst Sconst TransactionStmt CreateStmt UserId
279 %type  <str>    CreateAsElement OptCreateAs CreateAsList CreateAsStmt
280 %type  <str>    key_reference comment_text ConstraintDeferrabilitySpec
281 %type  <str>    key_match ColLabel SpecialRuleRelation ColId columnDef
282 %type  <str>    ColConstraint ColConstraintElem drop_type Bitconst
283 %type  <str>    OptTableElementList OptTableElement TableConstraint
284 %type  <str>    ConstraintElem key_actions ColQualList type_name DropSchemaStmt
285 %type  <str>    target_list target_el update_target_list alias_clause
286 %type  <str>    update_target_el opt_id qualified_name database_name
287 %type  <str>    access_method attr_name class index_name name func_name
288 %type  <str>    file_name AexprConst c_expr ConstTypename
289 %type  <str>    in_expr_nodes a_expr b_expr TruncateStmt CommentStmt
290 %type  <str>    opt_indirection expr_list extract_list extract_arg
291 %type  <str>    position_list substr_list substr_from alter_column_default
292 %type  <str>    trim_list in_expr substr_for attrs drop_behavior
293 %type  <str>    Typename SimpleTypename Generic Numeric opt_float opt_numeric
294 %type  <str>    opt_decimal Character character opt_varying opt_charset
295 %type  <str>    opt_collate opt_timezone opt_interval table_ref
296 %type  <str>    row_expr row_descriptor row_list ConstDatetime opt_chain
297 %type  <str>    SelectStmt into_clause OptTemp ConstraintAttributeSpec
298 %type  <str>    opt_table opt_all sort_clause sortby_list ConstraintAttr
299 %type  <str>    sortby OptUseOp qualified_name_list name_list ColId_or_Sconst
300 %type  <str>    group_clause having_clause from_clause opt_distinct
301 %type  <str>    join_outer where_clause relation_expr sub_type opt_arg
302 %type  <str>    opt_column_list insert_rest InsertStmt OptimizableStmt
303 %type  <str>    columnList DeleteStmt LockStmt UpdateStmt CursorStmt
304 %type  <str>    NotifyStmt columnElem copy_dirn UnlistenStmt copy_null
305 %type  <str>    copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary
306 %type  <str>    opt_with_copy FetchStmt direction fetch_how_many from_in
307 %type  <str>    ClosePortalStmt DropStmt VacuumStmt AnalyzeStmt opt_verbose
308 %type  <str>    opt_full func_arg OptWithOids opt_freeze opt_ecpg_into
309 %type  <str>    analyze_keyword opt_name_list ExplainStmt index_params
310 %type  <str>    index_list func_index index_elem opt_class access_method_clause
311 %type  <str>    index_opt_unique IndexStmt func_return ConstInterval
312 %type  <str>    func_args_list func_args opt_with ProcedureStmt def_arg
313 %type  <str>    def_elem def_list definition DefineStmt select_with_parens
314 %type  <str>    opt_instead event RuleActionList opt_using
315 %type  <str>    RuleActionStmtOrEmpty RuleActionMulti func_as reindex_type
316 %type  <str>    RuleStmt opt_column opt_name oper_argtypes NumConst
317 %type  <str>    MathOp RemoveFuncStmt aggr_argtype for_update_clause
318 %type  <str>    RemoveAggrStmt opt_procedural select_no_parens
319 %type  <str>    RemoveOperStmt RenameStmt all_Op opt_Trusted opt_lancompiler
320 %type  <str>    VariableSetStmt var_value zone_value VariableShowStmt
321 %type  <str>    VariableResetStmt AlterTableStmt DropUserStmt from_list
322 %type  <str>    opt_trans user_list OptUserList OptUserElem relation_name
323 %type  <str>    CreateUserStmt AlterUserStmt CreateSeqStmt OptSeqList
324 %type  <str>    OptSeqElem TriggerForSpec TriggerForOpt TriggerForType
325 %type  <str>    DropTrigStmt TriggerOneEvent TriggerEvents RuleActionStmt
326 %type  <str>    TriggerActionTime CreateTrigStmt DropPLangStmt
327 %type  <str>    CreatePLangStmt TriggerFuncArgs TriggerFuncArg simple_select
328 %type  <str>    ViewStmt LoadStmt CreatedbStmt createdb_opt_item
329 %type  <str>    createdb_opt_list opt_encoding OptInherit opt_equal
330 %type  <str>    AlterUserSetStmt privilege_list privilege privilege_target
331 %type  <str>    opt_grant_grant_option opt_revoke_grant_option
332 %type  <str>    function_with_argtypes_list function_with_argtypes
333 %type  <str>    DropdbStmt ClusterStmt grantee RevokeStmt Bit bit
334 %type  <str>    GrantStmt privileges PosAllConst constraints_set_list
335 %type  <str>    opt_cursor ConstraintsSetStmt AllConst CreateDomainStmt
336 %type  <str>    case_expr when_clause_list case_default case_arg when_clause
337 %type  <str>    select_clause opt_select_limit select_limit_value
338 %type  <str>    ConstraintTimeSpec AlterDatabaseSetStmt
339 %type  <str>    select_offset_value ReindexStmt join_type opt_boolean
340 %type  <str>    join_qual update_list AlterSchemaStmt joined_table
341 %type  <str>    opt_level opt_lock lock_type OptGroupList OptGroupElem
342 %type  <str>    OptConstrFromTable OptTempTableName StringConst
343 %type  <str>    constraints_set_mode comment_type opt_empty_parentheses
344 %type  <str>    CreateGroupStmt AlterGroupStmt DropGroupStmt key_delete
345 %type  <str>    opt_force key_update CreateSchemaStmt PosIntStringConst
346 %type  <str>    IntConst PosIntConst grantee_list func_type opt_or_replace
347 %type  <str>    select_limit opt_for_update_clause CheckPointStmt
348 %type  <str>    OptSchemaName OptSchemaEltList schema_stmt opt_drop_behavior
349 %type  <str>    handler_name any_name_list any_name opt_as insert_column_list
350 %type  <str>    columnref dotted_name function_name insert_target_el
351 %type  <str>    insert_target_list insert_column_item 
352
353 %type  <str>    ECPGWhenever ECPGConnect connection_target ECPGOpen
354 %type  <str>    indicator ECPGExecute ECPGPrepare ecpg_using ecpg_into
355 %type  <str>    storage_clause opt_initializer c_anything blockstart
356 %type  <str>    blockend variable_list variable c_thing c_term
357 %type  <str>    opt_pointer ECPGDisconnect dis_name storage_modifier
358 %type  <str>    stmt ECPGRelease execstring server_name
359 %type  <str>    connection_object opt_server opt_port c_stuff c_stuff_item
360 %type  <str>    user_name opt_user char_variable ora_user ident opt_reference
361 %type  <str>    quoted_ident_stringvar var_type_declarations
362 %type  <str>    db_prefix server opt_options opt_connection_name c_list
363 %type  <str>    ECPGSetConnection cpp_line ECPGTypedef c_args ECPGKeywords
364 %type  <str>    enum_type civar civarind ECPGCursorStmt ECPGDeallocate
365 %type  <str>    ECPGFree ECPGDeclare ECPGVar opt_at enum_definition
366 %type  <str>    struct_type s_struct vt_declarations variable_declarations
367 %type  <str>    var_declaration type_declaration 
368 %type  <str>    s_union union_type ECPGSetAutocommit on_off
369 %type  <str>    ECPGAllocateDescr ECPGDeallocateDescr symbol opt_symbol
370 %type  <str>    ECPGGetDescriptorHeader ECPGColLabel
371 %type  <str>    reserved_keyword unreserved_keyword
372 %type  <str>    col_name_keyword func_name_keyword
373 %type  <str>    ECPGTypeName variablelist cvariable
374
375 %type  <descriptor> ECPGGetDescriptor
376
377 %type  <type_enum> simple_type signed_type unsigned_type
378
379 %type  <dtype_enum> descriptor_item desc_header_item
380
381 %type  <type>   type
382
383 %type  <action> action
384
385 %type  <index>  opt_array_bounds opt_type_array_bounds
386
387 %type  <ival>   Iresult
388
389 %token YYERROR_VERBOSE
390 %%
391 prog: statements;
392
393 statements: /*EMPTY*/
394                 | statements statement
395                 ;
396
397 statement: ecpgstart opt_at stmt ';'    { connection = NULL; }
398                 | ecpgstart stmt ';'
399                 | ECPGDeclaration
400                 | c_thing                                               { fprintf(yyout, "%s", $1); free($1); }
401                 | cpp_line                                              { fprintf(yyout, "%s", $1); free($1); }
402                 | blockstart                                    { fputs($1, yyout); free($1); }
403                 | blockend                                              { fputs($1, yyout); free($1); }
404                 ;
405
406 opt_at: AT connection_target
407                 {
408                         connection = $2;
409                         /*
410                          *      if we have a variable as connection
411                          *      target, remove it from the variable
412                          *      list or else it will be used twice
413                          */
414                         if (argsinsert != NULL)
415                                 argsinsert = NULL;
416                 };
417
418 stmt:  AlterDatabaseSetStmt { output_statement($1, 0, connection); }
419                 | AlterGroupStmt        { output_statement($1, 0, connection); }
420                 | AlterSchemaStmt       { output_statement($1, 0, connection); }
421                 | AlterTableStmt        { output_statement($1, 0, connection); }
422                 | AlterUserStmt         { output_statement($1, 0, connection); }
423                 | AlterUserSetStmt      { output_statement($1, 0, connection); }
424                 | ClosePortalStmt       { output_statement($1, 0, connection); }
425                 | CommentStmt           { output_statement($1, 0, connection); }
426                 | CopyStmt              { output_statement($1, 0, connection); }
427                 | CreateStmt            { output_statement($1, 0, connection); }
428                 | CreateAsStmt          { output_statement($1, 0, connection); }
429                 | CreateDomainStmt      { output_statement($1, 0, connection); }
430                 | CreateSchemaStmt      { output_statement($1, 0, connection); }
431                 | CreateGroupStmt       { output_statement($1, 0, connection); }
432                 | CreateSeqStmt         { output_statement($1, 0, connection); }
433                 | CreatePLangStmt       { output_statement($1, 0, connection); }
434                 | CreateTrigStmt        { output_statement($1, 0, connection); }
435                 | CreateUserStmt        { output_statement($1, 0, connection); }
436                 | ClusterStmt           { output_statement($1, 0, connection); }
437                 | DefineStmt            { output_statement($1, 0, connection); }
438                 | DropStmt              { output_statement($1, 0, connection); }
439                 | DropSchemaStmt        { output_statement($1, 0, connection); }
440                 | TruncateStmt          { output_statement($1, 0, connection); }
441                 | DropGroupStmt         { output_statement($1, 0, connection); }
442                 | DropPLangStmt         { output_statement($1, 0, connection); }
443                 | DropTrigStmt          { output_statement($1, 0, connection); }
444                 | DropUserStmt          { output_statement($1, 0, connection); }
445                 | ExplainStmt           { output_statement($1, 0, connection); }
446                 | FetchStmt             { output_statement($1, 1, connection); }
447                 | GrantStmt             { output_statement($1, 0, connection); }
448                 | IndexStmt             { output_statement($1, 0, connection); }
449                 | ListenStmt            { output_statement($1, 0, connection); }
450                 | UnlistenStmt          { output_statement($1, 0, connection); }
451                 | LockStmt              { output_statement($1, 0, connection); }
452                 | NotifyStmt            { output_statement($1, 0, connection); }
453                 | ProcedureStmt         { output_statement($1, 0, connection); }
454                 | ReindexStmt           { output_statement($1, 0, connection); }
455                 | RemoveAggrStmt        { output_statement($1, 0, connection); }
456                 | RemoveOperStmt        { output_statement($1, 0, connection); }
457                 | RemoveFuncStmt        { output_statement($1, 0, connection); }
458                 | RenameStmt            { output_statement($1, 0, connection); }
459                 | RevokeStmt            { output_statement($1, 0, connection); }
460                 | OptimizableStmt
461                 {
462                         if (strncmp($1, "/* " , sizeof("/* ")-1) == 0)
463                                 output_simple_statement($1);
464                         else
465                                 output_statement($1, 1, connection);
466                 }
467                 | RuleStmt              { output_statement($1, 0, connection); }
468                 | TransactionStmt
469                 {
470                         fprintf(yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
471                         whenever_action(2);
472                         free($1);
473                 }
474                 | ViewStmt              { output_statement($1, 0, connection); }
475                 | LoadStmt              { output_statement($1, 0, connection); }
476                 | CreatedbStmt          { output_statement($1, 0, connection); }
477                 | DropdbStmt            { output_statement($1, 0, connection); }
478                 | VacuumStmt            { output_statement($1, 0, connection); }
479                 | AnalyzeStmt           { output_statement($1, 0, connection); }
480                 | VariableSetStmt       { output_statement($1, 0, connection); }
481                 | VariableShowStmt      { output_statement($1, 0, connection); }
482                 | VariableResetStmt     { output_statement($1, 0, connection); }
483                 | ConstraintsSetStmt    { output_statement($1, 0, connection); }
484                 | CheckPointStmt        { output_statement($1, 0, connection); }
485                 | ECPGAllocateDescr
486                 {
487                         fprintf(yyout,"ECPGallocate_desc(__LINE__, %s);",$1);
488                         whenever_action(0);
489                         free($1);
490                 }
491                 | ECPGConnect
492                 {
493                         if (connection)
494                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for connect statement.\n");
495
496                         fprintf(yyout, "{ ECPGconnect(__LINE__, %s, %d); ", $1, autocommit);
497                         reset_variables();
498                         whenever_action(2);
499                         free($1);
500                 }
501                 | ECPGCursorStmt
502                 {
503                         output_simple_statement($1);
504                 }
505                 | ECPGDeallocate
506                 {
507                         if (connection)
508                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for connect statement.\n");
509
510                         fputc('{', yyout);
511                         fputs($1, yyout);
512                         whenever_action(2);
513                         free($1);
514                 }
515                 | ECPGDeallocateDescr
516                 {
517                         fprintf(yyout,"ECPGdeallocate_desc(__LINE__, %s);",$1);
518                         whenever_action(0);
519                         free($1);
520                 }
521                 | ECPGDeclare
522                 {
523                         output_simple_statement($1);
524                 }
525                 | ECPGDisconnect
526                 {
527                         if (connection)
528                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for disconnect statement.\n");
529
530                         fprintf(yyout, "{ ECPGdisconnect(__LINE__, %s);", $1);
531                         whenever_action(2);
532                         free($1);
533                 }
534                 | ECPGExecute
535                 {
536                         output_statement($1, 0, connection);
537                 }
538                 | ECPGFree
539                 {
540                         fprintf(yyout, "{ ECPGdeallocate(__LINE__, \"%s\");", $1);
541
542                         whenever_action(2);
543                         free($1);
544                 }
545                 | ECPGGetDescriptor
546                 {
547                         lookup_descriptor($1.name, connection);
548                         output_get_descr($1.name, $1.str);
549                         free($1.name);
550                         free($1.str);
551                 }
552                 | ECPGGetDescriptorHeader
553                 {
554                         lookup_descriptor($1, connection);
555                         output_get_descr_header($1);
556                         free($1);
557                 }
558                 | ECPGOpen
559                 {
560                         struct cursor *ptr;
561                         struct arguments *p;
562
563                         for (ptr = cur; ptr != NULL; ptr=ptr->next)
564                         {
565                                 if (strcmp(ptr->name, $1) == 0)
566                                         break;
567                         }
568
569                         if (ptr == NULL)
570                         {
571                                 sprintf(errortext, "trying to open undeclared cursor %s\n", $1);
572                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
573                         }
574
575                         /* merge variables given in prepare statement with those given here */
576                         for (p = ptr->argsinsert; p; p = p->next)
577                                 append_variable(&argsinsert, p->variable, p->indicator);
578
579                         for (p = ptr->argsresult; p; p = p->next)
580                                 add_variable(&argsresult, p->variable, p->indicator);
581
582                         output_statement(mm_strdup(ptr->command), 0, ptr->connection ? mm_strdup(ptr->connection) : NULL);
583                 }
584                 | ECPGPrepare
585                 {
586                         if (connection)
587                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for set connection statement.\n");
588
589                         fprintf(yyout, "{ ECPGprepare(__LINE__, %s);", $1);
590                         whenever_action(2);
591                         free($1);
592                 }
593                 | ECPGRelease           { /* output already done */ }
594                 | ECPGSetAutocommit
595                 {
596                         fprintf(yyout, "{ ECPGsetcommit(__LINE__, \"%s\", %s);", $1, connection ? connection : "NULL");
597                         whenever_action(2);
598                         free($1);
599                 }
600                 | ECPGSetConnection
601                 {
602                         if (connection)
603                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for set connection statement.\n");
604
605                         fprintf(yyout, "{ ECPGsetconn(__LINE__, %s);", $1);
606                         whenever_action(2);
607                         free($1);
608                 }
609                 | ECPGTypedef
610                 {
611                         if (connection)
612                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for typedef statement.\n");
613
614                         fprintf(yyout, "%s", $1);
615                         free($1);
616                         output_line_number();
617                 }
618                 | ECPGVar
619                 {
620                         if (connection)
621                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for var statement.\n");
622
623                         output_simple_statement($1);
624                 }
625                 | ECPGWhenever
626                 {
627                         if (connection)
628                                 mmerror(PARSE_ERROR, ET_ERROR, "no at option for whenever statement.\n");
629
630                         output_simple_statement($1);
631                 }
632                 ;
633
634
635 /*
636  * We start with a lot of stuff that's very similar to the backend's parsing
637  */
638
639 /*****************************************************************************
640  *
641  * Create a new Postgres DBMS user
642  *
643  *
644  *****************************************************************************/
645
646 CreateUserStmt: CREATE USER UserId OptUserList
647                         { $$ = cat_str(3, make_str("create user"), $3, $4); }
648                 | CREATE USER UserId WITH OptUserList
649                         { $$ = cat_str(4, make_str("create user"), $3, make_str("with"), $5); }
650                 ;
651
652 /*****************************************************************************
653  *
654  * Alter a postgresql DBMS user
655  *
656  *
657  *****************************************************************************/
658
659 AlterUserStmt: ALTER USER UserId OptUserList
660                         { $$ = cat_str(3, make_str("alter user"), $3, $4); }
661                 | ALTER USER UserId WITH OptUserList
662                         { $$ = cat_str(4, make_str("alter user"), $3, make_str("with"), $5); }
663                 ;
664
665 AlterUserSetStmt: ALTER USER UserId VariableSetStmt
666                         { $$ = cat_str(3, make_str("alter user"), $3, $4); }
667                 | ALTER USER UserId VariableResetStmt
668                         { $$ = cat_str(3, make_str("alter user"), $3, $4); }
669                 ;
670
671 /*****************************************************************************
672  *
673  * Drop a postgresql DBMS user
674  *
675  *
676  *****************************************************************************/
677
678 DropUserStmt:  DROP USER user_list
679                         { $$ = cat2_str(make_str("drop user"), $3);}
680                 ;
681
682 /*
683  * Options for CREATE USER and ALTER USER
684  */
685 OptUserList: OptUserList OptUserElem    { $$ = cat2_str($1, $2); }
686                 | /* EMPTY */                                   { $$ = EMPTY; }
687                 ;
688
689 OptUserElem:  PASSWORD Sconst
690                 { $$ = cat2_str(make_str("password"), $2); }
691                 | SYSID Iconst
692                         { $$ = cat2_str(make_str("sysid"), $2); }
693                 | CREATEDB
694                         { $$ = make_str("createdb"); }
695                 | NOCREATEDB
696                         { $$ = make_str("nocreatedb"); }
697                 | CREATEUSER
698                         { $$ = make_str("createuser"); }
699                 | NOCREATEUSER
700                         { $$ = make_str("nocreateuser"); }
701                 | IN GROUP user_list
702                         { $$ = cat2_str(make_str("in group"), $3); }
703                 | VALID UNTIL Sconst
704                         { $$ = cat2_str(make_str("valid until"), $3); }
705                 ;
706
707 user_list:      user_list ',' UserId    
708                         { $$ = cat_str(3, $1, make_str(","), $3); }
709                 | UserId        
710                         { $$ = $1; }
711                 ;
712
713
714 /*****************************************************************************
715  *
716  * Create a postgresql group
717  *
718  *
719  ****************************************************************************/
720 CreateGroupStmt:  CREATE GROUP UserId OptGroupList
721                         { $$ = cat_str(3, make_str("create group"), $3, $4); }
722                 | CREATE GROUP UserId WITH OptGroupList
723                         { $$ = cat_str(4, make_str("create group"), $3, make_str("with"), $5); }
724                 ;
725
726 /*
727  * Options for CREATE GROUP
728  */
729 OptGroupList: OptGroupList OptGroupElem         { $$ = cat2_str($1, $2); }
730                 | /* EMPTY */                                           { $$ = EMPTY; }
731                 ;
732
733 OptGroupElem:  USER user_list
734                         { $$ = cat2_str(make_str("user"), $2); }
735                 | SYSID Iconst
736                         { $$ = cat2_str(make_str("sysid"), $2); }
737                 ;
738
739
740 /*****************************************************************************
741  *
742  * Alter a postgresql group
743  *
744  *
745  *****************************************************************************/
746 AlterGroupStmt: ALTER GROUP UserId ADD USER user_list
747                         { $$ = cat_str(4, make_str("alter group"), $3, make_str("add user"), $6); }
748                 | ALTER GROUP UserId DROP USER user_list
749                         { $$ = cat_str(4, make_str("alter group"), $3, make_str("drop user"), $6); }
750                 ;
751
752 /*****************************************************************************
753  *
754  * Drop a postgresql group
755  *
756  *
757  *****************************************************************************/
758 DropGroupStmt: DROP GROUP UserId
759                         { $$ = cat2_str(make_str("drop group"), $3); }
760                 ;
761
762 /*****************************************************************************
763  *
764  * Manipulate a schema
765  *
766  *
767  *****************************************************************************/
768
769 CreateSchemaStmt:  CREATE SCHEMA UserId OptSchemaName AUTHORIZATION UserId OptSchemaEltList
770                         { $$ = cat_str(6, make_str("create scheme"), $3, $4, make_str("authorization"), $6, $7); }
771                 | CREATE SCHEMA ColId OptSchemaEltList
772                         { $$ = cat_str(3, make_str("create scheme"), $3, $4); }
773                 ;
774
775 AlterSchemaStmt:  ALTER SCHEMA ColId
776                         { $$ = cat2_str(make_str("alter scheme"), $3); }
777                 ;
778
779 DropSchemaStmt:  DROP SCHEMA ColId
780                         { $$ = cat2_str(make_str("drop scheme"), $3); }
781                 ;
782
783 OptSchemaName: ColId            { $$ = $1; }
784                | /* EMPTY */   { $$ = EMPTY; }
785                ;
786
787 OptSchemaEltList: OptSchemaEltList schema_stmt         { $$ = cat2_str($1, $2); }
788                 | /* EMPTY */   { $$ = EMPTY; }
789                 ;
790
791 /*
792  *     schema_stmt are the ones that can show up inside a CREATE SCHEMA
793  *     statement (in addition to by themselves).
794  */
795 schema_stmt: CreateStmt         { $$ = $1; }
796                | GrantStmt      { $$ = $1; }
797                | ViewStmt       { $$ = $1; }
798                ;
799
800
801
802 /*****************************************************************************
803  *
804  * Set PG internal variable
805  *        SET name TO 'var_value'
806  * Include SQL92 syntax (thomas 1997-10-22):
807  *        SET TIME ZONE 'var_value'
808  *
809  *****************************************************************************/
810
811 VariableSetStmt:  SET ColId TO var_value
812                         { $$ = cat_str(4, make_str("set"), $2, make_str("to"), $4); }
813                 | SET ColId '=' var_value
814                         { $$ = cat_str(4, make_str("set"), $2, make_str("="), $4); }
815                 | SET TIME ZONE zone_value
816                         { $$ = cat2_str(make_str("set time zone"), $4); }
817                 | SET TRANSACTION ISOLATION LEVEL opt_level
818                         { $$ = cat2_str(make_str("set transaction isolation level"), $5); }
819                 | SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL opt_level
820                         { $$ = cat2_str(make_str("set session characteristics as transaction isolation level"), $8); }
821                 | SET NAMES opt_encoding
822                         { $$ = cat2_str(make_str("set names"), $3); }
823                 | SET SESSION AUTHORIZATION ColId_or_Sconst
824                         { $$ = cat2_str(make_str("set session authorization"), $4); }
825                 ;
826
827 opt_level:      READ COMMITTED  { $$ = make_str("read committed"); }
828                 | SERIALIZABLE          { $$ = make_str("serializable"); }
829                 ;
830
831
832 var_value:      opt_boolean             { $$ = $1; }
833                 | AllConst                      { $$ = $1; }
834                 | name_list
835                 {
836                         if (strlen($1) == 0)
837                         mmerror(PARSE_ERROR, ET_ERROR, "SET must have at least one argument.");
838
839                         $$ = $1;
840                 }
841                 | DEFAULT                       { $$ = make_str("default"); }
842                 ;
843
844 opt_boolean:  TRUE_P            { $$ = make_str("true"); }
845                 | FALSE_P                       { $$ = make_str("false"); }
846                 | ON                            { $$ = make_str("on"); }
847                 | OFF                           { $$ = make_str("off"); }
848                 ;
849
850 /* Timezone values can be:
851 * - a string such as 'pst8pdt'
852 * - an integer or floating point number
853 * - a time interval per SQL99
854 */
855 zone_value:  AllConst           { $$ = $1; }
856                 | ConstInterval StringConst opt_interval
857                         { $$ = cat_str(3, $1, $2, $3); }
858                 | ConstInterval '(' PosIntConst ')' StringConst opt_interval
859                         { $$ = cat_str(6, $1, make_str("("), $3, make_str(")"), $5, $6); }
860                 | DEFAULT       
861                         { $$ = make_str("default"); }
862                 | LOCAL         
863                         { $$ = make_str("local"); }
864                 ;
865
866 opt_encoding:   StringConst             { $$ = $1; }
867                 | DEFAULT                               { $$ = make_str("default"); }
868                 | /*EMPTY*/                             { $$ = EMPTY; }
869                 ;
870
871 ColId_or_Sconst: ColId                  { $$ = $1; }
872                 | StringConst                   { $$ = $1; }
873                 ;
874
875 VariableShowStmt:  SHOW ColId
876                         { $$ = cat2_str(make_str("show"), $2); }
877                 | SHOW TIME ZONE
878                         { $$ = make_str("show time zone"); }
879                 | SHOW ALL
880                         { $$ = make_str("show all"); }
881                 | SHOW TRANSACTION ISOLATION LEVEL
882                         { $$ = make_str("show transaction isolation level"); }
883                 ;
884
885 VariableResetStmt:      RESET ColId
886                         { $$ = cat2_str(make_str("reset"), $2); }
887                 | RESET TIME ZONE
888                         { $$ = make_str("reset time zone"); }
889                 | RESET TRANSACTION ISOLATION LEVEL
890                         { $$ = make_str("reset transaction isolation level"); }
891                 | RESET ALL
892                         { $$ = make_str("reset all"); }
893                 ;
894
895 ConstraintsSetStmt:    SET CONSTRAINTS constraints_set_list constraints_set_mode
896                         { $$ = cat_str(3, make_str("set constraints"), $3, $4); }
897                 ;
898
899 constraints_set_list:  ALL
900                         { $$ = make_str("all"); }
901                 | name_list
902                         { $$ = $1; }
903                 ;
904
905 constraints_set_mode:  DEFERRED         { $$ = make_str("deferred"); }
906                 | IMMEDIATE             { $$ = make_str("immediate"); }
907                 ;
908
909 /*
910  * Checkpoint statement
911  */
912 CheckPointStmt: CHECKPOINT         { $$= make_str("checkpoint"); }
913                 ;
914
915
916 /*****************************************************************************
917  *
918  *      ALTER TABLE variations
919  *
920  *****************************************************************************/
921
922 AlterTableStmt:
923 /* ALTER TABLE <relation> ADD [COLUMN] <coldef> */
924                 ALTER TABLE relation_expr ADD opt_column columnDef
925                         { $$ = cat_str(5, make_str("alter table"), $3, make_str("add"), $5, $6); }
926 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> {SET DEFAULT <expr>|DROP DEFAULT} */
927                 | ALTER TABLE relation_expr ALTER opt_column ColId alter_column_default
928                         { $$ = cat_str(6, make_str("alter table"), $3, make_str("alter"), $5, $6, $7); }
929 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> DROP NOT NULL */
930                 | ALTER TABLE relation_expr ALTER opt_column ColId DROP NOT NULL_P
931                         { $$ = cat_str(6, make_str("alter table"), $3, make_str("alter"), $5, $6, make_str("drop not null")); }
932 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> SET NOT NULL */
933                 | ALTER TABLE relation_expr ALTER opt_column ColId SET NOT NULL_P
934                         { $$ = cat_str(6, make_str("alter table"), $3, make_str("alter"), $5, $6, make_str("set not null")); }
935 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> SET STATISTICS <Iconst> */
936                 | ALTER TABLE relation_expr ALTER opt_column ColId SET STATISTICS Iconst
937                         { $$ = cat_str(7, make_str("alter table"), $3, make_str("alter"), $5, $6, make_str("set statistics"), $9); }
938 /* ALTER TABLE <relation> ALTER [COLUMN] <colname> SET STORAGE <storagemode> */
939                 | ALTER TABLE relation_expr ALTER opt_column ColId SET STORAGE ColId
940                         { $$ = cat_str(7, make_str("alter table"), $3, make_str("alter"), $5, $6, make_str("set storage"), $9); }
941 /* ALTER TABLE <relation> DROP [COLUMN] <colname> {RESTRICT|CASCADE} */
942                 | ALTER TABLE relation_expr DROP opt_column ColId drop_behavior
943                         { $$ = cat_str(6, make_str("alter table"), $3, make_str("drop"), $5, $6, $7); }
944 /* ALTER TABLE <relation> ADD CONSTRAINT ... */
945                 | ALTER TABLE relation_expr ADD TableConstraint
946                         { $$ = cat_str(4, make_str("alter table"), $3, make_str("add"), $5); }
947 /* ALTER TABLE <relation> DROP CONSTRAINT ... */
948                 | ALTER TABLE relation_expr DROP CONSTRAINT name drop_behavior
949                         { $$ = cat_str(5, make_str("alter table"), $3, make_str("drop constraint"), $6, $7); }
950  /* ALTER TABLE <name> CREATE TOAST TABLE */
951                 | ALTER TABLE qualified_name CREATE TOAST TABLE
952                         { $$ = cat_str(3, make_str("alter table"), $3, make_str("create toast table")); }
953 /* ALTER TABLE <name> OWNER TO UserId */
954                 | ALTER TABLE qualified_name OWNER TO UserId
955                         { $$ = cat_str(4, make_str("alter table"), $3, make_str("owner to"), $6); }
956                 ;
957
958 alter_column_default:
959                 SET DEFAULT a_expr              { $$ = cat2_str(make_str("set default"), $3); }
960                 | DROP DEFAULT                  { $$ = make_str("drop default"); }
961                 ;
962
963 drop_behavior: CASCADE                  { $$ = make_str("cascade"); }
964                 | RESTRICT                              { $$ = make_str("restrict"); }
965                 ;
966
967 opt_drop_behavior: CASCADE                      { $$ = make_str("cascade"); }
968                 | RESTRICT                      { $$ = make_str("restrict"); }
969                 | /* EMPTY */                   { $$ = EMPTY; }
970                 ;
971                 
972 /*****************************************************************************
973  *
974  *              QUERY :
975  *                              close <optname>
976  *
977  *****************************************************************************/
978
979 ClosePortalStmt:  CLOSE opt_id  { $$ = cat2_str(make_str("close"), $2); }
980                 ;
981
982 opt_id:  ColId                                  { $$ = $1; }
983                 | /*EMPTY*/                     { $$ = NULL; }
984                 ;
985
986 /*****************************************************************************
987  *
988  *              QUERY :
989  *                              COPY [BINARY] <relname> FROM/TO
990  *                              [USING DELIMITERS <delimiter>]
991  *
992  *****************************************************************************/
993
994 CopyStmt:  COPY opt_binary qualified_name opt_with_copy copy_dirn copy_file_name copy_delimiter copy_null
995                         { $$ = cat_str(8, make_str("copy"), $2, $3, $4, $5, $6, $7, $8); }
996                 ;
997
998 copy_dirn:      TO                                      { $$ = make_str("to"); }
999                 | FROM                                  { $$ = make_str("from"); }
1000                 ;
1001
1002 /*
1003  * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is
1004  * used depends on the direction. (It really doesn't make sense to copy from
1005  * stdout. We silently correct the "typo".               - AY 9/94
1006  */
1007 copy_file_name:  StringConst    { $$ = $1; }
1008                 | STDIN                                 { $$ = make_str("stdin"); }
1009                 | STDOUT                                { $$ = make_str("stdout"); }
1010                 ;
1011
1012 opt_binary:  BINARY                             { $$ = make_str("binary"); }
1013                 | /*EMPTY*/                             { $$ = EMPTY; }
1014                 ;
1015
1016 opt_with_copy:  WITH OIDS               { $$ = make_str("with oids"); }
1017                 | /*EMPTY*/                             { $$ = EMPTY; }
1018                 ;
1019
1020 /*
1021  * the default copy delimiter is tab but the user can configure it
1022  */
1023 copy_delimiter:  opt_using DELIMITERS StringConst
1024                         { $$ = cat_str(3, $1, make_str("delimiters"), $3); }
1025                 | /*EMPTY*/
1026                         { $$ = EMPTY; }
1027                 ;
1028
1029 opt_using:      USING           { $$ = make_str("using"); }
1030                 | /* EMPTY */   { $$ = EMPTY; }
1031                 ;
1032
1033 copy_null:      WITH NULL_P AS StringConst
1034                         { $$ = cat2_str(make_str("with null as"), $4); }
1035                 | /* EMPTY */
1036                         { $$ = EMPTY; }
1037                 ;
1038
1039 /*****************************************************************************
1040  *
1041  *              QUERY :
1042  *                              CREATE relname
1043  *
1044  *****************************************************************************/
1045
1046 CreateStmt:  CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
1047                                 OptInherit OptWithOids
1048                         { $$ = cat_str(9, make_str("create"), $2, make_str("table"), $4, make_str("("), $6, make_str(")"), $8, $9); }
1049                 ;
1050
1051 /*
1052  * Redundancy here is needed to avoid shift/reduce conflicts,
1053  * since TEMP is not a reserved word.  See also OptTempTableName.
1054  */
1055
1056 OptTemp: TEMPORARY                      { $$ = make_str("temporary"); }
1057                 | TEMP                          { $$ = make_str("temp"); }
1058                 | LOCAL TEMPORARY       { $$ = make_str("local temporary"); }
1059                 | LOCAL TEMP            { $$ = make_str("local temp"); }
1060                 | GLOBAL TEMPORARY
1061                 {
1062                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported CREATE TABLE / GLOBAL TEMPORARY will be passed to backend");
1063                         $$ = make_str("global temporary");
1064                 }
1065                 | GLOBAL TEMP
1066                 {
1067                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported CREATE TABLE / GLOBAL TEMP will be passed to backend");
1068                         $$ = make_str("global temp");
1069                 }
1070                 | /*EMPTY*/                     { $$ = EMPTY; }
1071                 ;
1072
1073 OptTableElementList:  OptTableElementList ',' OptTableElement
1074                         { $$ = cat_str(3, $1, make_str(","), $3); }
1075                 | OptTableElement
1076                         { $$ = $1; }
1077                 | /*EMPTY*/
1078                         { $$ = EMPTY; }
1079                 ;
1080
1081 OptTableElement:  columnDef             { $$ = $1; }
1082                 | TableConstraint               { $$ = $1; }
1083                 ;
1084
1085 columnDef:      ColId Typename ColQualList opt_collate
1086                 {
1087                         if (strlen($4) > 0)
1088                         {
1089                                 sprintf(errortext, "Currently unsupported CREATE TABLE / COLLATE %s will be passed to backend", $4);
1090                                 mmerror(PARSE_ERROR, ET_WARNING, errortext);
1091                         }
1092                         $$ = cat_str(4, $1, $2, $3, $4);
1093                 }
1094                 ;
1095
1096 ColQualList:  ColQualList ColConstraint { $$ = cat2_str($1,$2); }
1097                 | /*EMPTY*/                                             { $$ = EMPTY; }
1098                 ;
1099
1100 ColConstraint:  CONSTRAINT name ColConstraintElem
1101                         { $$ = cat_str(3, make_str("constraint"), $2, $3); }
1102                 | ColConstraintElem             { $$ = $1; }
1103                 | ConstraintAttr                { $$ = $1; }
1104                 ;
1105
1106 /* DEFAULT NULL is already the default for Postgres.
1107  * But define it here and carry it forward into the system
1108  * to make it explicit.
1109  * - thomas 1998-09-13
1110  *
1111  * WITH NULL and NULL are not SQL92-standard syntax elements,
1112  * so leave them out. Use DEFAULT NULL to explicitly indicate
1113  * that a column may have that value. WITH NULL leads to
1114  * shift/reduce conflicts with WITH TIME ZONE anyway.
1115  * - thomas 1999-01-08
1116  */
1117 ColConstraintElem:      NOT NULL_P
1118                         { $$ = make_str("not null"); }
1119                 | NULL_P
1120                         { $$ = make_str("null"); }
1121                 | UNIQUE
1122                         { $$ = make_str("unique"); }
1123                 | PRIMARY KEY
1124                         { $$ = make_str("primary key"); }
1125                 | CHECK '(' a_expr ')'
1126                         { $$ = cat_str(3, make_str("check ("), $3, make_str(")")); }
1127                 | DEFAULT b_expr
1128                         { $$ = cat2_str(make_str("default"), $2); }
1129                 |  REFERENCES qualified_name opt_column_list key_match key_actions
1130                         { $$ = cat_str(5, make_str("references"), $2, $3, $4, $5); }
1131                 ;
1132
1133 /*
1134  * ConstraintAttr represents constraint attributes, which we parse as if
1135  * they were independent constraint clauses, in order to avoid shift/reduce
1136  * conflicts (since NOT might start either an independent NOT NULL clause
1137  * or an attribute).  analyze.c is responsible for attaching the attribute
1138  * information to the preceding "real" constraint node, and for complaining
1139  * if attribute clauses appear in the wrong place or wrong combinations.
1140  *
1141  * See also ConstraintAttributeSpec, which can be used in places where
1142  * there is no parsing conflict.
1143  */
1144 ConstraintAttr: DEFERRABLE              { $$ = make_str("deferrable"); }
1145                 | NOT DEFERRABLE                { $$ = make_str("not deferrable"); }
1146                 | INITIALLY DEFERRED    { $$ = make_str("initially deferred"); }
1147                 | INITIALLY IMMEDIATE   { $$ = make_str("initially immediate"); }
1148                 ;
1149
1150 /* ConstraintElem specifies constraint syntax which is not embedded into
1151  *      a column definition. ColConstraintElem specifies the embedded form.
1152  * - thomas 1997-12-03
1153  */
1154 TableConstraint:  CONSTRAINT name ConstraintElem
1155                         { $$ = cat_str(3, make_str("constraint"), $2, $3); }
1156                 | ConstraintElem
1157                         { $$ = $1; }
1158                 ;
1159
1160 ConstraintElem:  CHECK '(' a_expr ')'
1161                         { $$ = cat_str(3, make_str("check("), $3, make_str(")")); }
1162                 | UNIQUE '(' columnList ')'
1163                         { $$ = cat_str(3, make_str("unique("), $3, make_str(")")); }
1164                 | PRIMARY KEY '(' columnList ')'
1165                         { $$ = cat_str(3, make_str("primary key("), $4, make_str(")")); }
1166                 | FOREIGN KEY '(' columnList ')' REFERENCES qualified_name opt_column_list
1167                         key_match key_actions ConstraintAttributeSpec
1168                         { $$ = cat_str(8, make_str("foreign key("), $4, make_str(") references"), $7, $8, $9, $10, $11); }
1169                 ;
1170
1171 opt_column_list:  '(' columnList ')'    { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
1172                | /*EMPTY*/              { $$ = EMPTY; }
1173                ;
1174
1175 columnList:  columnList ',' columnElem
1176                                { $$ = cat_str(3, $1, make_str(","), $3); }
1177                | columnElem
1178                                { $$ = $1; }
1179                ;
1180
1181 columnElem:  ColId      { $$ = $1; }
1182                 ;
1183
1184 key_match:      MATCH FULL
1185                         { $$ = make_str("match full"); }
1186                 | MATCH PARTIAL
1187                 {
1188                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported FOREIGN KEY/MATCH PARTIAL will be passed to backend");
1189                         $$ = make_str("match partial");
1190                 }
1191                 | /*EMPTY*/
1192                         { $$ = EMPTY; }
1193                 ;
1194
1195 key_actions:  key_delete                        { $$ = $1; }
1196                 | key_update                            { $$ = $1; }
1197                 | key_delete key_update         { $$ = cat2_str($1, $2); }
1198                 | key_update key_delete         { $$ = cat2_str($1, $2); }
1199                 | /*EMPTY*/                                     { $$ = EMPTY; }
1200                 ;
1201
1202 key_delete: ON DELETE key_reference 
1203                         { $$ = cat2_str(make_str("on delete"), $3); }
1204                 ;
1205
1206 key_update: ON UPDATE key_reference 
1207                         { $$ = cat2_str(make_str("on update"), $3); }
1208                 ;
1209
1210 key_reference:  NO ACTION                       { $$ = make_str("no action"); }
1211                 | RESTRICT                                      { $$ = make_str("restrict"); }
1212                 | CASCADE                                       { $$ = make_str("cascade"); }
1213                 | SET DEFAULT                           { $$ = make_str("set default"); }
1214                 | SET NULL_P                            { $$ = make_str("set null"); }
1215                 ;
1216
1217 OptInherit:  INHERITS '(' qualified_name_list ')'       
1218                         { $$ = cat_str(3, make_str("inherits ("), $3, make_str(")")); }
1219                 | /*EMPTY*/ 
1220                         { $$ = EMPTY; }
1221                 ;
1222
1223 OptWithOids:  WITH OIDS                         { $$ = make_str("with oids"); }
1224                 | WITHOUT OIDS                          { $$ = make_str("without oids"); }
1225                 | /*EMPTY*/                                     { $$ = EMPTY; }
1226                 ;
1227
1228
1229 /*
1230  * Note: CREATE TABLE ... AS SELECT ... is just another spelling for
1231  * SELECT ... INTO.
1232  */
1233
1234 CreateAsStmt:  CREATE OptTemp TABLE qualified_name OptCreateAs AS
1235                 { FoundInto = 0; } 
1236                 SelectStmt
1237                 {
1238                         if (FoundInto == 1)
1239                                 mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE / AS SELECT may not specify INTO");
1240
1241                         $$ = cat_str(7, make_str("create"), $2, make_str("table"), $4, $5, make_str("as"), $8);
1242                 }
1243                 ;
1244
1245 OptCreateAs:  '(' CreateAsList ')' 
1246                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
1247                 | /*EMPTY*/ 
1248                         { $$ = EMPTY; }
1249                 ;
1250
1251 CreateAsList:  CreateAsList ',' CreateAsElement 
1252                         { $$ = cat_str(3, $1, make_str(","), $3); }
1253                 | CreateAsElement       
1254                         { $$ = $1; }
1255                 ;
1256
1257 CreateAsElement:  ColId { $$ = $1; }
1258                 ;
1259
1260 /*****************************************************************************
1261  *
1262  *              QUERY :
1263  *                              CREATE SEQUENCE seqname
1264  *
1265  *****************************************************************************/
1266
1267 CreateSeqStmt:  CREATE OptTemp SEQUENCE qualified_name OptSeqList
1268                         { $$ = cat_str(4, make_str("create sequence"), $2, $4, $5); }
1269                 ;
1270
1271 OptSeqList:  OptSeqList OptSeqElem      { $$ = cat2_str($1, $2); }
1272                 | /*EMPTY*/                                     { $$ = EMPTY; }
1273                 ;
1274
1275 OptSeqElem:  CACHE NumConst
1276                         { $$ = cat2_str(make_str("cache"), $2); }
1277                 | CYCLE
1278                         { $$ = make_str("cycle"); }
1279                 | INCREMENT NumConst
1280                         { $$ = cat2_str(make_str("increment"), $2); }
1281                 | MAXVALUE NumConst
1282                         { $$ = cat2_str(make_str("maxvalue"), $2); }
1283                 | MINVALUE NumConst
1284                         { $$ = cat2_str(make_str("minvalue"), $2); }
1285                 | START NumConst
1286                         { $$ = cat2_str(make_str("start"), $2); }
1287                 ;
1288
1289 /*****************************************************************************
1290  *
1291  *              QUERIES :
1292  *                              CREATE PROCEDURAL LANGUAGE ...
1293  *                              DROP PROCEDURAL LANGUAGE ...
1294  *
1295  *****************************************************************************/
1296
1297 CreatePLangStmt:  CREATE opt_Trusted opt_procedural LANGUAGE ColId_or_Sconst
1298                         HANDLER handler_name opt_lancompiler
1299                         { $$ = cat_str(8, make_str("create"), $2, $3, make_str("language"), $5, make_str("handler"), $7, $8); }
1300                 ;
1301
1302 opt_Trusted:    TRUSTED { $$ = make_str("trusted"); }
1303                 | /*EMPTY*/             { $$ = EMPTY; }
1304                 ;
1305
1306 /* This ought to be just func_name, but that causes reduce/reduce conflicts
1307  * (CREATE LANGUAGE is the only place where func_name isn't followed by '(').
1308  * Work around by using name and dotted_name separately.
1309  */
1310 handler_name: name
1311                                { $$ = $1; }
1312         | dotted_name
1313                                { $$ = $1; /* XXX changing soon */ }
1314                ;
1315
1316 opt_lancompiler: LANCOMPILER StringConst
1317                         { $$ = cat2_str(make_str("lancompiler"), $2); }
1318                 | /*EMPTY*/
1319                         { $$ = ""; }
1320                 ;
1321
1322 DropPLangStmt:  DROP opt_procedural LANGUAGE StringConst
1323                         { $$ = cat_str(4, make_str("drop"), $2, make_str("language"), $4); }
1324                 ;
1325
1326 opt_procedural: PROCEDURAL      { $$ = make_str("prcedural"); }
1327                 | /*EMPTY*/                     { $$ = EMPTY; }
1328                 ;
1329
1330 /*****************************************************************************
1331  *
1332  *              QUERIES :
1333  *                              CREATE TRIGGER ...
1334  *                              DROP TRIGGER ...
1335  *
1336  *****************************************************************************/
1337
1338 CreateTrigStmt:  CREATE TRIGGER name TriggerActionTime TriggerEvents ON
1339                                 qualified_name TriggerForSpec
1340                                 EXECUTE PROCEDURE
1341                                 name '(' TriggerFuncArgs ')'
1342                         { $$ = cat_str(12, make_str("create trigger"), $3, $4, $5, make_str("on"), $7, $8, make_str("execute procedure"), $11, make_str("("), $13, make_str(")")); }
1343                 |       CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON
1344                                 qualified_name OptConstrFromTable
1345                                 ConstraintAttributeSpec
1346                                 FOR EACH ROW EXECUTE PROCEDURE
1347                                 func_name '(' TriggerFuncArgs ')'
1348                         { $$ = cat_str(13, make_str("create constraint trigger"), $4, make_str("after"), $6, make_str("on"), $8, $9, $10, make_str("for each row execute procedure"), $16, make_str("("), $18, make_str(")")); }
1349                 ;
1350
1351 TriggerActionTime:      BEFORE          { $$ = make_str("before"); }
1352                 | AFTER                                 { $$ = make_str("after"); }
1353                 ;
1354
1355 TriggerEvents:  TriggerOneEvent
1356                         { $$ = $1; }
1357                 | TriggerOneEvent OR TriggerOneEvent
1358                         { $$ = cat_str(3, $1, make_str("or"), $3); }
1359                 | TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
1360                         { $$ = cat_str(5, $1, make_str("or"), $3, make_str("or"), $5); }
1361                 ;
1362
1363 TriggerOneEvent:  INSERT        { $$ = make_str("insert"); }
1364                 | DELETE                        { $$ = make_str("delete"); }
1365                 | UPDATE                        { $$ = make_str("update"); }
1366                 ;
1367
1368 TriggerForSpec:  FOR TriggerForOpt TriggerForType
1369                         { $$ = cat_str(3, make_str("for"), $2, $3); }
1370                 ;
1371
1372 TriggerForOpt:  EACH            { $$ = make_str("each"); }
1373                 | /*EMPTY*/                     { $$ = EMPTY; }
1374                 ;
1375
1376 TriggerForType:  ROW            { $$ = make_str("row"); }
1377                 | STATEMENT                     { $$ = make_str("statement"); }
1378                 ;
1379
1380 TriggerFuncArgs:  TriggerFuncArg
1381                         { $$ = $1; }
1382                 | TriggerFuncArgs ',' TriggerFuncArg
1383                         { $$ = cat_str(3, $1, make_str(","), $3); }
1384                 | /*EMPTY*/
1385                         { $$ = EMPTY; }
1386                 ;
1387
1388 TriggerFuncArg:  PosAllConst { $$ = $1; }
1389                 | ColId                          { $$ = $1; }
1390                 ;
1391
1392 OptConstrFromTable: /* Empty */         { $$ = EMPTY; }
1393                 | FROM qualified_name   { $$ = cat2_str(make_str("from"), $2); }
1394                 ;
1395
1396 ConstraintAttributeSpec: ConstraintDeferrabilitySpec    { $$ = $1; }
1397                 | ConstraintDeferrabilitySpec ConstraintTimeSpec
1398                 {
1399                         if (strcmp($1, "deferrable") != 0 && strcmp($2, "initially deferrable") == 0 )
1400                                 mmerror(PARSE_ERROR, ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
1401
1402                         $$ = cat2_str($1, $2);
1403                 }
1404                 | ConstraintTimeSpec            { $$ = $1; }
1405                 | ConstraintTimeSpec ConstraintDeferrabilitySpec
1406                 {
1407                         if (strcmp($2, "deferrable") != 0 && strcmp($1, "initially deferrable") == 0 )
1408                                 mmerror(PARSE_ERROR, ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
1409
1410                         $$ = cat2_str($1, $2);
1411                 }
1412                 ;
1413
1414 ConstraintDeferrabilitySpec: NOT DEFERRABLE 
1415                         { $$ = make_str("not deferrable"); }
1416                 | DEFERRABLE    
1417                         { $$ = make_str("deferrable"); }
1418                 ;
1419
1420 ConstraintTimeSpec: INITIALLY IMMEDIATE         
1421                         { $$ = make_str("initially immediate"); }
1422                 | INITIALLY DEFERRED    
1423                         { $$ = make_str("initially deferred"); }
1424                 ;
1425
1426 DropTrigStmt:  DROP TRIGGER name ON qualified_name
1427                         { $$ = cat_str(4, make_str("drop trigger"), $3, make_str("on"), $5); }
1428                 ;
1429
1430 /*****************************************************************************
1431  *
1432  *              QUERY :
1433  *                              define (type,operator,aggregate)
1434  *
1435  *****************************************************************************/
1436
1437 DefineStmt:  CREATE AGGREGATE func_name definition
1438                         { $$ = cat_str(3, make_str("create aggregate"), $3, $4); }
1439                 | CREATE OPERATOR all_Op definition
1440                         { $$ = cat_str(3, make_str("create operator"), $3, $4); }
1441                 | CREATE TYPE_P any_name definition
1442                         { $$ = cat_str(3, make_str("create type"), $3, $4); }
1443                 ;
1444
1445 definition:  '(' def_list ')' 
1446                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
1447                 ;
1448
1449 def_list:  def_elem                                     { $$ = $1; }
1450                 | def_list ',' def_elem         { $$ = cat_str(3, $1, make_str(","), $3); }
1451                 ;
1452
1453 def_elem:  ColLabel '=' def_arg         { $$ = cat_str(3, $1, make_str("="), $3); }
1454                 | ColLabel                                      { $$ = $1; }
1455                 ;
1456
1457 /* Note: any simple identifier will be returned as a type name! */
1458 def_arg:  func_return                           {  $$ = $1; }
1459                 | all_Op                                        {  $$ = $1; }
1460                 | AllConst                                      {  $$ = $1; }
1461                 ;
1462
1463 /*****************************************************************************
1464  *
1465  *              QUERY:
1466  *
1467  *                         DROP itemtype itemname [, itemname ...]
1468  *
1469  *****************************************************************************/
1470
1471 DropStmt:  DROP drop_type any_name_list opt_drop_behavior
1472                         { $$ = cat_str(4, make_str("drop"), $2, $3, $4); }
1473                 ;
1474
1475 drop_type:      TABLE           { $$ = make_str("table"); }
1476                 | SEQUENCE              { $$ = make_str("sequence"); }
1477                 | VIEW                  { $$ = make_str("view"); }
1478                 | INDEX                 { $$ = make_str("index"); }
1479                 | RULE                  { $$ = make_str("rule"); }
1480                 | TYPE_P                { $$ = make_str("type"); }
1481                 | DOMAIN_P              { $$ = make_str("domain"); }
1482                 ;
1483
1484 any_name_list:  any_name
1485                        { $$ = $1; }
1486                | any_name_list ',' any_name
1487                        { $$ = cat_str(3, $1, make_str(","), $3); }
1488                ;
1489
1490 any_name: ColId
1491                        { $$ = $1; }
1492                | dotted_name
1493                        { $$ = $1; }
1494                 ;
1495 /*****************************************************************************
1496  *
1497  *                         QUERY:
1498  *                                                         truncate table relname
1499  *
1500  *****************************************************************************/
1501 TruncateStmt:  TRUNCATE opt_table qualified_name 
1502                         { $$ = cat_str(3, make_str("truncate table"), $2, $3); }
1503                 ;
1504
1505 /*****************************************************************************
1506  *
1507  *              QUERY:
1508  *                                         fetch/move [forward | backward] [ # | all ] [ in <portalname> ]
1509  *                                         fetch [ forward | backward | absolute | relative ]
1510  *                                                       [ # | all | next | prior ] [ [ in | from ] <portalname> ]
1511  *
1512  *****************************************************************************/
1513
1514 FetchStmt: FETCH direction fetch_how_many from_in name ecpg_into
1515                 {
1516                         if (strcmp($2, "relative") == 0 && atol($3) == 0L)
1517                                 mmerror(PARSE_ERROR, ET_ERROR, "FETCH/RELATIVE at current position is not supported");
1518
1519                         $$ = cat_str(5, make_str("fetch"), $2, $3, $4, $5);
1520                 }
1521                 | FETCH fetch_how_many from_in name ecpg_into
1522                         { $$ = cat_str(4, make_str("fetch"), $2, $3, $4); }
1523                 | FETCH direction from_in name ecpg_into
1524                         { $$ = cat_str(4, make_str("fetch"), $2, $3, $4); }
1525                 | FETCH from_in name ecpg_into
1526                         { $$ = cat_str(3, make_str("fetch"), $2, $3); }
1527                 | FETCH name ecpg_into
1528                         { $$ = cat2_str(make_str("fetch"), $2); }
1529                 | MOVE direction fetch_how_many from_in name
1530                         { $$ = cat_str(5, make_str("move"), $2, $3, $4, $5); }
1531                 | MOVE fetch_how_many from_in name
1532                         { $$ = cat_str(4, make_str("move"), $2, $3, $4); }
1533                 | MOVE direction from_in name
1534                         { $$ = cat_str(4, make_str("move"), $2, $3, $4); }
1535                 | MOVE from_in name
1536                         { $$ = cat_str(3, make_str("move"), $2, $3); }
1537                 | MOVE name
1538                         { $$ = cat2_str(make_str("move"), $2); }
1539                 ;
1540
1541 direction:      FORWARD         { $$ = make_str("forward"); }
1542                 | BACKWARD              { $$ = make_str("backward"); }
1543                 | RELATIVE              { $$ = make_str("relative"); }
1544                 | ABSOLUTE
1545                 {
1546                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported FETCH/ABSOLUTE will be passed to backend, backend will use RELATIVE");
1547                         $$ = make_str("absolute");
1548                 }
1549                 ;
1550
1551 fetch_how_many: IntConst        { $$ = $1; }
1552                 | ALL                           { $$ = make_str("all"); }
1553                 | NEXT                          { $$ = make_str("next"); }
1554                 | PRIOR                         { $$ = make_str("prior"); }
1555                 ;
1556
1557 from_in: IN                                     { $$ = make_str("in"); }
1558                 | FROM                          { $$ = make_str("from"); }
1559                 ;
1560
1561 /*****************************************************************************
1562  *
1563  *      The COMMENT ON statement can take different forms based upon the type of
1564  *      the object associated with the comment. The form of the statement is:
1565  *
1566  *      COMMENT ON [ [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]
1567  *                               <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION
1568  *                              <funcname> (arg1, arg2, ...) | OPERATOR <op>
1569  *                              (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
1570  *                              <relname> ] IS 'text'
1571  *
1572  *****************************************************************************/
1573 CommentStmt:   COMMENT ON comment_type name IS comment_text
1574                         { $$ = cat_str(5, make_str("comment on"), $3, $4, make_str("is"), $6); }
1575                 | COMMENT ON COLUMN ColId '.' attr_name IS comment_text
1576                         { $$ = cat_str(6, make_str("comment on column"), $4, make_str("."), $6, make_str("is"), $8); }
1577                 | COMMENT ON COLUMN ColId '.' ColId '.' attr_name IS comment_text
1578                         { $$ = cat_str(8, make_str("comment on column"), $4, make_str("("), $6, make_str("."), $8, make_str("is"), $10); }
1579                 | COMMENT ON AGGREGATE func_name '(' aggr_argtype ')' IS comment_text
1580                         { $$ = cat_str(6, make_str("comment on aggregate"), $4, make_str("("), $6, make_str(") is"), $9); }
1581                 | COMMENT ON FUNCTION func_name func_args IS comment_text
1582                         { $$ = cat_str(5, make_str("comment on function"), $4, $5, make_str("is"), $7); }
1583                 | COMMENT ON OPERATOR all_Op '(' oper_argtypes ')' IS comment_text
1584                         { $$ = cat_str(6, make_str("comment on operator"), $4, make_str("("), $6, make_str(") is"), $9); }
1585                 | COMMENT ON TRIGGER name ON qualified_name IS comment_text
1586                         { $$ = cat_str(6, make_str("comment on trigger"), $4, make_str("on"), $6, make_str("is"), $8); }
1587                 ;
1588
1589 comment_type:  DATABASE         { $$ = make_str("database"); }
1590                 | INDEX         { $$ = make_str("idnex"); }
1591                 | RULE          { $$ = make_str("rule"); }
1592                 | SEQUENCE      { $$ = make_str("sequence"); }
1593                 | TABLE         { $$ = make_str("table"); }
1594                 | DOMAIN_P      { $$ = make_str("domain"); }
1595                 | TYPE_P        { $$ = make_str("type"); }
1596                 | VIEW          { $$ = make_str("view"); }
1597                 ;
1598
1599 comment_text:   StringConst { $$ = $1; }
1600                 | NULL_P                        { $$ = make_str("null"); }
1601                 ;
1602
1603 /*****************************************************************************
1604  *
1605  *              QUERY:
1606  * GRANT and REVOKE statements
1607  *
1608  *****************************************************************************/
1609
1610 GrantStmt:      GRANT privileges ON privilege_target TO grantee_list opt_grant_grant_option
1611                         { $$ = cat_str(7, make_str("grant"), $2, make_str("on"), $4, make_str("to"), $6, $7); }
1612                 ;
1613
1614 RevokeStmt:  REVOKE opt_revoke_grant_option privileges ON privilege_target FROM grantee_list
1615                         { $$ = cat_str(8, make_str("revoke"), $2, $3, make_str("on"), $5, make_str("from"), $7); }
1616                 ;
1617
1618 privileges:  ALL PRIVILEGES             { $$ = make_str("all privileges"); }
1619                 | ALL                                   { $$ = make_str("all"); }
1620                 | privilege_list                { $$ = $1; }
1621                 ;
1622
1623 privilege_list:  privilege      
1624                         { $$ = $1; }
1625                 | privilege_list ',' privilege  
1626                         { $$ = cat_str(3, $1, make_str(","), $3); }
1627                 ;
1628
1629 privilege:      SELECT                  { $$ = make_str("select"); }
1630                 | INSERT                        { $$ = make_str("insert"); }
1631                 | UPDATE                        { $$ = make_str("update"); }
1632                 | DELETE                        { $$ = make_str("delete"); }
1633                 | RULE                          { $$ = make_str("rule"); }
1634                 | REFERENCES            { $$ = make_str("references"); }
1635                 | TRIGGER                       { $$ = make_str("trigger"); }
1636                 | EXECUTE                       { $$ = make_str("execute"); }
1637                 | USAGE                         { $$ = make_str("usage"); }
1638                 ;
1639
1640 privilege_target: qualified_name_list   
1641                         { $$ = $1; }
1642                 | TABLE qualified_name_list             
1643                         { $$ = cat2_str(make_str("table"), $2); }
1644                 | FUNCTION function_with_argtypes_list
1645                         { $$ = cat2_str(make_str("function"), $2); }
1646                 | LANGUAGE name_list                    
1647                         { $$ = cat2_str(make_str("language") , $2); }
1648                 ;
1649
1650 grantee_list: grantee                           
1651                         { $$ = $1; }
1652                 | grantee_list ',' grantee      
1653                         { $$ = cat_str(3, $1, make_str(","), $3); }
1654                 ;
1655
1656 grantee:  PUBLIC                        { $$ = make_str("public"); }
1657                 | GROUP ColId           { $$ = cat2_str(make_str("group"), $2); }
1658                 | ColId                         { $$ = $1; }
1659                 ;
1660
1661 opt_grant_grant_option:  WITH GRANT OPTION
1662                 {
1663                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported GRANT/WITH GRANT OPTION will be passed to backend");
1664                         $$ = make_str("with grant option");
1665                 }
1666                 | /*EMPTY*/     { $$ = EMPTY; }
1667                 ;
1668
1669 opt_revoke_grant_option: GRANT OPTION FOR
1670                 {
1671                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported REVOKE/GRANT OPTION FOR will be passed to backend");
1672                         $$ = make_str("with grant option");
1673                 }
1674                 | /*EMPTY*/     { $$ = EMPTY; }
1675                 ;
1676
1677 function_with_argtypes_list: function_with_argtypes
1678                         { $$ = $1; }
1679                 | function_with_argtypes_list ',' function_with_argtypes
1680                         { $$ = cat_str(3, $1, make_str(","), $3); }
1681                 ;
1682
1683 function_with_argtypes: func_name func_args { $$ = cat2_str($1, $2); };
1684
1685 /*****************************************************************************
1686  *
1687  *              QUERY:
1688  *                              create index <indexname> on <relname>
1689  *                                [ using <access> ] "(" (<col> with <op>)+ ")"
1690  *                                [ where <predicate> ]
1691  *
1692  *****************************************************************************/
1693
1694 IndexStmt:      CREATE index_opt_unique INDEX index_name ON qualified_name
1695                                 access_method_clause '(' index_params ')' where_clause
1696                         { $$ = cat_str(11, make_str("create"), $2, make_str("index"), $4, make_str("on"), $6, $7, make_str("("), $9, make_str(")"), $11); }
1697                 ;
1698
1699 index_opt_unique:  UNIQUE       { $$ = make_str("unique"); }
1700                 | /*EMPTY*/             { $$ = EMPTY; }
1701                 ;
1702
1703 access_method_clause:  USING access_method      
1704                         { $$ = cat2_str(make_str("using"), $2); }
1705                 | /*EMPTY*/                     
1706                         { $$ = EMPTY; }
1707                 ;
1708
1709 index_params:  index_list       { $$ = $1; }
1710                 | func_index            { $$ = $1; }
1711                 ;
1712
1713 index_list:  index_list ',' index_elem
1714                         { $$ = cat_str(3, $1, make_str(","), $3); }
1715                 | index_elem
1716                         { $$ = $1; }
1717                 ;
1718
1719 func_index:  func_name '(' name_list ')' opt_class
1720                         { $$ = cat_str(5, $1, make_str("("), $3, ")", $5); }
1721                 ;
1722
1723 index_elem:  attr_name opt_class
1724                         { $$ = cat2_str($1, $2); }
1725                 ;
1726
1727 opt_class:      class
1728                 {
1729                         /*
1730                          * Release 7.0 removed network_ops, timespan_ops, and
1731                          * datetime_ops, so we suppress it from being passed to
1732                          * the parser so the default *_ops is used.  This can be
1733                          * removed in some later release.       bjm 2000/02/07
1734                          *
1735                          * Release 7.1 removes lztext_ops, so suppress that too
1736                          * for a while.  tgl 2000/07/30
1737                          */
1738                         if (strcmp($1, "network_ops") != 0 &&
1739                                  strcmp($1, "timespan_ops") != 0 &&
1740                                  strcmp($1, "datetime_ops") != 0 &&
1741                                  strcmp($1, "lztext_ops") != 0)
1742                                 $$ = $1;
1743                         else
1744                                 $$ = EMPTY;
1745                 }
1746                 | USING class   { $$ = cat2_str(make_str("using"), $2); }
1747                 | /*EMPTY*/             { $$ = EMPTY; }
1748                 ;
1749
1750
1751 /*****************************************************************************
1752  *
1753  *              QUERY:
1754  *                              execute recipe <recipeName>
1755  *
1756  *****************************************************************************/
1757 /* NOT USED
1758 RecipeStmt:  EXECUTE RECIPE recipe_name
1759                                 {
1760                                         $$ = cat2_str(make_str("execute recipe"), $3);
1761                                 }
1762                 ;
1763 */
1764 /*****************************************************************************
1765  *
1766  *              QUERY:
1767  *                              create [or replace] function <fname>
1768  *                                              [(<type-1> { , <type-n>})]
1769  *                                              returns <type-r>
1770  *                                              as <filename or code in language as appropriate>
1771  *                                              language <lang> [with parameters]
1772  *
1773  *****************************************************************************/
1774
1775 ProcedureStmt:  CREATE opt_or_replace FUNCTION func_name func_args
1776                                         RETURNS func_return AS func_as LANGUAGE ColId_or_Sconst opt_with
1777                         { $$ = cat_str(12, make_str("create"), $2, make_str("function"), $4, $5, make_str("returns"), $7, make_str("as"), $9, make_str("language"), $11, $12); }
1778                 ;
1779
1780 opt_or_replace:  OR REPLACE             { $$ = make_str("or replace"); }
1781                 | /*EMPTY*/                             { $$ = EMPTY; }
1782                 ;
1783
1784 opt_with:  WITH definition              { $$ = cat2_str(make_str("with"), $2); }
1785                 | /*EMPTY*/                             { $$ = EMPTY; }
1786                 ;
1787
1788 func_args:      '(' func_args_list ')'
1789                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
1790                 | '(' ')'
1791                         { $$ = make_str("()"); }
1792                 ;
1793
1794 func_args_list:  func_arg
1795                         { $$ = $1; }
1796                 | func_args_list ',' func_arg
1797                         { $$ = cat_str(3, $1, make_str(","), $3); }
1798                 ;
1799
1800 func_arg:  opt_arg func_type
1801                 {
1802                         /* We can catch over-specified arguments here if we want to,
1803                          * but for now better to silently swallow typmod, etc.
1804                          * - thomas 2000-03-22
1805                          */
1806                         $$ = cat2_str($1, $2);
1807                 }
1808                 | func_type             { $$ = $1; }
1809                 ;
1810
1811 opt_arg:  IN    { $$ = make_str("in"); }
1812                 | OUT
1813                 {
1814                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported CREATE FUNCTION/OUT will be passed to backend");
1815
1816                         $$ = make_str("out");
1817                 }
1818                 | INOUT
1819                 {
1820                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported CREATE FUNCTION/INOUT will be passed to backend");
1821
1822                         $$ = make_str("inout");
1823                 }
1824                 ;
1825
1826 func_as: StringConst
1827                         { $$ = $1; }
1828                 | StringConst ',' StringConst
1829                         { $$ = cat_str(3, $1, make_str(","), $3); }
1830                 ;
1831
1832 func_return:  func_type
1833                 {
1834                         /* We can catch over-specified arguments here if we want to,
1835                          * but for now better to silently swallow typmod, etc.
1836                          * - thomas 2000-03-22
1837                          */
1838                         $$ = $1;
1839                 }
1840                 ;
1841
1842 func_type:      Typename
1843                         { $$ = $1; }
1844                 | type_name attrs '%' TYPE_P
1845                         { $$ = cat_str(3, $1, $2, make_str("% type")); }
1846                 ;
1847
1848 /*****************************************************************************
1849  *
1850  *              QUERY:
1851  *
1852  *                         DROP FUNCTION funcname (arg1, arg2, ...)
1853  *                         DROP AGGREGATE aggname (aggtype)
1854  *                         DROP OPERATOR opname (leftoperand_typ rightoperand_typ)
1855  *
1856  *****************************************************************************/
1857
1858 RemoveFuncStmt:  DROP FUNCTION func_name func_args
1859                         { $$ = cat_str(3, make_str("drop function"), $3, $4); }
1860                 ;
1861
1862 RemoveAggrStmt:  DROP AGGREGATE func_name '(' aggr_argtype ')'
1863                         { $$ = cat_str(5, make_str("drop aggregate"), $3, make_str("("), $5, make_str(")")); }
1864                 ;
1865
1866 aggr_argtype:  Typename         { $$ = $1; }
1867                 | '*'                           { $$ = make_str("*"); }
1868                 ;
1869
1870
1871 RemoveOperStmt:  DROP OPERATOR all_Op '(' oper_argtypes ')'
1872                         { $$ = cat_str(5, make_str("drop operator"), $3, make_str("("), $5, make_str(")")); }
1873                 ;
1874
1875 oper_argtypes:  Typename
1876                         { mmerror(PARSE_ERROR, ET_ERROR, "parser: argument type missing (use NONE for unary operators)"); }
1877                 | Typename ',' Typename
1878                         { $$ = cat_str(3, $1, make_str(","), $3); }
1879                 | NONE ',' Typename                     /* left unary */
1880                         { $$ = cat2_str(make_str("none,"), $3); }
1881                 | Typename ',' NONE                     /* right unary */
1882                         { $$ = cat2_str($1, make_str(", none")); }
1883                 ;
1884
1885 /*****************************************************************************
1886  *
1887  *                              QUERY:
1888  *
1889  *                              REINDEX type <typename> [FORCE] [ALL]
1890  *
1891  *****************************************************************************/
1892 ReindexStmt:  REINDEX reindex_type qualified_name opt_force
1893                         { $$ = cat_str(4, make_str("reindex"), $2, $3, $4); }
1894                 | REINDEX DATABASE name opt_force
1895                         { $$ = cat_str(3, make_str("reindex database"), $3, $4); }
1896                 ;
1897
1898 reindex_type:   INDEX           { $$ = make_str("index"); }
1899                 | TABLE         { $$ = make_str("table"); }
1900                 ;
1901
1902 opt_force: FORCE                        { $$ = make_str("force"); }
1903                 | /* EMPTY */           { $$ = EMPTY; }
1904                 ;
1905
1906 /*****************************************************************************
1907  *
1908  *              QUERY:
1909  *                              rename <attrname1> in <relname> [*] to <attrname2>
1910  *                              rename <relname1> to <relname2>
1911  *
1912  *****************************************************************************/
1913
1914 RenameStmt:  ALTER TABLE relation_expr RENAME opt_column opt_name TO name
1915                         { $$ = cat_str(7, make_str("alter table"), $3, make_str("rename"), $5, $6, make_str("to"), $8); }
1916                 ;
1917
1918 opt_name:  name                         { $$ = $1; }
1919                 | /*EMPTY*/                     { $$ = EMPTY; }
1920                 ;
1921
1922 opt_column:  COLUMN                     { $$ = make_str("column"); }
1923                 | /*EMPTY*/                     { $$ = EMPTY; }
1924                 ;
1925
1926
1927 /*****************************************************************************
1928  *
1929  *              QUERY:  Define Rewrite Rule
1930  *
1931  *****************************************************************************/
1932
1933 RuleStmt:  CREATE RULE name AS
1934                    { QueryIsRule=1; }
1935                    ON event TO qualified_name where_clause
1936                    DO opt_instead RuleActionList
1937                 {
1938                         QueryIsRule=0;
1939                         $$ = cat_str(10, make_str("create rule"), $3, make_str("as on"), $7, make_str("to"), $9, $10, make_str("do"), $12, $13);
1940                 }
1941                 ;
1942
1943 RuleActionList:  NOTHING                                { $$ = make_str("nothing"); }
1944                 | RuleActionStmt                                { $$ = $1; }
1945                 | '(' RuleActionMulti ')'               { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
1946                                 ;
1947
1948 /* the thrashing around here is to discard "empty" statements... */
1949 RuleActionMulti:  RuleActionMulti ';' RuleActionStmtOrEmpty
1950                         {  $$ = cat_str(3, $1, make_str(";"), $3); }
1951                 | RuleActionStmtOrEmpty
1952                         { $$ = cat2_str($1, make_str(";")); }
1953                 ;
1954
1955 RuleActionStmt:   SelectStmt
1956                 | InsertStmt
1957                 | UpdateStmt
1958                 | DeleteStmt
1959                 | NotifyStmt
1960                 ;
1961
1962 RuleActionStmtOrEmpty: RuleActionStmt   { $$ = $1; }
1963            | /*EMPTY*/                                          { $$ = EMPTY; }
1964            ;
1965
1966 /* change me to select, update, etc. some day */
1967 event:  SELECT                          { $$ = make_str("select"); }
1968                 | UPDATE                        { $$ = make_str("update"); }
1969                 | DELETE                        { $$ = make_str("delete"); }
1970                 | INSERT                        { $$ = make_str("insert"); }
1971                  ;
1972
1973 opt_instead:  INSTEAD           { $$ = make_str("instead"); }
1974                 | /*EMPTY*/                     { $$ = EMPTY; }
1975                 ;
1976
1977
1978 /*****************************************************************************
1979  *
1980  *              QUERY:
1981  *                              NOTIFY <qualified_name> can appear both in rule bodies and
1982  *                              as a query-level command
1983  *
1984  *****************************************************************************/
1985
1986 NotifyStmt:  NOTIFY qualified_name
1987                 { $$ = cat2_str(make_str("notify"), $2); }
1988                 ;
1989
1990 ListenStmt:  LISTEN qualified_name
1991                 { $$ = cat2_str(make_str("listen"), $2); }
1992                 ;
1993
1994 UnlistenStmt:  UNLISTEN qualified_name
1995                         { $$ = cat2_str(make_str("unlisten"), $2); }
1996                 | UNLISTEN '*'
1997                         { $$ = make_str("unlisten *"); }
1998                 ;
1999
2000
2001 /*****************************************************************************
2002  *
2003  *                              Transactions:
2004  *
2005  *        BEGIN / COMMIT / ROLLBACK
2006  *              (also older versions END / ABORT)
2007  *
2008  *****************************************************************************/
2009 TransactionStmt:  ABORT_TRANS opt_trans         { $$ = make_str("rollback"); }
2010                 | BEGIN_TRANS opt_trans                         { $$ = make_str("begin transaction"); }
2011                 | COMMIT opt_trans                                      { $$ = make_str("commit"); }
2012                 | COMMIT opt_trans opt_chain            { $$ = cat2_str(make_str("commit"), $3); }
2013                 | END_TRANS opt_trans                           { $$ = make_str("commit"); }
2014                 | ROLLBACK opt_trans                            { $$ = make_str("rollback"); }
2015                 | ROLLBACK opt_trans opt_chain          { $$ = cat2_str(make_str("rollback"), $3); }
2016                 ;
2017
2018 opt_trans: WORK                 { $$ = EMPTY; }
2019                 | TRANSACTION   { $$ = EMPTY; }
2020                 | /*EMPTY*/             { $$ = EMPTY; }
2021                 ;
2022
2023 opt_chain: AND NO CHAIN
2024                         { $$ = make_str("and no chain"); }
2025                 | AND CHAIN
2026                 {
2027                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported COMMIT/CHAIN will be passed to backend");
2028
2029                         $$ = make_str("and chain");
2030                 }
2031                 ;
2032
2033 /*****************************************************************************
2034  *
2035  *              QUERY:
2036  *                              define view <viewname> '('target-list ')' [where <quals> ]
2037  *
2038  *****************************************************************************/
2039
2040 ViewStmt:  CREATE VIEW qualified_name opt_column_list AS SelectStmt
2041                         { $$ = cat_str(5, make_str("create view"), $3, $4, make_str("as"), $6); }
2042                 ;
2043
2044
2045 /*****************************************************************************
2046  *
2047  *              QUERY:
2048  *                              load make_str("filename")
2049  *
2050  *****************************************************************************/
2051
2052 LoadStmt:  LOAD file_name
2053                         { $$ = cat2_str(make_str("load"), $2); }
2054                 ;
2055
2056
2057 /*****************************************************************************
2058  *
2059  *              CREATE DATABASE
2060  *
2061  *
2062  *****************************************************************************/
2063
2064 CreatedbStmt:  CREATE DATABASE database_name WITH createdb_opt_list
2065                         { $$ = cat_str(4, make_str("create database"), $3, make_str("with"), $5); }
2066                 | CREATE DATABASE database_name
2067                         { $$ = cat2_str(make_str("create database"), $3); }
2068                 ;
2069
2070 createdb_opt_list:      createdb_opt_item
2071                         { $$ = $1; }
2072                 | createdb_opt_list createdb_opt_item
2073                         { $$ = cat2_str($1, $2); }
2074                 ;
2075
2076 createdb_opt_item:      LOCATION opt_equal StringConst
2077                         { $$ = cat_str(3,make_str("location"), $2, $3); }
2078                 | LOCATION opt_equal DEFAULT
2079                         { $$ = cat_str(3, make_str("location"), $2, make_str("default")); }
2080                 | TEMPLATE opt_equal name
2081                         { $$ = cat_str(3, make_str("template"), $2, $3); }
2082                 | TEMPLATE opt_equal DEFAULT
2083                         { $$ = cat_str(3, make_str("template"), $2, make_str("default")); }
2084                 | ENCODING opt_equal PosIntStringConst
2085                         { $$ = cat_str(3, make_str("encoding"), $2, $3); }
2086                 | ENCODING opt_equal DEFAULT
2087                         { $$ = cat_str(3, make_str("encoding"), $2, make_str("default")); }
2088                 | OWNER opt_equal name
2089                         { $$ = cat_str(3, make_str("owner"), $2, $3); }
2090                 | OWNER opt_equal DEFAULT
2091                         { $$ = cat_str(3, make_str("owner"), $2, make_str("default")); }
2092                 ;
2093
2094 opt_equal: '='                                  { $$ = make_str("="); }
2095                 | /* EMPTY */                   { $$ = EMPTY; }
2096                 ;
2097
2098
2099 /*****************************************************************************
2100  *
2101  *                              ALTER DATABASE
2102  *
2103  *
2104  *****************************************************************************/
2105
2106 AlterDatabaseSetStmt: ALTER DATABASE database_name VariableSetStmt
2107                         { $$ = cat_str(3, make_str("alter database"), $3, $4); }
2108                 | ALTER DATABASE database_name VariableResetStmt
2109                         { $$ = cat_str(3, make_str("alter database"), $3, $4); }
2110                 ;
2111
2112 /*****************************************************************************
2113  *
2114  *              DROP DATABASE
2115  *
2116  *
2117  *****************************************************************************/
2118
2119 DropdbStmt: DROP DATABASE database_name
2120                         { $$ = cat2_str(make_str("drop database"), $3); }
2121                 ;
2122
2123
2124 /*****************************************************************************
2125  *
2126  * Manipulate a domain
2127  *
2128  *****************************************************************************/
2129
2130 CreateDomainStmt:  CREATE DOMAIN_P any_name opt_as Typename ColQualList opt_collate
2131                         {
2132                                 $$ = cat_str(6, make_str("create domain"), $3, $4, $5, $6, $7);
2133                         }
2134                 ;
2135  
2136 opt_as: AS      {$$ = make_str("as"); }
2137         | /* EMPTY */   {$$ = EMPTY; }
2138         ;
2139  
2140 /*****************************************************************************
2141  *
2142  *              QUERY:
2143  *                              cluster <index_name> on <qualified_name>
2144  *
2145  *****************************************************************************/
2146
2147 ClusterStmt:  CLUSTER index_name ON qualified_name
2148                         { $$ = cat_str(4, make_str("cluster"), $2, make_str("on"), $4); }
2149                 ;
2150
2151
2152 /*****************************************************************************
2153  *
2154  *              QUERY:
2155  *                              vacuum
2156  *                              analyze
2157  *
2158  *****************************************************************************/
2159
2160 VacuumStmt:  VACUUM opt_full opt_freeze opt_verbose
2161                         { $$ = cat_str(4, make_str("vacuum"), $2, $3, $4); }
2162                 | VACUUM opt_full opt_freeze opt_verbose qualified_name
2163                         { $$ = cat_str(5, make_str("vacuum"), $2, $3, $4, $5); }
2164                 | VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
2165                         { $$ = cat_str(5, make_str("vacuum"), $2, $3, $4, $5); }
2166                 ;
2167
2168 AnalyzeStmt:  analyze_keyword opt_verbose
2169                         { $$ = cat_str(2, $1, $2); }
2170                 | analyze_keyword opt_verbose qualified_name opt_name_list
2171                         { $$ = cat_str(4, $1, $2, $3, $4); }
2172                 ;
2173
2174 analyze_keyword:  ANALYZE               { $$ = make_str("analyze"); }
2175                 | ANALYSE                               { $$ = make_str("analyse"); }
2176                 ;
2177
2178 opt_verbose:  VERBOSE                   { $$ = make_str("verbose"); }
2179                 | /*EMPTY*/                             { $$ = EMPTY; }
2180                 ;
2181
2182 opt_full:  FULL                                 { $$ = make_str("full"); }
2183                 | /*EMPTY*/                             { $$ = EMPTY; }
2184                 ;
2185
2186 opt_freeze:  FREEZE                             { $$ = make_str("freeze"); }
2187                 | /*EMPTY*/                             { $$ = EMPTY; }
2188                 ;
2189
2190 opt_name_list:  '(' name_list ')'
2191                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2192                 | /*EMPTY*/
2193                         { $$ = EMPTY; }
2194                 ;
2195
2196
2197 /*****************************************************************************
2198  *
2199  *              QUERY:
2200  *                              EXPLAIN query
2201  *
2202  *****************************************************************************/
2203
2204 ExplainStmt:  EXPLAIN opt_verbose OptimizableStmt
2205                         { $$ = cat_str(3, make_str("explain"), $2, $3); }
2206                 | EXPLAIN analyze_keyword opt_verbose OptimizableStmt
2207                         { $$ = cat_str(4, make_str("explain"), $2, $3, $4); }
2208                 ;
2209
2210
2211 /*****************************************************************************
2212  *                                                                                                                                                       *
2213  *              Optimizable Stmts:                                                                                                       *
2214  *                                                                                                                                                       *
2215  *              one of the five queries processed by the planner                                         *
2216  *                                                                                                                                                       *
2217  *              [ultimately] produces query-trees as specified                                           *
2218  *              in the query-spec document in ~postgres/ref                                                      *
2219  *                                                                                                                                                       *
2220  *****************************************************************************/
2221
2222 OptimizableStmt:  SelectStmt
2223                 | CursorStmt
2224                 | UpdateStmt
2225                 | InsertStmt
2226                 | DeleteStmt
2227                 ;
2228
2229
2230 /*****************************************************************************
2231  *
2232  *              QUERY:
2233  *                              INSERT STATEMENTS
2234  *
2235  *****************************************************************************/
2236
2237 InsertStmt:  INSERT INTO qualified_name insert_rest
2238                         { $$ = cat_str(3, make_str("insert into"), $3, $4); }
2239                 ;
2240
2241 insert_rest:  VALUES '(' insert_target_list ')'
2242                         { $$ = cat_str(3, make_str("values("), $3, make_str(")")); }
2243                 | DEFAULT VALUES
2244                         { $$ = make_str("default values"); }
2245                 | SelectStmt
2246                         { $$ = $1; }
2247                 | '(' insert_column_list ')' VALUES '(' insert_target_list ')'
2248                         { $$ = cat_str(5, make_str("("), $2, make_str(") values ("), $6, make_str(")")); }
2249                 | '(' insert_column_list ')' SelectStmt
2250                         { $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); }
2251                 ;
2252
2253 insert_column_list: insert_column_list ',' insert_column_item
2254                         { $$ = cat_str(3, $1, make_str(","), $3); }
2255                 | insert_column_item
2256                         { $$ = $1; }
2257                 ;
2258
2259 insert_column_item:  ColId opt_indirection
2260                         { $$ = cat2_str($1, $2); }
2261                 ;
2262
2263
2264 /*****************************************************************************
2265  *
2266  *              QUERY:
2267  *                              DELETE STATEMENTS
2268  *
2269  *****************************************************************************/
2270
2271 DeleteStmt:  DELETE FROM relation_expr where_clause
2272                         { $$ = cat_str(3, make_str("delete from"), $3, $4); }
2273                 ;
2274
2275 LockStmt:  LOCK_P opt_table qualified_name_list opt_lock
2276                         { $$ = cat_str(4, make_str("lock"), $2, $3, $4); }
2277                 ;
2278
2279 opt_lock:  IN lock_type MODE
2280                         { $$ = cat_str(3, make_str("in"), $2, make_str("mode")); }
2281                 | /*EMPTY*/
2282                         { $$ = EMPTY;}
2283                 ;
2284
2285 lock_type:      ACCESS SHARE            { $$ = make_str("access share"); }
2286                 | ROW SHARE                             { $$ = make_str("access share"); }
2287                 | ROW EXCLUSIVE                 { $$ = make_str("row exclusive"); }
2288                 | SHARE UPDATE EXCLUSIVE { $$ = make_str("share update exclusive"); }
2289                 | SHARE                                 { $$ = make_str("share"); }
2290                 | SHARE ROW EXCLUSIVE   { $$ = make_str("share row exclusive"); }
2291                 | EXCLUSIVE                             { $$ = make_str("exclusive"); }
2292                 | ACCESS EXCLUSIVE              { $$ = make_str("access exclusive"); }
2293                 ;
2294
2295 /*****************************************************************************
2296  *
2297  *              QUERY:
2298  *                              UpdateStmt (UPDATE)
2299  *
2300  *****************************************************************************/
2301
2302 UpdateStmt:  UPDATE relation_expr
2303                                 SET update_target_list
2304                                 from_clause
2305                                 where_clause
2306                         {$$ = cat_str(6, make_str("update"), $2, make_str("set"), $4, $5, $6); }
2307                 ;
2308
2309
2310 /*****************************************************************************
2311  *
2312  *              QUERY:
2313  *                              CURSOR STATEMENTS
2314  *
2315  *****************************************************************************/
2316 CursorStmt:  DECLARE name opt_cursor CURSOR FOR SelectStmt
2317                 {
2318                         struct cursor *ptr, *this;
2319
2320                         for (ptr = cur; ptr != NULL; ptr = ptr->next)
2321                         {
2322                                 if (strcmp($2, ptr->name) == 0)
2323                                 {
2324                                                 /* re-definition is a bug */
2325                                         sprintf(errortext, "cursor %s already defined", $2);
2326                                         mmerror(PARSE_ERROR, ET_ERROR, errortext);
2327                                 }
2328                         }
2329
2330                         this = (struct cursor *) mm_alloc(sizeof(struct cursor));
2331
2332                         /* initial definition */
2333                         this->next = cur;
2334                         this->name = $2;
2335                         this->connection = connection;
2336                         this->command =  cat_str(5, make_str("declare"), mm_strdup($2), $3, make_str("cursor for"), $6);
2337                         this->argsinsert = argsinsert;
2338                         this->argsresult = argsresult;
2339                         argsinsert = argsresult = NULL;
2340
2341                         cur = this;
2342
2343                         $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
2344                 }
2345                 ;
2346
2347 opt_cursor:  BINARY                             { $$ = make_str("binary"); }
2348            | INSENSITIVE                        { $$ = make_str("insensitive"); }
2349            | SCROLL                                     { $$ = make_str("scroll"); }
2350            | INSENSITIVE SCROLL         { $$ = make_str("insensitive scroll"); }
2351            | /*EMPTY*/                          { $$ = EMPTY; }
2352            ;
2353
2354 /*****************************************************************************
2355  *
2356  *              QUERY:
2357  *                              SELECT STATEMENTS
2358  *
2359  *****************************************************************************/
2360
2361 SelectStmt: select_no_parens            %prec UMINUS
2362                         { $$ = $1; }
2363                 |       select_with_parens              %prec UMINUS
2364                         { $$ = $1; }
2365                 ;
2366
2367 select_with_parens: '(' select_no_parens ')'
2368                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2369                 | '(' select_with_parens ')'
2370                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2371                 ;
2372
2373 select_no_parens:          simple_select
2374                         { $$ = $1; }
2375                 | select_clause sort_clause opt_for_update_clause opt_select_limit
2376                         { $$ = cat_str(4, $1, $2, $3, $4); }
2377                 | select_clause for_update_clause opt_select_limit
2378                         { $$ = cat_str(3, $1, $2, $3); }
2379                 | select_clause select_limit
2380                         { $$ = cat2_str($1, $2); }
2381                 ;
2382
2383 select_clause: simple_select            { $$ = $1; }
2384                 | select_with_parens            { $$ = $1; }
2385                 ;
2386
2387 simple_select:  SELECT opt_distinct target_list
2388                                         into_clause from_clause where_clause
2389                                         group_clause having_clause
2390                         { $$ = cat_str(8, make_str("select"), $2, $3, $4, $5, $6, $7, $8); }
2391                 | select_clause UNION opt_all select_clause
2392                         { $$ = cat_str(4, $1, make_str("union"), $3, $4); }
2393                 | select_clause INTERSECT opt_all select_clause
2394                         { $$ = cat_str(4, $1, make_str("intersect"), $3, $4); }
2395                 | select_clause EXCEPT opt_all select_clause
2396                         { $$ = cat_str(4, $1, make_str("except"), $3, $4); }
2397                 ;
2398
2399 into_clause:  INTO OptTempTableName
2400                 {
2401                         FoundInto = 1;
2402                         $$= cat2_str(make_str("into"), $2);
2403                 }
2404                 | ecpg_into                     { $$ = EMPTY; }
2405                 | /*EMPTY*/                     { $$ = EMPTY; }
2406                 ;
2407
2408 /*
2409  * Redundancy here is needed to avoid shift/reduce conflicts,
2410  * since TEMP is not a reserved word.  See also OptTemp.
2411  *
2412  * The result is a cons cell (not a true list!) containing
2413  * a boolean and a table name.
2414  */
2415 OptTempTableName:  TEMPORARY opt_table qualified_name
2416                         { $$ = cat_str(3, make_str("temporary"), $2, $3); }
2417                 | TEMP opt_table qualified_name
2418                         { $$ = cat_str(3, make_str("temp"), $2, $3); }
2419                 | LOCAL TEMPORARY opt_table qualified_name
2420                         { $$ = cat_str(3, make_str("local temporary"), $3, $4); }
2421                 | LOCAL TEMP opt_table qualified_name
2422                         { $$ = cat_str(3, make_str("local temp"), $3, $4); }
2423                 | GLOBAL TEMPORARY opt_table qualified_name
2424                 {
2425                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported CREATE TABLE / GLOBAL TEMPORARY will be passed to backend");
2426                         $$ = cat_str(3, make_str("global temporary"), $3, $4);
2427                 }
2428                 | GLOBAL TEMP opt_table qualified_name
2429                 {
2430                         mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported CREATE TABLE / GLOBAL TEMP will be passed to backend");
2431                         $$ = cat_str(3, make_str("global temp"), $3, $4);
2432                 }
2433                 | TABLE qualified_name
2434                         { $$ = cat2_str(make_str("table"), $2); }
2435                 | qualified_name
2436                         { $$ = $1; }
2437                 ;
2438
2439 opt_table:      TABLE                           { $$ = make_str("table"); }
2440                 | /*EMPTY*/                             { $$ = EMPTY; }
2441                 ;
2442
2443 opt_all:  ALL                                   { $$ = make_str("all"); }
2444                 | /*EMPTY*/                             { $$ = EMPTY; }
2445                 ;
2446
2447 opt_distinct:  DISTINCT
2448                         { $$ = make_str("distinct"); }
2449                 | DISTINCT ON '(' expr_list ')'
2450                         { $$ = cat_str(3, make_str("distinct on ("), $4, make_str(")")); }
2451                 | ALL
2452                         { $$ = make_str("all"); }
2453                 | /*EMPTY*/
2454                         { $$ = EMPTY; }
2455                 ;
2456
2457 sort_clause:  ORDER BY sortby_list
2458                         { $$ = cat2_str(make_str("order by"), $3); }
2459                 ;
2460
2461 sortby_list:  sortby                                    { $$ = $1; }
2462                 | sortby_list ',' sortby                { $$ = cat_str(3, $1, make_str(","), $3); }
2463                 ;
2464
2465 sortby: a_expr OptUseOp
2466                         { $$ = cat2_str($1, $2); }
2467                 ;
2468
2469 OptUseOp:  USING all_Op         { $$ = cat2_str(make_str("using"), $2); }
2470                 | ASC                           { $$ = make_str("asc"); }
2471                 | DESC                          { $$ = make_str("desc"); }
2472                 | /*EMPTY*/                     { $$ = EMPTY; }
2473                 ;
2474
2475 select_limit:   LIMIT select_limit_value OFFSET select_offset_value
2476                    { $$ = cat_str(4, make_str("limit"), $2, make_str("offset"), $4); }
2477                 | OFFSET select_offset_value LIMIT select_limit_value
2478                    { $$ = cat_str(4, make_str("offset"), $2, make_str("limit"), $4); }
2479                 | LIMIT select_limit_value
2480                    { $$ = cat2_str(make_str("limit"), $2); }
2481                 | OFFSET select_offset_value
2482                    { $$ = cat2_str(make_str("offset"), $2); }
2483                 | LIMIT select_limit_value ',' select_offset_value
2484                    { mmerror(PARSE_ERROR, ET_WARNING, "No longer supported LIMIT #,# syntax passed to backend."); }
2485                 ;
2486
2487 opt_select_limit:       select_limit    { $$ = $1; }
2488                 | /*EMPTY*/                                     { $$ = EMPTY; }
2489                 ;
2490
2491 select_limit_value: PosIntConst
2492                 {
2493                         if (atoi($1) < 0)
2494                                 mmerror(PARSE_ERROR, ET_ERROR, "LIMIT must not be negative");
2495                         $$ = $1;
2496                 }
2497                 | ALL   { $$ = make_str("all"); }
2498                 | PARAM { $$ = make_name(); }
2499                 ;
2500
2501 select_offset_value:    PosIntConst
2502                 {
2503                         if (atoi($1) < 0)
2504                                 mmerror(PARSE_ERROR, ET_ERROR, "OFFSET must not be negative");
2505                         $$ = $1;
2506                 }
2507                 | PARAM { $$ = make_name(); }
2508                 ;
2509
2510 /*
2511  *      jimmy bell-style recursive queries aren't supported in the
2512  *      current system.
2513  *
2514  *      ...however, recursive addattr and rename supported.  make special
2515  *      cases for these.
2516  */
2517 group_clause:  GROUP BY expr_list
2518                         { $$ = cat2_str(make_str("group by"), $3); }
2519                 | /*EMPTY*/
2520                         { $$ = EMPTY; }
2521                 ;
2522
2523 having_clause:  HAVING a_expr
2524                         { $$ = cat2_str(make_str("having"), $2); }
2525                 | /*EMPTY*/
2526                         { $$ = EMPTY; }
2527                 ;
2528
2529 for_update_clause:      FOR UPDATE update_list
2530                         { $$ = make_str("for update"); }
2531                 | FOR READ ONLY
2532                         { $$ = make_str("for read only"); }
2533                 ;
2534
2535 opt_for_update_clause: for_update_clause        { $$ = $1; }
2536                 | /* EMPTY */                                           { $$ = EMPTY; }
2537                 ;
2538
2539 update_list:  OF name_list              { $$ = cat2_str(make_str("of"), $2); }
2540                 | /* EMPTY */                   { $$ = EMPTY; }
2541                 ;
2542
2543 /*****************************************************************************
2544  *
2545  *      clauses common to all Optimizable Stmts:
2546  *              from_clause - allow list of both JOIN expressions and table names
2547  *              where_clause    - qualifications for joins or restrictions
2548  *
2549  *****************************************************************************/
2550
2551 from_clause:    FROM from_list          { $$ = cat2_str(make_str("from"), $2); }
2552                 | /* EMPTY */                           { $$ = EMPTY; }
2553                 ;
2554
2555 from_list:      from_list ',' table_ref { $$ = cat_str(3, $1, make_str(","), $3); }
2556                 | table_ref                                     { $$ = $1; }
2557                 ;
2558
2559 /*
2560  * table_ref is where an alias clause can be attached.  Note we cannot make
2561  * alias_clause have an empty production because that causes parse conflicts
2562  * between table_ref := '(' joined_table ')' alias_clause
2563  * and joined_table := '(' joined_table ')'.  So, we must have the
2564  * redundant-looking productions here instead.
2565  */
2566 table_ref:      relation_expr
2567                         { $$ = $1; }
2568                 | relation_expr alias_clause
2569                         { $$= cat2_str($1, $2); }
2570                 | select_with_parens
2571                         {mmerror(PARSE_ERROR, ET_ERROR, "sub-SELECT in FROM must have an alias");}
2572                 | select_with_parens alias_clause
2573                         { $$=cat2_str($1, $2); }
2574                 | joined_table
2575                         { $$ = $1; }
2576                 | '(' joined_table ')' alias_clause
2577                         { $$=cat_str(4, make_str("("), $2, make_str(")"), $4); }
2578                 ;
2579
2580 /*
2581  * It may seem silly to separate joined_table from table_ref, but there is
2582  * method in SQL92's madness: if you don't do it this way you get reduce-
2583  * reduce conflicts, because it's not clear to the parser generator whether
2584  * to expect alias_clause after ')' or not.  For the same reason we must
2585  * treat 'JOIN' and 'join_type JOIN' separately, rather than allowing
2586  * join_type to expand to empty; if we try it, the parser generator can't
2587  * figure out when to reduce an empty join_type right after table_ref.
2588  *
2589  * Note that a CROSS JOIN is the same as an unqualified
2590  * INNER JOIN, and an INNER JOIN/ON has the same shape
2591  * but a qualification expression to limit membership.
2592  * A NATURAL JOIN implicitly matches column names between
2593  * tables and the shape is determined by which columns are
2594  * in common. We'll collect columns during the later transformations.
2595  */
2596
2597 joined_table:  '(' joined_table ')'
2598                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2599                 | table_ref CROSS JOIN table_ref
2600                         { $$ = cat_str(3, $1, make_str("cross join"), $4); }
2601                 | table_ref UNIONJOIN table_ref
2602                         { $$ = cat_str(3, $1, make_str("unionjoin"), $3); }
2603                 | table_ref join_type JOIN table_ref join_qual
2604                         { $$ = cat_str(5, $1, $2, make_str("join"), $4, $5); }
2605                 | table_ref JOIN table_ref join_qual
2606                         { $$ = cat_str(4, $1, make_str("join"), $3, $4); }
2607                 | table_ref NATURAL join_type JOIN table_ref
2608                         { $$ = cat_str(5, $1, make_str("natural"), $3, make_str("join"), $5); }
2609                 | table_ref NATURAL JOIN table_ref
2610                         { $$ = cat_str(3, $1, make_str("natural join"), $4); }
2611                 ;
2612
2613 alias_clause:  AS ColId '(' name_list ')'
2614                         { $$ = cat_str(5, make_str("as"), $2, make_str("("), $4, make_str(")")); }
2615                 | AS ColId
2616                         { $$ = cat2_str(make_str("as"), $2); }
2617                 | ColId '(' name_list ')'
2618                         { $$ = cat_str(4, $1, make_str("("), $3, make_str(")")); }
2619                 | ColId
2620                         { $$ = $1; }
2621                 ;
2622
2623 join_type:      FULL join_outer         { $$ = cat2_str(make_str("full"), $2); }
2624                 | LEFT join_outer               { $$ = cat2_str(make_str("left"), $2); }
2625                 | RIGHT join_outer              { $$ = cat2_str(make_str("right"), $2); }
2626                 | INNER_P                               { $$ = make_str("inner"); }
2627                 ;
2628
2629 /* OUTER is just noise... */
2630 join_outer:  OUTER_P                    { $$ = make_str("outer"); }
2631                 | /*EMPTY*/                             { $$ = EMPTY;  /* no qualifiers */ }
2632                 ;
2633
2634 /* JOIN qualification clauses
2635  * Possibilities are:
2636  *      USING ( column list ) allows only unqualified column names,
2637  *                                                which must match between tables.
2638  *      ON expr allows more general qualifications.
2639  */
2640
2641 join_qual:      USING '(' name_list ')'
2642                         { $$ = cat_str(3, make_str("using ("), $3, make_str(")")); }
2643                 | ON a_expr
2644                         { $$ = cat2_str(make_str("on"), $2); }
2645                 ;
2646
2647 relation_expr:  qualified_name
2648                         { /* normal relations */ $$ = $1; }
2649                 | qualified_name '*'
2650                         { /* inheritance query */ $$ = cat2_str($1, make_str("*")); }
2651                 | ONLY qualified_name
2652                         { /* inheritance query */ $$ = cat2_str(make_str("ONLY "), $2); }
2653                 ;
2654
2655 where_clause:  WHERE a_expr             { $$ = cat2_str(make_str("where"), $2); }
2656                 | /*EMPTY*/                             { $$ = EMPTY;  /* no qualifiers */ }
2657                 ;
2658
2659
2660 /*****************************************************************************
2661  *
2662  *      Type syntax
2663  *              SQL92 introduces a large amount of type-specific syntax.
2664  *              Define individual clauses to handle these cases, and use
2665  *               the generic case to handle regular type-extensible Postgres syntax.
2666  *              - thomas 1997-10-10
2667  *
2668  *****************************************************************************/
2669
2670 Typename:  SimpleTypename opt_array_bounds
2671                         { $$ = cat2_str($1, $2.str); }
2672                 | SETOF SimpleTypename
2673                         { $$ = cat2_str(make_str("setof"), $2); }
2674                 ;
2675
2676
2677 opt_array_bounds:  '[' ']' opt_array_bounds
2678                 {
2679                         $$.index1 = 0;
2680                         $$.index2 = $3.index1;
2681                         $$.str = cat2_str(make_str("[]"), $3.str);
2682                 }
2683                 | '[' Iresult ']' opt_array_bounds
2684                 {
2685                         char *txt = mm_alloc(20L);
2686
2687                         sprintf (txt, "%d", $2);
2688                         $$.index1 = $2;
2689                         $$.index2 = $4.index1;
2690                         $$.str = cat_str(4, make_str("["), txt, make_str("]"), $4.str);
2691                 }
2692                 | /* EMPTY */
2693                 {
2694                         $$.index1 = -1;
2695                         $$.index2 = -1;
2696                         $$.str= EMPTY;
2697                 }
2698                 ;
2699
2700 Iresult:        PosIntConst                             { $$ = atol($1); }
2701                 |       '(' Iresult ')'                 { $$ = $2; }
2702                 |       Iresult '+' Iresult             { $$ = $1 + $3; }
2703                 |       Iresult '-' Iresult             { $$ = $1 - $3; }
2704                 |       Iresult '*' Iresult             { $$ = $1 * $3; }
2705                 |       Iresult '/' Iresult             { $$ = $1 / $3; }
2706                 |       Iresult '%' Iresult             { $$ = $1 % $3; }
2707                 ;
2708
2709 SimpleTypename:  ConstTypename
2710                         { $$ = $1; }
2711                 | ConstInterval opt_interval
2712                         { $$ = cat2_str($1, $2); }
2713                 | ConstInterval '(' PosIntConst ')' opt_interval
2714                         { $$ = cat_str(5, $1, make_str("("), $3, make_str(")"), $5); }
2715                 | type_name attrs
2716                         { $$ = cat2_str($1, $2);}
2717                 ;
2718
2719 ConstTypename:  Generic         { $$ = $1; }
2720                 | ConstDatetime         { $$ = $1; }
2721                 | Numeric                       { $$ = $1; }
2722                 | Bit                           { $$ = $1; }
2723                 | Character                     { $$ = $1; }
2724                 ;
2725
2726 Generic:  type_name                     { $$ = $1; }
2727                 ;
2728
2729 /* SQL92 numeric data types
2730  * Check FLOAT() precision limits assuming IEEE floating types.
2731  * Provide real DECIMAL() and NUMERIC() implementations now - Jan 1998-12-30
2732  * - thomas 1997-09-18
2733  */
2734 Numeric:  FLOAT opt_float
2735                         { $$ = cat2_str(make_str("float"), $2); }
2736                 | DOUBLE PRECISION
2737                         { $$ = make_str("double precision"); }
2738                 | DECIMAL opt_decimal
2739                         { $$ = cat2_str(make_str("decimal"), $2); }
2740                 | DEC opt_decimal
2741                         { $$ = cat2_str(make_str("dec"), $2); }
2742                 | NUMERIC opt_numeric
2743                         { $$ = cat2_str(make_str("numeric"), $2); }
2744                 ;
2745
2746 opt_float:      '(' PosIntConst ')'
2747                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2748                 | /*EMPTY*/
2749                         { $$ = EMPTY; }
2750                 ;
2751
2752 opt_numeric:  '(' PosIntConst ',' PosIntConst ')'
2753                         { $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")")); }
2754                 | '(' PosIntConst ')'
2755                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2756                 | /*EMPTY*/
2757                         { $$ = EMPTY; }
2758                 ;
2759
2760 opt_decimal:  '(' PosIntConst ',' PosIntConst ')'
2761                         { $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")")); }
2762                 | '(' PosIntConst ')'
2763                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2764                 | /*EMPTY*/
2765                         { $$ = EMPTY; }
2766                 ;
2767
2768 /*
2769  * SQL92 bit-field data types
2770  * The following implements BIT() and BIT VARYING().
2771  */
2772 Bit:  bit '(' PosIntConst ')'
2773                         { $$ = cat_str(4, $1, make_str("("), $3, make_str(")")); }
2774                 | bit
2775                         { $$ = $1; }
2776                 ;
2777
2778 bit:  BIT opt_varying
2779                         { $$ = cat2_str(make_str("bit"), $2); }
2780                 ;
2781
2782 /*
2783  * SQL92 character data types
2784  * The following implements CHAR() and VARCHAR().
2785  *                                                              - ay 6/95
2786  */
2787 Character:      character '(' PosIntConst ')' opt_charset
2788                         { $$ = cat_str(5, $1, make_str("("), $3, make_str(")"), $5); }
2789                 | character opt_charset
2790                         { $$ = cat2_str($1, $2); }
2791                 ;
2792
2793 character:      CHARACTER opt_varying
2794                         { $$ = cat2_str(make_str("character"), $2); }
2795                 | CHAR opt_varying
2796                         { $$ = cat2_str(make_str("char"), $2); }
2797                 | VARCHAR
2798                         { $$ = make_str("varchar"); }
2799                 | NATIONAL CHARACTER opt_varying
2800                         { $$ = cat2_str(make_str("national character"), $3); }
2801                 | NATIONAL CHAR opt_varying
2802                         { $$ = cat2_str(make_str("national char"), $3); }
2803                 | NCHAR opt_varying
2804                         { $$ = cat2_str(make_str("nchar"), $2); }
2805                 ;
2806
2807 opt_varying:  VARYING
2808                         { $$ = make_str("varying"); }
2809                 | /*EMPTY*/
2810                         { $$ = EMPTY; }
2811                 ;
2812
2813 opt_charset:  CHARACTER SET ColId
2814                         { $$ = cat2_str(make_str("character set"), $3); }
2815                 | /*EMPTY*/
2816                         { $$ = EMPTY; }
2817                 ;
2818
2819 opt_collate:  COLLATE ColId
2820                         { $$ = cat2_str(make_str("collate"), $2); }
2821                 | /*EMPTY*/
2822                         { $$ = EMPTY; }
2823                 ;
2824
2825 ConstDatetime:  TIMESTAMP '(' PosIntConst ')' opt_timezone
2826                         { $$ = cat_str(4, make_str("timestamp("), $3, make_str(")"), $5); }
2827                 | TIMESTAMP opt_timezone
2828                         { $$ = cat2_str(make_str("timestamp"), $2); }
2829                 | TIME '(' PosIntConst ')' opt_timezone
2830                         { $$ = cat_str(4, make_str("time("), $3, make_str(")"), $5); }
2831                 | TIME opt_timezone
2832                         { $$ = cat2_str(make_str("time"), $2); }
2833                 ;
2834
2835 ConstInterval:  INTERVAL
2836                         { $$ = make_str("interval"); }
2837                 ;
2838
2839 opt_timezone:  WITH TIME ZONE
2840                         { $$ = make_str("with time zone"); }
2841                 | WITHOUT TIME ZONE
2842                         { $$ = make_str("without time zone"); }
2843                 | /*EMPTY*/
2844                         { $$ = EMPTY; }
2845                 ;
2846
2847 opt_interval:  YEAR_P                   { $$ = make_str("year"); }
2848                 | MONTH_P                               { $$ = make_str("month"); }
2849                 | DAY_P                                 { $$ = make_str("day"); }
2850                 | HOUR_P                                { $$ = make_str("hour"); }
2851                 | MINUTE_P                              { $$ = make_str("minute"); }
2852                 | SECOND_P                              { $$ = make_str("second"); }
2853                 | YEAR_P TO MONTH_P             { $$ = make_str("year to month"); }
2854                 | DAY_P TO HOUR_P               { $$ = make_str("day to hour"); }
2855                 | DAY_P TO MINUTE_P             { $$ = make_str("day to minute"); }
2856                 | DAY_P TO SECOND_P             { $$ = make_str("day to second"); }
2857                 | HOUR_P TO MINUTE_P    { $$ = make_str("hour to minute"); }
2858                 | MINUTE_P TO SECOND_P  { $$ = make_str("minute to second"); }
2859                 | HOUR_P TO SECOND_P    { $$ = make_str("hour to second"); }
2860                 | /*EMPTY*/                             { $$ = EMPTY; }
2861                 ;
2862
2863
2864 /*****************************************************************************
2865  *
2866  *      expression grammar
2867  *
2868  *****************************************************************************/
2869
2870 /* Expressions using row descriptors
2871  * Define row_descriptor to allow yacc to break the reduce/reduce conflict
2872  *      with singleton expressions.
2873  */
2874 row_expr: '(' row_descriptor ')' IN select_with_parens
2875                         { $$ = cat_str(4, make_str("("), $2, make_str(") in "), $5); }
2876                 | '(' row_descriptor ')' NOT IN select_with_parens
2877                         { $$ = cat_str(4, make_str("("), $2, make_str(") not in "), $6); }
2878                 | '(' row_descriptor ')' all_Op sub_type select_with_parens
2879                         { $$ = cat_str(6, make_str("("), $2, make_str(")"), $4, $5, $6); }
2880                 | '(' row_descriptor ')' all_Op select_with_parens
2881                         { $$ = cat_str(5, make_str("("), $2, make_str(")"), $4, $5); }
2882                 | '(' row_descriptor ')' all_Op '(' row_descriptor ')'
2883                         { $$ = cat_str(7, make_str("("), $2, make_str(")"), $4, make_str("("), $6, make_str(")")); }
2884                 | '(' row_descriptor ')' OVERLAPS '(' row_descriptor ')'
2885                         { $$ = cat_str(5, make_str("("), $2, make_str(") overlaps ("), $6, make_str(")")); }
2886                 ;
2887
2888 row_descriptor:  row_list ',' a_expr
2889                         { $$ = cat_str(3, $1, make_str(","), $3); }
2890                 ;
2891
2892 sub_type:  ANY                                  { $$ = make_str("ANY"); }
2893                 | SOME                                  { $$ = make_str("SOME"); }
2894                 | ALL                                   { $$ = make_str("ALL"); }
2895                           ;
2896
2897
2898 row_list:  row_list ',' a_expr
2899                         { $$ = cat_str(3, $1, make_str(","), $3); }
2900                 | a_expr
2901                         { $$ = $1; }
2902                 ;
2903
2904 all_Op:  Op | MathOp;
2905
2906 MathOp: '+'                             { $$ = make_str("+"); }
2907                 | '-'                   { $$ = make_str("-"); }
2908                 | '*'                   { $$ = make_str("*"); }
2909                 | '%'                   { $$ = make_str("%"); }
2910                 | '^'                   { $$ = make_str("^"); }
2911                 | '/'                   { $$ = make_str("/"); }
2912                 | '<'                   { $$ = make_str("<"); }
2913                 | '>'                   { $$ = make_str(">"); }
2914                 | '='                   { $$ = make_str("="); }
2915                 ;
2916
2917 /* General expressions
2918  * This is the heart of the expression syntax.
2919  *
2920  * We have two expression types: a_expr is the unrestricted kind, and
2921  * b_expr is a subset that must be used in some places to avoid shift/reduce
2922  * conflicts.  For example, we can't do BETWEEN as "BETWEEN a_expr AND a_expr"
2923  * because that use of AND conflicts with AND as a boolean operator.  So,
2924  * b_expr is used in BETWEEN and we remove boolean keywords from b_expr.
2925  *
2926  * Note that '(' a_expr ')' is a b_expr, so an unrestricted expression can
2927  * always be used by surrounding it with parens.
2928  *
2929  * c_expr is all the productions that are common to a_expr and b_expr;
2930  * it's factored out just to eliminate redundant coding.
2931  */
2932
2933 a_expr:  c_expr
2934                         { $$ = $1; }
2935                 | a_expr TYPECAST Typename
2936                         { $$ = cat_str(3, $1, make_str("::"), $3); }
2937                 | a_expr AT TIME ZONE c_expr
2938                         { $$ = cat_str(3, $1, make_str("at time zone"), $5); }
2939                 /*
2940                  * These operators must be called out explicitly in order to make use
2941                  * of yacc/bison's automatic operator-precedence handling.  All other
2942                  * operator names are handled by the generic productions using "Op",
2943                  * below; and all those operators will have the same precedence.
2944                  *
2945                  * If you add more explicitly-known operators, be sure to add them
2946                  * also to b_expr and to the MathOp list above.
2947                  */
2948                 | '+' a_expr %prec UMINUS
2949                         { $$ = cat2_str(make_str("+"), $2); }
2950                 | '-' a_expr %prec UMINUS
2951                         { $$ = cat2_str(make_str("-"), $2); }
2952                 | '%' a_expr
2953                         { $$ = cat2_str(make_str("%"), $2); }
2954                 | '^' a_expr
2955                         { $$ = cat2_str(make_str("^"), $2); }
2956                 | a_expr '%'
2957                         { $$ = cat2_str($1, make_str("%")); }
2958                 | a_expr '^'
2959                         { $$ = cat2_str($1, make_str("^")); }
2960                 | a_expr '+' a_expr
2961                         { $$ = cat_str(3, $1, make_str("+"), $3); }
2962                 | a_expr '-' a_expr
2963                         { $$ = cat_str(3, $1, make_str("-"), $3); }
2964                 | a_expr '*' a_expr
2965                         { $$ = cat_str(3, $1, make_str("*"), $3); }
2966                 | a_expr '/' a_expr
2967                         { $$ = cat_str(3, $1, make_str("/"), $3); }
2968                 | a_expr '%' a_expr
2969                         { $$ = cat_str(3, $1, make_str("%"), $3); }
2970                 | a_expr '^' a_expr
2971                         { $$ = cat_str(3, $1, make_str("^"), $3); }
2972                 | a_expr '<' a_expr
2973                         { $$ = cat_str(3, $1, make_str("<"), $3); }
2974                 | a_expr '>' a_expr
2975                         { $$ = cat_str(3, $1, make_str(">"), $3); }
2976                 | a_expr '=' a_expr
2977                         { $$ = cat_str(3, $1, make_str("="), $3); }
2978                 | a_expr Op a_expr
2979                         { $$ = cat_str(3, $1, $2, $3); }
2980                 | Op a_expr
2981                         { $$ = cat2_str($1, $2); }
2982                 | a_expr Op             %prec POSTFIXOP
2983                         { $$ = cat2_str($1, $2); }
2984                 | a_expr AND a_expr
2985                         { $$ = cat_str(3, $1, make_str("and"), $3); }
2986                 | a_expr OR a_expr
2987                         { $$ = cat_str(3, $1, make_str("or"), $3); }
2988                 | NOT a_expr
2989                         { $$ = cat2_str(make_str("not"), $2); }
2990                 | a_expr LIKE a_expr
2991                         { $$ = cat_str(3, $1, make_str("like"), $3); }
2992                 | a_expr LIKE a_expr ESCAPE a_expr
2993                         { $$ = cat_str(5, $1, make_str("like"), $3, make_str("escape"), $5); }
2994                 | a_expr NOT LIKE a_expr
2995                         { $$ = cat_str(3, $1, make_str("not like"), $4); }
2996                 | a_expr NOT LIKE a_expr ESCAPE a_expr
2997                         { $$ = cat_str(5, $1, make_str("not like"), $4, make_str("escape"), $6); }
2998                 | a_expr ILIKE a_expr
2999                         { $$ = cat_str(3, $1, make_str("ilike"), $3); }
3000                 | a_expr ILIKE a_expr ESCAPE a_expr
3001                         { $$ = cat_str(5, $1, make_str("ilike"), $3, make_str("escape"), $5); }
3002                 | a_expr NOT ILIKE a_expr
3003                         { $$ = cat_str(3, $1, make_str("not ilike"), $4); }
3004                 | a_expr NOT ILIKE a_expr ESCAPE a_expr
3005                         { $$ = cat_str(5, $1, make_str("not ilike"), $4, make_str("escape"), $6); }
3006                 | a_expr ISNULL
3007                         { $$ = cat2_str($1, make_str("isnull")); }
3008                 | a_expr IS NULL_P
3009                         { $$ = cat2_str($1, make_str("is null")); }
3010                 | a_expr NOTNULL
3011                         { $$ = cat2_str($1, make_str("notnull")); }
3012                 | a_expr IS NOT NULL_P
3013                         { $$ = cat2_str($1, make_str("is not null")); }
3014                 /* IS TRUE, IS FALSE, etc used to be function calls
3015                  *      but let's make them expressions to allow the optimizer
3016                  *      a chance to eliminate them if a_expr is a constant string.
3017                  * - thomas 1997-12-22
3018                  *
3019                  *      Created BooleanTest Node type, and changed handling
3020                  *      for NULL inputs
3021                  * - jec 2001-06-18
3022                  */
3023                 | a_expr IS TRUE_P
3024                         { $$ = cat2_str($1, make_str("is true")); }
3025                 | a_expr IS NOT TRUE_P
3026                         { $$ = cat2_str($1, make_str("is not true")); }
3027                 | a_expr IS FALSE_P
3028                         { $$ = cat2_str($1, make_str("is false")); }
3029                 | a_expr IS NOT FALSE_P
3030                         { $$ = cat2_str($1, make_str("is not false")); }
3031                 | a_expr IS UNKNOWN
3032                         { $$ = cat2_str($1, make_str("is unknown")); }
3033                 | a_expr IS NOT UNKNOWN
3034                         { $$ = cat2_str($1, make_str("is not unknown")); }
3035                 | a_expr BETWEEN b_expr AND b_expr      %prec BETWEEN
3036                         { $$ = cat_str(5, $1, make_str("between"), $3, make_str("and"), $5); }
3037                 | a_expr NOT BETWEEN b_expr AND b_expr  %prec BETWEEN
3038                         { $$ = cat_str(5, $1, make_str("not between"), $4, make_str("and"), $6); }
3039                 | a_expr IN in_expr
3040                         { $$ = cat_str(3, $1, make_str(" in"), $3); }
3041                 | a_expr NOT IN in_expr
3042                         { $$ = cat_str(3, $1, make_str(" not in "), $4); }
3043                 | a_expr all_Op sub_type select_with_parens %prec Op
3044                         { $$ = cat_str(4, $1, $2, $3, $4); }
3045                 | row_expr
3046                         { $$ = $1; }
3047                 ;
3048
3049 /* Restricted expressions
3050  *
3051  * b_expr is a subset of the complete expression syntax
3052  *
3053  * Presently, AND, NOT, IS and IN are the a_expr keywords that would
3054  * cause trouble in the places where b_expr is used.  For simplicity, we
3055  * just eliminate all the boolean-keyword-operator productions from b_expr.
3056  */
3057 b_expr:  c_expr
3058                         { $$ = $1; }
3059                 | b_expr TYPECAST Typename
3060                         { $$ = cat_str(3, $1, make_str("::"), $3); }
3061                 | '-' b_expr %prec UMINUS
3062                         { $$ = cat2_str(make_str("-"), $2); }
3063                 | '%' b_expr
3064                         { $$ = cat2_str(make_str("%"), $2); }
3065                 | '^' b_expr
3066                         { $$ = cat2_str(make_str("^"), $2); }
3067                 | b_expr '%'
3068                         { $$ = cat2_str($1, make_str("%")); }
3069                 | b_expr '^'
3070                         { $$ = cat2_str($1, make_str("^")); }
3071                 | b_expr '+' b_expr
3072                         { $$ = cat_str(3, $1, make_str("+"), $3); }
3073                 | b_expr '-' b_expr
3074                         { $$ = cat_str(3, $1, make_str("-"), $3); }
3075                 | b_expr '*' b_expr
3076                         { $$ = cat_str(3, $1, make_str("*"), $3); }
3077                 | b_expr '/' b_expr
3078                         { $$ = cat_str(3, $1, make_str("/"), $3); }
3079                 | b_expr '%' b_expr
3080                         { $$ = cat_str(3, $1, make_str("%"), $3); }
3081                 | b_expr '^' b_expr
3082                         { $$ = cat_str(3, $1, make_str("^"), $3); }
3083                 | b_expr '<' b_expr
3084                         { $$ = cat_str(3, $1, make_str("<"), $3); }
3085                 | b_expr '>' b_expr
3086                         { $$ = cat_str(3, $1, make_str(">"), $3); }
3087                 | b_expr '=' b_expr
3088                         { $$ = cat_str(3, $1, make_str("="), $3); }
3089                 | b_expr Op b_expr
3090                         { $$ = cat_str(3, $1, $2, $3); }
3091                 | Op b_expr
3092                         { $$ = cat2_str($1, $2); }
3093                 | b_expr Op             %prec POSTFIXOP
3094                         { $$ = cat2_str($1, $2); }
3095                 ;
3096
3097 /*
3098  * Productions that can be used in both a_expr and b_expr.
3099  *
3100  * Note: productions that refer recursively to a_expr or b_expr mostly
3101  * cannot appear here.  However, it's OK to refer to a_exprs that occur
3102  * inside parentheses, such as function arguments; that cannot introduce
3103  * ambiguity to the b_expr syntax.
3104  */
3105 c_expr: columnref 
3106                         { $$ = $1;      }
3107                 | AexprConst
3108                         { $$ = $1;      }
3109                 | PARAM attrs opt_indirection
3110                         { $$ = cat_str(3, make_str("param"), $2, $3); }
3111                 | '(' a_expr ')'
3112                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3113                 | '(' a_expr ')' attrs opt_indirection
3114                         { $$ = cat_str(5, make_str("("), $2, make_str(")"), $4, $5); }
3115                 | CAST '(' a_expr AS Typename ')'
3116                         { $$ = cat_str(5, make_str("cast("), $3, make_str("as"), $5, make_str(")")); }
3117                 | case_expr
3118                         { $$ = $1; }
3119                 | func_name '(' ')'
3120                         { $$ = cat2_str($1, make_str("()"));    }
3121                 | func_name '(' expr_list ')'
3122                         { $$ = cat_str(4, $1, make_str("("), $3, make_str(")"));        }
3123                 | func_name '(' ALL expr_list ')'
3124                         { $$ = cat_str(4, $1, make_str("( all"), $4, make_str(")"));    }
3125                 | func_name '(' DISTINCT expr_list ')'
3126                         { $$ = cat_str(4, $1, make_str("( distinct"), $4, make_str(")"));  }
3127                 | func_name '(' '*' ')'
3128                         { $$ = cat2_str($1, make_str("(*)")); }
3129                 | CURRENT_DATE
3130                         { $$ = make_str("current_date"); }
3131                 | CURRENT_TIME opt_empty_parentheses
3132                         { $$ = cat2_str(make_str("current_time"), $2); }
3133                 | CURRENT_TIME '(' PosIntConst ')'
3134                         { $$ = make_str("current_time"); }
3135                 | CURRENT_TIMESTAMP opt_empty_parentheses
3136                         { $$ = cat2_str(make_str("current_timestamp"), $2); }
3137                 | CURRENT_TIMESTAMP '(' PosIntConst ')'
3138                         { $$ = make_str("current_timestamp"); }
3139                 | CURRENT_USER opt_empty_parentheses
3140                         { $$ = cat2_str(make_str("current_user"), $2); }
3141                 | SESSION_USER opt_empty_parentheses
3142                         { $$ = cat2_str(make_str("session_user"), $2); }
3143                 | USER opt_empty_parentheses
3144                         { $$ = cat2_str(make_str("user"), $2); }
3145                 | EXTRACT '(' extract_list ')'
3146                         { $$ = cat_str(3, make_str("extract("), $3, make_str(")")); }
3147                 | POSITION '(' position_list ')'
3148                         { $$ = cat_str(3, make_str("position("), $3, make_str(")")); }
3149                 | SUBSTRING '(' substr_list ')'
3150                         { $$ = cat_str(3, make_str("substring("), $3, make_str(")")); }
3151                 /* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
3152                 | TRIM '(' BOTH trim_list ')'
3153                         { $$ = cat_str(3, make_str("trim(both"), $4, make_str(")")); }
3154                 | TRIM '(' LEADING trim_list ')'
3155                         { $$ = cat_str(3, make_str("trim(leading"), $4, make_str(")")); }
3156                 | TRIM '(' TRAILING trim_list ')'
3157                         { $$ = cat_str(3, make_str("trim(trailing"), $4, make_str(")")); }
3158                 | TRIM '(' trim_list ')'
3159                         { $$ = cat_str(3, make_str("trim("), $3, make_str(")")); }
3160                 | select_with_parens    %prec UMINUS
3161                         { $$ = $1; }
3162                 | EXISTS select_with_parens
3163                         { $$ = cat2_str(make_str("exists"), $2); }
3164                 ;
3165 /*
3166  * This used to use ecpg_expr, but since there is no shift/reduce conflict
3167  * anymore, we can remove ecpg_expr. - MM
3168  */
3169 opt_indirection:  '[' a_expr ']' opt_indirection
3170                         { $$ = cat_str(4, make_str("["), $2, make_str("]"), $4); }
3171                 | '[' a_expr ':' a_expr ']' opt_indirection
3172                         { $$ = cat_str(6, make_str("["), $2, make_str(":"), $4, make_str("]"), $6); }
3173                 | /* EMPTY */
3174                         { $$ = EMPTY; }
3175                 ;
3176
3177 expr_list:      a_expr
3178                         { $$ = $1; }
3179                 | expr_list ',' a_expr
3180                         { $$ = cat_str(3, $1, make_str(","), $3); }
3181                 | expr_list USING a_expr
3182                         { $$ = cat_str(3, $1, make_str("using"), $3); }
3183                 ;
3184
3185 extract_list:  extract_arg FROM a_expr
3186                         { $$ = cat_str(3, $1, make_str("from"), $3); }
3187                 | /* EMPTY */
3188                         { $$ = EMPTY; }
3189                 ;
3190
3191 /* Allow delimited string SCONST in extract_arg as an SQL extension.
3192  * - thomas 2001-04-12
3193  */
3194
3195 extract_arg:  IDENT                             { $$ = $1; }
3196                 | YEAR_P                                { $$ = make_str("year"); }
3197                 | MONTH_P                               { $$ = make_str("month"); }
3198                 | DAY_P                                 { $$ = make_str("day"); }
3199                 | HOUR_P                                { $$ = make_str("hour"); }
3200                 | MINUTE_P                              { $$ = make_str("minute"); }
3201                 | SECOND_P                              { $$ = make_str("second"); }
3202                 | StringConst                   { $$ = $1; }
3203                 ;
3204
3205 /* position_list uses b_expr not a_expr to avoid conflict with general IN */
3206 position_list:  b_expr IN b_expr
3207                         { $$ = cat_str(3, $1, make_str("in"), $3); }
3208                 | /* EMPTY */
3209                         { $$ = EMPTY; }
3210                 ;
3211
3212 substr_list:  a_expr substr_from substr_for
3213                         { $$ = cat_str(3, $1, $2, $3); }
3214                 | a_expr substr_for substr_from
3215                         { $$ = cat_str(3, $1, $2, $3); }
3216                 | a_expr substr_from
3217                         { $$ = cat2_str($1, $2); }
3218                 | a_expr substr_for
3219                         { $$ = cat2_str($1, $2); }
3220                 | expr_list
3221                         { $$ = $1; }
3222                 | /* EMPTY */
3223                         { $$ = EMPTY; }
3224                 ;
3225
3226 substr_from:  FROM a_expr
3227                         { $$ = cat2_str(make_str("from"), $2); }
3228                 ;
3229
3230 substr_for:  FOR a_expr
3231                         { $$ = cat2_str(make_str("for"), $2); }
3232                 ;
3233
3234 trim_list:      a_expr FROM expr_list
3235                         { $$ = cat_str(3, $1, make_str("from"), $3); }
3236                 | FROM expr_list
3237                         { $$ = cat2_str(make_str("from"), $2); }
3238                 | expr_list
3239                         { $$ = $1; }
3240                 ;
3241
3242 in_expr:  select_with_parens
3243                         { $$ = $1; }
3244                 | '(' in_expr_nodes ')'
3245                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3246                 ;
3247
3248 in_expr_nodes:  a_expr
3249                         { $$ = $1; }
3250                 | in_expr_nodes ',' a_expr
3251                         { $$ = cat_str(3, $1, make_str(","), $3);}
3252                 ;
3253
3254 /* Case clause
3255  * Define SQL92-style case clause.
3256  * Allow all four forms described in the standard:
3257  * - Full specification
3258  *      CASE WHEN a = b THEN c ... ELSE d END
3259  * - Implicit argument
3260  *      CASE a WHEN b THEN c ... ELSE d END
3261  * - Conditional NULL
3262  *      NULLIF(x,y)
3263  *      same as CASE WHEN x = y THEN NULL ELSE x END
3264  * - Conditional substitution from list, use first non-null argument
3265  *      COALESCE(a,b,...)
3266  * same as CASE WHEN a IS NOT NULL THEN a WHEN b IS NOT NULL THEN b ... END
3267  * - thomas 1998-11-09
3268  */
3269 case_expr:      CASE case_arg when_clause_list case_default END_TRANS
3270                         { $$ = cat_str(5, make_str("case"), $2, $3, $4, make_str("end")); }
3271                 | NULLIF '(' a_expr ',' a_expr ')'
3272                         { $$ = cat_str(5, make_str("nullif("), $3, make_str(","), $5, make_str(")")); }
3273                 | COALESCE '(' expr_list ')'
3274                         { $$ = cat_str(3, make_str("coalesce("), $3, make_str(")")); }
3275                 ;
3276
3277 when_clause_list:  when_clause_list when_clause
3278                         { $$ = cat2_str($1, $2); }
3279                 | when_clause
3280                         { $$ = $1; }
3281                 ;
3282
3283 when_clause:  WHEN a_expr THEN a_expr
3284                         { $$ = cat_str(4, make_str("when"), $2, make_str("then"), $4); }
3285                 ;
3286
3287 case_default:  ELSE a_expr
3288                         { $$ = cat2_str(make_str("else"), $2); }
3289                 | /*EMPTY*/
3290                         { $$ = EMPTY; }
3291                 ;
3292
3293 case_arg:  a_expr                       { $$ = $1; }
3294                 | /*EMPTY*/                     { $$ = EMPTY; }
3295                 ;
3296
3297 columnref: relation_name opt_indirection
3298                 { $$ = cat2_str($1, $2); }
3299         | dotted_name opt_indirection
3300                 { $$ = cat2_str($1, $2); }
3301         ;
3302         
3303 dotted_name: relation_name attrs 
3304                         { $$ = cat2_str($1, $2); }
3305                 ;
3306
3307 attrs: '.' attr_name
3308                         { $$ = cat2_str(make_str("."), $2); }
3309                 | '.' '*'
3310                         { $$ = make_str(".*"); }
3311                 | '.' attr_name attrs
3312                         { $$ = cat_str(3, make_str("."), $2, $3); }
3313                 ;
3314
3315 opt_empty_parentheses: '(' ')'  { $$ = make_str("()"); }
3316                 | /*EMPTY*/                             { $$ = EMPTY; }
3317                 ;
3318
3319
3320 /*****************************************************************************
3321  *
3322  *      target lists
3323  *
3324  *****************************************************************************/
3325
3326 /* Target lists as found in SELECT ... and INSERT VALUES ( ... ) */
3327 target_list:  target_list ',' target_el
3328                         { $$ = cat_str(3, $1, make_str(","), $3);  }
3329                 | target_el
3330                         { $$ = $1;      }
3331                 ;
3332
3333 /* AS is not optional because shift/red conflict with unary ops */
3334 target_el:      a_expr AS ColLabel
3335                         { $$ = cat_str(3, $1, make_str("as"), $3); }
3336                 | a_expr
3337                         { $$ = $1; }
3338                 | '*'
3339                         { $$ = make_str("*"); }
3340                 ;
3341
3342 /* Target list as found in UPDATE table SET ... */
3343 update_target_list:  update_target_list ',' update_target_el
3344                         { $$ = cat_str(3, $1, make_str(","),$3);        }
3345                 | update_target_el
3346                         { $$ = $1;      }
3347                 | '*'
3348                         { $$ = make_str("*"); }
3349                 ;
3350
3351 update_target_el:  ColId opt_indirection '=' a_expr
3352                         { $$ = cat_str(4, $1, $2, make_str("="), $4); }
3353                 ;
3354
3355 insert_target_list:  insert_target_list ',' insert_target_el
3356                                 {       $$ = cat_str(3, $1, make_str(","), $3);  }
3357                 | insert_target_el
3358                                 {       $$ = $1;  }
3359                 ;
3360
3361 insert_target_el:  target_el    {       $$ = $1;  }
3362                 | DEFAULT       {       $$ = make_str("default"); }
3363                 ;
3364
3365
3366 /*****************************************************************************
3367  *
3368  *         Names and constants
3369  *
3370  *****************************************************************************/
3371
3372 relation_name:  SpecialRuleRelation     { $$ = $1; }
3373                 | ColId                 { $$ = $1; }
3374                 ;
3375
3376 qualified_name_list:  qualified_name
3377                                 { $$ = $1; }
3378                 | qualified_name_list ',' qualified_name
3379                                 { $$ = cat_str(3, $1, make_str(","), $3); }
3380                 ;
3381
3382 qualified_name: ColId
3383                 { $$ = $1; }
3384                 | ColId '.' ColId
3385                 { $$ = cat_str(3, $1, make_str("."), $3); }
3386                 | ColId '.' ColId '.' ColId
3387                 { $$ = cat_str(5, $1, make_str("."), $3, make_str("."), $5); }
3388                 ;
3389
3390 name_list:  name
3391                         { $$ = $1; }
3392                 | name_list ',' name
3393                         { $$ = cat_str(3, $1, make_str(","), $3); }
3394                 ;
3395
3396
3397 name:                                   ColId                   { $$ = $1; };
3398 database_name:                  ColId                   { $$ = $1; };
3399 access_method:                  ColId                   { $$ = $1; };
3400 attr_name:                              ColId                   { $$ = $1; };
3401 class:                                  ColId                   { $$ = $1; };
3402 index_name:                             ColId                   { $$ = $1; };
3403
3404 file_name:                              StringConst             { $$ = $1; };
3405
3406 /* func_name will soon return a List ... but not yet */
3407 /*
3408 func_name: function_name
3409                         { $$ = makeList1(makeString($1)); }
3410                 | dotted_name
3411                         { $$ = $1; }
3412                 ;
3413 */
3414 func_name: function_name
3415                         { $$ = $1; }
3416                 | dotted_name
3417                         { $$ = $1; }
3418                 ;
3419
3420
3421 /* Constants
3422  * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
3423  */
3424 AexprConst:  PosAllConst
3425                         { $$ = $1; }
3426                 | ConstTypename StringConst
3427                         { $$ = cat2_str($1, $2); }
3428                 | ConstInterval StringConst opt_interval
3429                         { $$ = cat_str(3, $1, $2, $3); }
3430                 | ConstInterval  '(' PosIntConst ')' StringConst opt_interval
3431                         { $$ = cat_str(6, $1, make_str("("), $3, make_str(")"), $5, $6); }
3432                 | PARAM opt_indirection 
3433                         { $$ = cat2_str(make_str("param"), $2); }
3434                 | TRUE_P
3435                         { $$ = make_str("true"); }
3436                 | FALSE_P
3437                         { $$ = make_str("false"); }
3438                 | NULL_P
3439                         { $$ = make_str("null"); }
3440                 | civarind
3441                         { $$ = make_str("?"); }
3442                 ;
3443
3444 Iconst:  ICONST                         { $$ = make_name();};
3445 Fconst:  FCONST                         { $$ = make_name();};
3446 Bitconst:  BITCONST                     { $$ = make_name();};
3447 Sconst:  SCONST
3448                 {
3449                         $$ = (char *)mm_alloc(strlen($1) + 3);
3450                         $$[0]='\'';
3451                                         strcpy($$+1, $1);
3452                         $$[strlen($1)+2]='\0';
3453                         $$[strlen($1)+1]='\'';
3454                         free($1);
3455                 }
3456                 ;
3457
3458 PosIntConst:    Iconst          { $$ = $1; }
3459                 | civar                         { $$ = make_str("?"); }
3460                 ;
3461
3462 IntConst:       PosIntConst             { $$ = $1; }
3463                 | '-' PosIntConst       { $$ = cat2_str(make_str("-"), $2); }
3464                 ;
3465
3466 StringConst:    Sconst          { $$ = $1; }
3467                 | civar                         { $$ = make_str("?"); }
3468                 ;
3469
3470 PosIntStringConst:      Iconst  { $$ = $1; }
3471                 | Sconst                        { $$ = $1; }
3472                 | civar                         { $$ = make_str("?"); }
3473                 ;
3474
3475 NumConst:       Fconst                  { $$ = $1; }
3476                 | Iconst                        { $$ = $1; }
3477                 | '-' Fconst            { $$ = cat2_str(make_str("-"), $2); }
3478                 | '-' Iconst            { $$ = cat2_str(make_str("-"), $2); }
3479                 | civar                         { $$ = make_str("?"); }
3480                 ;
3481
3482 AllConst:       Sconst                  { $$ = $1; }
3483                 | NumConst                      { $$ = $1; }
3484                 ;
3485
3486 PosAllConst:    Sconst          { $$ = $1; }
3487                 | Fconst                        { $$ = $1; }
3488                 | Iconst                        { $$ = $1; }
3489                 | Bitconst                      { $$ = $1; }
3490                 | civar                         { $$ = make_str("?"); }
3491                 ;
3492
3493 UserId:  ColId                          { $$ = $1;};
3494
3495 SpecialRuleRelation:  OLD
3496                 {
3497                         if (!QueryIsRule)
3498                                 mmerror(PARSE_ERROR, ET_ERROR, "OLD used in non-rule query");
3499
3500                         $$ = make_str("old");
3501                 }
3502                 | NEW
3503                 {
3504                         if (!QueryIsRule)
3505                                 mmerror(PARSE_ERROR, ET_ERROR, "NEW used in non-rule query");
3506
3507                         $$ = make_str("new");
3508                 }
3509                 ;
3510
3511 /*
3512  * and now special embedded SQL stuff
3513  */
3514
3515 /*
3516  * the exec sql connect statement: connect to the given database
3517  */
3518 ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user
3519                         { $$ = cat_str(5, $3, make_str(","), $5, make_str(","), $4); }
3520                 | SQL_CONNECT TO DEFAULT
3521                         { $$ = make_str("NULL,NULL,NULL,\"DEFAULT\""); }
3522                   /* also allow ORACLE syntax */
3523                 | SQL_CONNECT ora_user
3524                         { $$ = cat_str(3, make_str("NULL,"), $2, make_str(",NULL")); }
3525                 ;
3526
3527 connection_target: database_name opt_server opt_port
3528                 {
3529                         /* old style: dbname[@server][:port] */
3530                         if (strlen($2) > 0 && *($2) != '@')
3531                         {
3532                                 sprintf(errortext, "Expected '@', found '%s'", $2);
3533                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
3534                         }
3535
3536                         $$ = make3_str(make_str("\""), make3_str($1, $2, $3), make_str("\""));
3537                 }
3538                 |  db_prefix ':' server opt_port '/' database_name opt_options
3539                 {
3540                         /* new style: <tcp|unix>:postgresql://server[:port][/dbname] */
3541                         if (strncmp($1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp($1, "tcp:postgresql", strlen("tcp:postgresql")) != 0)
3542                         {
3543                                 sprintf(errortext, "only protocols 'tcp' and 'unix' and database type 'postgresql' are supported");
3544                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
3545                         }
3546
3547                         if (strncmp($3, "//", strlen("//")) != 0)
3548                         {
3549                                 sprintf(errortext, "Expected '://', found '%s'", $3);
3550                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
3551                         }
3552
3553                         if (strncmp($1, "unix", strlen("unix")) == 0 &&
3554                                 strncmp($3 + strlen("//"), "localhost", strlen("localhost")) != 0 &&
3555                                 strncmp($3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0)
3556                         {
3557                                 sprintf(errortext, "unix domain sockets only work on 'localhost' but not on '%9.9s'", $3 + strlen("//"));
3558                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
3559                         }
3560
3561                         $$ = make3_str(make3_str(make_str("\""), $1, make_str(":")), $3, make3_str(make3_str($4, make_str("/"), $6),    $7, make_str("\"")));
3562                 }
3563                 | StringConst
3564                 {
3565                         if ($1[0] == '\"')
3566                                 $$ = $1;
3567                         else if (strcmp($1, "?") == 0) /* variable */
3568                         {
3569                                 enum ECPGttype type = argsinsert->variable->type->type;
3570
3571                                 /* if array see what's inside */
3572                                 if (type == ECPGt_array)
3573                                         type = argsinsert->variable->type->u.element->type;
3574
3575                                 /* handle varchars */
3576                                 if (type == ECPGt_varchar)
3577                                         $$ = make2_str(mm_strdup(argsinsert->variable->name), make_str(".arr"));
3578                                 else
3579                                         $$ = mm_strdup(argsinsert->variable->name);
3580                         }
3581                         else
3582                                 $$ = make3_str(make_str("\""), $1, make_str("\""));
3583                 }
3584                 ;
3585
3586 db_prefix: ident cvariable
3587                 {
3588                         if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0)
3589                         {
3590                                 sprintf(errortext, "Expected 'postgresql', found '%s'", $2);
3591                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
3592                         }
3593
3594                         if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0)
3595                         {
3596                                 sprintf(errortext, "Illegal connection type %s", $1);
3597                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
3598                         }
3599
3600                         $$ = make3_str($1, make_str(":"), $2);
3601                 }
3602                 ;
3603
3604 server: Op server_name
3605                 {
3606                         if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0)
3607                         {
3608                                 sprintf(errortext, "Expected '@' or '://', found '%s'", $1);
3609                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
3610                         }
3611
3612                         $$ = make2_str($1, $2);
3613                 }
3614                 ;
3615
3616 opt_server: server                      { $$ = $1; }
3617                 | /*EMPTY*/                     { $$ = EMPTY; }
3618                 ;
3619
3620 server_name: ColId                                      { $$ = $1; }
3621                 | ColId '.' server_name         { $$ = make3_str($1, make_str("."), $3); }
3622                 | IP                                            { $$ = make_name(); }
3623                 ;
3624
3625 opt_port: ':' PosIntConst       { $$ = make2_str(make_str(":"), $2); }
3626                 | /*EMPTY*/                     { $$ = EMPTY; }
3627                 ;
3628
3629 opt_connection_name: AS connection_target { $$ = $2; }
3630                 | /*EMPTY*/                     { $$ = make_str("NULL"); }
3631                 ;
3632
3633 opt_user: USER ora_user         { $$ = $2; }
3634                 | /*EMPTY*/                     { $$ = make_str("NULL,NULL"); }
3635                 ;
3636
3637 ora_user: user_name
3638                         { $$ = cat2_str($1, make_str(", NULL")); }
3639                 | user_name '/' user_name
3640                         { $$ = cat_str(3, $1, make_str(","), $3); }
3641                 | user_name SQL_IDENTIFIED BY user_name
3642                         { $$ = cat_str(3, $1, make_str(","), $4); }
3643                 | user_name USING user_name
3644                         { $$ = cat_str(3, $1, make_str(","), $3); }
3645                 ;
3646
3647 user_name: UserId
3648                 {
3649                         if ($1[0] == '\"')
3650                                 $$ = $1;
3651                         else
3652                                 $$ = make3_str(make_str("\""), $1, make_str("\""));
3653                 }
3654                 | StringConst
3655                 {
3656                         if ($1[0] == '\"')
3657                                 $$ = $1;
3658                         else if (strcmp($1, "?") == 0) /* variable */
3659                         {
3660                                 enum ECPGttype type = argsinsert->variable->type->type;
3661
3662                                 /* if array see what's inside */
3663                                 if (type == ECPGt_array)
3664                                         type = argsinsert->variable->type->u.element->type;
3665
3666                                 /* handle varchars */
3667                                 if (type == ECPGt_varchar)
3668                                         $$ = make2_str(mm_strdup(argsinsert->variable->name), make_str(".arr"));
3669                                 else
3670                                         $$ = mm_strdup(argsinsert->variable->name);
3671                         }
3672                         else
3673                                 $$ = make3_str(make_str("\""), $1, make_str("\""));
3674                 }
3675                 ;
3676
3677 char_variable: cvariable
3678                 {
3679                         /* check if we have a char variable */
3680                         struct variable *p = find_variable($1);
3681                         enum ECPGttype type = p->type->type;
3682
3683                         /* if array see what's inside */
3684                         if (type == ECPGt_array)
3685                                 type = p->type->u.element->type;
3686
3687                         switch (type)
3688                         {
3689                                 case ECPGt_char:
3690                                 case ECPGt_unsigned_char:
3691                                         $$ = $1;
3692                                         break;
3693                                 case ECPGt_varchar:
3694                                         $$ = make2_str($1, make_str(".arr"));
3695                                         break;
3696                                 default:
3697                                         mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype");
3698                                         break;
3699                         }
3700                 }
3701                 ;
3702
3703 opt_options: Op ColId
3704                 {
3705                         if (strlen($1) == 0)
3706                                 mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
3707
3708                         if (strcmp($1, "?") != 0)
3709                         {
3710                                 sprintf(errortext, "unrecognised token '%s'", $1);
3711                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
3712                         }
3713
3714                         $$ = make2_str(make_str("?"), $2);
3715                 }
3716                 | /*EMPTY*/     { $$ = EMPTY; }
3717                 ;
3718
3719 /*
3720  * Declare a prepared cursor. The syntax is different from the standard
3721  * declare statement, so we create a new rule.
3722  */
3723 ECPGCursorStmt:  DECLARE name opt_cursor CURSOR FOR ident
3724                 {
3725                         struct cursor *ptr, *this;
3726                         struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
3727
3728                         for (ptr = cur; ptr != NULL; ptr = ptr->next)
3729                         {
3730                                 if (strcmp($2, ptr->name) == 0)
3731                                 {
3732                                                 /* re-definition is a bug */
3733                                         sprintf(errortext, "cursor %s already defined", $2);
3734                                         mmerror(PARSE_ERROR, ET_ERROR, errortext);
3735                                 }
3736                         }
3737
3738                         this = (struct cursor *) mm_alloc(sizeof(struct cursor));
3739
3740                         /* initial definition */
3741                         this->next = cur;
3742                         this->name = $2;
3743                         this->connection = connection;
3744                         this->command =  cat_str(4, make_str("declare"), mm_strdup($2), $3, make_str("cursor for ?"));
3745                         this->argsresult = NULL;
3746
3747                         thisquery->type = &ecpg_query;
3748                         thisquery->brace_level = 0;
3749                         thisquery->next = NULL;
3750                         thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(\"\")") + strlen($6));
3751                         sprintf(thisquery->name, "ECPGprepared_statement(\"%s\")", $6);
3752
3753                         this->argsinsert = NULL;
3754                         add_variable(&(this->argsinsert), thisquery, &no_indicator);
3755
3756                         cur = this;
3757
3758                         $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
3759                 }
3760                 ;
3761
3762 /*
3763  * the exec sql deallocate prepare command to deallocate a previously
3764  * prepared statement
3765  */
3766 ECPGDeallocate: SQL_DEALLOCATE SQL_PREPARE ident
3767                         { $$ = cat_str(3, make_str("ECPGdeallocate(__LINE__, \""), $3, make_str("\");")); };
3768
3769 /*
3770  * variable declaration inside the exec sql declare block
3771  */
3772 ECPGDeclaration: sql_startdeclare
3773                 { fputs("/* exec sql begin declare section */", yyout); }
3774                 var_type_declarations sql_enddeclare
3775                 {
3776                         fprintf(yyout, "%s/* exec sql end declare section */", $3);
3777                         free($3);
3778                         output_line_number();
3779                 }
3780                 ;
3781
3782 sql_startdeclare: ecpgstart BEGIN_TRANS DECLARE SQL_SECTION ';' {};
3783
3784 sql_enddeclare: ecpgstart END_TRANS DECLARE SQL_SECTION ';' {};
3785
3786 var_type_declarations:  /*EMPTY*/                       { $$ = EMPTY; }
3787                 | vt_declarations                       { $$ = $1; }
3788                 ;
3789
3790 vt_declarations:  var_declaration                       { $$ = $1; }
3791                 | type_declaration                      { $$ = $1; }
3792                 | vt_declarations var_declaration       { $$ = cat2_str($1, $2); }
3793                 | vt_declarations type_declaration      { $$ = cat2_str($1, $2); }
3794                 ;
3795
3796 variable_declarations:  var_declaration                         { $$ = $1; }
3797                 | variable_declarations var_declaration         { $$ = cat2_str($1, $2); }
3798                 ;
3799
3800 type_declaration: S_TYPEDEF
3801         {
3802                 /* reset this variable so we see if there was */
3803                 /* an initializer specified */
3804                 initializer = 0;
3805         }
3806         type opt_pointer ECPGColLabel opt_type_array_bounds ';' 
3807         {
3808                 /* add entry to list */
3809                 struct typedefs *ptr, *this;
3810                 int dimension = $6.index1;
3811                 int length = $6.index2;
3812
3813                 if (($3.type_enum == ECPGt_struct ||
3814                      $3.type_enum == ECPGt_union) &&
3815                     initializer == 1)
3816                 {
3817                         mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in typedef command");
3818
3819                 }
3820                 else
3821                 {
3822                         for (ptr = types; ptr != NULL; ptr = ptr->next)
3823                         {
3824                                 if (strcmp($5, ptr->name) == 0)
3825                                 {
3826                                         /* re-definition is a bug */
3827                                         sprintf(errortext, "Type %s already defined", $5);
3828                                         mmerror(PARSE_ERROR, ET_ERROR, errortext);
3829                                 }
3830                         }
3831
3832                         adjust_array($3.type_enum, &dimension, &length, $3.type_dimension, $3.type_index, *$4?1:0);
3833
3834                         this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
3835
3836                         /* initial definition */
3837                         this->next = types;
3838                         this->name = $5;
3839                         this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
3840                         this->type->type_enum = $3.type_enum;
3841                         this->type->type_str = mm_strdup($5);
3842                         this->type->type_dimension = dimension; /* dimension of array */
3843                         this->type->type_index = length;    /* lenght of string */
3844                         this->type->type_sizeof = ECPGstruct_sizeof;
3845                         this->struct_member_list = ($3.type_enum == ECPGt_struct || $3.type_enum == ECPGt_union) ?
3846                                 struct_member_list[struct_level] : NULL;
3847
3848                         if ($3.type_enum != ECPGt_varchar &&
3849                             $3.type_enum != ECPGt_char &&
3850                             $3.type_enum != ECPGt_unsigned_char &&
3851                             this->type->type_index >= 0)
3852                                 mmerror(PARSE_ERROR, ET_ERROR, "No multi-dimensional array support for simple data types");
3853
3854                         types = this;
3855                 }
3856
3857                 fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4?"*":"", $5, $6.str);
3858                 output_line_number();
3859                 $$ = make_str("");
3860         };
3861
3862 var_declaration: storage_clause storage_modifier
3863                 {
3864                         actual_storage[struct_level] = cat2_str(mm_strdup($1), mm_strdup($2));
3865                         actual_startline[struct_level] = hashline_number();
3866                 }
3867                 type
3868                 {
3869                         actual_type[struct_level].type_enum = $4.type_enum;
3870                         actual_type[struct_level].type_dimension = $4.type_dimension;
3871                         actual_type[struct_level].type_index = $4.type_index;
3872                         actual_type[struct_level].type_sizeof = $4.type_sizeof;
3873
3874                         /* we do not need the string "varchar" for output */
3875                         /* so replace it with an empty string */
3876                         if ($4.type_enum == ECPGt_varchar)
3877                         {
3878                                 free($4.type_str);
3879                                 $4.type_str=EMPTY;
3880                         }
3881                 }
3882                 variable_list ';'
3883                 {
3884                         $$ = cat_str(6, actual_startline[struct_level], $1, $2, $4.type_str, $6, make_str(";\n"));
3885                 }
3886                 ;
3887
3888 storage_clause : S_EXTERN               { $$ = make_str("extern"); }
3889                 | S_STATIC                              { $$ = make_str("static"); }
3890                 | S_REGISTER                    { $$ = make_str("register"); }
3891                 | S_AUTO                                { $$ = make_str("auto"); }
3892                 | /*EMPTY*/                             { $$ = EMPTY; }
3893                 ;
3894
3895 storage_modifier : S_CONST              { $$ = make_str("const"); }
3896                 | S_VOLATILE                    { $$ = make_str("volatile"); }
3897                 | /*EMPTY*/                             { $$ = EMPTY; }
3898                 ;
3899
3900 type: simple_type
3901                 {
3902                         $$.type_enum = $1;
3903                         $$.type_str = mm_strdup(ECPGtype_name($1));
3904                         $$.type_dimension = -1;
3905                         $$.type_index = -1;
3906                         $$.type_sizeof = NULL;
3907                 }
3908                 | struct_type
3909                 {
3910                         $$.type_enum = ECPGt_struct;
3911                         $$.type_str = $1;
3912                         $$.type_dimension = -1;
3913                         $$.type_index = -1;
3914                         $$.type_sizeof = ECPGstruct_sizeof;
3915                 }
3916                 | union_type
3917                 {
3918                         $$.type_enum = ECPGt_union;
3919                         $$.type_str = $1;
3920                         $$.type_dimension = -1;
3921                         $$.type_index = -1;
3922                         $$.type_sizeof = NULL;
3923                 }
3924                 | enum_type
3925                 {
3926                         $$.type_str = $1;
3927                         $$.type_enum = ECPGt_int;
3928                         $$.type_dimension = -1;
3929                         $$.type_index = -1;
3930                         $$.type_sizeof = NULL;
3931                 }
3932                 | ECPGColLabel
3933                 {
3934                         /*
3935                          * Check for type names that the SQL grammar treats as
3936                          * unreserved keywords
3937                          */
3938                         if (strcmp($1, "varchar") == 0)
3939                         {
3940                                 $$.type_enum = ECPGt_varchar;
3941                                 $$.type_str = make_str("varchar");
3942                                 $$.type_dimension = -1;
3943                                 $$.type_index = -1;
3944                                 $$.type_sizeof = NULL;
3945                         }
3946                         else if (strcmp($1, "float") == 0)
3947                         {
3948                                 $$.type_enum = ECPGt_float;
3949                                 $$.type_str = make_str("float");
3950                                 $$.type_dimension = -1;
3951                                 $$.type_index = -1;
3952                                 $$.type_sizeof = NULL;
3953                         }
3954                         else if (strcmp($1, "double") == 0)
3955                         {
3956                                 $$.type_enum = ECPGt_double;
3957                                 $$.type_str = make_str("double");
3958                                 $$.type_dimension = -1;
3959                                 $$.type_index = -1;
3960                                 $$.type_sizeof = NULL;
3961                         }
3962                         else
3963                         {
3964                                 /* this is for typedef'ed types */
3965                                 struct typedefs *this = get_typedef($1);
3966
3967                                 $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
3968                                 $$.type_enum = this->type->type_enum;
3969                                 $$.type_dimension = this->type->type_dimension;
3970                                 $$.type_index = this->type->type_index;
3971                                 $$.type_sizeof = this->type->type_sizeof;
3972                                 struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
3973                         }
3974                 }
3975                 ;
3976
3977 enum_type: SQL_ENUM opt_symbol enum_definition
3978                         { $$ = cat_str(3, make_str("enum"), $2, $3); }
3979                 |  SQL_ENUM symbol
3980                         { $$ = cat2_str(make_str("enum"), $2); }
3981                 ;
3982
3983 enum_definition: '{' c_list '}'
3984                         { $$ = cat_str(3, make_str("{"), $2, make_str("}")); };
3985
3986 struct_type: s_struct '{' variable_declarations '}'
3987                 {
3988                         ECPGfree_struct_member(struct_member_list[struct_level]);
3989                         free(actual_storage[struct_level--]);
3990                         $$ = cat_str(4, $1, make_str("{"), $3, make_str("}"));
3991                 }
3992                 ;
3993
3994 union_type: s_union '{' variable_declarations '}'
3995                 {
3996                         ECPGfree_struct_member(struct_member_list[struct_level]);
3997                         free(actual_storage[struct_level--]);
3998                         $$ = cat_str(4, $1, make_str("{"), $3, make_str("}"));
3999                 }
4000                 ;
4001
4002 s_struct: SQL_STRUCT opt_symbol
4003                 {
4004                         struct_member_list[struct_level++] = NULL;
4005                         $$ = cat2_str(make_str("struct"), $2);
4006                         ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), strdup($$), make_str(")"));
4007                         if (struct_level >= STRUCT_DEPTH)
4008                                  mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure definition");
4009                 }
4010                 ;
4011
4012 s_union: UNION opt_symbol
4013                 {
4014                         struct_member_list[struct_level++] = NULL;
4015                         if (struct_level >= STRUCT_DEPTH)
4016                                  mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure definition");
4017
4018                         $$ = cat2_str(make_str("union"), $2);
4019                 }
4020                 ;
4021
4022 simple_type: unsigned_type                                      { $$=$1; }
4023                 |       opt_signed signed_type                  { $$=$2; }
4024                 ;
4025
4026 unsigned_type: SQL_UNSIGNED SQL_SHORT           { $$ = ECPGt_unsigned_short; }
4027                 | SQL_UNSIGNED SQL_SHORT SQL_INT        { $$ = ECPGt_unsigned_short; }
4028                 | SQL_UNSIGNED                                          { $$ = ECPGt_unsigned_int; }
4029                 | SQL_UNSIGNED SQL_INT                          { $$ = ECPGt_unsigned_int; }
4030                 | SQL_UNSIGNED SQL_LONG                         { $$ = ECPGt_unsigned_long; }
4031                 | SQL_UNSIGNED SQL_LONG SQL_INT         { $$ = ECPGt_unsigned_long; }
4032                 | SQL_UNSIGNED SQL_LONG SQL_LONG
4033                 {
4034 #ifdef HAVE_LONG_LONG_INT_64
4035                         $$ = ECPGt_unsigned_long_long;
4036 #else
4037                         $$ = ECPGt_unsigned_long;
4038 #endif
4039                 }
4040                 | SQL_UNSIGNED SQL_LONG SQL_LONG SQL_INT
4041                 {
4042 #ifdef HAVE_LONG_LONG_INT_64
4043                         $$ = ECPGt_unsigned_long_long;
4044 #else
4045                         $$ = ECPGt_unsigned_long;
4046 #endif
4047                 }
4048                 | SQL_UNSIGNED CHAR                     { $$ = ECPGt_unsigned_char; }
4049                 ;
4050
4051 signed_type: SQL_SHORT                          { $$ = ECPGt_short; }
4052                 | SQL_SHORT SQL_INT                     { $$ = ECPGt_short; }
4053                 | SQL_INT                                       { $$ = ECPGt_int; }
4054                 | SQL_LONG                                      { $$ = ECPGt_long; }
4055                 | SQL_LONG SQL_INT                      { $$ = ECPGt_long; }
4056                 | SQL_LONG SQL_LONG
4057                 {
4058 #ifdef HAVE_LONG_LONG_INT_64
4059                         $$ = ECPGt_long_long;
4060 #else
4061                         $$ = ECPGt_long;
4062 #endif
4063                 }
4064                 | SQL_LONG SQL_LONG SQL_INT
4065                 {
4066 #ifdef HAVE_LONG_LONG_INT_64
4067                         $$ = ECPGt_long_long;
4068 #else
4069                         $$ = ECPGt_long;
4070 #endif
4071                 }
4072                 | SQL_BOOL                                      { $$ = ECPGt_bool; }
4073                 | CHAR                                          { $$ = ECPGt_char; }
4074                 ;
4075
4076 opt_signed: SQL_SIGNED
4077                 |       /* EMPTY */
4078                 ;
4079
4080 variable_list: variable
4081                         { $$ = $1; }
4082                 | variable_list ',' variable
4083                         { $$ = cat_str(3, $1, make_str(","), $3); }
4084                 ;
4085
4086 variable: opt_pointer ECPGColLabel opt_array_bounds opt_initializer
4087                 {
4088                         struct ECPGtype * type;
4089                         int dimension = $3.index1; /* dimension of array */
4090                         int length = $3.index2;    /* lenght of string */
4091                         char dim[14L], ascii_len[12];
4092
4093                         adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1));
4094
4095                         switch (actual_type[struct_level].type_enum)
4096                         {
4097                                 case ECPGt_struct:
4098                                 case ECPGt_union:
4099                                         if (dimension < 0)
4100                                                 type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof);
4101                                         else
4102                                                 type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof), dimension);
4103
4104                                         $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4);
4105                                         break;
4106
4107                                 case ECPGt_varchar:
4108                                         if (dimension < 0)
4109                                                 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
4110                                         else
4111                                                 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
4112
4113                                         switch(dimension)
4114                                         {
4115                                                 case 0:
4116                                                 case -1:
4117                                                 case 1:
4118                                                         *dim = '\0';
4119                                                         break;
4120                                                 default:
4121                                                         sprintf(dim, "[%d]", dimension);
4122                                                         break;
4123                                         }
4124                                         sprintf(ascii_len, "%d", length);
4125
4126                                         if (length == 0)
4127                                                 mmerror(PARSE_ERROR, ET_ERROR, "pointer to varchar are not implemented");
4128
4129                                         if (dimension == 0)
4130                                                 $$ = cat_str(7, mm_strdup(actual_storage[struct_level]), make2_str(make_str(" struct varchar_"), mm_strdup($2)), make_str(" { int len; char arr["), mm_strdup(ascii_len), make_str("]; } *"), mm_strdup($2), $4);
4131                                         else
4132                                            $$ = cat_str(8, mm_strdup(actual_storage[struct_level]), make2_str(make_str(" struct varchar_"), mm_strdup($2)), make_str(" { int len; char arr["), mm_strdup(ascii_len), make_str("]; } "), mm_strdup($2), mm_strdup(dim), $4);
4133                                         break;
4134
4135                                 case ECPGt_char:
4136                                 case ECPGt_unsigned_char:
4137                                         if (dimension == -1)
4138                                                 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length);
4139                                         else
4140                                                 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension);
4141
4142                                         $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4);
4143                                         break;
4144
4145                                 default:
4146                                         if (dimension < 0)
4147                                                 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, 1);
4148                                         else
4149                                                 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, 1), dimension);
4150
4151                                         $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4);
4152                                         break;
4153                         }
4154
4155                         if (struct_level == 0)
4156                                 new_variable($2, type, braces_open);
4157                         else
4158                                 ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]));
4159
4160                         free($2);
4161                 }
4162                 ;
4163
4164 opt_initializer: /*EMPTY*/
4165                         { $$ = EMPTY; }
4166                 | '=' c_term
4167                 {
4168                         initializer = 1;
4169                         $$ = cat2_str(make_str("="), $2);
4170                 }
4171                 ;
4172
4173 opt_pointer: /*EMPTY*/                          { $$ = EMPTY; }
4174                 | '*'                                           { $$ = make_str("*"); }
4175                 | '*' '*'                                       { $$ = make_str("**"); }
4176                 ;
4177
4178 /*
4179  * As long as the prepare statement is not supported by the backend, we will
4180  * try to simulate it here so we get dynamic SQL
4181  */
4182 ECPGDeclare: DECLARE STATEMENT ident
4183                 {
4184                         /* this is only supported for compatibility */
4185                         $$ = cat_str(3, make_str("/* declare statement"), $3, make_str("*/"));
4186                 }
4187                 ;
4188 /*
4189  * the exec sql disconnect statement: disconnect from the given database
4190  */
4191 ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; }
4192                 ;
4193
4194 dis_name: connection_object                             { $$ = $1; }
4195                 | CURRENT                                               { $$ = make_str("\"CURRENT\""); }
4196                 | ALL                                                   { $$ = make_str("\"ALL\""); }
4197                 | /*EMPTY*/                                             { $$ = make_str("\"CURRENT\""); }
4198                 ;
4199
4200 connection_object: connection_target    { $$ = $1; }
4201                 | DEFAULT                                               { $$ = make_str("\"DEFAULT\""); }
4202                 ;
4203
4204 /*
4205  * execute a given string as sql command
4206  */
4207 ECPGExecute : EXECUTE IMMEDIATE execstring
4208                 {
4209                         struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
4210
4211                         thisquery->type = &ecpg_query;
4212                         thisquery->brace_level = 0;
4213                         thisquery->next = NULL;
4214                         thisquery->name = $3;
4215
4216                         add_variable(&argsinsert, thisquery, &no_indicator);
4217
4218                         $$ = make_str("?");
4219                 }
4220                 | EXECUTE ident
4221                 {
4222                         struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
4223
4224                         thisquery->type = &ecpg_query;
4225                         thisquery->brace_level = 0;
4226                         thisquery->next = NULL;
4227                         thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(\"\")") + strlen($2));
4228                         sprintf(thisquery->name, "ECPGprepared_statement(\"%s\")", $2);
4229
4230                         add_variable(&argsinsert, thisquery, &no_indicator);
4231                 }
4232                 ecpg_using opt_ecpg_into
4233                 {
4234                         $$ = make_str("?");
4235                 }
4236                 ;
4237
4238 execstring: char_variable
4239                         { $$ = $1; }
4240                 |       CSTRING
4241                         { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
4242                 ;
4243
4244 /*
4245  * the exec sql free command to deallocate a previously
4246  * prepared statement
4247  */
4248 ECPGFree:       SQL_FREE ident  { $$ = $2; };
4249
4250 /*
4251  * open is an open cursor, at the moment this has to be removed
4252  */
4253 ECPGOpen: SQL_OPEN name ecpg_using { $$ = $2; };
4254
4255 ecpg_using: /*EMPTY*/           { $$ = EMPTY; }
4256                 | USING variablelist
4257                 {
4258                         /* mmerror ("open cursor with variables not implemented yet"); */
4259                         $$ = EMPTY;
4260                 }
4261                 ;
4262
4263 opt_sql: /*EMPTY*/ | SQL_SQL;
4264
4265 ecpg_into: INTO into_list
4266                 {
4267                         $$ = EMPTY;
4268                 }
4269                 | INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
4270                 {
4271                         add_variable(&argsresult, descriptor_variable($4,0), &no_indicator);
4272                         $$ = EMPTY;
4273                 }
4274                 ;
4275
4276 opt_ecpg_into: /*EMPTY*/                        { $$ = EMPTY; }
4277                 | ecpg_into                                     { $$ = $1; }
4278                 ;
4279
4280 variable: civarind | civar
4281                 ;
4282 variablelist: variable | variable ',' variablelist;
4283
4284 /*
4285  * As long as the prepare statement is not supported by the backend, we will
4286  * try to simulate it here so we get dynamic SQL
4287  */
4288 ECPGPrepare: SQL_PREPARE ident FROM execstring
4289                         { $$ = cat2_str(make3_str(make_str("\""), $2, make_str("\",")), $4); }
4290                 ;
4291
4292 /*
4293  * dynamic SQL: descriptor based access
4294  *      written by Christof Petig <christof.petig@wtal.de>
4295  */
4296
4297 /*
4298  * deallocate a descriptor
4299  */
4300 ECPGDeallocateDescr:    SQL_DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
4301                 {
4302                         drop_descriptor($3,connection);
4303                         $$ = $3;
4304                 }
4305                 ;
4306
4307 /*
4308  * allocate a descriptor
4309  */
4310 ECPGAllocateDescr:      SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
4311                 {
4312                         add_descriptor($3,connection);
4313                         $$ = $3;
4314                 };
4315
4316 /*
4317  * read from descriptor
4318  */
4319
4320 ECPGGetDescHeaderItem: cvariable '=' desc_header_item
4321                         { push_assignment($1, $3); }
4322                 ;
4323
4324 desc_header_item:       SQL_COUNT                       { $$ = ECPGd_count; }
4325                 ;
4326
4327 ECPGGetDescItem: cvariable '=' descriptor_item  { push_assignment($1, $3); };
4328
4329 descriptor_item:        SQL_CARDINALITY         { $$ = ECPGd_cardinality; }
4330                 | SQL_DATA                                              { $$ = ECPGd_data; }
4331                 | SQL_DATETIME_INTERVAL_CODE    { $$ = ECPGd_di_code; }
4332                 | SQL_DATETIME_INTERVAL_PRECISION { $$ = ECPGd_di_precision; }
4333                 | SQL_INDICATOR                                 { $$ = ECPGd_indicator; }
4334                 | SQL_KEY_MEMBER                                { $$ = ECPGd_key_member; }
4335                 | SQL_LENGTH                                    { $$ = ECPGd_length; }
4336                 | SQL_NAME                                              { $$ = ECPGd_name; }
4337                 | SQL_NULLABLE                                  { $$ = ECPGd_nullable; }
4338                 | SQL_OCTET_LENGTH                              { $$ = ECPGd_octet; }
4339                 | PRECISION                                             { $$ = ECPGd_precision; }
4340                 | SQL_RETURNED_LENGTH                   { $$ = ECPGd_length; }
4341                 | SQL_RETURNED_OCTET_LENGTH             { $$ = ECPGd_ret_octet; }
4342                 | SQL_SCALE                                             { $$ = ECPGd_scale; }
4343                 | TYPE_P                                                { $$ = ECPGd_type; }
4344                 ;
4345
4346 ECPGGetDescHeaderItems: ECPGGetDescHeaderItem
4347                 | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem
4348                 ;
4349
4350 ECPGGetDescItems: ECPGGetDescItem
4351                 | ECPGGetDescItems ',' ECPGGetDescItem
4352                 ;
4353
4354 ECPGGetDescriptorHeader:        SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar
4355                                                                 ECPGGetDescHeaderItems
4356                         {  $$ = $3; }
4357                 ;
4358
4359 ECPGGetDescriptor:      SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar
4360                                                 SQL_VALUE cvariable ECPGGetDescItems
4361                         {  $$.str = $5; $$.name = $3; }
4362                 |       SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar SQL_VALUE Iconst ECPGGetDescItems
4363                         {  $$.str = $5; $$.name = $3; }
4364                 ;
4365
4366 /*
4367  * for compatibility with ORACLE we will also allow the keyword RELEASE
4368  * after a transaction statement to disconnect from the database.
4369  */
4370
4371 ECPGRelease: TransactionStmt SQL_RELEASE
4372                 {
4373                         if (strcmp($1, "begin") == 0)
4374                                                         mmerror(PARSE_ERROR, ET_ERROR, "RELEASE does not make sense when beginning a transaction");
4375
4376                         fprintf(yyout, "ECPGtrans(__LINE__, %s, \"%s\");",
4377                                         connection ? connection : "NULL", $1);
4378                         whenever_action(0);
4379                         fprintf(yyout, "ECPGdisconnect(__LINE__, \"\");");
4380                         whenever_action(0);
4381                         free($1);
4382                 }
4383                 ;
4384
4385 /*
4386  * set/reset the automatic transaction mode, this needs a differnet handling
4387  * as the other set commands
4388  */
4389 ECPGSetAutocommit:      SET SQL_AUTOCOMMIT to_equal on_off      { $$ = $4; }
4390                 ;
4391
4392 on_off: ON                              { $$ = make_str("on"); }
4393                 | OFF                   { $$ = make_str("off"); }
4394                 ;
4395
4396 to_equal:       TO | '=';
4397
4398 /*
4399  * set the actual connection, this needs a differnet handling as the other
4400  * set commands
4401  */
4402 ECPGSetConnection:      SET SQL_CONNECTION to_equal connection_object { $$ = $4; }
4403                 ;
4404
4405 /*
4406  * define a new type for embedded SQL
4407  */
4408 ECPGTypedef: TYPE_P
4409                 {
4410                         /* reset this variable so we see if there was */
4411                         /* an initializer specified */
4412                         initializer = 0;
4413                 }
4414                 ColLabel IS type opt_type_array_bounds opt_reference
4415                 {
4416                         /* add entry to list */
4417                         struct typedefs *ptr, *this;
4418                         int dimension = $6.index1;
4419                         int length = $6.index2;
4420
4421                         if (($5.type_enum == ECPGt_struct ||
4422                                  $5.type_enum == ECPGt_union) &&
4423                                 initializer == 1)
4424                                 mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL TYPE command");
4425                         else
4426                         {
4427                                 for (ptr = types; ptr != NULL; ptr = ptr->next)
4428                                 {
4429                                         if (strcmp($3, ptr->name) == 0)
4430                                         {
4431                                                 /* re-definition is a bug */
4432                                                 sprintf(errortext, "Type %s already defined", $3);
4433                                                 mmerror(PARSE_ERROR, ET_ERROR, errortext);
4434                                         }
4435                                 }
4436
4437                                 adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0);
4438
4439                                 this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
4440
4441                                 /* initial definition */
4442                                 this->next = types;
4443                                 this->name = $3;
4444                                 this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
4445                                 this->type->type_enum = $5.type_enum;
4446                                 this->type->type_str = mm_strdup($3);
4447                                 this->type->type_dimension = dimension; /* dimension of array */
4448                                 this->type->type_index = length;        /* lenght of string */
4449                                 this->type->type_sizeof = ECPGstruct_sizeof;
4450                                 this->struct_member_list = ($5.type_enum == ECPGt_struct || $5.type_enum == ECPGt_union) ?
4451                                         struct_member_list[struct_level] : NULL;
4452
4453                                 if ($5.type_enum != ECPGt_varchar &&
4454                                         $5.type_enum != ECPGt_char &&
4455                                         $5.type_enum != ECPGt_unsigned_char &&
4456                                         this->type->type_index >= 0)
4457                                         mmerror(PARSE_ERROR, ET_ERROR, "No multi-dimensional array support for simple data types");
4458
4459                                 types = this;
4460                         }
4461
4462                         if (auto_create_c == false)
4463                                 $$ = cat_str(7, make_str("/* exec sql type"), mm_strdup($3), make_str("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, make_str("*/"));
4464                         else
4465                                 $$ = cat_str(6, make_str("typedef "), mm_strdup($5.type_str), *$7?make_str("*"):make_str(""), mm_strdup($6.str), mm_strdup($3), make_str(";"));
4466                 }
4467                 ;
4468
4469 opt_type_array_bounds:  '[' ']' opt_type_array_bounds
4470                 {
4471                         $$.index1 = 0;
4472                         $$.index2 = $3.index1;
4473                         $$.str = cat2_str(make_str("[]"), $3.str);
4474                 }
4475                 | '(' ')' opt_type_array_bounds
4476                 {
4477                         $$.index1 = 0;
4478                         $$.index2 = $3.index1;
4479                         $$.str = cat2_str(make_str("[]"), $3.str);
4480                 }
4481                 | '[' Iresult ']' opt_type_array_bounds
4482                 {
4483                         char *txt = mm_alloc(20L);
4484
4485                         sprintf (txt, "%d", $2);
4486                         $$.index1 = $2;
4487                         $$.index2 = $4.index1;
4488                         $$.str = cat_str(4, make_str("["), txt, make_str("]"), $4.str);
4489                 }
4490                 | '(' Iresult ')' opt_type_array_bounds
4491                 {
4492                         char *txt = mm_alloc(20L);
4493
4494                         sprintf (txt, "%d", $2);
4495                         $$.index1 = $2;
4496                         $$.index2 = $4.index1;
4497                         $$.str = cat_str(4, make_str("["), txt, make_str("]"), $4.str);
4498                 }
4499                 | /* EMPTY */
4500                 {
4501                         $$.index1 = -1;
4502                         $$.index2 = -1;
4503                         $$.str= EMPTY;
4504                 }
4505                 ;
4506
4507 opt_reference: SQL_REFERENCE            { $$ = make_str("reference"); }
4508                 | /*EMPTY*/                                     { $$ = EMPTY; }
4509                 ;
4510
4511 /*
4512  * define the type of one variable for embedded SQL
4513  */
4514 ECPGVar: SQL_VAR
4515                 {
4516                         /* reset this variable so we see if there was */
4517                         /* an initializer specified */
4518                         initializer = 0;
4519                 }
4520                 ColLabel IS type opt_type_array_bounds opt_reference
4521                 {
4522                         struct variable *p = find_variable($3);
4523                         int dimension = $6.index1;
4524                         int length = $6.index2;
4525                         struct ECPGtype * type;
4526
4527                         if (($5.type_enum == ECPGt_struct ||
4528                                  $5.type_enum == ECPGt_union) &&
4529                                 initializer == 1)
4530                                 mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL VAR command");
4531                         else
4532                         {
4533                                 adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0);
4534
4535                                 switch ($5.type_enum)
4536                                 {
4537                                         case ECPGt_struct:
4538                                         case ECPGt_union:
4539                                                 if (dimension < 0)
4540                                                         type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_sizeof);
4541                                                 else
4542                                                         type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum,$5.type_sizeof), dimension);
4543                                                 break;
4544
4545                                         case ECPGt_varchar:
4546                                                 if (dimension == -1)
4547                                                         type = ECPGmake_simple_type($5.type_enum, length);
4548                                                 else
4549                                                         type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length), dimension);
4550                                                 break;
4551
4552                                         case ECPGt_char:
4553                                         case ECPGt_unsigned_char:
4554                                                 if (dimension == -1)
4555                                                         type = ECPGmake_simple_type($5.type_enum, length);
4556                                                 else
4557                                                         type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length), dimension);
4558                                                 break;
4559
4560                                         default:
4561                                                 if (length >= 0)
4562                                                         mmerror(PARSE_ERROR, ET_ERROR, "No multi-dimensional array support for simple data types");
4563
4564                                                 if (dimension < 0)
4565                                                         type = ECPGmake_simple_type($5.type_enum, 1);
4566                                                 else
4567                                                         type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, 1), dimension);
4568                                                 break;
4569                                 }
4570
4571                                 ECPGfree_type(p->type);
4572                                 p->type = type;
4573                         }
4574
4575                         $$ = cat_str(7, make_str("/* exec sql var"), mm_strdup($3), make_str("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, make_str("*/"));
4576                 }
4577                 ;
4578
4579 /*
4580  * whenever statement: decide what to do in case of error/no data found
4581  * according to SQL standards we lack: SQLSTATE, CONSTRAINT and SQLEXCEPTION
4582  */
4583 ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action
4584                 {
4585                         when_error.code = $<action>3.code;
4586                         when_error.command = $<action>3.command;
4587                         $$ = cat_str(3, make_str("/* exec sql whenever sqlerror "), $3.str, make_str("; */\n"));
4588                 }
4589                 | SQL_WHENEVER NOT SQL_FOUND action
4590                 {
4591                         when_nf.code = $<action>4.code;
4592                         when_nf.command = $<action>4.command;
4593                         $$ = cat_str(3, make_str("/* exec sql whenever not found "), $4.str, make_str("; */\n"));
4594                 }
4595                 | SQL_WHENEVER SQL_SQLWARNING action
4596                 {
4597                         when_warn.code = $<action>3.code;
4598                         when_warn.command = $<action>3.command;
4599                         $$ = cat_str(3, make_str("/* exec sql whenever sql_warning "), $3.str, make_str("; */\n"));
4600                 }
4601                 ;
4602
4603 action : SQL_CONTINUE
4604                 {
4605                         $<action>$.code = W_NOTHING;
4606                         $<action>$.command = NULL;
4607                         $<action>$.str = make_str("continue");
4608                 }
4609                 | SQL_SQLPRINT
4610                 {
4611                         $<action>$.code = W_SQLPRINT;
4612                         $<action>$.command = NULL;
4613                         $<action>$.str = make_str("sqlprint");
4614                 }
4615                 | SQL_STOP
4616                 {
4617                         $<action>$.code = W_STOP;
4618                         $<action>$.command = NULL;
4619                         $<action>$.str = make_str("stop");
4620                 }
4621                 | SQL_GOTO name
4622                 {
4623                         $<action>$.code = W_GOTO;
4624                         $<action>$.command = strdup($2);
4625                         $<action>$.str = cat2_str(make_str("goto "), $2);
4626                 }
4627                 | SQL_GO TO name
4628                 {
4629                         $<action>$.code = W_GOTO;
4630                         $<action>$.command = strdup($3);
4631                         $<action>$.str = cat2_str(make_str("goto "), $3);
4632                 }
4633                 | DO name '(' c_args ')'
4634                 {
4635                         $<action>$.code = W_DO;
4636                         $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
4637                         $<action>$.str = cat2_str(make_str("do"), mm_strdup($<action>$.command));
4638                 }
4639                 | DO SQL_BREAK
4640                 {
4641                         $<action>$.code = W_BREAK;
4642                         $<action>$.command = NULL;
4643                         $<action>$.str = make_str("break");
4644                 }
4645                 | SQL_CALL name '(' c_args ')'
4646                 {
4647                         $<action>$.code = W_DO;
4648                         $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
4649                         $<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
4650                 }
4651                 ;
4652
4653 /* some other stuff for ecpg */
4654
4655 /* additional unreserved keywords */
4656 ECPGKeywords:  SQL_BREAK                { $$ = make_str("break"); }
4657                 | SQL_CALL                              { $$ = make_str("call"); }
4658                 | SQL_CARDINALITY               { $$ = make_str("cardinality"); }
4659                 | SQL_CONNECT                   { $$ = make_str("connect"); }
4660                 | SQL_CONTINUE                  { $$ = make_str("continue"); }
4661                 | SQL_COUNT                             { $$ = make_str("count"); }
4662                 | SQL_DATA                              { $$ = make_str("data"); }
4663                 | SQL_DATETIME_INTERVAL_CODE    { $$ = make_str("datetime_interval_code"); }
4664                 | SQL_DATETIME_INTERVAL_PRECISION       { $$ = make_str("datetime_interval_precision"); }
4665                 | SQL_DEALLOCATE                { $$ = make_str("deallocate"); }
4666                 | SQL_DISCONNECT                { $$ = make_str("disconnect"); }
4667                 | SQL_FOUND                             { $$ = make_str("found"); }
4668                 | SQL_GO                                { $$ = make_str("go"); }
4669                 | SQL_GOTO                              { $$ = make_str("goto"); }
4670                 | SQL_IDENTIFIED                { $$ = make_str("identified"); }
4671                 | SQL_INDICATOR                 { $$ = make_str("indicator"); }
4672                 | SQL_KEY_MEMBER                { $$ = make_str("key_member"); }
4673                 | SQL_LENGTH                    { $$ = make_str("length"); }
4674                 | SQL_NAME                              { $$ = make_str("name"); }
4675                 | SQL_NULLABLE                  { $$ = make_str("nullable"); }
4676                 | SQL_OCTET_LENGTH              { $$ = make_str("octet_length"); }
4677                 | SQL_OPEN                              { $$ = make_str("open"); }
4678                 | SQL_PREPARE                   { $$ = make_str("prepare"); }
4679                 | SQL_RELEASE                   { $$ = make_str("release"); }
4680                 | SQL_RETURNED_LENGTH           { $$ = make_str("returned_length"); }
4681                 | SQL_RETURNED_OCTET_LENGTH { $$ = make_str("returned_octet_length"); }
4682                 | SQL_SCALE                             { $$ = make_str("scale"); }
4683                 | SQL_SECTION                   { $$ = make_str("section"); }
4684                 | SQL_SQLERROR                  { $$ = make_str("sqlerror"); }
4685                 | SQL_SQLPRINT                  { $$ = make_str("sqlprint"); }
4686                 | SQL_SQLWARNING                { $$ = make_str("sqlwarning"); }
4687                 | SQL_STOP                              { $$ = make_str("stop"); }
4688                 | SQL_VAR                               { $$ = make_str("var"); }
4689                 | SQL_WHENEVER                  { $$ = make_str("whenever"); }
4690                 ;
4691
4692 /* additional keywords that can be SQL type names (but not ECPGColLabels) */
4693 ECPGTypeName:  SQL_BOOL                         { $$ = make_str("bool"); }
4694                 | SQL_INT                       { $$ = make_str("int"); }
4695                 | SQL_LONG                      { $$ = make_str("long"); }
4696                 | SQL_SHORT                     { $$ = make_str("short"); }
4697                 | SQL_STRUCT                    { $$ = make_str("struct"); }
4698                 | SQL_SIGNED                    { $$ = make_str("signed"); }
4699                 | SQL_UNSIGNED                  { $$ = make_str("unsigned"); }
4700                 ;
4701
4702 opt_symbol: symbol                              { $$ = $1; }
4703                 | /*EMPTY*/                             { $$ = EMPTY; }
4704                 ;
4705
4706 symbol: ColLabel                                { $$ = $1; }
4707                 ;
4708
4709 /*
4710  * Name classification hierarchy.
4711  *
4712  * IDENT is the lexeme returned by the lexer for identifiers that match
4713  * no known keyword.  In most cases, we can accept certain keywords as
4714  * names, not only IDENTs.      We prefer to accept as many such keywords
4715  * as possible to minimize the impact of "reserved words" on programmers.
4716  * So, we divide names into several possible classes.  The classification
4717  * is chosen in part to make keywords acceptable as names wherever possible.
4718  */
4719
4720 /* Column identifier --- names that can be column, table, etc names.
4721  */
4722 ColId:  ident                                                   { $$ = $1; }
4723                 | unreserved_keyword                    { $$ = $1; }
4724                 | col_name_keyword                              { $$ = $1; }
4725                 | ECPGKeywords                                  { $$ = $1; }
4726                 | CHAR                                                  { $$ = make_str("char"); }
4727                 ;
4728
4729 /* Type identifier --- names that can be type names.
4730  */
4731 type_name:      ident                                           { $$ = $1; }
4732                 | unreserved_keyword                    { $$ = $1; }
4733                 | ECPGKeywords                                  { $$ = $1; }
4734                 | ECPGTypeName                                  { $$ = $1; }
4735                 ;
4736
4737 /* Function identifier --- names that can be function names.
4738  */
4739 function_name:  ident                                           { $$ = $1; }
4740                 | unreserved_keyword                    { $$ = $1; }
4741                 | func_name_keyword                             { $$ = $1; }
4742                 | ECPGKeywords                                  { $$ = $1; }
4743                 ;
4744
4745 /* Column label --- allowed labels in "AS" clauses.
4746  * This presently includes *all* Postgres keywords.
4747  */
4748 ColLabel:  ECPGColLabel                                 { $$ = $1; }
4749                 | ECPGTypeName                                  { $$ = $1; }
4750                 | CHAR                                                  { $$ = make_str("char"); }
4751                 | UNION                                                 { $$ = make_str("union"); }
4752                 ;
4753
4754 ECPGColLabel:  ident                                    { $$ = $1; }
4755                 | unreserved_keyword                    { $$ = $1; }
4756                 | col_name_keyword                              { $$ = $1; }
4757                 | func_name_keyword                             { $$ = $1; }
4758                 | reserved_keyword                              { $$ = $1; }
4759                 | ECPGKeywords                                  { $$ = $1; }
4760                 ;
4761
4762
4763 /*
4764  * Keyword classification lists.  Generally, every keyword present in
4765  * the Postgres grammar should appear in exactly one of these lists.
4766  *
4767  * Put a new keyword into the first list that it can go into without causing
4768  * shift or reduce conflicts.  The earlier lists define "less reserved"
4769  * categories of keywords.
4770  */
4771
4772 /* "Unreserved" keywords --- available for use as any kind of name.
4773  */
4774 unreserved_keyword:
4775                   ABORT_TRANS                                   { $$ = make_str("abort"); }
4776                 | ABSOLUTE                                              { $$ = make_str("absolute"); }
4777                 | ACCESS                                                { $$ = make_str("access"); }
4778                 | ACTION                                                { $$ = make_str("action"); }
4779                 | ADD                                                   { $$ = make_str("add"); }
4780                 | AFTER                                                 { $$ = make_str("after"); }
4781                 | AGGREGATE                                             { $$ = make_str("aggregate"); }
4782                 | ALTER                                                 { $$ = make_str("alter"); }
4783                 | AT                                                    { $$ = make_str("at"); }
4784                 | BACKWARD                                              { $$ = make_str("backward"); }
4785                 | BEFORE                                                { $$ = make_str("before"); }
4786                 | BEGIN_TRANS                                   { $$ = make_str("begin"); }
4787                 | BY                                                    { $$ = make_str("by"); }
4788                 | CACHE                                                 { $$ = make_str("cache"); }
4789                 | CASCADE                                               { $$ = make_str("cascade"); }
4790                 | CHAIN                                                 { $$ = make_str("chain"); }
4791                 | CHARACTERISTICS                               { $$ = make_str("characteristics"); }
4792                 | CHECKPOINT                                    { $$ = make_str("checkpoint"); }
4793                 | CLOSE                                                 { $$ = make_str("close"); }
4794                 | CLUSTER                                               { $$ = make_str("cluster"); }
4795                 | COMMENT                                               { $$ = make_str("comment"); }
4796                 | COMMIT                                                { $$ = make_str("commit"); }
4797                 | COMMITTED                                             { $$ = make_str("committed"); }
4798                 | CONSTRAINTS                                   { $$ = make_str("constraints"); }
4799                 | COPY                                                  { $$ = make_str("copy"); }
4800                 | CREATEDB                                              { $$ = make_str("createdb"); }
4801                 | CREATEUSER                                    { $$ = make_str("createuser"); }
4802                 | CURSOR                                                { $$ = make_str("cursor"); }
4803                 | CYCLE                                                 { $$ = make_str("cycle"); }
4804                 | DATABASE                                              { $$ = make_str("database"); }
4805                 | DAY_P                                                 { $$ = make_str("day"); }
4806                 | DECLARE                                               { $$ = make_str("declare"); }
4807                 | DEFERRED                                              { $$ = make_str("deferred"); }
4808                 | DELETE                                                { $$ = make_str("delete"); }
4809                 | DELIMITERS                                    { $$ = make_str("delimiters"); }
4810                 | DOMAIN_P                                      { $$ = make_str("domain"); }
4811                 | DOUBLE                                                { $$ = make_str("double"); }
4812                 | DROP                                                  { $$ = make_str("drop"); }
4813                 | EACH                                                  { $$ = make_str("each"); }
4814                 | ENCODING                                              { $$ = make_str("encoding"); }
4815                 | ENCRYPTED                                             { $$ = make_str("encrypted"); }
4816                 | ESCAPE                                                { $$ = make_str("escape"); }
4817                 | EXCLUSIVE                                             { $$ = make_str("exclusive"); }
4818                 | EXECUTE                                               { $$ = make_str("execute"); }
4819                 | EXPLAIN                                               { $$ = make_str("explain"); }
4820                 | FETCH                                                 { $$ = make_str("fetch"); }
4821                 | FORCE                                                 { $$ = make_str("force"); }
4822                 | FORWARD                                               { $$ = make_str("forward"); }
4823                 | FUNCTION                                              { $$ = make_str("function"); }
4824                 | GLOBAL                                                { $$ = make_str("global"); }
4825                 | HANDLER                                               { $$ = make_str("handler"); }
4826                 | HOUR_P                                                { $$ = make_str("hour"); }
4827                 | IMMEDIATE                                             { $$ = make_str("immediate"); }
4828                 | INCREMENT                                             { $$ = make_str("increment"); }
4829                 | INDEX                                                 { $$ = make_str("index"); }
4830                 | INHERITS                                              { $$ = make_str("inherits"); }
4831                 | INOUT                                                 { $$ = make_str("inout"); }
4832                 | INSENSITIVE                                   { $$ = make_str("insensitive"); }
4833                 | INSERT                                                { $$ = make_str("insert"); }
4834                 | INSTEAD                                               { $$ = make_str("instead"); }
4835                 | ISOLATION                                             { $$ = make_str("isolation"); }
4836                 | KEY                                                   { $$ = make_str("key"); }
4837                 | LANGUAGE                                              { $$ = make_str("language"); }
4838                 | LANCOMPILER                                   { $$ = make_str("lancompiler"); }
4839                 | LEVEL                                                 { $$ = make_str("level"); }
4840                 | LISTEN                                                { $$ = make_str("listen"); }
4841                 | LOAD                                                  { $$ = make_str("load"); }
4842                 | LOCAL                                                 { $$ = make_str("local"); }
4843                 | LOCATION                                              { $$ = make_str("location"); }
4844                 | LOCK_P                                                { $$ = make_str("lock"); }
4845                 | MATCH                                                 { $$ = make_str("match"); }
4846                 | MAXVALUE                                              { $$ = make_str("maxvalue"); }
4847                 | MINUTE_P                                              { $$ = make_str("minute"); }
4848                 | MINVALUE                                              { $$ = make_str("minvalue"); }
4849                 | MODE                                                  { $$ = make_str("mode"); }
4850                 | MONTH_P                                               { $$ = make_str("month"); }
4851                 | MOVE                                                  { $$ = make_str("move"); }
4852                 | NAMES                                                 { $$ = make_str("names"); }
4853                 | NATIONAL                                              { $$ = make_str("national"); }
4854                 | NEXT                                                  { $$ = make_str("next"); }
4855                 | NO                                                    { $$ = make_str("no"); }
4856                 | NOCREATEDB                                    { $$ = make_str("nocreatedb"); }
4857                 | NOCREATEUSER                                  { $$ = make_str("nocreateuser"); }
4858                 | NOTHING                                               { $$ = make_str("nothing"); }
4859                 | NOTIFY                                                { $$ = make_str("notify"); }
4860                 | OF                                                    { $$ = make_str("of"); }
4861                 | OIDS                                                  { $$ = make_str("oids"); }
4862                 | OPERATOR                                              { $$ = make_str("operator"); }
4863                 | OPTION                                                { $$ = make_str("option"); }
4864                 | OUT                                                   { $$ = make_str("out"); }
4865                 | OWNER                                                 { $$ = make_str("owner"); }
4866                 | PARTIAL                                               { $$ = make_str("partial"); }
4867                 | PASSWORD                                              { $$ = make_str("password"); }
4868                 | PATH_P                                                { $$ = make_str("path"); }
4869                 | PENDANT                                               { $$ = make_str("pendant"); }
4870                 | PRECISION                                             { $$ = make_str("precision"); }
4871                 | PRIOR                                                 { $$ = make_str("prior"); }
4872                 | PRIVILEGES                                    { $$ = make_str("privileges"); }
4873                 | PROCEDURAL                                    { $$ = make_str("procedural"); }
4874                 | PROCEDURE                                             { $$ = make_str("procedure"); }
4875                 | READ                                                  { $$ = make_str("read"); }
4876                 | REINDEX                                               { $$ = make_str("reindex"); }
4877                 | RELATIVE                                              { $$ = make_str("relative"); }
4878                 | RENAME                                                { $$ = make_str("rename"); }
4879                 | REPLACE                                               { $$ = make_str("replace"); }
4880                 | RESET                                                 { $$ = make_str("reset"); }
4881                 | RESTRICT                                              { $$ = make_str("restrict"); }
4882                 | RETURNS                                               { $$ = make_str("returns"); }
4883                 | REVOKE                                                { $$ = make_str("revoke"); }
4884                 | ROLLBACK                                              { $$ = make_str("rollback"); }
4885                 | ROW                                                   { $$ = make_str("row"); }
4886                 | RULE                                                  { $$ = make_str("rule"); }
4887                 | SCHEMA                                                { $$ = make_str("schema"); }
4888                 | SCROLL                                                { $$ = make_str("scroll"); }
4889                 | SECOND_P                                              { $$ = make_str("second"); }
4890                 | SESSION                                               { $$ = make_str("session"); }
4891                 | SEQUENCE                                              { $$ = make_str("sequence"); }
4892                 | SERIALIZABLE                                  { $$ = make_str("serializable"); }
4893                 | SET                                                   { $$ = make_str("set"); }
4894                 | SHARE                                                 { $$ = make_str("share"); }
4895                 | SHOW                                                  { $$ = make_str("show"); }
4896                 | START                                                 { $$ = make_str("start"); }
4897                 | STATEMENT                                             { $$ = make_str("statement"); }
4898                 | STATISTICS                                    { $$ = make_str("statistics"); }
4899                 | STDIN                                                 { $$ = make_str("stdin"); }
4900                 | STDOUT                                                { $$ = make_str("stdout"); }
4901                 | STORAGE                                               { $$ = make_str("storage"); }
4902                 | SYSID                                                 { $$ = make_str("sysid"); }
4903                 | TEMP                                                  { $$ = make_str("temp"); }
4904                 | TEMPLATE                                              { $$ = make_str("template"); }
4905                 | TEMPORARY                                             { $$ = make_str("temporary"); }
4906                 | TOAST                                                 { $$ = make_str("toast"); }
4907                 | TRANSACTION                                   { $$ = make_str("transaction"); }
4908                 | TRIGGER                                               { $$ = make_str("trigger"); }
4909                 | TRUNCATE                                              { $$ = make_str("truncate"); }
4910                 | TRUSTED                                               { $$ = make_str("trusted"); }
4911                 | TYPE_P                                                { $$ = make_str("type"); }
4912                 | UNENCRYPTED                                   { $$ = make_str("unencrypted"); }
4913                 | UNKNOWN                                               { $$ = make_str("unknown"); }
4914                 | UNLISTEN                                              { $$ = make_str("unlisten"); }
4915                 | UNTIL                                                 { $$ = make_str("until"); }
4916                 | UPDATE                                                { $$ = make_str("update"); }
4917                 | USAGE                                                 { $$ = make_str("usage"); }
4918                 | VACUUM                                                { $$ = make_str("vacuum"); }
4919                 | VALID                                                 { $$ = make_str("valid"); }
4920                 | VALUES                                                { $$ = make_str("values"); }
4921                 | VARYING                                               { $$ = make_str("varying"); }
4922                 | VERSION                                               { $$ = make_str("version"); }
4923                 | VIEW                                                  { $$ = make_str("view"); }
4924                 | WITH                                                  { $$ = make_str("with"); }
4925                 | WITHOUT                                               { $$ = make_str("without"); }
4926                 | WORK                                                  { $$ = make_str("work"); }
4927                 | YEAR_P                                                { $$ = make_str("year"); }
4928                 | ZONE                                                  { $$ = make_str("zone"); }
4929                 ;
4930
4931 /* Column identifier --- keywords that can be column, table, etc names.
4932  *
4933  * Many of these keywords will in fact be recognized as type or function
4934  * names too; but they have special productions for the purpose, and so
4935  * can't be treated as "generic" type or function names.
4936  *
4937  * The type names appearing here are not usable as function names
4938  * because they can be followed by '(' in typename productions, which
4939  * looks too much like a function call for an LR(1) parser.
4940  */
4941 col_name_keyword:
4942                   BIT                                                   { $$ = make_str("bit"); }
4943 /* CHAR must be excluded from ECPGColLabel because of conflict with UNSIGNED
4944                 | CHAR                                                  { $$ = make_str("char"); }
4945  */
4946                 | CHARACTER                                             { $$ = make_str("character"); }
4947                 | COALESCE                                              { $$ = make_str("coalesce"); }
4948                 | DEC                                                   { $$ = make_str("dec"); }
4949                 | DECIMAL                                               { $$ = make_str("decimal"); }
4950                 | EXISTS                                                { $$ = make_str("exists"); }
4951                 | EXTRACT                                               { $$ = make_str("extract"); }
4952                 | FLOAT                                                 { $$ = make_str("float"); }
4953                 | INTERVAL                                              { $$ = make_str("interval"); }
4954                 | NCHAR                                                 { $$ = make_str("nchar"); }
4955                 | NONE                                                  { $$ = make_str("none"); }
4956                 | NULLIF                                                { $$ = make_str("nullif"); }
4957                 | NUMERIC                                               { $$ = make_str("numeric"); }
4958                 | POSITION                                              { $$ = make_str("position"); }
4959                 | SETOF                                                 { $$ = make_str("setof"); }
4960                 | SUBSTRING                                             { $$ = make_str("substring"); }
4961                 | TIME                                                  { $$ = make_str("time"); }
4962                 | TIMESTAMP                                             { $$ = make_str("timestamp"); }
4963                 | TRIM                                                  { $$ = make_str("trim"); }
4964                 | VARCHAR                                               { $$ = make_str("varchar"); }
4965                 ;
4966
4967 /* Function identifier --- keywords that can be function names.
4968  *
4969  * Most of these are keywords that are used as operators in expressions;
4970  * in general such keywords can't be column names because they would be
4971  * ambiguous with variables, but they are unambiguous as function identifiers.
4972  *
4973  * Do not include POSITION, SUBSTRING, etc here since they have explicit
4974  * productions in a_expr to support the goofy SQL9x argument syntax.
4975  *      - thomas 2000-11-28
4976  */
4977 func_name_keyword:
4978                   AUTHORIZATION                                 { $$ = make_str("authorization"); }
4979                 | BETWEEN                                               { $$ = make_str("between"); }
4980                 | BINARY                                                { $$ = make_str("binary"); }
4981                 | CROSS                                                 { $$ = make_str("cross"); }
4982                 | FREEZE                                                { $$ = make_str("freeze"); }
4983                 | FULL                                                  { $$ = make_str("full"); }
4984                 | ILIKE                                                 { $$ = make_str("ilike"); }
4985                 | IN                                                    { $$ = make_str("in"); }
4986                 | INNER_P                                               { $$ = make_str("inner"); }
4987                 | IS                                                    { $$ = make_str("is"); }
4988                 | ISNULL                                                { $$ = make_str("isnull"); }
4989                 | JOIN                                                  { $$ = make_str("join"); }
4990                 | LEFT                                                  { $$ = make_str("left"); }
4991                 | LIKE                                                  { $$ = make_str("like"); }
4992                 | NATURAL                                               { $$ = make_str("natural"); }
4993                 | NOTNULL                                               { $$ = make_str("notnull"); }
4994                 | OUTER_P                                               { $$ = make_str("outer"); }
4995                 | OVERLAPS                                              { $$ = make_str("overlaps"); }
4996                 | PUBLIC                                                { $$ = make_str("public"); }
4997                 | RIGHT                                                 { $$ = make_str("right"); }
4998                 | VERBOSE                                               { $$ = make_str("verbose"); }
4999                 ;
5000
5001 /* Reserved keyword --- these keywords are usable only as a ColLabel.
5002  *
5003  * Keywords appear here if they could not be distinguished from variable,
5004  * type, or function names in some contexts.  Don't put things here unless
5005  * forced to.
5006  */
5007 reserved_keyword:
5008                   ALL                                                   { $$ = make_str("all"); }
5009                 | ANALYSE                                               { $$ = make_str("analyse"); } /* British */
5010                 | ANALYZE                                               { $$ = make_str("analyze"); }
5011                 | AND                                                   { $$ = make_str("and"); }
5012                 | ANY                                                   { $$ = make_str("any"); }
5013                 | AS                                                    { $$ = make_str("as"); }
5014                 | ASC                                                   { $$ = make_str("asc"); }
5015                 | BOTH                                                  { $$ = make_str("both"); }
5016                 | CASE                                                  { $$ = make_str("case"); }
5017                 | CAST                                                  { $$ = make_str("cast"); }
5018                 | CHECK                                                 { $$ = make_str("check"); }
5019                 | COLLATE                                               { $$ = make_str("collate"); }
5020                 | COLUMN                                                { $$ = make_str("column"); }
5021                 | CONSTRAINT                                    { $$ = make_str("constraint"); }
5022                 | CREATE                                                { $$ = make_str("create"); }
5023                 | CURRENT_DATE                                  { $$ = make_str("current_date"); }
5024                 | CURRENT_TIME                                  { $$ = make_str("current_time"); }
5025                 | CURRENT_TIMESTAMP                             { $$ = make_str("current_timestamp"); }
5026                 | CURRENT_USER                                  { $$ = make_str("current_user"); }
5027                 | DEFAULT                                               { $$ = make_str("default"); }
5028                 | DEFERRABLE                                    { $$ = make_str("deferrable"); }
5029                 | DESC                                                  { $$ = make_str("desc"); }
5030                 | DISTINCT                                              { $$ = make_str("distinct"); }
5031                 | DO                                                    { $$ = make_str("do"); }
5032                 | ELSE                                                  { $$ = make_str("else"); }
5033                 | END_TRANS                                             { $$ = make_str("end"); }
5034                 | EXCEPT                                                { $$ = make_str("except"); }
5035                 | FALSE_P                                               { $$ = make_str("false"); }
5036                 | FOR                                                   { $$ = make_str("for"); }
5037                 | FOREIGN                                               { $$ = make_str("foreign"); }
5038                 | FROM                                                  { $$ = make_str("from"); }
5039                 | GRANT                                                 { $$ = make_str("grant"); }
5040                 | GROUP                                                 { $$ = make_str("group"); }
5041                 | HAVING                                                { $$ = make_str("having"); }
5042                 | INITIALLY                                             { $$ = make_str("initially"); }
5043                 | INTERSECT                                             { $$ = make_str("intersect"); }
5044                 | INTO                                                  { $$ = make_str("into"); }
5045                 | LEADING                                               { $$ = make_str("leading"); }
5046                 | LIMIT                                                 { $$ = make_str("limit"); }
5047                 | NEW                                                   { $$ = make_str("new"); }
5048                 | NOT                                                   { $$ = make_str("not"); }
5049                 | NULL_P                                                { $$ = make_str("null"); }
5050                 | OFF                                                   { $$ = make_str("off"); }
5051                 | OFFSET                                                { $$ = make_str("offset"); }
5052                 | OLD                                                   { $$ = make_str("old"); }
5053                 | ON                                                    { $$ = make_str("on"); }
5054                 | ONLY                                                  { $$ = make_str("only"); }
5055                 | OR                                                    { $$ = make_str("or"); }
5056                 | ORDER                                                 { $$ = make_str("order"); }
5057                 | PRIMARY                                               { $$ = make_str("primary"); }
5058                 | REFERENCES                                    { $$ = make_str("references"); }
5059                 | SELECT                                                { $$ = make_str("select"); }
5060                 | SESSION_USER                                  { $$ = make_str("session_user"); }
5061                 | SOME                                                  { $$ = make_str("some"); }
5062                 | TABLE                                                 { $$ = make_str("table"); }
5063                 | THEN                                                  { $$ = make_str("then"); }
5064                 | TO                                                    { $$ = make_str("to"); }
5065                 | TRAILING                                              { $$ = make_str("trailing"); }
5066                 | TRUE_P                                                { $$ = make_str("true"); }
5067 /* UNION must be excluded from ECPGColLabel because of conflict with s_union
5068                 | UNION                                                 { $$ = make_str("union"); }
5069  */
5070                 | UNIQUE                                                { $$ = make_str("unique"); }
5071                 | USER                                                  { $$ = make_str("user"); }
5072                 | USING                                                 { $$ = make_str("using"); }
5073                 | WHEN                                                  { $$ = make_str("when"); }
5074                 | WHERE                                                 { $$ = make_str("where"); }
5075                 ;
5076
5077
5078 into_list : coutputvariable | into_list ',' coutputvariable
5079                 ;
5080
5081 ecpgstart: SQL_START    { reset_variables(); }
5082                 ;
5083
5084 c_args: /*EMPTY*/               { $$ = EMPTY; }
5085                 | c_list                { $$ = $1; }
5086                 ;
5087
5088 coutputvariable: cvariable indicator
5089                         { add_variable(&argsresult, find_variable($1), find_variable($2)); }
5090                 | cvariable
5091                         { add_variable(&argsresult, find_variable($1), &no_indicator); }
5092                 ;
5093
5094
5095 civarind: cvariable indicator
5096                 {
5097                         if ($2 != NULL && (find_variable($2))->type->type == ECPGt_array)
5098                                 mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input");
5099
5100                         add_variable(&argsinsert, find_variable($1), ($2 == NULL) ? &no_indicator : find_variable($2));
5101                 }
5102                 ;
5103
5104 civar: cvariable
5105                 {
5106                         add_variable(&argsinsert, find_variable($1), &no_indicator);
5107                         $$ = $1;
5108                 }
5109                 ;
5110
5111 cvariable: CVARIABLE                            { $$ = $1; }
5112                 ;
5113
5114 indicator: CVARIABLE                            { check_indicator((find_variable($1))->type); $$ = $1; }
5115                 | SQL_INDICATOR cvariable       { check_indicator((find_variable($2))->type); $$ = $2; }
5116                 | SQL_INDICATOR name            { check_indicator((find_variable($2))->type); $$ = $2; }
5117                 ;
5118
5119 ident: IDENT                                            { $$ = $1; }
5120                 | CSTRING                                       { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
5121                 ;
5122
5123 quoted_ident_stringvar: IDENT
5124                         { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
5125                 | CSTRING
5126                         { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
5127                 | char_variable
5128                         { $$ = make3_str(make_str("("), $1, make_str(")")); }
5129                 ;
5130
5131 /*
5132  * C stuff
5133  */
5134
5135 cpp_line: CPP_LINE      { $$ = $1; };
5136
5137 c_stuff_item: c_anything                        { $$ = $1; }
5138                 | '(' ')'                                       { $$ = make_str("()"); }
5139                 | '(' c_stuff ')'
5140                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
5141                 ;
5142
5143 c_stuff: c_stuff_item   { $$ = $1; }
5144                 | c_stuff c_stuff_item
5145                         { $$ = cat2_str($1, $2); }
5146                 ;
5147
5148 c_list: c_term                                          { $$ = $1; }
5149                 | c_list ',' c_term                     { $$ = cat_str(3, $1, make_str(","), $3); }
5150                 ;
5151
5152 c_term:  c_stuff                                        { $$ = $1; }
5153                 | '{' c_list '}'                        { $$ = cat_str(3, make_str("{"), $2, make_str("}")); }
5154                 ;
5155
5156 c_thing:        c_anything      { $$ = $1; }
5157                 |       '('                                             { $$ = make_str("("); }
5158                 |       ')'                                             { $$ = make_str(")"); }
5159                 |       ','                                             { $$ = make_str(","); }
5160                 |       ';'                                             { $$ = make_str(";"); }
5161                 ;
5162
5163 c_anything:  IDENT                                      { $$ = $1; }
5164                 | CSTRING                                       { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
5165                 | PosIntConst                           { $$ = $1; }
5166                 | Fconst                                        { $$ = $1; }
5167                 | Sconst                                        { $$ = $1; }
5168                 | '*'                                           { $$ = make_str("*"); }
5169                 | '+'                                           { $$ = make_str("+"); }
5170                 | '-'                                           { $$ = make_str("-"); }
5171                 | '/'                                           { $$ = make_str("/"); }
5172                 | '%'                                           { $$ = make_str("%"); }
5173                 | NULL_P                                        { $$ = make_str("NULL"); }
5174                 | S_ADD                                         { $$ = make_str("+="); }
5175                 | S_AND                                         { $$ = make_str("&&"); }
5176                 | S_ANYTHING                            { $$ = make_name(); }
5177                 | S_AUTO                                        { $$ = make_str("auto"); }
5178                 | S_CONST                                       { $$ = make_str("const"); }
5179                 | S_DEC                                         { $$ = make_str("--"); }
5180                 | S_DIV                                         { $$ = make_str("/="); }
5181                 | S_DOTPOINT                            { $$ = make_str(".*"); }
5182                 | S_EQUAL                                       { $$ = make_str("=="); }
5183                 | S_EXTERN                                      { $$ = make_str("extern"); }
5184                 | S_INC                                         { $$ = make_str("++"); }
5185                 | S_LSHIFT                                      { $$ = make_str("<<"); }
5186                 | S_MEMBER                                      { $$ = make_str("->"); }
5187                 | S_MEMPOINT                            { $$ = make_str("->*"); }
5188                 | S_MOD                                         { $$ = make_str("%="); }
5189                 | S_MUL                                         { $$ = make_str("*="); }
5190                 | S_NEQUAL                                      { $$ = make_str("!="); }
5191                 | S_OR                                          { $$ = make_str("||"); }
5192                 | S_REGISTER                            { $$ = make_str("register"); }
5193                 | S_RSHIFT                                      { $$ = make_str(">>"); }
5194                 | S_STATIC                                      { $$ = make_str("static"); }
5195                 | S_SUB                                         { $$ = make_str("-="); }
5196                 | S_TYPEDEF                             { $$ = make_str("typedef"); }
5197                 | SQL_BOOL                                      { $$ = make_str("bool"); }
5198                 | SQL_ENUM                                      { $$ = make_str("enum"); }
5199                 | SQL_INT                                       { $$ = make_str("int"); }
5200                 | SQL_LONG                                      { $$ = make_str("long"); }
5201                 | SQL_SHORT                                     { $$ = make_str("short"); }
5202                 | SQL_SIGNED                            { $$ = make_str("signed"); }
5203                 | SQL_STRUCT                            { $$ = make_str("struct"); }
5204                 | SQL_UNSIGNED                          { $$ = make_str("unsigned"); }
5205                 | CHAR                                          { $$ = make_str("char"); }
5206                 | DOUBLE                                        { $$ = make_str("double"); }
5207                 | FLOAT                                         { $$ = make_str("float"); }
5208                 | UNION                                         { $$ = make_str("union"); }
5209                 | VARCHAR                                       { $$ = make_str("varchar"); }
5210                 | '['                                           { $$ = make_str("["); }
5211                 | ']'                                           { $$ = make_str("]"); }
5212                 | '='                                           { $$ = make_str("="); }
5213                 ;
5214
5215 blockstart : '{'
5216                 {
5217                         braces_open++;
5218                         $$ = make_str("{");
5219                 };
5220
5221 blockend : '}'
5222                 {
5223                         remove_variables(braces_open--);
5224                         $$ = make_str("}");
5225                 };
5226
5227 %%
5228
5229 void yyerror( char * error)
5230 {
5231         char buf[1024];
5232
5233         snprintf(buf,sizeof buf,"%s at or near \"%s\"",error,yytext);
5234         buf[sizeof(buf)-1]=0;
5235         mmerror(PARSE_ERROR, ET_ERROR, buf);
5236 }