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