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