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