preproc.y 237 KB
Newer Older
1
/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.379 2008/10/28 14:09:45 petere Exp $ */
2

3 4
/* Copyright comment */
%{
5
#include "postgres_fe.h"
6 7

#include "extern.h"
8
#include <unistd.h>
9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/* Location tracking support --- simpler than bison's default */
#define YYLLOC_DEFAULT(Current, Rhs, N) \
	do { \
                if (N) \
			(Current) = (Rhs)[1]; \
		else \
		        (Current) = (Rhs)[0]; \
	} while (0)

/*
 * The %name-prefix option below will make bison call base_yylex, but we
 * really want it to call filtered_base_yylex (see parser.c).
 */
#define base_yylex filtered_base_yylex

25 26 27
/*
 * Variables containing simple states.
 */
28 29
int struct_level = 0;
int braces_open; /* brace level counter */
30
int ecpg_informix_var = 0;
Michael Meskes's avatar
Michael Meskes committed
31
char	*connection = NULL;
32
char	*input_filename = NULL;
Michael Meskes's avatar
Michael Meskes committed
33

34
static int	QueryIsRule = 0, FoundInto = 0;
Michael Meskes's avatar
Michael Meskes committed
35
static int	initializer = 0;
36 37
static int	pacounter = 1;
static char     pacounter_buffer[sizeof(int) * CHAR_BIT * 10 / 3]; /* a rough guess at the size we need */
38
static struct this_type actual_type[STRUCT_DEPTH];
39
static char *actual_startline[STRUCT_DEPTH];
40

41
/* temporarily store struct members while creating the data structure */
42
struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL };
43

44 45 46
/* also store struct type so we can do a sizeof() later */
static char *ECPGstruct_sizeof = NULL;

47 48 49
/* for forward declarations we have to store some data as well */
static char *forward_name = NULL;

50
struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, NULL, NULL, {NULL}, 0};
51 52
struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};

53
struct ECPGtype ecpg_query = {ECPGt_char_variable, NULL, NULL, {NULL}, 0};
54

Michael Meskes's avatar
Michael Meskes committed
55 56 57
/*
 * Handle parsing errors and warnings
 */
Michael Meskes's avatar
Michael Meskes committed
58
void
59
mmerror(int error_code, enum errortype type, char * error, ...)
Michael Meskes's avatar
Michael Meskes committed
60
{
61
	va_list ap;
62

63 64 65
	/* internationalize the error message string */
	error = _(error);

66
	fprintf(stderr, "%s:%d: ", input_filename, yylineno);
67

68 69 70
	switch(type)
	{
		case ET_WARNING:
71
			fprintf(stderr, _("WARNING: "));
72 73 74
			break;
		case ET_ERROR:
		case ET_FATAL:
75
			fprintf(stderr, _("ERROR: "));
76 77 78 79 80 81
			break;
	}

	va_start(ap, error);
	vfprintf(stderr, error, ap);
	va_end(ap);
82

83
	fprintf(stderr, "\n");
84

85 86 87 88 89 90 91 92
	switch(type)
	{
		case ET_WARNING:
			break;
		case ET_ERROR:
			ret_value = error_code;
			break;
		case ET_FATAL:
93 94 95 96
			if (yyin)
				fclose(yyin);
			if (yyout)
				fclose(yyout);
97
			if (unlink(output_filename) != 0 && *output_filename != '-')
98
			        fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename);
99 100
			exit(error_code);
	}
Michael Meskes's avatar
Michael Meskes committed
101 102
}

Michael Meskes's avatar
Michael Meskes committed
103 104 105 106
/*
 * string concatenation
 */

Marc G. Fournier's avatar
Marc G. Fournier committed
107
static char *
108
cat2_str(char *str1, char *str2)
109 110
{
	char * res_str	= (char *)mm_alloc(strlen(str1) + strlen(str2) + 2);
Marc G. Fournier's avatar
Marc G. Fournier committed
111 112 113 114

	strcpy(res_str, str1);
	strcat(res_str, " ");
	strcat(res_str, str2);
115 116
	free(str1);
	free(str2);
Marc G. Fournier's avatar
Marc G. Fournier committed
117 118 119 120
	return(res_str);
}

static char *
Michael Meskes's avatar
Michael Meskes committed
121 122 123
cat_str(int count, ...)
{
	va_list		args;
124
	int			i;
Michael Meskes's avatar
Michael Meskes committed
125
	char		*res_str;
Marc G. Fournier's avatar
Marc G. Fournier committed
126

Michael Meskes's avatar
Michael Meskes committed
127
	va_start(args, count);
Marc G. Fournier's avatar
Marc G. Fournier committed
128

Michael Meskes's avatar
Michael Meskes committed
129 130 131 132 133 134 135 136 137
	res_str = va_arg(args, char *);

	/* now add all other strings */
	for (i = 1; i < count; i++)
		res_str = cat2_str(res_str, va_arg(args, char *));

	va_end(args);

	return(res_str);
Marc G. Fournier's avatar
Marc G. Fournier committed
138 139
}

Michael Meskes's avatar
Michael Meskes committed
140
char *
Michael Meskes's avatar
Michael Meskes committed
141 142
make_str(const char *str)
{
143
	char * res_str = (char *)mm_alloc(strlen(str) + 1);
Michael Meskes's avatar
Michael Meskes committed
144 145 146

	strcpy(res_str, str);
	return res_str;
Marc G. Fournier's avatar
Marc G. Fournier committed
147 148 149
}

static char *
Michael Meskes's avatar
Michael Meskes committed
150
make2_str(char *str1, char *str2)
151 152
{
	char * res_str	= (char *)mm_alloc(strlen(str1) + strlen(str2) + 1);
Michael Meskes's avatar
Michael Meskes committed
153 154 155

	strcpy(res_str, str1);
	strcat(res_str, str2);
156 157
	free(str1);
	free(str2);
Michael Meskes's avatar
Michael Meskes committed
158 159
	return(res_str);
}
Marc G. Fournier's avatar
Marc G. Fournier committed
160 161

static char *
Michael Meskes's avatar
Michael Meskes committed
162
make3_str(char *str1, char *str2, char *str3)
163 164
{
	char * res_str	= (char *)mm_alloc(strlen(str1) + strlen(str2) +strlen(str3) + 1);
Michael Meskes's avatar
Michael Meskes committed
165 166 167

	strcpy(res_str, str1);
	strcat(res_str, str2);
Marc G. Fournier's avatar
Marc G. Fournier committed
168
	strcat(res_str, str3);
169 170 171
	free(str1);
	free(str2);
	free(str3);
Michael Meskes's avatar
Michael Meskes committed
172 173
	return(res_str);
}
Marc G. Fournier's avatar
Marc G. Fournier committed
174

175
/* and the rest */
Marc G. Fournier's avatar
Marc G. Fournier committed
176 177 178 179 180 181 182 183 184 185
static char *
make_name(void)
{
	char * name = (char *)mm_alloc(yyleng + 1);

	strncpy(name, yytext, yyleng);
	name[yyleng] = '\0';
	return(name);
}

186 187 188 189 190 191 192
static char *
create_questionmarks(char *name, bool array)
{
	struct variable *p = find_variable(name);
	int count;
	char *result = EMPTY;

193 194 195
	/* In case we have a struct, we have to print as many "?" as there are attributes in the struct
	 * An array is only allowed together with an element argument
	 * This is essantially only used for inserts, but using a struct as input parameter is an error anywhere else
196
	 * so we don't have to worry here. */
197

198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
	if (p->type->type == ECPGt_struct || (array && p->type->type == ECPGt_array && p->type->u.element->type == ECPGt_struct))
	{
		struct ECPGstruct_member *m;

		if (p->type->type == ECPGt_struct)
			m = p->type->u.members;
		else
			m = p->type->u.element->u.members;

		for (count = 0; m != NULL; m=m->next, count++);
	}
	else
		count = 1;

	for (; count > 0; count --)
213 214 215 216
	{
		sprintf(pacounter_buffer, "$%d", pacounter++);
		result = cat_str(3, result, strdup(pacounter_buffer), make_str(" , "));
	}
217 218 219 220 221 222 223

	/* removed the trailing " ," */

	result[strlen(result)-3] = '\0';
	return(result);
}

224 225 226 227
static char *
adjust_informix(struct arguments *list)
{
	/* Informix accepts DECLARE with variables that are out of scope when OPEN is called.
228
 	 * for instance you can declare variables in a function, and then subsequently use them
229
	 * {
230 231 232
	 *      declare_vars();
	 *      exec sql ... which uses vars declared in the above function
	 *
233
	 * This breaks standard and leads to some very dangerous programming.
234 235
	 * Since they do, we have to work around and accept their syntax as well.
	 * But we will do so ONLY in Informix mode.
236
	 * We have to change the variables to our own struct and just store the pointer instead of the variable
237
	 */
238 239 240 241 242 243

	 struct arguments *ptr;
	 char *result = make_str("");

	 for (ptr = list; ptr != NULL; ptr = ptr->next)
	 {
Michael Meskes's avatar
Michael Meskes committed
244
	 	char temp[20]; /* this should be sufficient unless you have 8 byte integers */
245
		char *original_var;
246

247 248 249
	 	/* change variable name to "ECPG_informix_get_var(<counter>)" */
		original_var = ptr->variable->name;
		sprintf(temp, "%d))", ecpg_informix_var);
250

251
		if ((ptr->variable->type->type != ECPGt_varchar && ptr->variable->type->type != ECPGt_char && ptr->variable->type->type != ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
Michael Meskes's avatar
Michael Meskes committed
252
		{
253
			ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, make_str("1"), ptr->variable->type->u.element->lineno), ptr->variable->type->size), 0);
Michael Meskes's avatar
Michael Meskes committed
254
			sprintf(temp, "%d, (", ecpg_informix_var++);
255
		}
256
		else if ((ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_char || ptr->variable->type->type == ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
257
		{
258
			ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
259
			sprintf(temp, "%d, (", ecpg_informix_var++);
Michael Meskes's avatar
Michael Meskes committed
260 261 262
		}
		else
		{
263
			ptr->variable = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
Michael Meskes's avatar
Michael Meskes committed
264 265
			sprintf(temp, "%d, &(", ecpg_informix_var++);
		}
266

267
		/* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */
268
		result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
269

Michael Meskes's avatar
Michael Meskes committed
270 271 272 273 274 275
		/* now the indicator if there is one */
		if (ptr->indicator->type->type != ECPGt_NO_INDICATOR)
		{
			/* change variable name to "ECPG_informix_get_var(<counter>)" */
			original_var = ptr->indicator->name;
			sprintf(temp, "%d))", ecpg_informix_var);
276

Michael Meskes's avatar
Michael Meskes committed
277 278 279
			/* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */
			if (atoi(ptr->indicator->type->size) > 1)
			{
280
				ptr->indicator = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0);
Michael Meskes's avatar
Michael Meskes committed
281 282 283 284
				sprintf(temp, "%d, (", ecpg_informix_var++);
			}
			else
			{
285
				ptr->indicator = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0);
Michael Meskes's avatar
Michael Meskes committed
286 287 288 289
				sprintf(temp, "%d, &(", ecpg_informix_var++);
			}
			result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
		}
290 291 292 293 294
	 }

	 return result;
}

295 296 297 298 299 300 301 302 303 304 305 306 307 308
static struct cursor *
add_additional_variables(char *name, bool insert)
{
	struct cursor *ptr;
	struct arguments *p;

	for (ptr = cur; ptr != NULL; ptr=ptr->next)
	{
		if (strcmp(ptr->name, name) == 0)
			break;
	}

	if (ptr == NULL)
	{
309
		mmerror(PARSE_ERROR, ET_ERROR, "trying to access an undeclared cursor \"%s\"\n", name);
310 311
		return NULL;
	}
312

313 314
	if (insert)
	{
315
		/* add all those input variables that were given earlier
316
		 * note that we have to append here but have to keep the existing order */
317
		for (p = ptr->argsinsert; p; p = p->next)
318
			add_variable_to_tail(&argsinsert, p->variable, p->indicator);
319
	}
320 321 322

	/* add all those output variables that were given earlier */
	for (p = ptr->argsresult; p; p = p->next)
323
		add_variable_to_tail(&argsresult, p->variable, p->indicator);
324

325 326
	return ptr;
}
327 328 329 330 331 332 333 334 335 336

static void
add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enum, char *type_dimension, char *type_index, int initializer, int array)
{
	/* add entry to list */
	struct typedefs *ptr, *this;

	if ((type_enum == ECPGt_struct ||
	     type_enum == ECPGt_union) &&
	    initializer == 1)
337
		mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in typedef command");
338 339 340 341 342 343
	else
	{
		for (ptr = types; ptr != NULL; ptr = ptr->next)
		{
			if (strcmp(name, ptr->name) == 0)
				/* re-definition is a bug */
344
				mmerror(PARSE_ERROR, ET_ERROR, "type %s already defined", name);
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
		}
		adjust_array(type_enum, &dimension, &length, type_dimension, type_index, array, true);

		this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));

		/* initial definition */
		this->next = types;
		this->name = name;
		this->brace_level = braces_open;
		this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
		this->type->type_enum = type_enum;
		this->type->type_str = mm_strdup(name);
		this->type->type_dimension = dimension; /* dimension of array */
		this->type->type_index = length;	/* length of string */
		this->type->type_sizeof = ECPGstruct_sizeof;
		this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ?
		ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL;

		if (type_enum != ECPGt_varchar &&
			type_enum != ECPGt_char &&
			type_enum != ECPGt_unsigned_char &&
			atoi(this->type->type_index) >= 0)
367
			mmerror(PARSE_ERROR, ET_ERROR, "no multidimensional array support for simple data types");
368 369 370 371

		types = this;
	}
}
372 373
%}

374 375 376
%name-prefix="base_yy"
%locations

377
%union {
378 379
	double	dval;
	char	*str;
380
	int     ival;
381 382 383 384 385 386 387
	struct	when		action;
	struct	index		index;
	int		tagname;
	struct	this_type	type;
	enum	ECPGttype	type_enum;
	enum	ECPGdtype	dtype_enum;
	struct	fetch_desc	descriptor;
388
	struct  su_symbol	struct_union;
389
	struct	prep		prep;
390 391
}

Marc G. Fournier's avatar
Marc G. Fournier committed
392
/* special embedded SQL token */
393
%token	SQL_ALLOCATE SQL_AUTOCOMMIT SQL_BOOL SQL_BREAK
394
		SQL_CALL SQL_CARDINALITY SQL_CONNECT
395
		SQL_COUNT
396
		SQL_DATETIME_INTERVAL_CODE
397
		SQL_DATETIME_INTERVAL_PRECISION SQL_DESCRIBE
398
		SQL_DESCRIPTOR SQL_DISCONNECT SQL_FOUND
Michael Meskes's avatar
Michael Meskes committed
399
		SQL_FREE SQL_GET SQL_GO SQL_GOTO SQL_IDENTIFIED
400
		SQL_INDICATOR SQL_KEY_MEMBER SQL_LENGTH
401
		SQL_LONG SQL_NULLABLE SQL_OCTET_LENGTH
Michael Meskes's avatar
Michael Meskes committed
402
		SQL_OPEN SQL_OUTPUT SQL_REFERENCE
403 404 405
		SQL_RETURNED_LENGTH SQL_RETURNED_OCTET_LENGTH SQL_SCALE
		SQL_SECTION SQL_SHORT SQL_SIGNED SQL_SQL SQL_SQLERROR
		SQL_SQLPRINT SQL_SQLWARNING SQL_START SQL_STOP
406
		SQL_STRUCT SQL_UNSIGNED SQL_VAR SQL_WHENEVER
Marc G. Fournier's avatar
Marc G. Fournier committed
407 408

/* C token */
409 410 411 412
%token	S_ADD S_AND S_ANYTHING S_AUTO S_CONST S_DEC S_DIV
		S_DOTPOINT S_EQUAL S_EXTERN S_INC S_LSHIFT S_MEMPOINT
		S_MEMBER S_MOD S_MUL S_NEQUAL S_OR S_REGISTER S_RSHIFT
		S_STATIC S_SUB S_VOLATILE
413
		S_TYPEDEF
Marc G. Fournier's avatar
Marc G. Fournier committed
414 415

/* I need this and don't know where it is defined inside the backend */
416
%token	TYPECAST
Marc G. Fournier's avatar
Marc G. Fournier committed
417

418
/* ordinary key words in alphabetical order */
419
%token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
420
	AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC
421
	ASSERTION ASSIGNMENT ASYMMETRIC AT AUTHORIZATION
422

423 424
	BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
	BOOLEAN_P BOTH BY
425

426
	CACHE CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_P
427 428
	CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
	CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT
429
	COMMITTED CONCURRENTLY CONFIGURATION CONNECTION CONSTRAINT CONSTRAINTS 
Michael Meskes's avatar
Michael Meskes committed
430
	CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE CREATEDB
431 432
	CREATEROLE CREATEUSER CROSS CSV CTYPE CURRENT_P
	CURRENT_CATALOG CURRENT_DATE CURRENT_ROLE CURRENT_SCHEMA
433
	CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE
434

435
	DATA_P DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS
436 437
	DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DESC
	DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP
438

439
	EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EXCEPT EXCLUSIVE EXCLUDING
440
	EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
441

442
	FALSE_P FAMILY FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD FREEZE FROM
443
	FULL FUNCTION
444

Michael Meskes's avatar
Michael Meskes committed
445
	GLOBAL GRANT GRANTED GREATEST GROUP_P
446

447
	HANDLER HAVING HEADER_P HOLD HOUR_P
448

Michael Meskes's avatar
Michael Meskes committed
449 450 451 452
	IDENTITY_P IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P
	INCLUDING INCREMENT INDEX INDEXES INHERIT INHERITS INITIALLY
	INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
	INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
453

454
	JOIN
455

456
	KEY
457

458 459 460
	LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEAST LEFT LEVEL
	LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
	LOCK_P LOGIN_P
461

462
	MAPPING MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
463

464
	NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
465
	NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
466
	NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC
467

468
	OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OR ORDER
469
	OUT_P OUTER_P OVERLAPS OVERLAY OWNED OWNER
470

471
	PARSER PARTIAL PASSWORD PLACING PLANS POSITION
472 473
	PRECISION PRESERVE PREPARE PREPARED PRIMARY
	PRIOR PRIVILEGES PROCEDURAL PROCEDURE
474

475
	QUOTE
476

477
	READ REAL REASSIGN RECHECK RECURSIVE REFERENCES REINDEX RELATIVE_P RELEASE RENAME
478 479
	REPEATABLE REPLACE REPLICA RESET RESTART RESTRICT RETURNING RETURNS REVOKE
	RIGHT ROLE ROLLBACK ROW ROWS RULE
480

481
	SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE
482
	SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
483 484 485
	SHOW SIMILAR SIMPLE SMALLINT SOME STABLE STANDALONE_P START STATEMENT
	STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP_P SUBSTRING SUPERUSER_P
	SYMMETRIC SYSID SYSTEM_P
486

487
	TABLE TABLESPACE TEMP TEMPLATE TEMPORARY TEXT_P THEN TIME TIMESTAMP TO 
488
	TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P TRUNCATE TRUSTED TYPE_P
489

490
	UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL
491
	UPDATE USER USING
492

493
	VACUUM VALID VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING
494 495 496 497 498 499 500 501
	VERBOSE VERSION_P VIEW VOLATILE
	WHEN WHERE WHITESPACE_P WITH WITHOUT WORK WRITE

	XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLFOREST XMLPARSE
	XMLPI XMLROOT XMLSERIALIZE

	YEAR_P YES_P

502
	ZONE
Marc G. Fournier's avatar
Marc G. Fournier committed
503

504 505 506 507
/* The grammar thinks these are keywords, but they are not in the keywords.c
 * list and so can never be entered directly.  The filter in parser.c
 * creates these tokens when required.
 */
508
%token           NULLS_FIRST NULLS_LAST WITH_TIME
509

510
/* Special token types, not actually keywords - see the "lex" file */
511 512
%token <str>	IDENT SCONST Op CSTRING CVARIABLE CPP_LINE IP BCONST
%token <str>	XCONST DOLCONST ECONST NCONST
513 514
%token <ival>	ICONST PARAM
%token <dval>	FCONST
Marc G. Fournier's avatar
Marc G. Fournier committed
515

Michael Meskes's avatar
Michael Meskes committed
516
/* precedence: lowest to highest */
517
%nonassoc	SET                             /* see relation_expr_opt_alias */
518 519
%left		UNION EXCEPT
%left		INTERSECT
Marc G. Fournier's avatar
Marc G. Fournier committed
520 521 522 523 524
%left		OR
%left		AND
%right		NOT
%right		'='
%nonassoc	'<' '>'
525
%nonassoc	LIKE ILIKE SIMILAR
526
%nonassoc	ESCAPE
Michael Meskes's avatar
Michael Meskes committed
527
%nonassoc	OVERLAPS
Michael Meskes's avatar
Michael Meskes committed
528
%nonassoc	BETWEEN
Jan Wieck's avatar
Jan Wieck committed
529
%nonassoc	IN_P
530 531 532
%left		POSTFIXOP		/* dummy for postfix Op rules */
%nonassoc	IDENT			/* to support target_el without AS */
%left		Op OPERATOR		/* multi-character ops and user-defined operators */
Marc G. Fournier's avatar
Marc G. Fournier committed
533 534
%nonassoc	NOTNULL
%nonassoc	ISNULL
535
%nonassoc	IS NULL_P TRUE_P FALSE_P UNKNOWN
Marc G. Fournier's avatar
Marc G. Fournier committed
536
%left		'+' '-'
Michael Meskes's avatar
Michael Meskes committed
537
%left		'*' '/' '%'
Michael Meskes's avatar
Michael Meskes committed
538
%left		'^'
Marc G. Fournier's avatar
Marc G. Fournier committed
539
/* Unary Operators */
540
%left		AT ZONE
Marc G. Fournier's avatar
Marc G. Fournier committed
541 542
%right		UMINUS
%left		'[' ']'
543
%left		'(' ')'
Michael Meskes's avatar
Michael Meskes committed
544
%left		TYPECAST
545
%left		'.'
546
%left		JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL
547 548
/* kluge to keep xml_whitespace_option from causing shift/reduce conflicts */
%right         PRESERVE STRIP_P
Marc G. Fournier's avatar
Marc G. Fournier committed
549

550
%type  <str>	Iconst Fconst Sconst TransactionStmt CreateStmt RoleId
Marc G. Fournier's avatar
Marc G. Fournier committed
551
%type  <str>	CreateAsElement OptCreateAs CreateAsList CreateAsStmt
552
%type  <str>	comment_text ConstraintDeferrabilitySpec TableElementList
553
%type  <str>	key_match ColLabel SpecialRuleRelation ColId columnDef
554
%type  <str>	ColConstraint ColConstraintElem drop_type Bconst Iresult
555
%type  <str>	TableConstraint OptTableElementList Xconst opt_transaction
556
%type  <str>	ConstraintElem key_actions ColQualList cluster_index_specification
557 558
%type  <str>	target_list target_el alias_clause type_func_name_keyword
%type  <str>	qualified_name database_name alter_using type_function_name
Michael Meskes's avatar
Michael Meskes committed
559
%type  <str>	access_method attr_name index_name name func_name opt_restart_seqs
Michael Meskes's avatar
Michael Meskes committed
560
%type  <str>	file_name AexprConst c_expr ConstTypename var_list 
Michael Meskes's avatar
Michael Meskes committed
561
%type  <str>	a_expr b_expr TruncateStmt CommentStmt OnCommitOption opt_by
Michael Meskes's avatar
Michael Meskes committed
562
%type  <str>	opt_indirection expr_list extract_list extract_arg OptSeqOptList
Michael Meskes's avatar
Michael Meskes committed
563
%type  <str>	position_list substr_list substr_from alter_column_default
564
%type  <str>	trim_list in_expr substr_for attrs TableFuncElement
565 566
%type  <str>	Typename SimpleTypename Numeric opt_float DiscardStmt
%type  <str>	Character character opt_varying opt_charset enum_val_list
567
%type  <str>	opt_timezone opt_interval table_ref fetch_direction
Michael Meskes's avatar
Michael Meskes committed
568
%type  <str>	ConstDatetime AlterDomainStmt AlterSeqStmt table_func_column
Michael Meskes's avatar
Michael Meskes committed
569 570
%type  <str>	SelectStmt into_clause OptTemp ConstraintAttributeSpec
%type  <str>	opt_table opt_all sort_clause sortby_list ConstraintAttr
571
%type  <str>	sortby qualified_name_list name_list ColId_or_Sconst
572
%type  <str>	group_clause having_clause from_clause opt_distinct opt_hold
573
%type  <str>	join_outer where_clause relation_expr sub_type arg_class
574
%type  <str>	opt_column_list insert_rest InsertStmt param_name
575
%type  <str>	columnList DeleteStmt UpdateStmt DeclareCursorStmt
576
%type  <str>	NotifyStmt columnElem UnlistenStmt TableElement fetch_count
Michael Meskes's avatar
Michael Meskes committed
577
%type  <str>	copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary
578
%type  <str>	FetchStmt from_in CreateOpClassStmt returning_clause
579
%type  <str>	ClosePortalStmt DropStmt VacuumStmt AnalyzeStmt opt_verbose
580
%type  <str>	opt_full func_arg OptWith opt_freeze alter_table_cmd
581
%type  <str>	analyze_keyword opt_name_list ExplainStmt index_params
582
%type  <str>	index_elem opt_class access_method_clause alter_table_cmds
583
%type  <str>	index_opt_unique IndexStmt func_return ConstInterval
584
%type  <str>	func_args_list func_args opt_with def_arg overlay_placing
Michael Meskes's avatar
Michael Meskes committed
585 586 587
%type  <str>	def_elem def_list definition DefineStmt select_with_parens
%type  <str>	opt_instead event RuleActionList opt_using CreateAssertStmt
%type  <str>	RuleActionStmtOrEmpty RuleActionMulti func_as reindex_type
588
%type  <str>	RuleStmt opt_column opt_set_data oper_argtypes NumConst var_name
589
%type  <str>	MathOp RemoveFuncStmt ECPGunreserved_con opt_database_name
590
%type  <str>	RemoveAggrStmt opt_procedural select_no_parens CreateCastStmt
591
%type  <str>	RemoveOperStmt RenameStmt all_Op opt_trusted opt_lancompiler
592
%type  <str>	VariableSetStmt var_value zone_value VariableShowStmt
593
%type  <str>	VariableResetStmt AlterTableStmt from_list overlay_list
Michael Meskes's avatar
Michael Meskes committed
594
%type  <str>	relation_name OptTableSpace LockStmt opt_lock table_func_column_list
Michael Meskes's avatar
Michael Meskes committed
595 596
%type  <str>	CreateUserStmt AlterUserStmt CreateSeqStmt SeqOptList
%type  <str>	SeqOptElem TriggerForSpec TriggerForOpt TriggerForType
Michael Meskes's avatar
Michael Meskes committed
597
%type  <str>	DropTrigStmt TriggerOneEvent TriggerEvents RuleActionStmt
598
%type  <str>	TriggerActionTime CreateTrigStmt DropPLangStmt DropCastStmt
Michael Meskes's avatar
Michael Meskes committed
599
%type  <str>	CreatePLangStmt TriggerFuncArgs TriggerFuncArg simple_select
600
%type  <str>	ViewStmt LoadStmt CreatedbStmt createdb_opt_item ExplainableStmt
Michael Meskes's avatar
Michael Meskes committed
601
%type  <str>	createdb_opt_list opt_encoding OptInherit opt_equal
602
%type  <str>	privilege_list privilege privilege_target opt_if_exists
603
%type  <str>	opt_grant_grant_option cursor_options DropOwnedStmt
Michael Meskes's avatar
Michael Meskes committed
604
%type  <str>	transaction_mode_list_or_empty transaction_mode_list
605
%type  <str>	function_with_argtypes_list function_with_argtypes IntConstVar
606
%type  <str>	DropdbStmt ClusterStmt grantee RevokeStmt Bit DropOpClassStmt
Michael Meskes's avatar
Michael Meskes committed
607
%type  <str>	GrantStmt privileges PosAllConst constraints_set_list
608
%type  <str>	ConstraintsSetStmt AllConst CreateDomainStmt opt_nowait
609
%type  <str>	case_expr when_clause_list case_default case_arg when_clause
610
%type  <str>	select_clause opt_select_limit select_limit_value opt_recheck
Michael Meskes's avatar
Michael Meskes committed
611
%type  <str>	ConstraintTimeSpec AlterDatabaseSetStmt DropAssertStmt
612
%type  <str>	select_offset_value ReindexStmt join_type opt_boolean
613 614
%type  <str>	join_qual joined_table opclass_item relation_expr_opt_alias
%type  <str>	lock_type array_expr_list ReassignOwnedStmt for_locking_item
615
%type  <str>	OptConstrFromTable OptTempTableName StringConst array_expr
616
%type  <str>	constraints_set_mode comment_type opt_check_option
Michael Meskes's avatar
Michael Meskes committed
617 618 619
%type  <str>	CreateGroupStmt AlterGroupStmt DropGroupStmt key_delete
%type  <str>	opt_force key_update CreateSchemaStmt PosIntStringConst
%type  <str>	IntConst PosIntConst grantee_list func_type opt_or_replace
620
%type  <str>	select_limit CheckPointStmt ECPGColId old_aggr_list
Michael Meskes's avatar
Michael Meskes committed
621 622
%type  <str>	OptSchemaName OptSchemaEltList schema_stmt opt_drop_behavior
%type  <str>	handler_name any_name_list any_name opt_as insert_column_list
623 624
%type  <str>	columnref values_clause AllConstVar prep_type_clause ExecuteStmt
%type  <str>	insert_column_item DropRuleStmt ctext_expr execute_param_clause 
Michael Meskes's avatar
Michael Meskes committed
625 626
%type  <str>	createfunc_opt_item set_rest with_clause common_table_expr
%type  <str>	CreateFunctionStmt createfunc_opt_list func_table cte_list
Michael Meskes's avatar
Michael Meskes committed
627
%type  <str>	DropUserStmt copy_from copy_opt_list copy_opt_item
628
%type  <str>	opt_oids TableLikeClause key_action opt_definition
629
%type  <str>	cast_context row qual_Op qual_all_Op opt_default
630
%type  <str>	CreateConversionStmt any_operator opclass_item_list
631
%type  <str>	iso_level type_list CharacterWithLength ConstCharacter
632
%type  <str>	CharacterWithoutLength BitWithLength BitWithoutLength
633
%type  <str>	ConstBit GenericType TableFuncElementList opt_analyze
Michael Meskes's avatar
Michael Meskes committed
634
%type  <str>	opt_sort_clause subquery_Op transaction_mode_item
Michael Meskes's avatar
Michael Meskes committed
635
%type  <str>	ECPGWhenever ECPGConnect connection_target ECPGOpen
Michael Meskes's avatar
Michael Meskes committed
636
%type  <str>	indicator ecpg_using ecpg_into DeallocateStmt interval_second
637
%type  <str>	storage_declaration storage_clause opt_initializer c_anything
638
%type  <str>	variable_list variable c_thing c_term ECPGKeywords_vanames
639
%type  <str>	opt_pointer ECPGDisconnect dis_name storage_modifier
Michael Meskes's avatar
Michael Meskes committed
640
%type  <str>	execstring server_name ECPGVarDeclaration func_expr
641
%type  <str>	connection_object opt_server opt_port c_stuff c_stuff_item
642
%type  <str>	user_name opt_user char_variable ora_user ident opt_reference
643
%type  <str>	var_type_declarations quoted_ident_stringvar ECPGKeywords_rest
644
%type  <str>	db_prefix server connect_options opt_options opt_connection_name c_list
645
%type  <str>	ECPGSetConnection ECPGTypedef c_args ECPGKeywords ECPGCKeywords
646
%type  <str>	enum_type civar civarind ECPGCursorStmt PreparableStmt
647
%type  <str>	ECPGFree ECPGDeclare ECPGVar at enum_definition opt_opt_value
Michael Meskes's avatar
Michael Meskes committed
648
%type  <str>	struct_union_type s_struct_union vt_declarations execute_rest
649
%type  <str>	var_declaration type_declaration single_vt_declaration
650
%type  <str>	ECPGSetAutocommit on_off variable_declarations ECPGDescribe
651
%type  <str>	ECPGAllocateDescr ECPGDeallocateDescr symbol opt_output
652
%type  <str>	ECPGGetDescriptorHeader ECPGColLabel SetResetClause AlterUserSetStmt
Michael Meskes's avatar
Michael Meskes committed
653
%type  <str>	reserved_keyword unreserved_keyword ecpg_interval opt_ecpg_using
654
%type  <str>	col_name_keyword precision opt_scale ECPGExecuteImmediateStmt
655 656
%type  <str>	ECPGTypeName using_list ECPGColLabelCommon UsingConst 
%type  <str>	using_descriptor into_descriptor opt_nulls_order opt_asc_desc
Michael Meskes's avatar
Michael Meskes committed
657
%type  <str>	prepared_name struct_union_type_with_symbol OptConsTableSpace
658
%type  <str>	ECPGunreserved ECPGunreserved_interval cvariable opt_bit_field
659
%type  <str>	AlterOwnerStmt OptTableSpaceOwner CreateTableSpaceStmt
660
%type  <str>	DropTableSpaceStmt indirection indirection_el ECPGSetDescriptorHeader
661
%type  <str>	AlterDatabaseStmt CreateRoleStmt OptRoleList AlterRoleStmt AlterRoleSetStmt
662
%type  <str>	DropRoleStmt add_drop opt_validator common_func_opt_item Param
663 664 665
%type  <str>	opt_grant_admin_option AlterFunctionStmt alterfunc_opt_list opt_restrict
%type  <str>	AlterObjectSchemaStmt alterdb_opt_list for_locking_clause opt_for_locking_clause
%type  <str>	locked_rels_list opt_granted_by RevokeRoleStmt alterdb_opt_item using_clause
666
%type  <str>	GrantRoleStmt opt_asymmetric aggr_args old_aggr_definition
667
%type  <str>	old_aggr_elem for_locking_items TableLikeOptionList TableLikeOption
Michael Meskes's avatar
Michael Meskes committed
668
%type  <str>	set_target_list	set_clause_list set_clause multiple_set_clause
669 670 671 672 673
%type  <str>	ctext_expr_list ctext_row single_set_clause set_target opt_type_modifiers
%type  <str>	opclass_drop_list opclass_drop DropOpFamilyStmt opt_opfamily
%type  <str>	CreateOpFamilyStmt AlterOpFamilyStmt create_as_target
%type  <str>	xml_attributes xml_attribute_list document_or_content xml_whitespace_option
%type  <str>	opt_xml_root_standalone xml_root_version xml_attribute_el 
674
%type  <str>	where_or_current_clause AlterTSConfigurationStmt AlterTSDictionaryStmt
675 676

%type  <struct_union> s_struct_union_symbol
Michael Meskes's avatar
Michael Meskes committed
677

678
%type  <descriptor> ECPGGetDescriptor ECPGSetDescriptor
679

680
%type  <type_enum> simple_type signed_type unsigned_type
Marc G. Fournier's avatar
Marc G. Fournier committed
681

Michael Meskes's avatar
Michael Meskes committed
682 683
%type  <dtype_enum> descriptor_item desc_header_item

684
%type  <type>	var_type
685

686 687
%type  <prep>	PrepareStmt

Marc G. Fournier's avatar
Marc G. Fournier committed
688 689
%type  <action> action

690
%type  <index>	opt_array_bounds
691

Marc G. Fournier's avatar
Marc G. Fournier committed
692 693 694
%%
prog: statements;

695 696
statements: /*EMPTY*/
		| statements statement
697
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
698

699
statement: ecpgstart at stmt ';'	{ connection = NULL; }
700
		| ecpgstart stmt ';'
701 702 703
		| ecpgstart ECPGVarDeclaration
		{
			fprintf(yyout, "%s", $2);
704
			free($2);
705 706
			output_line_number();
		}
707
		| ECPGDeclaration
708 709 710
		| c_thing		{ fprintf(yyout, "%s", $1); free($1); }
		| CPP_LINE		{ fprintf(yyout, "%s", $1); free($1); }
		| '{'			{ braces_open++; fputs("{", yyout); }
711
		| '}'			{ remove_typedefs(braces_open); remove_variables(braces_open--); fputs("}", yyout); }
712 713
		;

714
at: AT connection_object
715 716 717
		{
			connection = $2;
			/*
718 719
			 *	Do we have a variable as connection target?
			 *	Remove the variable from the variable
720 721 722 723
			 *	list or else it will be used twice
			 */
			if (argsinsert != NULL)
				argsinsert = NULL;
724 725 726 727 728 729 730 731 732 733 734 735 736 737
		}
	;

stmt:  AlterDatabaseStmt		{ output_statement($1, 0, ECPGst_normal); }
		| AlterDatabaseSetStmt	{ output_statement($1, 0, ECPGst_normal); }
		| AlterDomainStmt	{ output_statement($1, 0, ECPGst_normal); }
		| AlterFunctionStmt	{ output_statement($1, 0, ECPGst_normal); }
		| AlterGroupStmt	{ output_statement($1, 0, ECPGst_normal); }
		| AlterObjectSchemaStmt	{ output_statement($1, 0, ECPGst_normal); }
		| AlterOwnerStmt	{ output_statement($1, 0, ECPGst_normal); }
		| AlterSeqStmt		{ output_statement($1, 0, ECPGst_normal); }
		| AlterTableStmt	{ output_statement($1, 0, ECPGst_normal); }
		| AlterRoleSetStmt	{ output_statement($1, 0, ECPGst_normal); }
		| AlterRoleStmt		{ output_statement($1, 0, ECPGst_normal); }
738 739
		| AlterTSConfigurationStmt	{ output_statement($1, 0, ECPGst_normal); }
		| AlterTSDictionaryStmt	{ output_statement($1, 0, ECPGst_normal); }
740
		| AlterUserStmt		{ output_statement($1, 0, ECPGst_normal); }
741
		| AlterUserSetStmt	{ output_statement($1, 0, ECPGst_normal); }
742 743
		| AnalyzeStmt		{ output_statement($1, 0, ECPGst_normal); }
		| CheckPointStmt	{ output_statement($1, 0, ECPGst_normal); }
744 745 746 747
		| ClosePortalStmt
		{
			if (INFORMIX_MODE)
			{
748 749 750 751 752
				/*
				 *	Informix also has a CLOSE DATABASE command that
				 *	essantially works like a DISCONNECT CURRENT
				 *	as far as I know.
				 */
753
				if (pg_strcasecmp($1+strlen("close "), "database") == 0)
754 755
				{
					if (connection)
756
						mmerror(PARSE_ERROR, ET_ERROR, "no at option for close database statement\n");
757

758
					fprintf(yyout, "{ ECPGdisconnect(__LINE__, \"CURRENT\");");
759 760
					whenever_action(2);
					free($1);
761 762
				}
				else
763
					output_statement($1, 0, ECPGst_normal);
764 765
			}
			else
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
				output_statement($1, 0, ECPGst_normal);
		}
		| ClusterStmt		{ output_statement($1, 0, ECPGst_normal); }
		| CommentStmt		{ output_statement($1, 0, ECPGst_normal); }
		| ConstraintsSetStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CopyStmt		{ output_statement($1, 0, ECPGst_normal); }
		| CreateAsStmt		{ output_statement($1, 0, ECPGst_normal); }
		| CreateAssertStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreateCastStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreateConversionStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreateDomainStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreateFunctionStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreateGroupStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreatePLangStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreateOpClassStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreateOpFamilyStmt	{ output_statement($1, 0, ECPGst_normal); }
		| AlterOpFamilyStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreateRoleStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreateSchemaStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreateSeqStmt		{ output_statement($1, 0, ECPGst_normal); }
		| CreateStmt		{ output_statement($1, 0, ECPGst_normal); }
		| CreateTableSpaceStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreateTrigStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreateUserStmt	{ output_statement($1, 0, ECPGst_normal); }
		| CreatedbStmt		{ output_statement($1, 0, ECPGst_normal); }
		| DeallocateStmt
		{
			if (connection)
794
				mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement\n");
795 796
				
			output_deallocate_prepare_statement($1);
797
		}
798
		| DeclareCursorStmt	{ output_simple_statement($1); }
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
		| DefineStmt		{ output_statement($1, 0, ECPGst_normal); }
		| DeleteStmt		{ output_statement($1, 1, ECPGst_normal); }
		| DiscardStmt		{ output_statement($1, 1, ECPGst_normal); }
		| DropAssertStmt	{ output_statement($1, 0, ECPGst_normal); }
		| DropCastStmt		{ output_statement($1, 0, ECPGst_normal); }
		| DropGroupStmt		{ output_statement($1, 0, ECPGst_normal); }
		| DropOpClassStmt	{ output_statement($1, 0, ECPGst_normal); }
		| DropOpFamilyStmt	{ output_statement($1, 0, ECPGst_normal); }
		| DropOwnedStmt		{ output_statement($1, 0, ECPGst_normal); }
		| DropPLangStmt		{ output_statement($1, 0, ECPGst_normal); }
		| DropRoleStmt		{ output_statement($1, 0, ECPGst_normal); }
		| DropRuleStmt		{ output_statement($1, 0, ECPGst_normal); }
		| DropStmt		{ output_statement($1, 0, ECPGst_normal); }
		| DropTableSpaceStmt	{ output_statement($1, 0, ECPGst_normal); }
		| DropTrigStmt		{ output_statement($1, 0, ECPGst_normal); }
		| DropUserStmt		{ output_statement($1, 0, ECPGst_normal); }
		| DropdbStmt		{ output_statement($1, 0, ECPGst_normal); }
		| ExplainStmt		{ output_statement($1, 0, ECPGst_normal); }
817
		| ExecuteStmt		{ output_statement($1, 1, ECPGst_execute); }
818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
		| FetchStmt		{ output_statement($1, 1, ECPGst_normal); }
		| GrantStmt		{ output_statement($1, 0, ECPGst_normal); }
		| GrantRoleStmt		{ output_statement($1, 0, ECPGst_normal); }
		| IndexStmt		{ output_statement($1, 0, ECPGst_normal); }
		| InsertStmt		{ output_statement($1, 1, ECPGst_normal); }
		| ListenStmt		{ output_statement($1, 0, ECPGst_normal); }
		| LoadStmt		{ output_statement($1, 0, ECPGst_normal); }
		| LockStmt		{ output_statement($1, 0, ECPGst_normal); }
		| NotifyStmt		{ output_statement($1, 0, ECPGst_normal); }
		| PrepareStmt		{ 
						if ($1.type == NULL || strlen($1.type) == 0) /* use PQprepare without type parameters */
							output_prepare_statement($1.name, $1.stmt);  
						else	/* use PQexec and let backend do its stuff */
						{
							char *txt = cat_str(5, make_str("prepare"), $1.name, $1.type, make_str("as"), $1.stmt);
							output_statement(txt, 0, ECPGst_normal);
						}
					}		
		| ReassignOwnedStmt	{ output_statement($1, 0, ECPGst_normal); }
		| ReindexStmt		{ output_statement($1, 0, ECPGst_normal); }
		| RemoveAggrStmt	{ output_statement($1, 0, ECPGst_normal); }
		| RemoveOperStmt	{ output_statement($1, 0, ECPGst_normal); }
		| RemoveFuncStmt	{ output_statement($1, 0, ECPGst_normal); }
		| RenameStmt		{ output_statement($1, 0, ECPGst_normal); }
		| RevokeStmt		{ output_statement($1, 0, ECPGst_normal); }
		| RevokeRoleStmt	{ output_statement($1, 0, ECPGst_normal); }
		| RuleStmt		{ output_statement($1, 0, ECPGst_normal); }
		| SelectStmt		{ output_statement($1, 1, ECPGst_normal); }
846 847 848 849 850 851
		| TransactionStmt
		{
			fprintf(yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
			whenever_action(2);
			free($1);
		}
852 853 854 855 856 857 858 859
		| TruncateStmt		{ output_statement($1, 0, ECPGst_normal); }
		| UnlistenStmt		{ output_statement($1, 0, ECPGst_normal); }
		| UpdateStmt		{ output_statement($1, 1, ECPGst_normal); }
		| VacuumStmt		{ output_statement($1, 0, ECPGst_normal); }
		| VariableSetStmt	{ output_statement($1, 0, ECPGst_normal); }
		| VariableShowStmt	{ output_statement($1, 0, ECPGst_normal); }
		| VariableResetStmt	{ output_statement($1, 0, ECPGst_normal); }
		| ViewStmt		{ output_statement($1, 0, ECPGst_normal); }
860 861 862 863 864 865 866 867 868
		| ECPGAllocateDescr
		{
			fprintf(yyout,"ECPGallocate_desc(__LINE__, %s);",$1);
			whenever_action(0);
			free($1);
		}
		| ECPGConnect
		{
			if (connection)
869
				mmerror(PARSE_ERROR, ET_ERROR, "no at option for connect statement\n");
870

871
			fprintf(yyout, "{ ECPGconnect(__LINE__, %d, %s, %d); ", compat, $1, autocommit);
872 873 874 875 876 877 878 879 880 881
			reset_variables();
			whenever_action(2);
			free($1);
		}
		| ECPGCursorStmt
		{
			output_simple_statement($1);
		}
		| ECPGDeallocateDescr
		{
Michael Meskes's avatar
Michael Meskes committed
882
			if (connection)
883
				mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement\n");
884 885 886 887 888 889 890 891
			fprintf(yyout,"ECPGdeallocate_desc(__LINE__, %s);",$1);
			whenever_action(0);
			free($1);
		}
		| ECPGDeclare
		{
			output_simple_statement($1);
		}
892 893
		| ECPGDescribe
		{
894 895 896 897 898
			fprintf(yyout, "{ ECPGdescribe(__LINE__, %s,", $1);
			dump_variables(argsresult, 1);
			fputs("ECPGt_EORT);", yyout);
			fprintf(yyout, "}");
			output_line_number();
899

900 901 902
			/* whenever_action(2); */
			free($1);
		}
903 904 905
		| ECPGDisconnect
		{
			if (connection)
906
				mmerror(PARSE_ERROR, ET_ERROR, "no at option for disconnect statement\n");
907

908 909
			fprintf(yyout, "{ ECPGdisconnect(__LINE__, %s);",
					$1 ? $1 : "\"CURRENT\"");
910 911 912
			whenever_action(2);
			free($1);
		}
913
		| ECPGExecuteImmediateStmt	{ output_statement($1, 0, ECPGst_exec_immediate); }
914 915
		| ECPGFree
		{
916
			const char *con = connection ? connection : "NULL";
917
			if (strcmp($1, "all"))
918
				fprintf(yyout, "{ ECPGdeallocate(__LINE__, %d, %s, \"%s\");", compat, con, $1);
919
			else
920
				fprintf(yyout, "{ ECPGdeallocate_all(__LINE__, %d, %s);", compat, con);
921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941

			whenever_action(2);
			free($1);
		}
		| ECPGGetDescriptor
		{
			lookup_descriptor($1.name, connection);
			output_get_descr($1.name, $1.str);
			free($1.name);
			free($1.str);
		}
		| ECPGGetDescriptorHeader
		{
			lookup_descriptor($1, connection);
			output_get_descr_header($1);
			free($1);
		}
		| ECPGOpen
		{
			struct cursor *ptr;

942
			if ((ptr = add_additional_variables($1, true)) != NULL)
943
			{
944 945
				connection = ptr->connection ? mm_strdup(ptr->connection) : NULL;
				output_statement(mm_strdup(ptr->command), 0, 0);
946 947
				ptr->opened = true;
			}
948 949 950 951 952 953 954 955 956 957
		}
		| ECPGSetAutocommit
		{
			fprintf(yyout, "{ ECPGsetcommit(__LINE__, \"%s\", %s);", $1, connection ? connection : "NULL");
			whenever_action(2);
			free($1);
		}
		| ECPGSetConnection
		{
			if (connection)
958
				mmerror(PARSE_ERROR, ET_ERROR, "no at option for set connection statement\n");
959

960 961 962 963
			fprintf(yyout, "{ ECPGsetconn(__LINE__, %s);", $1);
			whenever_action(2);
			free($1);
		}
964 965 966 967 968 969 970 971 972 973 974 975 976
		| ECPGSetDescriptor
		{
			lookup_descriptor($1.name, connection);
			output_set_descr($1.name, $1.str);
			free($1.name);
			free($1.str);
		}
		| ECPGSetDescriptorHeader
		{
			lookup_descriptor($1, connection);
			output_set_descr_header($1);
			free($1);
		}
977 978 979
		| ECPGTypedef
		{
			if (connection)
980
				mmerror(PARSE_ERROR, ET_ERROR, "no at option for typedef statement\n");
981

982 983 984
			fprintf(yyout, "%s", $1);
			free($1);
			output_line_number();
985 986 987 988
		}
		| ECPGVar
		{
			if (connection)
989
				mmerror(PARSE_ERROR, ET_ERROR, "no at option for var statement\n");
990

991 992 993 994 995
			output_simple_statement($1);
		}
		| ECPGWhenever
		{
			if (connection)
996
				mmerror(PARSE_ERROR, ET_ERROR, "no at option for whenever statement\n");
997

998 999
			output_simple_statement($1);
		}
1000 1001
		;

Michael Meskes's avatar
Michael Meskes committed
1002 1003 1004 1005 1006 1007 1008

/*
 * We start with a lot of stuff that's very similar to the backend's parsing
 */

/*****************************************************************************
 *
1009
 * Create a new Postgres DBMS role
Michael Meskes's avatar
Michael Meskes committed
1010 1011 1012 1013
 *
 *
 *****************************************************************************/

1014
CreateRoleStmt: CREATE ROLE RoleId opt_with OptRoleList
1015
			{ $$ = cat_str(4, make_str("create role"), $3, $4, $5); }
Michael Meskes's avatar
Michael Meskes committed
1016 1017
		;

1018 1019 1020 1021
opt_with:  WITH 		{ $$ = make_str("with"); }
		| /*EMPTY*/	{ $$ = EMPTY; }
		;

1022 1023 1024 1025 1026 1027 1028
/*
 * Options for CREATE ROLE and ALTER ROLE (also used by CREATE/ALTER USER
 * for backwards compatibility).  Note: the only option required by SQL99
 * is "WITH ADMIN name".
 */
OptRoleList:
	PASSWORD Sconst			{ $$ = cat2_str(make_str("password"), $2); }
1029
	| PASSWORD NULL_P		{ $$ = make_str("password null"); }
1030 1031 1032 1033
	| ENCRYPTED PASSWORD Sconst	{ $$ = cat2_str(make_str("encrypted password"), $3); }
	| UNENCRYPTED PASSWORD Sconst	{ $$ = cat2_str(make_str("unencrypted password"), $3); }
	| SUPERUSER_P			{ $$ = make_str("superuser"); }
	| NOSUPERUSER			{ $$ = make_str("nosuperuser"); }
1034 1035 1036
	| INHERIT				{ $$ = make_str("inherit"); }
	| NOINHERIT				{ $$ = make_str("noinherit"); }
	| CREATEDB				{ $$ = make_str("createdb"); }
1037 1038 1039
	| NOCREATEDB			{ $$ = make_str("nocreatedb"); }
	| CREATEROLE			{ $$ = make_str("createrole"); }
	| NOCREATEROLE			{ $$ = make_str("nocreaterole"); }
1040 1041
	| LOGIN_P				{ $$ = make_str("login"); }
	| NOLOGIN_P				{ $$ = make_str("nologin"); }
1042 1043 1044 1045 1046 1047
	| CONNECTION LIMIT IntConst	{ $$ = cat2_str(make_str("connection limit"), $3); }
	| VALID UNTIL Sconst		{ $$ = cat2_str(make_str("valid until"), $3); }
	| USER name_list		{ $$ = cat2_str(make_str("user"), $2); }
	| SYSID PosIntConst		{ $$ = cat2_str(make_str("sysid"), $2); }
	| ADMIN name_list		{ $$ = cat2_str(make_str("admin"), $2); }
	| ROLE name_list		{ $$ = cat2_str(make_str("role"), $2); }
1048
	| IN_P ROLE name_list	{ $$ = cat2_str(make_str("in role"), $3); }
1049 1050
	| IN_P GROUP_P name_list	{ $$ = cat2_str(make_str("in group"), $3); }
	;
1051

Michael Meskes's avatar
Michael Meskes committed
1052 1053
/*****************************************************************************
 *
1054 1055 1056 1057 1058
 * Create a new Postgres DBMS user (role with implied login ability)
 *
 *****************************************************************************/

CreateUserStmt:
1059 1060 1061
	CREATE USER RoleId opt_with OptRoleList
		{$$ = cat_str(4, make_str("create user"), $3, $4, $5); }
	;
1062

1063 1064 1065 1066 1067 1068
	/*****************************************************************************
	 *
	 * Alter a postgresql DBMS role
	 *
	 *
	 *****************************************************************************/
1069

1070
	AlterRoleStmt: ALTER ROLE RoleId opt_with OptRoleList
1071
			{ $$ = cat_str(4, make_str("alter role"), $3, $4, $5); }
Michael Meskes's avatar
Michael Meskes committed
1072
		;
1073

1074
	AlterRoleSetStmt: ALTER ROLE RoleId SetResetClause
1075 1076
			{ $$ = cat_str(3, make_str("alter role"), $3, $4); }
		;
1077

1078 1079 1080 1081 1082
	/*****************************************************************************
	 *
	 * Alter a postgresql DBMS user
	 *
	 *****************************************************************************/
1083

1084
	AlterUserStmt: ALTER USER RoleId opt_with OptRoleList
1085
		{ $$ = cat_str(4, make_str("alter user"), $3, $4, $5); };
1086

1087
	AlterUserSetStmt: ALTER USER RoleId SetResetClause
Michael Meskes's avatar
Michael Meskes committed
1088 1089
			{ $$ = cat_str(3, make_str("alter user"), $3, $4); }
		;
1090

1091 1092 1093 1094 1095 1096 1097
	/*****************************************************************************
	 *
	 * Drop a postgresql DBMS role
	 *
	 *
	 *****************************************************************************/
	DropRoleStmt:  DROP ROLE name_list
1098
			{ $$ = cat2_str(make_str("drop role"), $3);}
1099 1100
		     | DROP ROLE IF_P EXISTS name_list
		        { $$ = cat2_str(make_str("drop role if exists"), $5);}
1101
		;
1102

1103 1104 1105 1106 1107 1108 1109
	/*****************************************************************************
	 *
	 * Drop a postgresql DBMS user
	 *
	 *
	 *****************************************************************************/
	DropUserStmt:  DROP USER name_list
Michael Meskes's avatar
Michael Meskes committed
1110
			{ $$ = cat2_str(make_str("drop user"), $3);}
1111 1112 1113
		     | DROP USER IF_P EXISTS name_list
			{ $$ = cat2_str(make_str("drop user if exists"), $5);}

Michael Meskes's avatar
Michael Meskes committed
1114
		;
1115

1116 1117 1118 1119 1120 1121 1122
	/*****************************************************************************
	 *
	 * Create a postgresql group
	 *
	 *
	 ****************************************************************************/
	CreateGroupStmt:  CREATE GROUP_P RoleId opt_with OptRoleList
1123
			{ $$ = cat_str(4, make_str("create group"), $3, $4, $5); }
Michael Meskes's avatar
Michael Meskes committed
1124
		;
1125

1126 1127 1128 1129 1130 1131 1132
	/*****************************************************************************
	 *
	 * Alter a postgresql group
	 *
	 *
	 *****************************************************************************/
	AlterGroupStmt: ALTER GROUP_P RoleId add_drop USER name_list
1133
			{ $$ = cat_str(5, make_str("alter group"), $3, $4, make_str("user"), $6); }
Michael Meskes's avatar
Michael Meskes committed
1134
		;
1135 1136 1137

	add_drop: ADD_P		{ $$ = make_str("add"); }
		| DROP 		{ $$ = make_str("drop"); }
1138
		;
1139

1140 1141 1142 1143 1144 1145 1146
	/*****************************************************************************
	 *
	 * Drop a postgresql group
	 *
	 *
	 *****************************************************************************/
	DropGroupStmt: DROP GROUP_P name_list
Michael Meskes's avatar
Michael Meskes committed
1147
			{ $$ = cat2_str(make_str("drop group"), $3); }
1148 1149
		     | DROP GROUP_P IF_P EXISTS name_list
			{ $$ = cat2_str(make_str("drop group if exists"), $5); }
Michael Meskes's avatar
Michael Meskes committed
1150
		;
1151

1152 1153 1154 1155 1156 1157
	/*****************************************************************************
	 *
	 * Manipulate a schema
	 *
	 *
	 *****************************************************************************/
1158

1159
	CreateSchemaStmt:  CREATE SCHEMA OptSchemaName AUTHORIZATION RoleId OptSchemaEltList
1160 1161 1162
			{ $$ = cat_str(5, make_str("create schema"), $3, make_str("authorization"), $5, $6); }
		| CREATE SCHEMA ColId OptSchemaEltList
			{ $$ = cat_str(3, make_str("create schema"), $3, $4); }
Michael Meskes's avatar
Michael Meskes committed
1163
		;
1164

1165 1166 1167
	OptSchemaName: ColId		{ $$ = $1; }
		| /* EMPTY */	{ $$ = EMPTY; }
		;
Michael Meskes's avatar
Michael Meskes committed
1168 1169 1170 1171 1172 1173 1174 1175 1176 1177

OptSchemaEltList: OptSchemaEltList schema_stmt         { $$ = cat2_str($1, $2); }
		| /* EMPTY */   { $$ = EMPTY; }
		;

/*
 *     schema_stmt are the ones that can show up inside a CREATE SCHEMA
 *     statement (in addition to by themselves).
 */
schema_stmt: CreateStmt		{ $$ = $1; }
1178 1179 1180 1181 1182 1183
		   | IndexStmt		{ $$ = $1; }
		   | CreateSeqStmt	{ $$ = $1; }
		   | CreateTrigStmt { $$ = $1; }
		   | GrantStmt		{ $$ = $1; }
		   | ViewStmt		{ $$ = $1; }
		   ;
Michael Meskes's avatar
Michael Meskes committed
1184 1185 1186



Marc G. Fournier's avatar
Marc G. Fournier committed
1187 1188 1189 1190 1191
/*****************************************************************************
 *
 * Set PG internal variable
 *	  SET name TO 'var_value'
 * Include SQL92 syntax (thomas 1997-10-22):
1192
 *	  SET TIME ZONE 'var_value'
Marc G. Fournier's avatar
Marc G. Fournier committed
1193 1194
 *
 *****************************************************************************/
1195 1196 1197
VariableSetStmt:  SET set_rest
			{ $$ = cat2_str(make_str("set"), $2 ); }
		| SET LOCAL set_rest
1198
			{ $$ = cat2_str(make_str("set local"), $3 ); }
1199
		| SET SESSION set_rest
1200
			{ $$ = cat2_str(make_str("set session"), $3 ); }
1201 1202
		;

1203 1204
set_rest:	/* Generic SET syntaxes: */
		var_name TO var_list
1205
			{ $$ = cat_str(3, $1, make_str("to"), $3); }
1206
		| var_name "=" var_list
1207
			{ $$ = cat_str(3, $1, make_str("="), $3); }
1208 1209 1210 1211 1212 1213 1214
		| var_name TO DEFAULT
			{ $$ = cat2_str($1, make_str("to default")); }
		| var_name "=" DEFAULT
			{ $$ = cat2_str($1, make_str("= default")); }
		| var_name FROM CURRENT_P
			{ $$ = cat2_str($1, make_str("from current")); }
		/* Special syntaxes mandated by SQL standard: */
1215 1216
		| TIME ZONE zone_value
			{ $$ = cat2_str(make_str("time zone"), $3); }
Michael Meskes's avatar
Michael Meskes committed
1217 1218 1219 1220
		| TRANSACTION transaction_mode_list
			{ $$ = cat2_str(make_str("transaction"), $2); }
		| SESSION CHARACTERISTICS AS TRANSACTION transaction_mode_list
			{ $$ = cat2_str(make_str("session characteristics as transaction"), $5); }
1221 1222 1223 1224
		| CATALOG_P Sconst
			{ $$ = cat2_str(make_str("catalog"), $2); }
		| SCHEMA Sconst
			{ $$ = cat2_str(make_str("schema"), $2); }
1225 1226
		| NAMES opt_encoding
			{ $$ = cat2_str(make_str("names"), $2); }
1227 1228
		| ROLE ColId_or_Sconst
			{ $$ = cat2_str(make_str("role"), $2); }
1229 1230
		| SESSION AUTHORIZATION ColId_or_Sconst
			{ $$ = cat2_str(make_str("session authorization"), $3); }
1231
		| SESSION AUTHORIZATION DEFAULT
1232
			{ $$ = make_str("session authorization default"); }
1233 1234
		| XML_P OPTION document_or_content
			{ $$ = cat2_str(make_str("xml option"), $3); }
1235 1236
		;

1237
var_name:	ECPGColId		{ $$ = $1; }
1238 1239
		| var_name '.' ColId	{ $$ = cat_str(3, $1, make_str("."), $3); }
		;
1240

1241

1242 1243 1244 1245 1246
var_list:  var_value
			{ $$ = $1; }
		| var_list ',' var_value
			{ $$ = cat_str(3, $1, make_str(","), $3); }
		;
1247

1248
iso_level:	READ UNCOMMITTED	{ $$ = make_str("read uncommitted"); }
1249 1250 1251
		| READ COMMITTED		{ $$ = make_str("read committed"); }
		| REPEATABLE READ		{ $$ = make_str("repeatable read"); }
		| SERIALIZABLE			{ $$ = make_str("serializable"); }
1252 1253 1254
		;

var_value:	opt_boolean		{ $$ = $1; }
1255 1256 1257 1258 1259 1260 1261 1262 1263 1264
		| AllConst			{ 	/* we have to check for a variable here because it has to be
						     	replaced with its value on the client side */
							if ($1[1] == '$')
							{
								$$ = make_str("$0");
								free($1);
							}
							else
								$$ = $1;
						}
1265
		| ColId				{ $$ = $1; }
Michael Meskes's avatar
Michael Meskes committed
1266 1267
		;

1268 1269 1270 1271
opt_boolean:  TRUE_P		{ $$ = make_str("true"); }
		| FALSE_P			{ $$ = make_str("false"); }
		| ON				{ $$ = make_str("on"); }
		| OFF				{ $$ = make_str("off"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
1272
		;
1273
/* Timezone values can be:
1274 1275 1276 1277 1278 1279 1280
 * - a string such as 'pst8pdt'
 * - a column identifier such as "pst8pdt"
 * - an integer or floating point number
 * - a time interval per SQL99
 * ConstInterval and ColId give shift/reduce errors,
 * so use IDENT and reject anything which is a reserved word.
 */
1281
zone_value:  AllConst		{ $$ = $1; }
1282
		| ident		{ $$ = $1; }
1283
		| ConstInterval StringConst opt_interval
1284
			{ $$ = cat_str(3, $1, $2, $3); }
1285
		| ConstInterval '(' PosIntConst ')' StringConst opt_interval
1286
			{ $$ = cat_str(6, $1, make_str("("), $3, make_str(")"), $5, $6); }
1287
		| DEFAULT
1288
			{ $$ = make_str("default"); }
1289
		| LOCAL
1290
			{ $$ = make_str("local"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
1291 1292
		;

1293 1294 1295
opt_encoding:	StringConst		{ $$ = $1; }
		| DEFAULT				{ $$ = make_str("default"); }
		| /*EMPTY*/				{ $$ = EMPTY; }
Michael Meskes's avatar
Michael Meskes committed
1296 1297
		;

1298 1299
ColId_or_Sconst: ColId			{ $$ = $1; }
		| StringConst			{ $$ = $1; }
1300 1301
		;

1302
VariableShowStmt:  SHOW var_name ecpg_into
1303
			{ $$ = cat2_str(make_str("show"), $2); }
1304
		| SHOW TIME ZONE ecpg_into
1305
			{ $$ = make_str("show time zone"); }
1306
		| SHOW TRANSACTION ISOLATION LEVEL ecpg_into
1307
			{ $$ = make_str("show transaction isolation level"); }
1308
		| SHOW SESSION AUTHORIZATION ecpg_into
1309 1310
			{ $$ = make_str("show session authorization"); }
		| SHOW ALL
1311 1312 1313 1314
		   	{
				mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL not implemented");
				$$ = EMPTY;
			}
Marc G. Fournier's avatar
Marc G. Fournier committed
1315 1316
		;

1317
VariableResetStmt:	RESET var_name
1318
			{ $$ = cat2_str(make_str("reset"), $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
1319
		| RESET TIME ZONE
1320
			{ $$ = make_str("reset time zone"); }
1321
		| RESET TRANSACTION ISOLATION LEVEL
1322
			{ $$ = make_str("reset transaction isolation level"); }
1323 1324
		| RESET SESSION AUTHORIZATION
			{ $$ = make_str("reset session authorization"); }
1325
		| RESET ALL
1326
			{ $$ = make_str("reset all"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
1327 1328
		;

1329 1330 1331 1332 1333 1334
/* SetResetClause allows SET or RESET without LOCAL */
SetResetClause:
		SET set_rest		{ $$ = cat2_str(make_str("set"), $2); }
		| VariableResetStmt 	{ $$ = $1; }
		;

Michael Meskes's avatar
Michael Meskes committed
1335 1336 1337 1338 1339 1340
ConstraintsSetStmt:    SET CONSTRAINTS constraints_set_list constraints_set_mode
			{ $$ = cat_str(3, make_str("set constraints"), $3, $4); }
		;

constraints_set_list:  ALL
			{ $$ = make_str("all"); }
1341
		| qualified_name_list
Michael Meskes's avatar
Michael Meskes committed
1342 1343 1344 1345 1346 1347 1348
			{ $$ = $1; }
		;

constraints_set_mode:  DEFERRED		{ $$ = make_str("deferred"); }
		| IMMEDIATE		{ $$ = make_str("immediate"); }
		;

1349 1350 1351
/*
 * Checkpoint statement
 */
1352 1353
CheckPointStmt: CHECKPOINT	   { $$= make_str("checkpoint"); }
		;
1354

1355 1356 1357 1358 1359 1360
DiscardStmt:
		DISCARD ALL		{ $$ = make_str("discard all"); }
		| DISCARD TEMP		{ $$ = make_str("discard temp"); }
		| DISCARD TEMPORARY	{ $$ = make_str("discard temporary"); }
		| DISCARD PLANS		{ $$ = make_str("discard plans"); }
		;
Michael Meskes's avatar
Michael Meskes committed
1361 1362 1363

/*****************************************************************************
 *
Michael Meskes's avatar
Michael Meskes committed
1364
 *	ALTER [ TABLE | INDEX | SEQUENCE | VIEW ] variations
Michael Meskes's avatar
Michael Meskes committed
1365 1366 1367 1368
 *
 *****************************************************************************/

AlterTableStmt:
1369 1370
		ALTER TABLE relation_expr alter_table_cmds
			{ $$ = cat_str(3, make_str("alter table"), $3, $4); }
Michael Meskes's avatar
Michael Meskes committed
1371 1372 1373 1374 1375 1376
		|       ALTER INDEX relation_expr alter_table_cmds
			{ $$ = cat_str(3, make_str("alter index"), $3, $4); }
		|       ALTER SEQUENCE relation_expr alter_table_cmds
			{ $$ = cat_str(3, make_str("alter sequence"), $3, $4); }
		|       ALTER VIEW relation_expr alter_table_cmds
			{ $$ = cat_str(3, make_str("alter view"), $3, $4); }
1377 1378 1379 1380 1381 1382 1383 1384
		;

alter_table_cmds:
		alter_table_cmd 			{ $$ = $1; }
		| alter_table_cmds ',' alter_table_cmd	{ $$ = cat_str(3, $1, make_str(","), $3); }
		;

alter_table_cmd:
Michael Meskes's avatar
Michael Meskes committed
1385
/* ALTER TABLE <name> ADD [COLUMN] <coldef> */
1386
		ADD_P opt_column columnDef
1387
			{ $$ = cat_str(3, make_str("add"), $2, $3); }
Michael Meskes's avatar
Michael Meskes committed
1388
/* ALTER TABLE <name> ALTER [COLUMN] <colname> {SET DEFAULT <expr>|DROP DEFAULT} */
1389 1390
		| ALTER opt_column ColId alter_column_default
			{ $$ = cat_str(4, make_str("alter"), $2, $3, $4); }
Michael Meskes's avatar
Michael Meskes committed
1391
/* ALTER TABLE <name> ALTER [COLUMN] <colname> DROP NOT NULL */
1392 1393
		| ALTER opt_column ColId DROP NOT NULL_P
			{ $$ = cat_str(4, make_str("alter"), $2, $3, make_str("drop not null")); }
Michael Meskes's avatar
Michael Meskes committed
1394
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET NOT NULL */
1395 1396
		| ALTER opt_column ColId SET NOT NULL_P
			{ $$ = cat_str(4, make_str("alter"), $2, $3, make_str("set not null")); }
Michael Meskes's avatar
Michael Meskes committed
1397
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STATISTICS <IntegerOnly> */
1398 1399
		| ALTER opt_column ColId SET STATISTICS PosIntConst
			{ $$ = cat_str(5, make_str("alter"), $2, $3, make_str("set statistics"), $6); }
Michael Meskes's avatar
Michael Meskes committed
1400
/* ALTER TABLE <name> ALTER [COLUMN] <colname> SET STORAGE <storagemode> */
1401 1402
		| ALTER opt_column ColId SET STORAGE ColId
			{ $$ = cat_str(5, make_str("alter"), $2, $3, make_str("set storage"), $6); }
Michael Meskes's avatar
Michael Meskes committed
1403
/* ALTER TABLE <name> DROP [COLUMN] <colname> {RESTRICT|CASCADE} */
1404 1405
		| DROP opt_column ColId opt_drop_behavior
			{ $$ = cat_str(4, make_str("drop"), $2, $3, $4); }
1406 1407 1408
/* ALTER TABLE <name> ALTER [COLUMN] <colname> [SET DATA] TYPE <typename> [ USING <expression> ] */
		| ALTER opt_column ColId opt_set_data TYPE_P Typename alter_using
			{ $$ = cat_str(7, make_str("alter"), $2, $3, $4, make_str("type"), $6, $7); }
Michael Meskes's avatar
Michael Meskes committed
1409
/* ALTER TABLE <name> ADD CONSTRAINT ... */
1410
		| ADD_P TableConstraint
1411
			{ $$ = cat_str(2, make_str("add"), $2); }
Michael Meskes's avatar
Michael Meskes committed
1412
/* ALTER TABLE <name> DROP CONSTRAINT ... */
1413 1414
		| DROP CONSTRAINT name opt_drop_behavior
			{ $$ = cat_str(3, make_str("drop constraint"), $3, $4); }
Michael Meskes's avatar
Michael Meskes committed
1415
/* ALTER TABLE <name> SET WITHOUT OIDS  */
1416 1417
		| SET WITHOUT OIDS
			{ $$ = make_str("set without oids"); }
1418
/* ALTER TABLE <name> CLUSTER ON <indexname> */
1419 1420
		| CLUSTER ON name
			{ $$ = cat_str(2, make_str("cluster on"), $3); }
1421 1422 1423
/* ALTER TABLE <name> SET WITHOUT CLUSTER */
		| SET WITHOUT CLUSTER
			{ $$ = make_str("set without cluster"); }
1424
/* ALTER TABLE <name> ENABLE TRIGGER <trig> */
1425
		| ENABLE_P TRIGGER name
1426
			{ $$ = cat2_str(make_str("enable trigger"), $3); }
1427 1428 1429 1430 1431 1432
/* ALTER TABLE <name> ENABLE ALWAYS TRIGGER <trig> */
		| ENABLE_P ALWAYS TRIGGER name
			{ $$ = cat2_str(make_str("enable always trigger"), $4); }
/* ALTER TABLE <name> ENABLE REPLICA TRIGGER <trig> */
		| ENABLE_P REPLICA TRIGGER name
			{ $$ = cat2_str(make_str("enable replica trigger"), $4); }
1433
/* ALTER TABLE <name> ENABLE TRIGGER ALL */
1434
		| ENABLE_P TRIGGER ALL
1435 1436
			{ $$ = make_str("enable trigger all"); }
/* ALTER TABLE <name> ENABLE TRIGGER USER */
1437
		| ENABLE_P TRIGGER USER
1438 1439
			{ $$ = make_str("enable trigger user"); }
/* ALTER TABLE <name> DISABLE TRIGGER <trig> */
1440
		| DISABLE_P TRIGGER name
1441 1442
			{ $$ = cat2_str(make_str("disable trigger"), $3); }
/* ALTER TABLE <name> DISABLE TRIGGER ALL */
1443
		| DISABLE_P TRIGGER ALL
1444 1445
			{ $$ = make_str("disable trigger all"); }
/* ALTER TABLE <name> DISABLE TRIGGER USER */
1446
		| DISABLE_P TRIGGER USER
1447
			{ $$ = make_str("disable trigger user"); }
1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459
/* ALTER TABLE <name> ENABLE RULE <rule> */
		| ENABLE_P RULE name
			{ $$ = cat2_str(make_str("enable rule"), $3); }
/* ALTER TABLE <name> ENABLE ALWAYS RULE <rule> */
		| ENABLE_P ALWAYS RULE name
			{ $$ = cat2_str(make_str("enable always rule"), $4); }
/* ALTER TABLE <name> ENABLE REPLICA RULE <rule> */
		| ENABLE_P REPLICA RULE name
			{ $$ = cat2_str(make_str("enable replica rule"), $4); }
/* ALTER TABLE <name> DISABLE RULE <rule> */
		| DISABLE_P RULE name
			{ $$ = cat2_str(make_str("disable rule"), $3); }
1460 1461 1462
/* ALTER TABLE <name> ALTER INHERITS ADD <parent> */
		| INHERIT qualified_name
			{ $$ = cat2_str(make_str("inherit"), $2); }
Michael Meskes's avatar
Michael Meskes committed
1463
/* ALTER TABLE <name> NO INHERITS <parent> */
1464 1465
		| NO INHERIT qualified_name
			{ $$ = cat2_str(make_str("no inherit"), $3); }
Michael Meskes's avatar
Michael Meskes committed
1466 1467
		/* ALTER <name> OWNER TO RoleId */
		| OWNER TO RoleId
1468
			{ $$ = cat2_str(make_str("owner to"), $3); }
Michael Meskes's avatar
Michael Meskes committed
1469
		/* ALTER <name> SET TABLESPACE <tablespacename> */
1470
		| SET TABLESPACE name
1471 1472 1473 1474 1475
			{ $$ = cat2_str(make_str("set tablespace"), $3); }
		| SET definition
			{ $$ = cat2_str(make_str("set"), $2); }
		| RESET definition
			{ $$ = cat2_str(make_str("reset"), $2); }
Michael Meskes's avatar
Michael Meskes committed
1476 1477 1478 1479 1480 1481 1482
		;

alter_column_default:
		SET DEFAULT a_expr		{ $$ = cat2_str(make_str("set default"), $3); }
		| DROP DEFAULT			{ $$ = make_str("drop default"); }
		;

1483 1484
opt_drop_behavior: CASCADE		{ $$ = make_str("cascade"); }
		| RESTRICT 				{ $$ = make_str("restrict"); }
1485 1486
		| /* EMPTY */ 			{ $$ = EMPTY; }
		;
1487

1488 1489
alter_using:	USING a_expr	{ $$ = cat2_str(make_str("using"), $2); }
		| /* EMPTY */			{ $$ = EMPTY; }
1490
		;
1491

Marc G. Fournier's avatar
Marc G. Fournier committed
1492 1493 1494
/*****************************************************************************
 *
 *		QUERY :
1495
 *				close <portalname>
Marc G. Fournier's avatar
Marc G. Fournier committed
1496 1497 1498
 *
 *****************************************************************************/

1499
ClosePortalStmt:  CLOSE name
1500
			{ $$ = cat2_str(make_str("close"), $2);	}
1501 1502
		| CLOSE ALL
			{ $$ = make_str("close all"); }
1503
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
1504

1505 1506
CopyStmt:  COPY opt_binary qualified_name opt_oids copy_from
		copy_file_name copy_delimiter opt_with copy_opt_list
1507 1508
			{
				if (strcmp($5, "to") == 0 && strcmp($6, "stdin") == 0)
1509
					mmerror(PARSE_ERROR, ET_ERROR, "copy to stdin not possible\n");
1510
				else if (strcmp($5, "from") == 0 && strcmp($6, "stdout") == 0)
1511
					mmerror(PARSE_ERROR, ET_ERROR, "copy from stdout not possible\n");
1512
				else if (strcmp($5, "from") == 0 && strcmp($6, "stdin") == 0)
1513
					mmerror(PARSE_ERROR, ET_WARNING, "copy from stdin not implemented\n");
1514 1515 1516
				
				$$ = cat_str(9, make_str("copy"), $2, $3, $4, $5, $6, $7, $8, $9);
			}
Michael Meskes's avatar
Michael Meskes committed
1517 1518 1519
		| COPY select_with_parens TO copy_file_name opt_with copy_opt_list
			{
				if (strcmp($4, "stdin") == 0)
1520
					mmerror(PARSE_ERROR, ET_ERROR, "copy to stdin is not possible\n");
Michael Meskes's avatar
Michael Meskes committed
1521 1522 1523
				
				$$ = cat_str(6, make_str("copy"), $2, make_str("to"), $4, $5, $6);
			}
Michael Meskes's avatar
Michael Meskes committed
1524 1525
		;

1526
copy_from:	TO					{ $$ = make_str("to"); }
Michael Meskes's avatar
Michael Meskes committed
1527 1528 1529
		| FROM					{ $$ = make_str("from"); }
		;

1530
copy_file_name:  StringConst				{ $$ = $1; }
Michael Meskes's avatar
Michael Meskes committed
1531 1532 1533 1534
		| STDIN					{ $$ = make_str("stdin"); }
		| STDOUT				{ $$ = make_str("stdout"); }
		;

1535 1536 1537
copy_opt_list: copy_opt_list copy_opt_item	{ $$ = cat2_str($1, $2); }
		| /* EMPTY */ 			{ $$ = EMPTY; }
		;
1538

1539 1540 1541 1542 1543 1544
copy_opt_item:	BINARY		{ $$ = make_str("binary"); }
		| OIDS		{ $$ = make_str("oids"); }
		| DELIMITER opt_as StringConst
			{ $$ = cat_str(3, make_str("delimiter"), $2, $3); }
		| NULL_P opt_as StringConst
			{ $$ = cat_str(3, make_str("null"), $2, $3); }
1545
		| CSV		{ $$ = make_str("csv"); }
1546
		| HEADER_P	{ $$ = make_str("header"); }
1547 1548 1549 1550 1551 1552 1553 1554
		| QUOTE opt_as Sconst
			{ $$ = cat_str(3, make_str("quote"), $2, $3); }
		| ESCAPE opt_as Sconst
			{ $$ = cat_str(3, make_str("escape"), $2, $3); }
		| FORCE QUOTE columnList
			{ $$ = cat2_str(make_str("force quote"), $3); }
		| FORCE NOT NULL_P columnList
			{ $$ = cat2_str(make_str("force not null"), $4); }
1555

Michael Meskes's avatar
Michael Meskes committed
1556 1557
		;

1558 1559
opt_binary:	BINARY		{ $$ = make_str("binary"); }
		| /* EMPTY */	{ $$ = EMPTY; }
Michael Meskes's avatar
Michael Meskes committed
1560 1561
		;

1562 1563 1564
opt_oids:	WITH OIDS	{ $$ = make_str("with oids"); }
		| /* EMPTY */   { $$ = EMPTY; }
		;
1565 1566


Michael Meskes's avatar
Michael Meskes committed
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579
/*
 * the default copy delimiter is tab but the user can configure it
 */
copy_delimiter:  opt_using DELIMITERS StringConst
			{ $$ = cat_str(3, $1, make_str("delimiters"), $3); }
		| /*EMPTY*/
			{ $$ = EMPTY; }
		;

opt_using:	USING		{ $$ = make_str("using"); }
		| /* EMPTY */	{ $$ = EMPTY; }
		;

Marc G. Fournier's avatar
Marc G. Fournier committed
1580 1581 1582
/*****************************************************************************
 *
 *		QUERY :
Michael Meskes's avatar
Michael Meskes committed
1583
 *				CREATE TABLE relname
Marc G. Fournier's avatar
Marc G. Fournier committed
1584 1585 1586
 *
 *****************************************************************************/

1587
CreateStmt:  CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
1588
				OptInherit OptWith OnCommitOption OptTableSpace
1589
			{ $$ = cat_str(11, make_str("create"), $2, make_str("table"), $4, make_str("("), $6, make_str(")"), $8, $9, $10, $11); }
1590
		| CREATE OptTemp TABLE qualified_name OF qualified_name
1591
			'(' OptTableElementList ')' OptWith OnCommitOption OptTableSpace
1592
			{ $$ = cat_str(12, make_str("create"), $2, make_str("table"), $4, make_str("of"), $6, make_str("("), $8, make_str(")"), $10, $11, $12); }
Marc G. Fournier's avatar
Marc G. Fournier committed
1593 1594
		;

Michael Meskes's avatar
Michael Meskes committed
1595 1596 1597 1598
/*
 * Redundancy here is needed to avoid shift/reduce conflicts,
 * since TEMP is not a reserved word.  See also OptTempTableName.
 */
Michael Meskes's avatar
Michael Meskes committed
1599

1600
OptTemp: TEMPORARY			{ $$ = make_str("temporary"); }
1601
		| TEMP				{ $$ = make_str("temp"); }
Michael Meskes's avatar
Michael Meskes committed
1602 1603
		| LOCAL TEMPORARY	{ $$ = make_str("local temporary"); }
		| LOCAL TEMP		{ $$ = make_str("local temp"); }
1604 1605
		| GLOBAL TEMPORARY 	{ $$ = make_str("global temporary"); }
		| GLOBAL TEMP 		{ $$ = make_str("global temp"); }
1606
		| /*EMPTY*/			{ $$ = EMPTY; }
1607 1608
		;

1609 1610

OptTableElementList:  TableElementList
1611 1612 1613
			{ $$ = $1; }
		| /*EMPTY*/
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
1614
		;
1615 1616 1617 1618 1619
TableElementList: TableElement
			{ $$ = $1; }
		| TableElementList ',' TableElement
			{ $$ = cat_str(3, $1, make_str(","), $3); }
		;
1620

1621 1622 1623
TableElement:  columnDef		{ $$ = $1; }
		| TableLikeClause	{ $$ = $1; }
		| TableConstraint	{ $$ = $1; }
Marc G. Fournier's avatar
Marc G. Fournier committed
1624 1625
		;

1626
columnDef:	ColId Typename ColQualList
1627
			{$$ = cat_str(3, $1, $2, $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
1628 1629
		;

Michael Meskes's avatar
Michael Meskes committed
1630 1631 1632 1633 1634 1635 1636 1637 1638 1639
ColQualList:  ColQualList ColConstraint { $$ = cat2_str($1,$2); }
		| /*EMPTY*/						{ $$ = EMPTY; }
		;

ColConstraint:	CONSTRAINT name ColConstraintElem
			{ $$ = cat_str(3, make_str("constraint"), $2, $3); }
		| ColConstraintElem		{ $$ = $1; }
		| ConstraintAttr		{ $$ = $1; }
		;

Michael Meskes's avatar
Michael Meskes committed
1640 1641
/* DEFAULT NULL is already the default for Postgres.
 * But define it here and carry it forward into the system
1642 1643
 * to make it explicit.
 * - thomas 1998-09-13
Michael Meskes's avatar
Michael Meskes committed
1644
 *
1645 1646 1647 1648 1649
 * WITH NULL and NULL are not SQL92-standard syntax elements,
 * so leave them out. Use DEFAULT NULL to explicitly indicate
 * that a column may have that value. WITH NULL leads to
 * shift/reduce conflicts with WITH TIME ZONE anyway.
 * - thomas 1999-01-08
1650
 */
Michael Meskes's avatar
Michael Meskes committed
1651 1652 1653 1654
ColConstraintElem:	NOT NULL_P
			{ $$ = make_str("not null"); }
		| NULL_P
			{ $$ = make_str("null"); }
1655 1656 1657 1658
		| UNIQUE opt_definition OptConsTableSpace
			{ $$ = cat_str(3, make_str("unique"), $2, $3); }
		| PRIMARY KEY opt_definition OptConsTableSpace
			{ $$ = cat_str(3, make_str("primary key"), $3, $4); }
Michael Meskes's avatar
Michael Meskes committed
1659 1660 1661 1662 1663 1664 1665
		| CHECK '(' a_expr ')'
			{ $$ = cat_str(3, make_str("check ("), $3, make_str(")")); }
		| DEFAULT b_expr
			{ $$ = cat2_str(make_str("default"), $2); }
		|  REFERENCES qualified_name opt_column_list key_match key_actions
			{ $$ = cat_str(5, make_str("references"), $2, $3, $4, $5); }
		;
Michael Meskes's avatar
Michael Meskes committed
1666

Michael Meskes's avatar
Michael Meskes committed
1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678
/*
 * ConstraintAttr represents constraint attributes, which we parse as if
 * they were independent constraint clauses, in order to avoid shift/reduce
 * conflicts (since NOT might start either an independent NOT NULL clause
 * or an attribute).  analyze.c is responsible for attaching the attribute
 * information to the preceding "real" constraint node, and for complaining
 * if attribute clauses appear in the wrong place or wrong combinations.
 *
 * See also ConstraintAttributeSpec, which can be used in places where
 * there is no parsing conflict.
 */
ConstraintAttr: DEFERRABLE		{ $$ = make_str("deferrable"); }
1679
		| NOT DEFERRABLE	{ $$ = make_str("not deferrable"); }
Michael Meskes's avatar
Michael Meskes committed
1680 1681
		| INITIALLY DEFERRED	{ $$ = make_str("initially deferred"); }
		| INITIALLY IMMEDIATE	{ $$ = make_str("initially immediate"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
1682
		;
Michael Meskes's avatar
Michael Meskes committed
1683

1684
TableLikeClause:  LIKE qualified_name TableLikeOptionList
1685
			{$$ = cat_str(3, make_str("like"), $2, $3); }
1686
		;
1687

1688 1689 1690 1691 1692 1693
TableLikeOptionList: TableLikeOptionList TableLikeOption
				{ $$ = cat2_str($1, $2); }
		| /* EMPTY */ 	{ $$ = EMPTY; }
		;

TableLikeOption:
1694
		INCLUDING DEFAULTS      { $$ = make_str("including defaults"); }
1695
		| EXCLUDING DEFAULTS	{ $$ = make_str("excluding defaults"); }
1696 1697 1698 1699
		| INCLUDING CONSTRAINTS { $$ = make_str("including constraints"); }
		| EXCLUDING CONSTRAINTS	{ $$ = make_str("excluding constraints"); }
		| INCLUDING INDEXES     { $$ = make_str("including indexes"); }
		| EXCLUDING INDEXES	{ $$ = make_str("excluding indexes"); }
1700
		;
1701

Michael Meskes's avatar
Michael Meskes committed
1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713
/* ConstraintElem specifies constraint syntax which is not embedded into
 *	a column definition. ColConstraintElem specifies the embedded form.
 * - thomas 1997-12-03
 */
TableConstraint:  CONSTRAINT name ConstraintElem
			{ $$ = cat_str(3, make_str("constraint"), $2, $3); }
		| ConstraintElem
			{ $$ = $1; }
		;

ConstraintElem:  CHECK '(' a_expr ')'
			{ $$ = cat_str(3, make_str("check("), $3, make_str(")")); }
1714 1715 1716 1717
		| UNIQUE '(' columnList ')' opt_definition OptConsTableSpace
			{ $$ = cat_str(5, make_str("unique("), $3, make_str(")"), $5, $6); }
		| PRIMARY KEY '(' columnList ')' opt_definition OptConsTableSpace
			{ $$ = cat_str(5, make_str("primary key("), $4, make_str(")"), $6, $7); }
Michael Meskes's avatar
Michael Meskes committed
1718 1719 1720 1721 1722
		| FOREIGN KEY '(' columnList ')' REFERENCES qualified_name opt_column_list
			key_match key_actions ConstraintAttributeSpec
			{ $$ = cat_str(8, make_str("foreign key("), $4, make_str(") references"), $7, $8, $9, $10, $11); }
		;

1723
opt_column_list:  '(' columnList ')'	{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
1724 1725
		| /*EMPTY*/		{ $$ = EMPTY; }
		;
1726 1727

columnList:  columnList ',' columnElem
1728 1729 1730 1731
			{ $$ = cat_str(3, $1, make_str(","), $3); }
		| columnElem
			{ $$ = $1; }
		;
1732 1733 1734 1735

columnElem:  ColId	{ $$ = $1; }
		;

1736 1737 1738
key_match:	MATCH FULL
			{ $$ = make_str("match full"); }
		| MATCH PARTIAL
Michael Meskes's avatar
Michael Meskes committed
1739
		{
1740
			mmerror(PARSE_ERROR, ET_WARNING, "currently unsupported FOREIGN KEY/MATCH PARTIAL will be passed to backend");
Michael Meskes's avatar
Michael Meskes committed
1741
			$$ = make_str("match partial");
Michael Meskes's avatar
Michael Meskes committed
1742 1743
		}
		| /*EMPTY*/
1744
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
1745 1746
		;

1747 1748 1749 1750 1751
key_actions:  key_delete			{ $$ = $1; }
		| key_update				{ $$ = $1; }
		| key_delete key_update 	{ $$ = cat2_str($1, $2); }
		| key_update key_delete 	{ $$ = cat2_str($1, $2); }
		| /*EMPTY*/					{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
1752 1753
		;

1754
key_delete: ON DELETE_P key_action
1755
			{ $$ = cat2_str(make_str("on delete"), $3); }
1756
		;
Michael Meskes's avatar
Michael Meskes committed
1757

1758
key_update: ON UPDATE key_action
1759
			{ $$ = cat2_str(make_str("on update"), $3); }
1760
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
1761

1762
key_action:	NO ACTION				{ $$ = make_str("no action"); }
1763 1764 1765 1766
		| RESTRICT					{ $$ = make_str("restrict"); }
		| CASCADE					{ $$ = make_str("cascade"); }
		| SET DEFAULT				{ $$ = make_str("set default"); }
		| SET NULL_P				{ $$ = make_str("set null"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
1767 1768
		;

1769
OptInherit:  INHERITS '(' qualified_name_list ')'
1770
			{ $$ = cat_str(3, make_str("inherits ("), $3, make_str(")")); }
1771
		| /*EMPTY*/
1772 1773
			{ $$ = EMPTY; }
		;
1774

1775 1776 1777 1778
OptWith:	WITH definition			{ $$ = cat2_str(make_str("with"), $2); }
		| WITH OIDS			{ $$ = make_str("with oids"); }
		| WITHOUT OIDS			{ $$ = make_str("without oids"); }
		| /*EMPTY*/			{ $$ = EMPTY; }
1779 1780
		;

1781
OnCommitOption:   ON COMMIT DROP	{ $$ = make_str("on commit drop"); }
Michael Meskes's avatar
Michael Meskes committed
1782 1783
		| ON COMMIT DELETE_P ROWS	{ $$ = make_str("on commit delete rows"); }
		| ON COMMIT PRESERVE ROWS	{ $$ = make_str("on commit preserve rows"); }
1784
		| /*EMPTY*/					{ $$ = EMPTY; }
Michael Meskes's avatar
Michael Meskes committed
1785
		;
1786

1787 1788 1789
OptTableSpace:  TABLESPACE name	{ $$ = cat2_str(make_str("tablespace"), $2); }
		| /*EMPTY*/	{ $$ = EMPTY; }
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
1790

Michael Meskes's avatar
Michael Meskes committed
1791 1792 1793
OptConsTableSpace: USING INDEX TABLESPACE name	{ $$ = cat2_str(make_str("using index tablespace"), $4); }
			| /*EMPTY*/		{ $$ = EMPTY; }
			;
1794

Michael Meskes's avatar
Michael Meskes committed
1795 1796 1797 1798 1799
/*
 * Note: CREATE TABLE ... AS SELECT ... is just another spelling for
 * SELECT ... INTO.
 */

1800
CreateAsStmt:  CREATE OptTemp TABLE create_as_target AS
1801
		{ FoundInto = 0; }
1802
		SelectStmt
Marc G. Fournier's avatar
Marc G. Fournier committed
1803
		{
Michael Meskes's avatar
Michael Meskes committed
1804
			if (FoundInto == 1)
1805
				mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE / AS SELECT cannot specify INTO");
Michael Meskes's avatar
Michael Meskes committed
1806

1807 1808 1809 1810 1811 1812 1813
			$$ = cat_str(6, make_str("create"), $2, make_str("table"), $4, make_str("as"), $7);
		}
		;

create_as_target:  qualified_name OptCreateAs OptWith OnCommitOption OptTableSpace
		{
			$$ = cat_str(5, $1, $2, $3, $4, $5);
Marc G. Fournier's avatar
Marc G. Fournier committed
1814 1815 1816
		}
		;

1817
OptCreateAs:  '(' CreateAsList ')'
1818
			{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
1819
		| /*EMPTY*/
1820
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
1821 1822
		;

1823
CreateAsList:  CreateAsList ',' CreateAsElement
1824
			{ $$ = cat_str(3, $1, make_str(","), $3); }
1825
		| CreateAsElement
1826
			{ $$ = $1; }
Marc G. Fournier's avatar
Marc G. Fournier committed
1827 1828 1829 1830
		;

CreateAsElement:  ColId { $$ = $1; }
		;
Michael Meskes's avatar
Michael Meskes committed
1831 1832 1833 1834 1835

/*****************************************************************************
 *
 *		QUERY :
 *				CREATE SEQUENCE seqname
1836
 *                              ALTER SEQUENCE seqname
Michael Meskes's avatar
Michael Meskes committed
1837 1838 1839
 *
 *****************************************************************************/

Michael Meskes's avatar
Michael Meskes committed
1840
CreateSeqStmt:	CREATE OptTemp SEQUENCE qualified_name OptSeqOptList
1841
			{ $$ = cat_str(5, make_str("create"), $2, make_str("sequence"), $4, $5); }
Michael Meskes's avatar
Michael Meskes committed
1842 1843
		;

Michael Meskes's avatar
Michael Meskes committed
1844
AlterSeqStmt: ALTER SEQUENCE relation_expr SeqOptList
1845 1846 1847
			{ $$ = cat_str(3,make_str("alter sequence"), $3, $4); }
		;

Michael Meskes's avatar
Michael Meskes committed
1848 1849 1850 1851 1852 1853
OptSeqOptList:  SeqOptList	{ $$ = $1; }
		| /*EMPTY*/	{ $$ = EMPTY; }
		;

SeqOptList: 	SeqOptElem		{ $$ = $1; }
		| SeqOptList SeqOptElem	{ $$ = cat2_str($1, $2); }
Michael Meskes's avatar
Michael Meskes committed
1854 1855
		;

Michael Meskes's avatar
Michael Meskes committed
1856
SeqOptElem:  CACHE NumConst
Michael Meskes's avatar
Michael Meskes committed
1857 1858 1859
			{ $$ = cat2_str(make_str("cache"), $2); }
		| CYCLE
			{ $$ = make_str("cycle"); }
Michael Meskes's avatar
Michael Meskes committed
1860 1861 1862 1863
		| NO CYCLE
			{ $$ = make_str("no cycle"); }
		| INCREMENT opt_by NumConst
			{ $$ = cat_str(3, make_str("increment"), $2, $3); }
Michael Meskes's avatar
Michael Meskes committed
1864 1865 1866 1867
		| MAXVALUE NumConst
			{ $$ = cat2_str(make_str("maxvalue"), $2); }
		| MINVALUE NumConst
			{ $$ = cat2_str(make_str("minvalue"), $2); }
1868 1869 1870 1871
		| NO MAXVALUE
			{ $$ = make_str("no maxvalue"); }
		| NO MINVALUE
			{ $$ = make_str("no minvalue"); }
Michael Meskes's avatar
Michael Meskes committed
1872 1873
		| OWNED BY any_name
			{ $$ = cat2_str(make_str("owned by"), $3); }
1874
		| START opt_with NumConst
Michael Meskes's avatar
Michael Meskes committed
1875
			{ $$ = cat_str(3, make_str("start"), $2, $3); }
Michael Meskes's avatar
Michael Meskes committed
1876 1877
		| RESTART
			{ $$ = make_str("restart"); }
1878 1879
		| RESTART opt_with NumConst
			{ $$ = cat_str(3, make_str("restart"), $2, $3); }
Michael Meskes's avatar
Michael Meskes committed
1880 1881
		;

Michael Meskes's avatar
Michael Meskes committed
1882 1883 1884
opt_by:		BY	{ $$ = make_str("by"); }
		| /*EMPTY*/	{ $$ = EMPTY; }
		;
1885

Michael Meskes's avatar
Michael Meskes committed
1886 1887 1888 1889 1890 1891 1892 1893
/*****************************************************************************
 *
 *		QUERIES :
 *				CREATE PROCEDURAL LANGUAGE ...
 *				DROP PROCEDURAL LANGUAGE ...
 *
 *****************************************************************************/

1894 1895 1896 1897 1898
CreatePLangStmt:  CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
			{ $$ = cat_str(5, make_str("create"), $2, $3, make_str("language"), $5); }
		| CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst
			HANDLER handler_name opt_validator opt_lancompiler
			{ $$ = cat_str(9, make_str("create"), $2, $3, make_str("language"), $5, make_str("handler"), $7, $8, $9); }
Michael Meskes's avatar
Michael Meskes committed
1899 1900
		;

1901
opt_trusted:	TRUSTED { $$ = make_str("trusted"); }
Michael Meskes's avatar
Michael Meskes committed
1902 1903 1904 1905 1906
		| /*EMPTY*/		{ $$ = EMPTY; }
		;

/* This ought to be just func_name, but that causes reduce/reduce conflicts
 * (CREATE LANGUAGE is the only place where func_name isn't followed by '(').
1907
 * Work around by using simple names instead.
Michael Meskes's avatar
Michael Meskes committed
1908
 */
1909
handler_name: name	{ $$ = $1; }
1910 1911
		| name attrs    { $$ = cat2_str($1, $2); }
		;
Michael Meskes's avatar
Michael Meskes committed
1912

1913 1914 1915 1916 1917
opt_validator: VALIDATOR handler_name
			{ $$ = cat2_str(make_str("validator"), $2); }
		| /*EMPTY*/
			{ $$ = ""; }
		;
Michael Meskes's avatar
Michael Meskes committed
1918 1919 1920 1921 1922 1923
opt_lancompiler: LANCOMPILER StringConst
			{ $$ = cat2_str(make_str("lancompiler"), $2); }
		| /*EMPTY*/
			{ $$ = ""; }
		;

1924 1925
DropPLangStmt:	DROP opt_procedural LANGUAGE StringConst opt_drop_behavior
			{ $$ = cat_str(5, make_str("drop"), $2, make_str("language"), $4, $5); }
1926 1927
		| DROP opt_procedural LANGUAGE IF_P EXISTS StringConst opt_drop_behavior
			{ $$ = cat_str(5, make_str("drop"), $2, make_str("language if exists"), $6, $7); }
Michael Meskes's avatar
Michael Meskes committed
1928 1929 1930 1931 1932 1933
		;

opt_procedural: PROCEDURAL	{ $$ = make_str("prcedural"); }
		| /*EMPTY*/			{ $$ = EMPTY; }
		;

1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959
/*****************************************************************************
 *
 *             QUERY:
 *             CREATE TABLESPACE tablespace LOCATION '/path/to/tablespace/'
 *
 *****************************************************************************/

CreateTableSpaceStmt: CREATE TABLESPACE name OptTableSpaceOwner LOCATION Sconst
			{ $$ = cat_str(5,make_str("create tablespace"), $3, $4, make_str("location"), $6); }
		;

OptTableSpaceOwner: OWNER name	{ $$ = cat2_str(make_str("owner"), $2); }
		| /*EMPTY*/ 	{ $$ = EMPTY; }
		;

/*****************************************************************************
 *
 *             QUERY :
 *                             DROP TABLESPACE <tablespace>
 *
 *             No need for drop behaviour as we cannot implement dependencies for
 *             objects in other databases; we can only support RESTRICT.
 *
 ****************************************************************************/


1960 1961
DropTableSpaceStmt: DROP TABLESPACE name
			{ $$ = cat2_str(make_str("drop tablespace"), $3); }
1962 1963
		| DROP TABLESPACE IF_P EXISTS name
			{ $$ = cat2_str(make_str("drop tablespace if exists"), $5); }
1964
		;
1965 1966


Michael Meskes's avatar
Michael Meskes committed
1967 1968 1969 1970 1971 1972 1973 1974 1975
/*****************************************************************************
 *
 *		QUERIES :
 *				CREATE TRIGGER ...
 *				DROP TRIGGER ...
 *
 *****************************************************************************/

CreateTrigStmt:  CREATE TRIGGER name TriggerActionTime TriggerEvents ON
1976 1977
				qualified_name TriggerForSpec EXECUTE PROCEDURE name
				'(' TriggerFuncArgs ')'
Michael Meskes's avatar
Michael Meskes committed
1978 1979
			{ $$ = 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(")")); }
		|	CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON
1980
				qualified_name OptConstrFromTable ConstraintAttributeSpec
Michael Meskes's avatar
Michael Meskes committed
1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004
				FOR EACH ROW EXECUTE PROCEDURE
				func_name '(' TriggerFuncArgs ')'
			{ $$ = 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(")")); }
		;

TriggerActionTime:	BEFORE		{ $$ = make_str("before"); }
		| AFTER					{ $$ = make_str("after"); }
		;

TriggerEvents:	TriggerOneEvent
			{ $$ = $1; }
		| TriggerOneEvent OR TriggerOneEvent
			{ $$ = cat_str(3, $1, make_str("or"), $3); }
		| TriggerOneEvent OR TriggerOneEvent OR TriggerOneEvent
			{ $$ = cat_str(5, $1, make_str("or"), $3, make_str("or"), $5); }
		;

TriggerOneEvent:  INSERT	{ $$ = make_str("insert"); }
		| DELETE_P			{ $$ = make_str("delete"); }
		| UPDATE			{ $$ = make_str("update"); }
		;

TriggerForSpec:  FOR TriggerForOpt TriggerForType
			{ $$ = cat_str(3, make_str("for"), $2, $3); }
Michael Meskes's avatar
Michael Meskes committed
2005 2006
		| /* EMPTY */
			{ $$ = EMPTY; }
Michael Meskes's avatar
Michael Meskes committed
2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024
		;

TriggerForOpt:	EACH		{ $$ = make_str("each"); }
		| /*EMPTY*/			{ $$ = EMPTY; }
		;

TriggerForType:  ROW		{ $$ = make_str("row"); }
		| STATEMENT			{ $$ = make_str("statement"); }
		;

TriggerFuncArgs:  TriggerFuncArg
			{ $$ = $1; }
		| TriggerFuncArgs ',' TriggerFuncArg
			{ $$ = cat_str(3, $1, make_str(","), $3); }
		| /*EMPTY*/
			{ $$ = EMPTY; }
		;

2025 2026
TriggerFuncArg:  PosAllConst 	{ $$ = $1; }
		| ColId		{ $$ = $1; }
Michael Meskes's avatar
Michael Meskes committed
2027 2028 2029
		;

OptConstrFromTable: /* Empty */		{ $$ = EMPTY; }
2030
		| FROM qualified_name		{ $$ = cat2_str(make_str("from"), $2); }
Michael Meskes's avatar
Michael Meskes committed
2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048
		;

ConstraintAttributeSpec: ConstraintDeferrabilitySpec	{ $$ = $1; }
		| ConstraintDeferrabilitySpec ConstraintTimeSpec
		{
			if (strcmp($1, "deferrable") != 0 && strcmp($2, "initially deferrable") == 0 )
				mmerror(PARSE_ERROR, ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");

			$$ = cat2_str($1, $2);
		}
		| ConstraintTimeSpec		{ $$ = $1; }
		| ConstraintTimeSpec ConstraintDeferrabilitySpec
		{
			if (strcmp($2, "deferrable") != 0 && strcmp($1, "initially deferrable") == 0 )
				mmerror(PARSE_ERROR, ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");

			$$ = cat2_str($1, $2);
		}
Michael Meskes's avatar
Michael Meskes committed
2049 2050 2051 2052
		| /* EMPTY */
		{
			$$ = EMPTY;
		}
Michael Meskes's avatar
Michael Meskes committed
2053 2054
		;

2055
ConstraintDeferrabilitySpec: NOT DEFERRABLE
Michael Meskes's avatar
Michael Meskes committed
2056
			{ $$ = make_str("not deferrable"); }
2057
		| DEFERRABLE
Michael Meskes's avatar
Michael Meskes committed
2058 2059 2060
			{ $$ = make_str("deferrable"); }
		;

2061
ConstraintTimeSpec: INITIALLY IMMEDIATE
Michael Meskes's avatar
Michael Meskes committed
2062
			{ $$ = make_str("initially immediate"); }
2063
		| INITIALLY DEFERRED
Michael Meskes's avatar
Michael Meskes committed
2064 2065 2066
			{ $$ = make_str("initially deferred"); }
		;

2067 2068
DropTrigStmt:  DROP TRIGGER name ON qualified_name opt_drop_behavior
			{ $$ = cat_str(5, make_str("drop trigger"), $3, make_str("on"), $5, $6); }
2069 2070
		| DROP TRIGGER IF_P EXISTS name ON qualified_name opt_drop_behavior
			{ $$ = cat_str(5, make_str("drop trigger if exists"), $5, make_str("on"), $7, $8); }
Michael Meskes's avatar
Michael Meskes committed
2071 2072 2073 2074 2075 2076 2077 2078 2079 2080
		;

/*****************************************************************************
 *
 *             QUERIES :
 *                             CREATE ASSERTION ...
 *                             DROP ASSERTION ...
 *
 *****************************************************************************/
CreateAssertStmt:  CREATE ASSERTION name
2081 2082 2083 2084 2085
		CHECK '(' a_expr ')' ConstraintAttributeSpec
		{
			mmerror(PARSE_ERROR, ET_ERROR, "CREATE ASSERTION is not yet supported");
			$$ = cat_str(6, make_str("create assertion"), $3, make_str("check ("), $6, make_str(")"), $8);
		}
Michael Meskes's avatar
Michael Meskes committed
2086 2087 2088
		;

DropAssertStmt:  DROP ASSERTION name
2089 2090 2091 2092 2093
		{
			mmerror(PARSE_ERROR, ET_ERROR, "DROP ASSERTION is not yet supported");
			$$ = cat2_str(make_str("drop assertion"), $3);
		}
		;
Michael Meskes's avatar
Michael Meskes committed
2094

2095

Michael Meskes's avatar
Michael Meskes committed
2096 2097 2098 2099 2100 2101 2102
/*****************************************************************************
 *
 *		QUERY :
 *				define (type,operator,aggregate)
 *
 *****************************************************************************/

2103 2104 2105
DefineStmt:  CREATE AGGREGATE func_name aggr_args definition
			{ $$ = cat_str(4, make_str("create aggregate"), $3, $4, $5); }
		| CREATE AGGREGATE func_name old_aggr_definition
Michael Meskes's avatar
Michael Meskes committed
2106
			{ $$ = cat_str(3, make_str("create aggregate"), $3, $4); }
Michael Meskes's avatar
Michael Meskes committed
2107
		| CREATE OPERATOR any_operator definition
Michael Meskes's avatar
Michael Meskes committed
2108 2109 2110
			{ $$ = cat_str(3, make_str("create operator"), $3, $4); }
		| CREATE TYPE_P any_name definition
			{ $$ = cat_str(3, make_str("create type"), $3, $4); }
2111 2112 2113 2114
		| CREATE TYPE_P any_name
			{ $$ = cat2_str(make_str("create type"), $3); }
		| CREATE TYPE_P any_name AS '(' TableFuncElementList ')'
			{ $$ = cat_str(5, make_str("create type"), $3, make_str("as ("), $6, make_str(")")); }
2115 2116
		| CREATE TYPE_P any_name AS ENUM_P '(' enum_val_list ')'
			{ $$ = cat_str(5, make_str("create type"), $3, make_str("as enum ("), $7, make_str(")")); }
2117 2118 2119 2120 2121 2122 2123 2124
		| CREATE TEXT_P SEARCH PARSER any_name definition
			{ $$ = cat_str(3, make_str("create text search parser"), $5, $6); }
		| CREATE TEXT_P SEARCH DICTIONARY any_name definition
			{ $$ = cat_str(3, make_str("create text search dictionary"), $5, $6); }
		| CREATE TEXT_P SEARCH TEMPLATE any_name definition
			{ $$ = cat_str(3, make_str("create text search template"), $5, $6); }
		| CREATE TEXT_P SEARCH CONFIGURATION any_name definition
			{ $$ = cat_str(3, make_str("create text search configuration"), $5, $6); }
Michael Meskes's avatar
Michael Meskes committed
2125 2126
		;

2127
definition:  '(' def_list ')'
2128
			{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
2129 2130 2131
		;

def_list:  def_elem					{ $$ = $1; }
2132
		| def_list ',' def_elem		{ $$ = cat_str(3, $1, make_str(","), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
2133 2134
		;

2135 2136
def_elem:  ColLabel '=' def_arg		{ $$ = cat_str(3, $1, make_str("="), $3); }
		| ColLabel					{ $$ = $1; }
Marc G. Fournier's avatar
Marc G. Fournier committed
2137 2138
		;

2139
/* Note: any simple identifier will be returned as a type name! */
2140
def_arg:  func_type				{ $$ = $1; }
2141
		| reserved_keyword		{ $$ = $1; }
2142
		| qual_all_Op			{ $$ = $1; }
2143
		| AllConst			{ $$ = $1; }
Marc G. Fournier's avatar
Marc G. Fournier committed
2144 2145
		;

2146
aggr_args:      '(' type_list ')'		{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159
		| '(' '*' ')'                   { $$ = make_str("(*)"); }
		;

old_aggr_definition: '(' old_aggr_list ')'	{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
		;

old_aggr_list: old_aggr_elem				{ $$ = $1; }
		 | old_aggr_list ',' old_aggr_elem	{ $$ = cat_str(3, $1, make_str(","), $3); }
		 ;

old_aggr_elem:  ident '=' def_arg	{ $$ = cat_str(3, $1, make_str("="), $3); }
		;

2160 2161 2162
enum_val_list:  StringConst			{ $$ = $1; }
		| enum_val_list ',' StringConst	{ $$ = cat_str(3, $1, make_str(","), $3);}
		;
2163

2164
CreateOpClassStmt:      CREATE OPERATOR CLASS any_name opt_default FOR TYPE_P Typename
2165
						USING access_method opt_opfamily AS opclass_item_list
2166
		{
2167
			$$ = cat_str(10, make_str("create operator class"), $4, $5, make_str("for type"), $8, make_str("using"), $10, $11, make_str("as"), $13);
2168 2169
		}
		;
2170 2171

opclass_item_list:	opclass_item		{ $$ = $1; }
2172 2173
		| opclass_item_list ',' opclass_item	{ $$ = cat_str(3, $1, make_str(","), $3); }
		;
2174

2175 2176
opclass_item:	OPERATOR PosIntConst any_operator opt_recheck
			{ $$ = cat_str(4, make_str("operator"), $2, $3, $4); }
Michael Meskes's avatar
Michael Meskes committed
2177 2178
		| OPERATOR PosIntConst any_operator oper_argtypes opt_recheck
			{ $$ =  cat_str(5, make_str("operator"), $2, $3, $4, $5); }
2179 2180
		| FUNCTION PosIntConst func_name func_args
			{ $$ = cat_str(4, make_str("function"), $2, $3, $4); }
2181 2182
		| FUNCTION PosIntConst '(' type_list ')' func_name func_args
			{ $$ = cat_str(7, make_str("function"), $2, make_str("("), $4, make_str(")"), $6, $7); }
2183 2184 2185
		| STORAGE Typename
			{ $$ = cat2_str(make_str("storage"), $2); }
		;
2186

2187
opt_default:   DEFAULT	{ $$ = make_str("default"); }
2188 2189
		|  /*EMPTY*/    { $$ = EMPTY; }
		;
2190

2191 2192 2193 2194
opt_opfamily:  FAMILY any_name		{ $$ = cat2_str(make_str("family"), $2); }
                       | /*EMPTY*/	{ $$ = EMPTY; }
               ;

Michael Meskes's avatar
Michael Meskes committed
2195 2196 2197 2198
opt_recheck:   RECHECK		{ 
					mmerror(PARSE_ERROR, ET_WARNING, "no longer supported RECHECK OPTION will be passed to backend");
					$$ = make_str("recheck");
				}
2199 2200
		|  /*EMPTY*/    { $$ = EMPTY; }
		;
2201

2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222
CreateOpFamilyStmt: CREATE OPERATOR FAMILY any_name USING access_method
		{ $$ = cat_str(4, make_str("create operator family"), $4, make_str("using"), $6); }
		;

AlterOpFamilyStmt: ALTER OPERATOR FAMILY any_name USING access_method ADD_P opclass_item_list
			{ $$ = cat_str(6, make_str("alter operator family"), $4, make_str("using"), $6, make_str("add"), $8); }
		 | ALTER OPERATOR FAMILY any_name USING access_method DROP opclass_drop_list
		        { $$ = cat_str(6, make_str("alter operator family"), $4, make_str("using"), $6, make_str("drop"), $8); }
		 ;

opclass_drop_list: opclass_drop				{ $$ = $1; }
		| opclass_drop_list ',' opclass_drop	{ $$ = cat_str(3, $1, make_str(","), $3); }
		;

opclass_drop:
		OPERATOR PosIntConst '(' type_list ')'
			{ $$ = cat_str(5, make_str("operator"), $2, make_str("("), $4, make_str(")")); }
		| FUNCTION PosIntConst '(' type_list ')'
			{ $$ = cat_str(5, make_str("function"), $2, make_str("("), $4, make_str(")")); }
		;

2223 2224
DropOpClassStmt: DROP OPERATOR CLASS any_name USING access_method opt_drop_behavior
			{ $$ = cat_str(5,make_str("drop operator class"), $4, make_str("using"), $6, $7); }
2225 2226
		| DROP OPERATOR CLASS IF_P EXISTS any_name USING access_method opt_drop_behavior
			{ $$ = cat_str(5,make_str("drop operator class if exists"), $6, make_str("using"), $8, $9); }
2227
		;
2228

2229 2230 2231 2232 2233 2234
DropOpFamilyStmt: DROP OPERATOR FAMILY any_name USING access_method opt_drop_behavior
			{ $$ = cat_str(5,make_str("drop operator family"), $4, make_str("using"), $6, $7); }
		| DROP OPERATOR FAMILY IF_P EXISTS any_name USING access_method opt_drop_behavior
			{ $$ = cat_str(5,make_str("drop operator family if exists"), $6, make_str("using"), $8, $9); }
		;

Marc G. Fournier's avatar
Marc G. Fournier committed
2235 2236 2237
/*****************************************************************************
 *
 *		QUERY:
2238
 *
2239 2240 2241 2242 2243 2244
 *		DROP OWNED BY username [, username ...] [ RESTRICT | CASCADE ]
 *		REASSIGN OWNED BY username [, username ...] TO username
 *
 *****************************************************************************/
DropOwnedStmt:
	DROP OWNED BY name_list opt_drop_behavior
2245
			{$$ = cat_str(3, make_str("drop owned by"), $4, $5); }
2246 2247 2248 2249
		;

ReassignOwnedStmt:
	REASSIGN OWNED BY name_list TO name
2250
			{$$ = cat_str(4, make_str("reassign owned by"), $4, make_str("to"), $6); }
2251
		;
2252

2253 2254 2255 2256 2257
/*****************************************************************************
 *
 *		QUERY:
 *
 *			   DROP itemtype [ IF EXISTS ] itemname [, itemname ...] [ RESTRICT | CASCADE ]
Marc G. Fournier's avatar
Marc G. Fournier committed
2258 2259 2260
 *
 *****************************************************************************/

2261 2262
DropStmt:  DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
			{ $$ = cat_str(5, make_str("drop"), $2, make_str("if exists"), $5, $6); }
2263
		| DROP drop_type any_name_list opt_drop_behavior
2264
			{ $$ = cat_str(4, make_str("drop"), $2, $3, $4); }
Marc G. Fournier's avatar
Marc G. Fournier committed
2265 2266
		;

2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278
drop_type:	TABLE				{ $$ = make_str("table"); }
		| SEQUENCE			{ $$ = make_str("sequence"); }
		| VIEW				{ $$ = make_str("view"); }
		| INDEX				{ $$ = make_str("index"); }
		| TYPE_P			{ $$ = make_str("type"); }
		| DOMAIN_P			{ $$ = make_str("domain"); }
		| CONVERSION_P			{ $$ = make_str("conversion"); }
		| SCHEMA			{ $$ = make_str("schema"); }
		| TEXT_P SEARCH PARSER		{ $$ = make_str("text search parser"); }
		| TEXT_P SEARCH DICTIONARY	{ $$ = make_str("text search dictionary"); }
		| TEXT_P SEARCH TEMPLATE	{ $$ = make_str("text search template"); }
		| TEXT_P SEARCH CONFIGURATION 	{ $$ = make_str("text search configuration"); }
2279
		;
2280

2281
any_name_list:  any_name
2282 2283 2284 2285
			{ $$ = $1; }
		| any_name_list ',' any_name
			{ $$ = cat_str(3, $1, make_str(","), $3); }
		;
2286

2287
any_name: ColId        { $$ = $1; }
2288 2289
		| ColId attrs  { $$ = cat2_str($1, $2); }
		;
2290 2291

attrs: '.' attr_name		{ $$ = cat2_str(make_str("."), $2); }
2292 2293
		| attrs '.' attr_name 	{ $$ = cat_str(3, $1, make_str("."), $3); }
		;
2294

Michael Meskes's avatar
Michael Meskes committed
2295 2296
/*****************************************************************************
 *
2297
 *			   QUERY:
2298
 *				   truncate table relname1, relname2, ....
Michael Meskes's avatar
Michael Meskes committed
2299 2300
 *
 *****************************************************************************/
Michael Meskes's avatar
Michael Meskes committed
2301 2302
TruncateStmt:  TRUNCATE opt_table qualified_name_list opt_restart_seqs opt_drop_behavior
			{ $$ = cat_str(5, make_str("truncate table"), $2, $3, $4, $5); }
2303
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
2304

Michael Meskes's avatar
Michael Meskes committed
2305 2306 2307 2308 2309 2310
opt_restart_seqs:
			CONTINUE_P IDENTITY_P	{ $$ = cat2_str(make_str("continue"), make_str("identity")); }
			| RESTART IDENTITY_P	{ $$ = cat2_str(make_str("restart"), make_str("identity")); }
			| /* EMPTY */		{ $$ = EMPTY; }
			;

Marc G. Fournier's avatar
Marc G. Fournier committed
2311 2312 2313
/*****************************************************************************
 *
 *		QUERY:
2314
 *			fetch/move
Marc G. Fournier's avatar
Marc G. Fournier committed
2315 2316 2317
 *
 *****************************************************************************/

2318
/* This is different from the backend as we try to be compatible with many other
2319
 * embedded SQL implementations. So we accept their syntax as well and
2320
 * translate it to the PGSQL syntax. */
2321

2322
FetchStmt: FETCH fetch_direction from_in name ecpg_into
2323 2324 2325 2326
			{
				add_additional_variables($4, false);
				$$ = cat_str(4, make_str("fetch"), $2, $3, $4);
			}
2327
		| FETCH fetch_direction name ecpg_into
2328 2329 2330 2331
			{
				add_additional_variables($3, false);
				$$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
			}
2332
		| FETCH from_in name ecpg_into
2333
			{
2334
				add_additional_variables($3, false);
2335 2336
				$$ = cat_str(3, make_str("fetch"), $2, $3);
			}
2337
		| FETCH name ecpg_into
2338
			{
2339
				add_additional_variables($2, false);
2340 2341
				$$ = cat2_str(make_str("fetch"), $2);
			}
2342
		| FETCH fetch_direction from_in name
2343
			{
2344
				add_additional_variables($4, false);
2345 2346
				$$ = cat_str(4, make_str("fetch"), $2, $3, $4);
			}
2347
		| FETCH fetch_direction name
2348
			{
2349
				add_additional_variables($3, false);
2350 2351
				$$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
			}
2352
		| FETCH from_in name
2353 2354 2355 2356
			{
				add_additional_variables($3, false);
				$$ = cat_str(3, make_str("fetch"), $2, $3);
			}
2357
		| FETCH name
2358
			{
2359
				add_additional_variables($2, false);
2360 2361
				$$ = cat2_str(make_str("fetch"), $2);
			}
2362
		| MOVE fetch_direction from_in name
2363
			{ $$ = cat_str(4, make_str("move"), $2, $3, $4); }
Michael Meskes's avatar
Michael Meskes committed
2364
		| MOVE name
2365
			{ $$ = cat2_str(make_str("move"), $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
2366 2367
		;

2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386
fetch_direction:  NEXT				{ $$ = make_str("next"); }
		| PRIOR				{ $$ = make_str("prior"); }
		| FIRST_P			{ $$ = make_str("first"); }
		| LAST_P			{ $$ = make_str("last"); }
		| ABSOLUTE_P fetch_count	{ $$ = cat2_str(make_str("absolute"), $2); }
		| RELATIVE_P fetch_count	{ $$ = cat2_str(make_str("relative"), $2); }
		| fetch_count			{ $$ = $1; }
		| ALL				{ $$ = make_str("all"); }
		| FORWARD			{ $$ = make_str("forward"); }
		| FORWARD fetch_count		{ $$ = cat2_str(make_str("forward"), $2); }
		| FORWARD ALL			{ $$ = make_str("forward all"); }
		| BACKWARD			{ $$ = make_str("backward"); }
		| BACKWARD fetch_count		{ $$ = cat2_str(make_str("backward"), $2); }
		| BACKWARD ALL			{ $$ = make_str("backward all"); }
		;

fetch_count:	IntConst	{
		                	if ($1[1] == '$')
					{
Michael Meskes's avatar
Michael Meskes committed
2387
						/* a variable here has to be replaced on the client side, thus we have to use '$0' here */
2388 2389
						$$ = make_str("$0");
						free($1);
2390
					}
2391
					else
2392
						$$ = $1;
2393
				}
2394

2395
from_in: IN_P				{ $$ = make_str("in"); }
2396
		| FROM			{ $$ = make_str("from"); }
2397
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
2398

Michael Meskes's avatar
Michael Meskes committed
2399 2400
CommentStmt:   COMMENT ON comment_type name IS comment_text
			{ $$ = cat_str(5, make_str("comment on"), $3, $4, make_str("is"), $6); }
2401 2402
		| COMMENT ON AGGREGATE func_name aggr_args IS comment_text
			{ $$ = cat_str(5, make_str("comment on aggregate"), $4, $5, make_str("is"), $7); }
Michael Meskes's avatar
Michael Meskes committed
2403 2404
		| COMMENT ON FUNCTION func_name func_args IS comment_text
			{ $$ = cat_str(5, make_str("comment on function"), $4, $5, make_str("is"), $7); }
Michael Meskes's avatar
Michael Meskes committed
2405 2406
		| COMMENT ON OPERATOR any_operator oper_argtypes IS comment_text
			{ $$ = cat_str(5, make_str("comment on operator"), $4, $5, make_str("is"), $7); }
2407
		| COMMENT ON TRIGGER name ON any_name IS comment_text
Michael Meskes's avatar
Michael Meskes committed
2408 2409 2410 2411 2412
			{ $$ = cat_str(6, make_str("comment on trigger"), $4, make_str("on"), $6, make_str("is"), $8); }
		| COMMENT ON RULE name ON any_name IS comment_text
			{ $$ = cat_str(6, make_str("comment on rule"), $4, make_str("on"), $6, make_str("is"), $8); }
		| COMMENT ON RULE name IS comment_text
			{ $$ = cat_str(4, make_str("comment on rule"), $4, make_str("is"), $6); }
2413 2414
		| COMMENT ON OPERATOR CLASS any_name USING access_method IS comment_text
			{ $$ = cat_str(6, make_str("comment on operator class"), $5, make_str("using"), $7, make_str("is"), $9); }
2415 2416
		| COMMENT ON OPERATOR FAMILY any_name USING access_method IS comment_text
			{ $$ = cat_str(6, make_str("comment on operator family"), $5, make_str("using"), $7, make_str("is"), $9); }
2417 2418 2419 2420 2421 2422
		| COMMENT ON LARGE_P OBJECT_P NumConst IS comment_text
			{ $$ = cat_str(4, make_str("comment on large object"), $5, make_str("is"), $7); }
		| COMMENT ON CAST '(' Typename AS Typename ')' IS comment_text
			{ $$ = cat_str(6, make_str("comment on cast ("), $5, make_str("as"), $7, make_str(") is"), $10); }
		| COMMENT ON opt_procedural LANGUAGE any_name IS comment_text
			{ $$ = cat_str(6, make_str("comment on"), $3, make_str("language"), $5, make_str("is"), $7); }
2423 2424 2425 2426 2427 2428 2429 2430
		| COMMENT ON TEXT_P SEARCH PARSER any_name IS comment_text
			{ $$ = cat_str(4, make_str("comment on test search parser"), $6, make_str("is"), $8); }
		| COMMENT ON TEXT_P SEARCH DICTIONARY any_name IS comment_text
			{ $$ = cat_str(4, make_str("comment on test search dictionary"), $6, make_str("is"), $8); }
		| COMMENT ON TEXT_P SEARCH TEMPLATE any_name IS comment_text
			{ $$ = cat_str(4, make_str("comment on test search template"), $6, make_str("is"), $8); }
		| COMMENT ON TEXT_P SEARCH CONFIGURATION any_name IS comment_text
			{ $$ = cat_str(4, make_str("comment on test search configuration"), $6, make_str("is"), $8); }
Michael Meskes's avatar
Michael Meskes committed
2431 2432 2433
		;

comment_type:  COLUMN		{ $$ = make_str("column"); }
2434 2435 2436 2437 2438 2439 2440 2441
		| DATABASE			{ $$ = make_str("database"); }
		| SCHEMA			{ $$ = make_str("schema"); }
		| INDEX				{ $$ = make_str("idnex"); }
		| SEQUENCE			{ $$ = make_str("sequence"); }
		| TABLE				{ $$ = make_str("table"); }
		| DOMAIN_P			{ $$ = make_str("domain"); }
		| TYPE_P			{ $$ = make_str("type"); }
		| VIEW				{ $$ = make_str("view"); }
2442 2443 2444
		| CONVERSION_P			{ $$ = make_str("conversion"); }
		| TABLESPACE			{ $$ = make_str("tablespace"); }
		| ROLE				{ $$ = make_str("role"); }
Michael Meskes's avatar
Michael Meskes committed
2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461
		;

comment_text:	StringConst { $$ = $1; }
		| NULL_P			{ $$ = make_str("null"); }
	   	;

/*****************************************************************************
 *
 *		QUERY:
 * GRANT and REVOKE statements
 *
 *****************************************************************************/

GrantStmt:	GRANT privileges ON privilege_target TO grantee_list opt_grant_grant_option
			{ $$ = cat_str(7, make_str("grant"), $2, make_str("on"), $4, make_str("to"), $6, $7); }
		;

2462
RevokeStmt:  REVOKE privileges ON privilege_target FROM grantee_list opt_drop_behavior
2463
			{$$ = cat_str(7, make_str("revoke"), $2, make_str("on"), $4, make_str("from"), $6, $7); }
2464
		| REVOKE GRANT OPTION FOR privileges ON privilege_target FROM grantee_list opt_drop_behavior
2465
			{$$ = cat_str(7, make_str("revoke grant option for"), $5, make_str("on"), $7, make_str("from"), $9, $10); }
Michael Meskes's avatar
Michael Meskes committed
2466 2467 2468 2469 2470 2471 2472
		;

privileges:  ALL PRIVILEGES		{ $$ = make_str("all privileges"); }
		| ALL					{ $$ = make_str("all"); }
		| privilege_list		{ $$ = $1; }
		;

2473
privilege_list:  privilege
Michael Meskes's avatar
Michael Meskes committed
2474
			{ $$ = $1; }
2475
		| privilege_list ',' privilege
Michael Meskes's avatar
Michael Meskes committed
2476 2477 2478 2479 2480
			{ $$ = cat_str(3, $1, make_str(","), $3); }
		;

privilege:	SELECT			{ $$ = make_str("select"); }
		| REFERENCES		{ $$ = make_str("references"); }
2481 2482
		| CREATE			{ $$ = make_str("create"); }
		| ColId				{ $$ = $1; }
Michael Meskes's avatar
Michael Meskes committed
2483 2484
		;

2485
privilege_target: qualified_name_list
Michael Meskes's avatar
Michael Meskes committed
2486
			{ $$ = $1; }
2487
		| TABLE qualified_name_list
Michael Meskes's avatar
Michael Meskes committed
2488
			{ $$ = cat2_str(make_str("table"), $2); }
2489 2490
		| SEQUENCE qualified_name_list
			{ $$ = cat2_str(make_str("sequence"), $2); }
Michael Meskes's avatar
Michael Meskes committed
2491 2492 2493 2494
		| FUNCTION function_with_argtypes_list
			{ $$ = cat2_str(make_str("function"), $2); }
		| DATABASE name_list
			{ $$ = cat2_str(make_str("database"), $2); }
2495
		| LANGUAGE name_list
Michael Meskes's avatar
Michael Meskes committed
2496
			{ $$ = cat2_str(make_str("language") , $2); }
2497
		| SCHEMA name_list
Michael Meskes's avatar
Michael Meskes committed
2498
			{ $$ = cat2_str(make_str("schema") , $2); }
2499 2500
		| TABLESPACE name_list
			{ $$ = cat2_str(make_str("tablespace") , $2); }
Michael Meskes's avatar
Michael Meskes committed
2501 2502
		;

2503
grantee_list: grantee
Michael Meskes's avatar
Michael Meskes committed
2504
			{ $$ = $1; }
2505
		| grantee_list ',' grantee
Michael Meskes's avatar
Michael Meskes committed
2506 2507 2508
			{ $$ = cat_str(3, $1, make_str(","), $3); }
		;

2509 2510
grantee:  RoleId			{ $$ = $1; }
		| GROUP_P RoleId	{ $$ = cat2_str(make_str("group"), $2); }
Michael Meskes's avatar
Michael Meskes committed
2511 2512 2513 2514
		;

opt_grant_grant_option:  WITH GRANT OPTION
		{
2515
			mmerror(PARSE_ERROR, ET_WARNING, "currently unsupported GRANT/WITH GRANT OPTION will be passed to backend");
Michael Meskes's avatar
Michael Meskes committed
2516 2517
			$$ = make_str("with grant option");
		}
2518
		| /*EMPTY*/ 		{ $$ = EMPTY; }
Michael Meskes's avatar
Michael Meskes committed
2519 2520 2521 2522 2523 2524 2525 2526 2527 2528
		;

function_with_argtypes_list: function_with_argtypes
			{ $$ = $1; }
		| function_with_argtypes_list ',' function_with_argtypes
			{ $$ = cat_str(3, $1, make_str(","), $3); }
		;

function_with_argtypes: func_name func_args { $$ = cat2_str($1, $2); };

2529 2530 2531 2532 2533 2534 2535
/*****************************************************************************
 *
 * GRANT and REVOKE ROLE statements
 *
 *****************************************************************************/

GrantRoleStmt:
2536 2537 2538
		GRANT privilege_list TO name_list opt_grant_admin_option opt_granted_by
			{ $$ = cat_str(6, make_str("grant"), $2, make_str("to"), $4, $5, $6); }
		;
2539 2540

RevokeRoleStmt:
2541 2542 2543
		REVOKE privilege_list FROM name_list opt_granted_by opt_drop_behavior
			{ $$ = cat_str(6, make_str("revoke"), $2, make_str("from"), $4, $5, $6); }
		;
2544 2545 2546 2547

opt_grant_admin_option: WITH ADMIN OPTION	{ $$ = make_str("with admin option"); }
		| /*EMPTY*/		 	{ $$ = EMPTY; }
		;
2548

2549 2550 2551 2552
opt_granted_by: GRANTED BY RoleId	 { $$ = cat2_str(make_str("granted by"), $3); }
		| /*EMPTY*/		 { $$ = EMPTY; }
		;

Marc G. Fournier's avatar
Marc G. Fournier committed
2553 2554 2555
/*****************************************************************************
 *
 *		QUERY:
Michael Meskes's avatar
Michael Meskes committed
2556 2557 2558 2559 2560 2561 2562
 *             QUERY: CREATE INDEX
 *
 * Note: we can't factor CONCURRENTLY into a separate production without
 * making it a reserved word.
 *
 * Note: we cannot put TABLESPACE clause after WHERE clause unless we are
 * willing to make TABLESPACE a fully reserved word.
Marc G. Fournier's avatar
Marc G. Fournier committed
2563 2564 2565
 *
 *****************************************************************************/

2566
IndexStmt:	CREATE index_opt_unique INDEX index_name ON qualified_name
2567 2568
				access_method_clause '(' index_params ')' opt_definition OptTableSpace where_clause
			{ $$ = cat_str(13, make_str("create"), $2, make_str("index"), $4, make_str("on"), $6, $7, make_str("("), $9, make_str(")"), $11, $12, $13); }
Michael Meskes's avatar
Michael Meskes committed
2569 2570 2571
		| CREATE index_opt_unique INDEX CONCURRENTLY index_name ON qualified_name
				access_method_clause '(' index_params ')' opt_definition OptTableSpace where_clause
			{ $$ = cat_str(13, make_str("create"), $2, make_str("index concurrently"), $5, make_str("on"), $7, $8, make_str("("), $10, make_str(")"), $12, $13, $14); }
Marc G. Fournier's avatar
Marc G. Fournier committed
2572 2573
		;

Michael Meskes's avatar
Michael Meskes committed
2574
index_opt_unique:  UNIQUE	{ $$ = make_str("unique"); }
2575
		| /*EMPTY*/ 		{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
2576 2577
		;

2578
access_method_clause:  USING access_method
2579
			{ $$ = cat2_str(make_str("using"), $2); }
2580
		| /*EMPTY*/
2581
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
2582 2583
		;

2584
index_params:  index_elem			{ $$ = $1; }
2585
		| index_params ',' index_elem	{ $$ = cat_str(3, $1, make_str(","), $3); }
2586
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
2587

2588 2589 2590 2591 2592 2593
index_elem:  ColId opt_class opt_asc_desc opt_nulls_order
			{ $$ = cat_str(4, $1, $2, $3, $4); }
		| func_expr opt_class opt_asc_desc opt_nulls_order
			{ $$ = cat_str(4, $1, $2, $3, $4); }
		| '(' a_expr ')' opt_class opt_asc_desc opt_nulls_order
			{ $$ = cat_str(6, make_str("("), $2, make_str(")"), $4, $5, $6); }
2594
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
2595

2596 2597
opt_class:	any_name 	{ $$ = $1; }
		| USING any_name	{ $$ = cat2_str(make_str("using"), $2); }
2598
		| /*EMPTY*/		{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
2599 2600
		;

2601 2602 2603 2604 2605 2606 2607 2608 2609 2610
opt_asc_desc: 	ASC 		{ $$ = make_str("asc"); }
		| DESC		{ $$ = make_str("desc"); } 
		| /*EMPTY*/	{ $$ = EMPTY; }
		;

opt_nulls_order: 	NULLS_FIRST 		{ $$ = make_str("nulls first"); }
			| NULLS_LAST		{ $$ = make_str("nulls last"); } 
			| /*EMPTY*/	{ $$ = EMPTY; }
			;

2611
CreateFunctionStmt:	CREATE opt_or_replace FUNCTION func_name func_args
2612
					RETURNS func_return createfunc_opt_list opt_definition
2613
			{ $$ = cat_str(8, make_str("create"), $2, make_str("function"), $4, $5, make_str("returns"), $7, $8); }
Michael Meskes's avatar
Michael Meskes committed
2614 2615 2616
		| CREATE opt_or_replace FUNCTION func_name func_args
					RETURNS TABLE '(' table_func_column_list ')' createfunc_opt_list opt_definition
			{ $$ = cat_str(9, make_str("create"), $2, make_str("function"), $4, $5, make_str("returns table ("), $9, make_str(")"), $11, $12); }
2617
		| CREATE opt_or_replace FUNCTION func_name func_args
2618 2619
					createfunc_opt_list opt_definition
			{ $$ = cat_str(6, make_str("create"), $2, make_str("function"), $4, $5, $6, $7); }
2620
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
2621

2622
opt_or_replace:  OR REPLACE		{ $$ = make_str("or replace"); }
2623
		| /*EMPTY*/				{ $$ = EMPTY; }
2624 2625
		;

2626 2627 2628 2629
func_args:	'(' func_args_list ')'
			{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
		| '(' ')'
			{ $$ = make_str("()"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
2630 2631
		;

2632 2633
func_args_list:  func_arg
			{ $$ = $1; }
Michael Meskes's avatar
Michael Meskes committed
2634
		| func_args_list ',' func_arg
2635
			{ $$ = cat_str(3, $1, make_str(","), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
2636 2637
		;

2638 2639 2640 2641 2642
func_arg:  arg_class param_name func_type		{ $$ = cat_str(3, $1, $2, $3); }
		| param_name arg_class func_type	{ $$ = cat_str(3, $1, $2, $3); }
		| param_name func_type			{ $$ = cat2_str($1, $2); }
		| arg_class func_type			{ $$ = cat2_str($1, $2); }
		| func_type				{ $$ = $1; }
2643
		;
Michael Meskes's avatar
Michael Meskes committed
2644

2645 2646 2647 2648
arg_class:  IN_P		{ $$ = make_str("in"); }
		| OUT_P 	{ $$ = make_str("out"); }
		| INOUT 	{ $$ = make_str("inout"); }
		| IN_P OUT_P 	{ $$ = make_str("in out"); }
2649
		| VARIADIC 	{ $$ = make_str("variadic"); }
2650
		;
Michael Meskes's avatar
Michael Meskes committed
2651

2652 2653 2654 2655
func_as: StringConst
			{ $$ = $1; }
		| StringConst ',' StringConst
			{ $$ = cat_str(3, $1, make_str(","), $3); }
2656
		;
2657

2658
param_name:    type_function_name	{ $$ = $1; };
2659

2660
func_return:  func_type
2661 2662 2663 2664 2665 2666 2667
		{
			/* We can catch over-specified arguments here if we want to,
			 * but for now better to silently swallow typmod, etc.
			 * - thomas 2000-03-22
			 */
			$$ = $1;
		}
Marc G. Fournier's avatar
Marc G. Fournier committed
2668 2669
		;

2670
func_type:	Typename
2671
			{ $$ = $1; }
2672
		| type_function_name attrs '%' TYPE_P
2673
			{ $$ = cat_str(3, $1, $2, make_str("% type")); }
2674 2675
		| SETOF type_function_name attrs '%' TYPE_P
			{ $$ = cat_str(4, make_str("setof"), $2, $3, make_str("% type")); }
2676 2677
		;

2678 2679 2680 2681 2682 2683 2684

createfunc_opt_list: createfunc_opt_item
			{ $$ = $1; }
		| createfunc_opt_list createfunc_opt_item
			{ $$ = cat2_str($1, $2); }
		;

2685 2686 2687 2688 2689 2690 2691
common_func_opt_item:
		CALLED ON NULL_P INPUT_P
				{ $$ = make_str("called on null input"); }
		| RETURNS NULL_P ON NULL_P INPUT_P
				{ $$ = make_str("returns null on null input"); }
		| STRICT_P
				{ $$ = make_str("strict"); }
2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705
		| IMMUTABLE
				{ $$ = make_str("immutable"); }
		| STABLE
				{ $$ = make_str("stable"); }
		| VOLATILE
				{ $$ = make_str("volatile"); }
		| EXTERNAL SECURITY DEFINER
				{ $$ = make_str("external security definer"); }
		| EXTERNAL SECURITY INVOKER
				{ $$ = make_str("external security invoker"); }
		| SECURITY DEFINER
				{ $$ = make_str("security definer"); }
		| SECURITY INVOKER
				{ $$ = make_str("security invoker"); }
2706 2707 2708 2709
		| COST NumConst
				{ $$ = cat2_str(make_str("cost"), $2); }
		| ROWS NumConst
				{ $$ = cat2_str(make_str("rows"), $2); }
2710 2711
		| SetResetClause
				{ $$ = $1; }
2712
		;
2713

2714 2715 2716 2717 2718 2719 2720
createfunc_opt_item: AS func_as
				{ $$ = cat2_str(make_str("as"), $2); }
		| LANGUAGE ColId_or_Sconst
				{ $$ = cat2_str(make_str("language"), $2); }
		| common_func_opt_item
				{ $$ = $1; }
		;
2721

2722
opt_definition: WITH definition	{ $$ = cat2_str(make_str("with"), $2); }
2723 2724
		| /*EMPTY*/ 	{ $$ = EMPTY; }
		;
2725

Michael Meskes's avatar
Michael Meskes committed
2726 2727 2728 2729 2730 2731 2732 2733
table_func_column:      param_name func_type	{ $$ = cat2_str($1, $2); }
			;

table_func_column_list:
			table_func_column				{ $$ = $1; }
			| table_func_column_list ',' table_func_column	{ $$ = cat_str(3, $1, make_str(","), $3); }
			; 

2734
AlterFunctionStmt:
2735 2736 2737
		ALTER FUNCTION function_with_argtypes alterfunc_opt_list opt_restrict
			{ $$ = cat_str(4, make_str("alter function"), $3, $4, $5); }
		;
2738 2739 2740 2741 2742 2743

alterfunc_opt_list: common_func_opt_item			{ $$ = $1; }
		| alterfunc_opt_list common_func_opt_item 	{ $$ = cat2_str($1, $2);}
		;

opt_restrict:	RESTRICT	{ $$ = make_str("restrict"); }
2744
		| /*EMPTY*/	  { $$ = EMPTY; }
2745 2746
		;

Marc G. Fournier's avatar
Marc G. Fournier committed
2747 2748 2749 2750
/*****************************************************************************
 *
 *		QUERY:
 *
2751
 *			   DROP FUNCTION funcname (arg1, arg2, ...)
2752
 *			   DROP AGGREGATE (arg1, ...) [ RESTRICT | CASCADE ]
2753
 *			   DROP OPERATOR opname (leftoperand_typ rightoperand_typ)
Marc G. Fournier's avatar
Marc G. Fournier committed
2754 2755 2756
 *
 *****************************************************************************/

2757 2758
RemoveFuncStmt:  DROP FUNCTION func_name func_args opt_drop_behavior
			{ $$ = cat_str(4, make_str("drop function"), $3, $4, $5); }
2759 2760
		| DROP FUNCTION IF_P EXISTS func_name func_args opt_drop_behavior
			{ $$ = cat_str(4, make_str("drop function if exists"), $5, $6, $7); }
Marc G. Fournier's avatar
Marc G. Fournier committed
2761 2762
		;

2763 2764
RemoveAggrStmt:  DROP AGGREGATE func_name aggr_args opt_drop_behavior
			{ $$ = cat_str(4, make_str("drop aggregate"), $3, $4, $5); }
2765 2766
		| DROP AGGREGATE IF_P EXISTS func_name aggr_args opt_drop_behavior
			{ $$ = cat_str(4, make_str("drop aggregate if exists"), $5, $6, $7); }
Marc G. Fournier's avatar
Marc G. Fournier committed
2767 2768
		;

Michael Meskes's avatar
Michael Meskes committed
2769 2770 2771 2772
RemoveOperStmt:  DROP OPERATOR any_operator oper_argtypes opt_drop_behavior
			{ $$ = cat_str(4, make_str("drop operator"), $3, $4, $5); }
		| DROP OPERATOR IF_P EXISTS any_operator oper_argtypes opt_drop_behavior
			{ $$ = cat_str(4, make_str("drop operator if exists"), $5, $6, $7); }
Marc G. Fournier's avatar
Marc G. Fournier committed
2773 2774
		;

Michael Meskes's avatar
Michael Meskes committed
2775
oper_argtypes:	'(' Typename ')'
2776 2777 2778 2779
			{
				mmerror(PARSE_ERROR, ET_ERROR, "parser: argument type missing (use NONE for unary operators)");
				$$ = make_str("none");
			}
Michael Meskes's avatar
Michael Meskes committed
2780 2781 2782 2783 2784 2785
		| '(' Typename ',' Typename ')'
			{ $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")")); }
		| '(' NONE ',' Typename ')'		/* left unary */
			{ $$ = cat_str(3, make_str("(none,"), $4, make_str(")")); }
		| '(' Typename ',' NONE ')'		/* right unary */
			{ $$ = cat_str(3, make_str("("), $2, make_str(", none)")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
2786 2787
		;

2788
any_operator:
2789 2790 2791 2792 2793
		all_Op
			{ $$ = $1; }
		| ColId '.' any_operator
			{ $$ = cat_str(3, $1, make_str("."), $3); }
		;
2794

2795
CreateCastStmt:		CREATE CAST '(' Typename AS Typename ')'
2796 2797
				WITH FUNCTION function_with_argtypes cast_context
			{ $$ = cat_str(6, make_str("create cast ("), $4, make_str("as"), $6, make_str(") with function"), $10); }
2798
		| CREATE CAST '(' Typename AS Typename ')'
2799 2800 2801 2802 2803 2804 2805 2806 2807
				WITHOUT FUNCTION cast_context
			{ $$ = cat_str(6, make_str("create cast ("), $4, make_str("as"), $6, make_str(") without function"), $10); }
		;

cast_context: AS ASSIGNMENT   { $$ = make_str("as assignment"); }
		| /*EMPTY*/	{ $$ = EMPTY; }
		;


2808 2809 2810 2811 2812 2813
DropCastStmt: DROP CAST opt_if_exists  '(' Typename AS Typename ')' opt_drop_behavior
			{ $$ = cat_str(8, make_str("drop cast"), $3, make_str("("), $5, make_str("as"), $7, make_str(")"), $9); }
		;

opt_if_exists: IF_P EXISTS	{ $$ = make_str("if exists"); }
		| /* EMPTY */	{ $$ = EMPTY; }
2814 2815
		;

Michael Meskes's avatar
Michael Meskes committed
2816 2817
/*****************************************************************************
 *
2818
 *				QUERY:
Michael Meskes's avatar
Michael Meskes committed
2819
 *
2820
 *				REINDEX type <typename> [FORCE] [ALL]
Michael Meskes's avatar
Michael Meskes committed
2821 2822
 *
 *****************************************************************************/
2823
ReindexStmt:  REINDEX reindex_type qualified_name opt_force
2824
			{ $$ = cat_str(4, make_str("reindex"), $2, $3, $4); }
2825 2826
		| REINDEX SYSTEM_P name opt_force
			{ $$ = cat_str(3, make_str("reindex system"), $3, $4); }
2827 2828
		| REINDEX DATABASE name opt_force
			{ $$ = cat_str(3, make_str("reindex database"), $3, $4); }
2829
		;
Michael Meskes's avatar
Michael Meskes committed
2830

2831
reindex_type:	INDEX		{ $$ = make_str("index"); }
2832
		| TABLE		{ $$ = make_str("table"); }
2833 2834 2835 2836 2837
		;

opt_force: FORCE			{ $$ = make_str("force"); }
		| /* EMPTY */		{ $$ = EMPTY; }
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
2838 2839 2840 2841 2842 2843 2844 2845 2846

/*****************************************************************************
 *
 *		QUERY:
 *				rename <attrname1> in <relname> [*] to <attrname2>
 *				rename <relname1> to <relname2>
 *
 *****************************************************************************/

2847 2848
RenameStmt:  ALTER AGGREGATE func_name aggr_args RENAME TO name
			{ $$ = cat_str(5, make_str("alter aggregate"), $3, $4, make_str("rename to"), $7); }
2849
		| ALTER CONVERSION_P any_name RENAME TO name
Michael Meskes's avatar
Michael Meskes committed
2850
			{ $$ = cat_str(4, make_str("alter conversion"), $3, make_str("rename to"), $6); }
2851
		| ALTER DATABASE database_name RENAME TO database_name
Michael Meskes's avatar
Michael Meskes committed
2852
			{ $$ = cat_str(4, make_str("alter database"), $3, make_str("rename to"), $6); }
2853 2854
		| ALTER FUNCTION function_with_argtypes RENAME TO name
			{ $$ = cat_str(4, make_str("alter function"), $3, make_str("rename to"), $6); }
2855
		| ALTER GROUP_P RoleId RENAME TO RoleId
Michael Meskes's avatar
Michael Meskes committed
2856
			{ $$ = cat_str(4, make_str("alter group"), $3, make_str("rename to"), $6); }
2857 2858
		| ALTER opt_procedural LANGUAGE name RENAME TO name
			{ $$ = cat_str(6, make_str("alter"), $2, make_str("language"), $4, make_str("rename to"), $7); }
2859
		| ALTER OPERATOR CLASS any_name USING access_method RENAME TO name
Michael Meskes's avatar
Michael Meskes committed
2860
			{ $$ = cat_str(6, make_str("alter operator class"), $4, make_str("using"), $6, make_str("rename to"), $9); }
2861 2862
		| ALTER OPERATOR FAMILY any_name USING access_method RENAME TO name
			{ $$ = cat_str(6, make_str("alter operator family"), $4, make_str("using"), $6, make_str("rename to"), $9); }
2863
		| ALTER SCHEMA name RENAME TO name
Michael Meskes's avatar
Michael Meskes committed
2864
			{ $$ = cat_str(4, make_str("alter schema"), $3, make_str("rename to"), $6); }
2865
		| ALTER TABLE relation_expr RENAME TO name
2866
			{ $$ = cat_str(4, make_str("alter table"), $3, make_str("rename to"), $6); }
Michael Meskes's avatar
Michael Meskes committed
2867 2868
		| ALTER TABLE relation_expr SET SCHEMA name
			{ $$ = cat_str(4, make_str("alter table"), $3, make_str("set schema"), $6); }
Michael Meskes's avatar
Michael Meskes committed
2869 2870 2871 2872
		| ALTER SEQUENCE relation_expr RENAME TO name
			{ $$ = cat_str(4, make_str("alter sequence"), $3, make_str("rename to"), $6); }
		| ALTER VIEW relation_expr RENAME TO name
			{ $$ = cat_str(4, make_str("alter view"), $3, make_str("rename to"), $6); }
2873
		| ALTER INDEX relation_expr RENAME TO name
Michael Meskes's avatar
Michael Meskes committed
2874
			{ $$ = cat_str(4, make_str("alter index"), $3, make_str("rename to"), $6); }
2875
		| ALTER TABLE relation_expr RENAME opt_column name TO name
2876
			{ $$ = cat_str(7, make_str("alter table"), $3, make_str("rename"), $5, $6, make_str("to"), $8); }
2877
		| ALTER TRIGGER name ON relation_expr RENAME TO name
Michael Meskes's avatar
Michael Meskes committed
2878
			{ $$ = cat_str(6, make_str("alter trigger"), $3, make_str("on"), $5, make_str("rename to"), $8); }
2879
		| ALTER USER RoleId RENAME TO RoleId
Michael Meskes's avatar
Michael Meskes committed
2880
			{ $$ = cat_str(4, make_str("alter user"), $3, make_str("rename to"), $6); }
2881
		| ALTER TABLESPACE name RENAME TO name
2882
			{ $$ = cat_str(4, make_str("alter tablespace"), $3, make_str("rename to"), $6); }
2883 2884 2885 2886 2887 2888 2889 2890
		| ALTER TEXT_P SEARCH PARSER any_name RENAME TO name
			{ $$ = cat_str(4, make_str("alter text search parser"), $5, make_str("rename to"), $8); }
		| ALTER TEXT_P SEARCH DICTIONARY any_name RENAME TO name
			{ $$ = cat_str(4, make_str("alter text search dictionary"), $5, make_str("rename to"), $8); }
		| ALTER TEXT_P SEARCH TEMPLATE any_name RENAME TO name
			{ $$ = cat_str(4, make_str("alter text search template"), $5, make_str("rename to"), $8); }
		| ALTER TEXT_P SEARCH CONFIGURATION any_name RENAME TO name
			{ $$ = cat_str(4, make_str("alter text search configuration"), $5, make_str("rename to"), $8); }
Michael Meskes's avatar
Michael Meskes committed
2891 2892
		| ALTER TYPE_P any_name RENAME TO name
			{ $$ = cat_str(4, make_str("alter type"), $3, make_str("rename to"), $6); }
Marc G. Fournier's avatar
Marc G. Fournier committed
2893 2894
		;

2895 2896
opt_column:  COLUMN			{ $$ = make_str("column"); }
		| /*EMPTY*/			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
2897 2898
		;

2899 2900 2901 2902
opt_set_data:  SET DATA_P			{ $$ = make_str("set data"); }
		| /*EMPTY*/			{ $$ = EMPTY; }
		;

2903 2904
/*****************************************************************************
 *
2905
 * ALTER THING name SET SCHEMA name
2906 2907 2908
 *
 *****************************************************************************/

2909
AlterObjectSchemaStmt:
2910 2911
		ALTER AGGREGATE func_name aggr_args SET SCHEMA name
			{ $$ = cat_str(5, make_str("alter aggregate"), $3, $4, make_str("set schema"), $7); }
2912 2913
		| ALTER DOMAIN_P any_name SET SCHEMA name
			{ $$ = cat_str(4, make_str("alter domain"), $3, make_str("set schema"), $6); }
2914 2915
		| ALTER FUNCTION function_with_argtypes SET SCHEMA name
			{ $$ = cat_str(4, make_str("alter function"), $3, make_str("set schema"), $6); }
2916 2917
		| ALTER SEQUENCE relation_expr SET SCHEMA name
			{ $$ = cat_str(4, make_str("alter sequence"), $3, make_str("set schema"), $6); }
Michael Meskes's avatar
Michael Meskes committed
2918
		| ALTER VIEW relation_expr SET SCHEMA name
2919 2920 2921 2922
			{ $$ = cat_str(4, make_str("alter sequence"), $3, make_str("set schema"), $6); }
		| ALTER TYPE_P any_name SET SCHEMA name
			{ $$ = cat_str(4, make_str("alter type"), $3, make_str("set schema"), $6); }
		;
2923

2924 2925 2926 2927 2928 2929
/*****************************************************************************
 *
 * ALTER THING name OWNER TO newname
 *
 *****************************************************************************/

2930 2931
AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
			{ $$ = cat_str(5, make_str("alter aggregate"), $3, $4, make_str("owner to"), $7); }
2932
		| ALTER CONVERSION_P any_name OWNER TO RoleId
2933
			{ $$ = cat_str(4, make_str("alter conversion"), $3, make_str("owner to"), $6); }
2934
		| ALTER DATABASE database_name OWNER TO RoleId
2935
			{ $$ = cat_str(4, make_str("alter database"), $3, make_str("owner to"), $6); }
2936
		| ALTER DOMAIN_P database_name OWNER TO RoleId
2937
			{ $$ = cat_str(4, make_str("alter domain"), $3, make_str("owner to"), $6); }
2938 2939
		| ALTER FUNCTION function_with_argtypes OWNER TO RoleId
			{ $$ = cat_str(4, make_str("alter function"), $3, make_str("owner to"), $6); }
2940 2941
		| ALTER opt_procedural LANGUAGE name OWNER TO RoleId
			{ $$ = cat_str(6, make_str("alter"), $2, make_str("language"), $4, make_str("owner to"), $7); }
Michael Meskes's avatar
Michael Meskes committed
2942 2943
		| ALTER OPERATOR any_operator oper_argtypes OWNER TO RoleId
			{ $$ = cat_str(5, make_str("alter operator"), $3, $4, make_str("owner to"), $7); }
2944
		| ALTER OPERATOR CLASS any_name USING access_method OWNER TO RoleId
2945
			{ $$ = cat_str(6, make_str("alter operator class"), $4, make_str("using"), $6, make_str("owner to"), $9); }
2946 2947
		| ALTER OPERATOR FAMILY any_name USING access_method OWNER TO RoleId
			{ $$ = cat_str(6, make_str("alter operator family"), $4, make_str("using"), $6, make_str("owner to"), $9); }
2948
		| ALTER SCHEMA name OWNER TO RoleId
2949
			{ $$ = cat_str(4, make_str("alter schema"), $3, make_str("owner to"), $6); }
2950
		| ALTER TYPE_P any_name OWNER TO RoleId
2951
			{ $$ = cat_str(4, make_str("alter type"), $3, make_str("owner to"), $6); }
2952
		| ALTER TABLESPACE name OWNER TO RoleId
2953
			{ $$ = cat_str(4, make_str("alter tablespace"), $3, make_str("owner to"), $6); }
2954 2955 2956 2957
		| ALTER TEXT_P SEARCH DICTIONARY any_name OWNER TO RoleId
			{ $$ = cat_str(4, make_str("alter text search dictionary"), $5, make_str("owner to"), $8); }
		| ALTER TEXT_P SEARCH CONFIGURATION any_name OWNER TO RoleId
			{ $$ = cat_str(4, make_str("alter text search configuration"), $5, make_str("owner to"), $8); }
2958 2959
		;

Marc G. Fournier's avatar
Marc G. Fournier committed
2960 2961 2962

/*****************************************************************************
 *
2963
 *		QUERY:	Define Rewrite Rule
Marc G. Fournier's avatar
Marc G. Fournier committed
2964 2965 2966
 *
 *****************************************************************************/

2967
RuleStmt:  CREATE opt_or_replace RULE name AS
Marc G. Fournier's avatar
Marc G. Fournier committed
2968
		   { QueryIsRule=1; }
2969
		   ON event TO qualified_name where_clause
2970
		   DO opt_instead RuleActionList
2971 2972
		{
			QueryIsRule=0;
2973
			$$ = cat_str(12, make_str("create"), $2, make_str("rule"), $4, make_str("as on"), $8, make_str("to"), $10, $11, make_str("do"), $13, $14);
2974
		}
Marc G. Fournier's avatar
Marc G. Fournier committed
2975 2976
		;

2977
RuleActionList:  NOTHING				{ $$ = make_str("nothing"); }
Michael Meskes's avatar
Michael Meskes committed
2978
		| RuleActionStmt				{ $$ = $1; }
2979 2980
		| '(' RuleActionMulti ')'		{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
				;
Marc G. Fournier's avatar
Marc G. Fournier committed
2981

Michael Meskes's avatar
Michael Meskes committed
2982
/* the thrashing around here is to discard "empty" statements... */
Michael Meskes's avatar
Michael Meskes committed
2983 2984 2985 2986
RuleActionMulti:  RuleActionMulti ';' RuleActionStmtOrEmpty
			{  $$ = cat_str(3, $1, make_str(";"), $3); }
		| RuleActionStmtOrEmpty
			{ $$ = cat2_str($1, make_str(";")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
2987 2988
		;

Michael Meskes's avatar
Michael Meskes committed
2989 2990 2991 2992 2993 2994 2995 2996
RuleActionStmt:   SelectStmt
		| InsertStmt
		| UpdateStmt
		| DeleteStmt
		| NotifyStmt
		;

RuleActionStmtOrEmpty: RuleActionStmt	{ $$ = $1; }
2997 2998
		| /*EMPTY*/						{ $$ = EMPTY; }
		;
Michael Meskes's avatar
Michael Meskes committed
2999

Marc G. Fournier's avatar
Marc G. Fournier committed
3000
/* change me to select, update, etc. some day */
3001
event:	SELECT				{ $$ = make_str("select"); }
Michael Meskes's avatar
Michael Meskes committed
3002
		| UPDATE			{ $$ = make_str("update"); }
Jan Wieck's avatar
Jan Wieck committed
3003
		| DELETE_P			{ $$ = make_str("delete"); }
Michael Meskes's avatar
Michael Meskes committed
3004
		| INSERT			{ $$ = make_str("insert"); }
Michael Meskes's avatar
Michael Meskes committed
3005
		| TRUNCATE			{ $$ = make_str("truncate"); }
3006
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
3007

3008
opt_instead:  INSTEAD		{ $$ = make_str("instead"); }
3009
		| ALSO		{ $$ = make_str("also"); }
3010
		| /*EMPTY*/			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
3011 3012
		;

3013
DropRuleStmt:  DROP RULE name ON qualified_name opt_drop_behavior
3014
			{ $$ = cat_str(5, make_str("drop rule"), $3, make_str("on"), $5, $6);}
3015 3016
		| DROP RULE IF_P EXISTS name ON qualified_name opt_drop_behavior
			{ $$ = cat_str(5, make_str("drop rule if exists"), $5, make_str("on"), $7, $8);}
3017
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
3018 3019 3020 3021

/*****************************************************************************
 *
 *		QUERY:
3022
 *				NOTIFY <qualified_name>	can appear both in rule bodies and
Marc G. Fournier's avatar
Marc G. Fournier committed
3023 3024 3025 3026
 *				as a query-level command
 *
 *****************************************************************************/

3027
NotifyStmt:  NOTIFY ColId
3028
			{ $$ = cat2_str(make_str("notify"), $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3029 3030
		;

3031
ListenStmt:  LISTEN ColId
3032
			{ $$ = cat2_str(make_str("listen"), $2); }
3033
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
3034

3035
UnlistenStmt:  UNLISTEN ColId
3036
			{ $$ = cat2_str(make_str("unlisten"), $2); }
3037
		| UNLISTEN '*'
3038 3039 3040
			{ $$ = make_str("unlisten *"); }
		;

3041

Marc G. Fournier's avatar
Marc G. Fournier committed
3042 3043
/*****************************************************************************
 *
3044
 *				Transactions:
Marc G. Fournier's avatar
Marc G. Fournier committed
3045
 *
Michael Meskes's avatar
Michael Meskes committed
3046
 *	  BEGIN / COMMIT / ROLLBACK
3047
 *		(also older versions END / ABORT)
Marc G. Fournier's avatar
Marc G. Fournier committed
3048 3049
 *
 *****************************************************************************/
3050
TransactionStmt:  ABORT_P opt_transaction	 { $$ = make_str("rollback"); }
3051 3052
		| BEGIN_P opt_transaction transaction_mode_list_or_empty { $$ = cat2_str(make_str("begin transaction"), $3); }
		| START TRANSACTION transaction_mode_list_or_empty	 { $$ = cat2_str(make_str("start transaction"), $3); }
3053 3054 3055
		| COMMIT opt_transaction			 { $$ = make_str("commit"); }
		| END_P opt_transaction				 { $$ = make_str("commit"); }
		| ROLLBACK opt_transaction			 { $$ = make_str("rollback"); }
Michael Meskes's avatar
Michael Meskes committed
3056
		| SAVEPOINT ColId					 { $$ = cat2_str(make_str("savepoint"), $2); }
3057
		| RELEASE SAVEPOINT ColId			 { $$ = cat2_str(make_str("release savepoint"), $3); }
Michael Meskes's avatar
Michael Meskes committed
3058 3059
		| RELEASE ColId						 { $$ = cat2_str(make_str("release"), $2); }
		| ROLLBACK opt_transaction TO SAVEPOINT ColId		 { $$ = cat_str(4, make_str("rollback"), $2, make_str("to savepoint"), $5); }
3060 3061 3062 3063
		| ROLLBACK opt_transaction TO ColId	 { $$ = cat_str(4, make_str("rollback"), $2, make_str("to"), $4); }
		| PREPARE TRANSACTION StringConst	 { $$ = cat2_str(make_str("prepare transaction"), $3); }
		| COMMIT PREPARED StringConst		 { $$ = cat2_str(make_str("commit prepared"), $3); }
		| ROLLBACK PREPARED StringConst		 { $$ = cat2_str(make_str("rollback prepared"), $3); }
3064
		;
3065

3066
opt_transaction: WORK	{ $$ = EMPTY; }
3067 3068 3069 3070
		| TRANSACTION	{ $$ = EMPTY; }
		| /*EMPTY*/		{ $$ = EMPTY; }
		;

Michael Meskes's avatar
Michael Meskes committed
3071
transaction_mode_item:
3072 3073 3074 3075 3076
		ISOLATION LEVEL iso_level
			{ $$ = cat2_str(make_str("isolation level"), $3); }
		| READ ONLY	{ $$ = make_str("read only"); }
		| READ WRITE 	{ $$ = make_str("read write"); }
		;
3077

Michael Meskes's avatar
Michael Meskes committed
3078
transaction_mode_list:
3079 3080 3081 3082
		transaction_mode_item	 				{ $$ = $1; }
		| transaction_mode_list ',' transaction_mode_item	{ $$ = cat_str(3, $1, make_str(","), $3); }
		| transaction_mode_list transaction_mode_item		{ $$ = cat_str(3, $1, make_str(" "), $2); }
		;
3083

Michael Meskes's avatar
Michael Meskes committed
3084
transaction_mode_list_or_empty:
3085 3086 3087
		transaction_mode_list	{ $$ = $1; }
		| /* EMPTY */		{ $$ = EMPTY; }
		;
Michael Meskes's avatar
Michael Meskes committed
3088

Marc G. Fournier's avatar
Marc G. Fournier committed
3089 3090
/*****************************************************************************
 *
3091
 *	QUERY:
3092 3093
 *		CREATE [ OR REPLACE ] [ TEMP ] VIEW <viewname> '('target-list ')'
 *                     AS <query> [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]
Marc G. Fournier's avatar
Marc G. Fournier committed
3094 3095 3096
 *
 *****************************************************************************/

3097 3098 3099 3100
ViewStmt:  CREATE OptTemp VIEW qualified_name opt_column_list AS SelectStmt opt_check_option
			{ $$ = cat_str(8, make_str("create"), $2, make_str("view"), $4, $5, make_str("as"), $7, $8); }
		| CREATE OR REPLACE OptTemp VIEW qualified_name opt_column_list AS SelectStmt opt_check_option
			{ $$ = cat_str(8, make_str("create or replace"), $4, make_str("view"), $6, $7, make_str("as"), $9, $10); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3101 3102
		;

3103
opt_check_option:
3104
                   WITH CHECK OPTION
3105 3106 3107 3108
		   { 
		   	mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented");
			$$ = EMPTY;
		   }
3109
                   | WITH CASCADED CHECK OPTION
3110 3111 3112 3113
		   { 
		   	mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented");
			$$ = EMPTY;
		   }
3114
		   | WITH LOCAL CHECK OPTION
3115 3116 3117 3118
		   {
		   	mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented");
			$$ = EMPTY;
		   }
3119 3120 3121
		   | /* EMPTY */
		   { $$ = EMPTY; } 
		   ;
Marc G. Fournier's avatar
Marc G. Fournier committed
3122 3123 3124 3125

/*****************************************************************************
 *
 *		QUERY:
Michael Meskes's avatar
Michael Meskes committed
3126
 *				load make_str("filename")
Marc G. Fournier's avatar
Marc G. Fournier committed
3127 3128 3129 3130
 *
 *****************************************************************************/

LoadStmt:  LOAD file_name
3131
			{ $$ = cat2_str(make_str("load"), $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3132 3133 3134 3135 3136
		;


/*****************************************************************************
 *
Michael Meskes's avatar
Michael Meskes committed
3137 3138
 *		CREATE DATABASE
 *
Marc G. Fournier's avatar
Marc G. Fournier committed
3139 3140 3141
 *
 *****************************************************************************/

3142 3143 3144 3145
CreatedbStmt:  CREATE DATABASE database_name WITH createdb_opt_list
			{ $$ = cat_str(4, make_str("create database"), $3, make_str("with"), $5); }
		| CREATE DATABASE database_name
			{ $$ = cat2_str(make_str("create database"), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3146 3147
		;

3148 3149 3150
createdb_opt_list:	createdb_opt_item
			{ $$ = $1; }
		| createdb_opt_list createdb_opt_item
3151 3152 3153
			{ $$ = cat2_str($1, $2); }
		;

3154 3155 3156 3157 3158
createdb_opt_item:	TABLESPACE opt_equal name
			{ $$ = cat_str(3,make_str("tablespace"), $2, $3); }
		| TABLESPACE opt_equal DEFAULT
			{ $$ = cat_str(3, make_str("tablespace"), $2, make_str("default")); }
		| LOCATION opt_equal StringConst
3159 3160 3161 3162 3163 3164 3165 3166 3167
			{ $$ = cat_str(3,make_str("location"), $2, $3); }
		| LOCATION opt_equal DEFAULT
			{ $$ = cat_str(3, make_str("location"), $2, make_str("default")); }
		| TEMPLATE opt_equal name
			{ $$ = cat_str(3, make_str("template"), $2, $3); }
		| TEMPLATE opt_equal DEFAULT
			{ $$ = cat_str(3, make_str("template"), $2, make_str("default")); }
		| ENCODING opt_equal PosIntStringConst
			{ $$ = cat_str(3, make_str("encoding"), $2, $3); }
Michael Meskes's avatar
Michael Meskes committed
3168
		| ENCODING opt_equal DEFAULT
3169
			{ $$ = cat_str(3, make_str("encoding"), $2, make_str("default")); }
Michael Meskes's avatar
Michael Meskes committed
3170 3171 3172 3173 3174 3175 3176 3177
		| COLLATE opt_equal StringConst
			{ $$ = cat_str(3, make_str("collate"), $2, $3); }
		| COLLATE opt_equal DEFAULT
			{ $$ = cat_str(3, make_str("collate"), $2, make_str("default")); }
		| CTYPE opt_equal StringConst
			{ $$ = cat_str(3, make_str("ctype"), $2, $3); }
		| CTYPE opt_equal DEFAULT
			{ $$ = cat_str(3, make_str("ctype"), $2, make_str("default")); }
3178 3179
		| CONNECTION LIMIT opt_equal PosIntConst
			{ $$ = cat_str(3, make_str("connection limit"), $3, $4); }
3180 3181
		| OWNER opt_equal name
			{ $$ = cat_str(3, make_str("owner"), $2, $3); }
Michael Meskes's avatar
Michael Meskes committed
3182
		| OWNER opt_equal DEFAULT
3183 3184 3185 3186 3187 3188
			{ $$ = cat_str(3, make_str("owner"), $2, make_str("default")); }
		;

opt_equal: '='					{ $$ = make_str("="); }
		| /* EMPTY */			{ $$ = EMPTY; }
		;
3189

Michael Meskes's avatar
Michael Meskes committed
3190 3191 3192

/*****************************************************************************
 *
3193
 *				ALTER DATABASE
Michael Meskes's avatar
Michael Meskes committed
3194 3195 3196 3197
 *
 *
 *****************************************************************************/

3198 3199 3200
AlterDatabaseStmt: ALTER DATABASE database_name opt_with alterdb_opt_list
			{ $$ = cat_str(4, make_str("alter database"), $3, $4, $5); }
		;
3201

3202
AlterDatabaseSetStmt: ALTER DATABASE database_name SetResetClause
3203 3204 3205
			{ $$ = cat_str(3, make_str("alter database"), $3, $4); }
		;

3206 3207 3208 3209 3210 3211
alterdb_opt_list:
		alterdb_opt_list alterdb_opt_item 	{ $$ = cat2_str($1, $2);}
		| /* EMPTY */				{ $$ = EMPTY; }
	        ;

alterdb_opt_item:
3212
		CONNECTION LIMIT opt_equal PosIntConst { $$ = cat_str(3, make_str("connection limit"), $3, $4); }
3213
		;
3214

Marc G. Fournier's avatar
Marc G. Fournier committed
3215 3216
/*****************************************************************************
 *
3217
 *		DROP DATABASE [ IF EXISTS ]
Michael Meskes's avatar
Michael Meskes committed
3218
 *
Marc G. Fournier's avatar
Marc G. Fournier committed
3219 3220 3221
 *
 *****************************************************************************/

3222 3223
DropdbStmt: DROP DATABASE database_name
			{ $$ = cat2_str(make_str("drop database"), $3); }
3224
		| DROP DATABASE IF_P EXISTS database_name
3225
			{ $$ = cat2_str(make_str("drop database if exists"), $5); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3226 3227 3228
		;


3229 3230 3231 3232 3233 3234
/*****************************************************************************
 *
 * Manipulate a domain
 *
 *****************************************************************************/

3235
CreateDomainStmt:  CREATE DOMAIN_P any_name opt_as Typename ColQualList
3236 3237 3238
		{
			$$ = cat_str(5, make_str("create domain"), $3, $4, $5, $6);
 		}
Michael Meskes's avatar
Michael Meskes committed
3239
		;
3240

Michael Meskes's avatar
Michael Meskes committed
3241
AlterDomainStmt:
3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252
		ALTER DOMAIN_P any_name alter_column_default
			{ $$ = cat_str(3, make_str("alter domain"), $3, $4); }
		| ALTER DOMAIN_P any_name DROP NOT NULL_P
			{ $$ = cat_str(3, make_str("alter domain"), $3, make_str("drop not null")); }
		| ALTER DOMAIN_P any_name SET NOT NULL_P
			{ $$ = cat_str(3, make_str("alter domain"), $3, make_str("set not null")); }
		| ALTER DOMAIN_P any_name ADD_P TableConstraint
			{ $$ = cat_str(4, make_str("alter domain"), $3, make_str("add"), $5); }
		| ALTER DOMAIN_P any_name DROP CONSTRAINT name opt_drop_behavior
			{ $$ = cat_str(5, make_str("alter domain"), $3, make_str("drop constraint"), $6, $7); }
		;
3253

3254
opt_as:	AS	{$$ = make_str("as"); }
3255 3256
		| /* EMPTY */	{$$ = EMPTY; }
		;
3257

3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277
AlterTSDictionaryStmt:
		ALTER TEXT_P SEARCH DICTIONARY any_name definition
			{ $$ = cat_str(3, make_str("alter text search dictionary"), $5, $6); }
		;

AlterTSConfigurationStmt:
		ALTER TEXT_P SEARCH CONFIGURATION any_name ADD_P MAPPING FOR name_list WITH any_name_list
			{ $$ = cat_str(6, make_str("alter text search configuration"), $5, make_str("add mapping for"), $9, make_str("with"), $11); }
		| ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING FOR name_list WITH any_name_list
			{ $$ = cat_str(6, make_str("alter text search configuration"), $5, make_str("alter mapping for"), $9, make_str("with"), $11); }
		| ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING REPLACE any_name WITH any_name
			{ $$ = cat_str(6, make_str("alter text search configuration"), $5, make_str("alter mapping replace"), $9, make_str("with"), $11); }
		| ALTER TEXT_P SEARCH CONFIGURATION any_name ALTER MAPPING FOR name_list REPLACE any_name WITH any_name
			{ $$ = cat_str(8, make_str("alter text search configuration"), $5, make_str("alter mapping for"), $9, make_str("replace"), $11, make_str("with"), $13); }
		| ALTER TEXT_P SEARCH CONFIGURATION any_name DROP MAPPING FOR name_list
			{ $$ = cat_str(4, make_str("alter text search configuration"), $5, make_str("drop mapping for"), $9); }
		| ALTER TEXT_P SEARCH CONFIGURATION any_name DROP MAPPING IF_P EXISTS FOR name_list
			{ $$ = cat_str(4, make_str("alter text search configuration"), $5, make_str("drop mapping if exists for"), $11); }
		;

3278
CreateConversionStmt:
3279 3280 3281 3282
	   CREATE opt_default CONVERSION_P any_name FOR StringConst
	   TO StringConst FROM any_name
		   { $$ = cat_str(10, make_str("create"), $2, make_str("conversion"), $4, make_str("for"), $6, make_str("to"), $8, make_str("from"), $10); }
	   ;
3283

Marc G. Fournier's avatar
Marc G. Fournier committed
3284 3285 3286
/*****************************************************************************
 *
 *		QUERY:
Michael Meskes's avatar
Michael Meskes committed
3287
 *			       cluster <index_name> on <qualified_name>
Michael Meskes's avatar
Michael Meskes committed
3288
 *                             cluster <qualified_name>
Michael Meskes's avatar
Michael Meskes committed
3289
 *                             cluster
Marc G. Fournier's avatar
Marc G. Fournier committed
3290 3291 3292
 *
 *****************************************************************************/

3293 3294
ClusterStmt:  CLUSTER qualified_name cluster_index_specification
				{ $$ = cat_str(3,make_str("cluster"), $2, $3); }
3295 3296
		| CLUSTER
				{ $$ = make_str("cluster"); }
3297 3298
		| CLUSTER qualified_name ON qualified_name
				{ $$ = cat_str(4, make_str("cluster"), $2, make_str("on"), $4); }
3299
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
3300

3301 3302 3303 3304
cluster_index_specification:
		USING index_name	{ $$ = cat2_str(make_str("using"), $2); }
		| /*EMPTY*/		{ $$ = EMPTY; }
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
3305 3306 3307 3308 3309

/*****************************************************************************
 *
 *		QUERY:
 *				vacuum
3310
 *				analyze
Marc G. Fournier's avatar
Marc G. Fournier committed
3311 3312 3313
 *
 *****************************************************************************/

3314
VacuumStmt:  VACUUM opt_full opt_freeze opt_verbose
3315
			{ $$ = cat_str(4, make_str("vacuum"), $2, $3, $4); }
3316
		| VACUUM opt_full opt_freeze opt_verbose qualified_name
3317
			{ $$ = cat_str(5, make_str("vacuum"), $2, $3, $4, $5); }
3318
		| VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
3319
			{ $$ = cat_str(5, make_str("vacuum"), $2, $3, $4, $5); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3320 3321
		;

3322
AnalyzeStmt:  analyze_keyword opt_verbose
3323
			{ $$ = cat_str(2, $1, $2); }
3324
		| analyze_keyword opt_verbose qualified_name opt_name_list
3325
			{ $$ = cat_str(4, $1, $2, $3, $4); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3326 3327
		;

3328
analyze_keyword:  ANALYZE		{ $$ = make_str("analyze"); }
3329
		| ANALYSE		{ $$ = make_str("analyse"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3330 3331
		;

3332 3333
opt_verbose:  VERBOSE			{ $$ = make_str("verbose"); }
		| /*EMPTY*/				{ $$ = EMPTY; }
3334 3335
		;

3336 3337
opt_full:  FULL					{ $$ = make_str("full"); }
		| /*EMPTY*/				{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
3338 3339
		;

3340 3341
opt_freeze:  FREEZE				{ $$ = make_str("freeze"); }
		| /*EMPTY*/				{ $$ = EMPTY; }
3342 3343
		;

3344 3345 3346 3347
opt_name_list:	'(' name_list ')'
			{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
		| /*EMPTY*/
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
3348 3349 3350 3351 3352 3353 3354 3355 3356 3357
		;


/*****************************************************************************
 *
 *		QUERY:
 *				EXPLAIN query
 *
 *****************************************************************************/

3358
ExplainStmt:  EXPLAIN opt_analyze opt_verbose ExplainableStmt
3359
			{ $$ = cat_str(4, make_str("explain"), $2, $3, $4); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3360 3361
		;

3362 3363 3364
ExplainableStmt:
		SelectStmt
		| InsertStmt
3365
		| UpdateStmt
3366 3367
		| DeleteStmt
		| DeclareCursorStmt
3368
		| ExecuteStmt
3369
		;
3370
opt_analyze:
3371 3372 3373
		analyze_keyword                 { $$ = $1; }
		| /* EMPTY */			{ $$ = EMPTY; }
		;
3374

3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386
PrepareStmt: PREPARE prepared_name prep_type_clause AS PreparableStmt
		{
			$$.name = $2;
			$$.type = $3;
			$$.stmt = cat_str(3, make_str("\""), $5, make_str("\""));
		}
		| PREPARE prepared_name FROM execstring /* ECPG addon */
		{
			$$.name = $2;
			$$.type = NULL;
			$$.stmt = $4;
		}
3387 3388
		;

3389
PreparableStmt:
3390 3391 3392 3393 3394
		SelectStmt
		| InsertStmt
		| UpdateStmt
		| DeleteStmt
		;
3395

3396
prep_type_clause: '(' type_list ')'	{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3397
		| /* EMPTY */		{ $$ = EMPTY; }
3398 3399
			;

3400 3401
ExecuteStmt: EXECUTE prepared_name execute_param_clause execute_rest /* execute_rest is an ecpg addon */
			{
3402
				/* $$ = cat_str(3, make_str("ECPGprepared_statement("), connection, $2, make_str("__LINE__)"));*/
3403 3404
				$$ = $2;
			}
3405
		| CREATE OptTemp TABLE create_as_target AS
3406 3407
			EXECUTE prepared_name execute_param_clause
			{ $$ = cat_str(7, make_str("create"), $2, make_str("table"), $4,  make_str("as execute"), $7, $8); }
3408 3409
		;

3410
execute_param_clause: '(' expr_list ')'	{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
3411
		| /* EMPTY */		{ $$ = EMPTY; }
3412
		;
3413

3414 3415 3416 3417
DeallocateStmt: DEALLOCATE prepared_name		{ $$ = $2; }
		| DEALLOCATE PREPARE prepared_name	{ $$ = $3; }
		| DEALLOCATE ALL			{ $$ = make_str("all"); }
		| DEALLOCATE PREPARE ALL		{ $$ = make_str("all"); }
3418
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
3419 3420 3421 3422 3423 3424 3425 3426

/*****************************************************************************
 *
 *		QUERY:
 *				INSERT STATEMENTS
 *
 *****************************************************************************/

3427 3428
InsertStmt:  INSERT INTO qualified_name insert_rest returning_clause
			{ $$ = cat_str(4, make_str("insert into"), $3, $4, $5); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3429 3430
		;

3431 3432
insert_rest:  
		SelectStmt
3433
			{ $$ = $1; }
3434
		| '(' insert_column_list ')' SelectStmt
3435
			{ $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); }
3436 3437
		| DEFAULT VALUES
			{ $$ = make_str("default values"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3438 3439
		;

3440
insert_column_list: insert_column_list ',' insert_column_item
3441
			{ $$ = cat_str(3, $1, make_str(","), $3); }
3442
		| insert_column_item
3443
			{ $$ = $1; }
Marc G. Fournier's avatar
Marc G. Fournier committed
3444 3445
		;

3446
insert_column_item:  ColId opt_indirection
3447
			{ $$ = cat2_str($1, $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3448 3449
		;

3450 3451 3452
returning_clause:  RETURNING target_list	{ $$ = cat2_str(make_str("returning"), $2); }
		| /* EMPTY */			{ $$ = EMPTY; }
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
3453 3454 3455 3456 3457 3458 3459 3460

/*****************************************************************************
 *
 *		QUERY:
 *				DELETE STATEMENTS
 *
 *****************************************************************************/

3461
DeleteStmt:  DELETE_P FROM relation_expr_opt_alias using_clause where_or_current_clause returning_clause
3462
			{ $$ = cat_str(5, make_str("delete from"), $3, $4, $5, $6); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3463 3464
		;

Michael Meskes's avatar
Michael Meskes committed
3465
using_clause: USING from_list	{ $$ = cat2_str(make_str("using"), $2); }
3466
			| /* EMPTY */		{ $$ = EMPTY; }
3467
		;
3468

3469 3470
LockStmt:  LOCK_P opt_table qualified_name_list opt_lock opt_nowait
			{ $$ = cat_str(5, make_str("lock"), $2, $3, $4, $5); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3471 3472
		;

Jan Wieck's avatar
Jan Wieck committed
3473
opt_lock:  IN_P lock_type MODE
3474 3475 3476 3477
			{ $$ = cat_str(3, make_str("in"), $2, make_str("mode")); }
		| /*EMPTY*/
			{ $$ = EMPTY;}
		;
3478

3479
lock_type:	ACCESS SHARE		{ $$ = make_str("access share"); }
3480 3481 3482 3483 3484 3485 3486 3487
		| ROW SHARE				{ $$ = make_str("access share"); }
		| ROW EXCLUSIVE			{ $$ = make_str("row exclusive"); }
		| SHARE UPDATE EXCLUSIVE { $$ = make_str("share update exclusive"); }
		| SHARE					{ $$ = make_str("share"); }
		| SHARE ROW EXCLUSIVE	{ $$ = make_str("share row exclusive"); }
		| EXCLUSIVE				{ $$ = make_str("exclusive"); }
		| ACCESS EXCLUSIVE		{ $$ = make_str("access exclusive"); }
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
3488

3489 3490 3491 3492
opt_nowait:    NOWAIT                   { $$ = make_str("nowait"); }
		| /* EMPTY */		{ $$ = EMPTY; }
		;

Marc G. Fournier's avatar
Marc G. Fournier committed
3493 3494 3495 3496 3497 3498 3499
/*****************************************************************************
 *
 *		QUERY:
 *				UpdateStmt (UPDATE)
 *
 *****************************************************************************/

3500
UpdateStmt:  UPDATE relation_expr_opt_alias
Michael Meskes's avatar
Michael Meskes committed
3501
				SET set_clause_list
3502
				from_clause
3503
				where_or_current_clause
3504 3505
				returning_clause
			{$$ = cat_str(7, make_str("update"), $2, make_str("set"), $4, $5, $6, $7); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3506 3507
		;

Michael Meskes's avatar
Michael Meskes committed
3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529
set_clause_list:
		set_clause				{ $$ = $1; }
		| set_clause_list ',' set_clause	{ $$ = cat_str(3, $1, make_str(","), $3); }
		;

set_clause:
		single_set_clause		{ $$ = $1; }
		| multiple_set_clause		{ $$ = $1; }
		;

single_set_clause:
		set_target '=' ctext_expr	{ $$ = cat_str(3, $1, make_str("="), $3); };

multiple_set_clause:
		'(' set_target_list ')' '=' ctext_row	{ $$ = cat_str(4, make_str("("), $2, make_str(")="), $5); };

set_target:
		ColId opt_indirection		{ $$ = cat2_str($1, $2); };

set_target_list:
		set_target  				{ $$ = $1; }
		| set_target_list ',' set_target	{ $$ = cat_str(3, $1, make_str(","), $3); }
Michael Meskes's avatar
Michael Meskes committed
3530
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
3531 3532 3533 3534 3535 3536 3537

/*****************************************************************************
 *
 *		QUERY:
 *				CURSOR STATEMENTS
 *
 *****************************************************************************/
3538
DeclareCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt
3539 3540 3541 3542 3543 3544
		{
			struct cursor *ptr, *this;

			for (ptr = cur; ptr != NULL; ptr = ptr->next)
			{
				if (strcmp($2, ptr->name) == 0)
3545
					/* re-definition is a bug */
3546
					mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" already defined", $2);
3547 3548 3549 3550 3551 3552 3553 3554
			}

			this = (struct cursor *) mm_alloc(sizeof(struct cursor));

			/* initial definition */
			this->next = cur;
			this->name = $2;
			this->connection = connection;
3555
			this->opened = false;
3556
			this->command =  cat_str(7, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for"), $7);
3557 3558 3559 3560 3561
			this->argsinsert = argsinsert;
			this->argsresult = argsresult;
			argsinsert = argsresult = NULL;
			cur = this;

3562
			if (INFORMIX_MODE)
3563 3564 3565
				$$ = cat_str(5, adjust_informix(this->argsinsert), adjust_informix(this->argsresult), make_str("/*"), mm_strdup(this->command), make_str("*/"));
			else
				$$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
3566
		}
Marc G. Fournier's avatar
Marc G. Fournier committed
3567 3568
		;

3569
cursor_options:  /* EMPTY */		{ $$ = EMPTY; }
3570 3571 3572 3573 3574
		| cursor_options BINARY 	{ $$ = cat2_str($1, make_str("binary")); }
		| cursor_options INSENSITIVE	{ $$ = cat2_str($1, make_str("insensitive")); }
		| cursor_options SCROLL 	{ $$ = cat2_str($1, make_str("scroll")); }
		| cursor_options NO SCROLL	{ $$ = cat2_str($1, make_str("no scroll")); }
		;
3575

3576 3577 3578 3579 3580 3581 3582 3583 3584 3585
opt_hold:	/* EMPTY */
		{
			if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit == true)
				$$ = make_str("with hold");
			else
				 $$ = EMPTY;
		}
		| WITH HOLD			{ $$ = make_str("with hold"); }
		| WITHOUT HOLD			{ $$ = make_str("without hold"); }
		;
3586

Marc G. Fournier's avatar
Marc G. Fournier committed
3587 3588 3589 3590 3591 3592 3593
/*****************************************************************************
 *
 *		QUERY:
 *				SELECT STATEMENTS
 *
 *****************************************************************************/

3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607
SelectStmt: select_no_parens		%prec UMINUS
			{ $$ = $1; }
		|	select_with_parens		%prec UMINUS
			{ $$ = $1; }
		;

select_with_parens: '(' select_no_parens ')'
			{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
		| '(' select_with_parens ')'
			{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
		;

select_no_parens:	   simple_select
			{ $$ = $1; }
3608
		| select_clause sort_clause
3609
			{ $$ = cat2_str($1, $2); }
3610
		| select_clause opt_sort_clause for_locking_clause opt_select_limit
3611
			{ $$ = cat_str(4, $1, $2, $3, $4); }
3612
		| select_clause opt_sort_clause select_limit opt_for_locking_clause
3613
			{ $$ = cat_str(4, $1, $2, $3, $4); }
Michael Meskes's avatar
Michael Meskes committed
3614 3615 3616 3617 3618 3619 3620 3621
		| with_clause simple_select
			{ $$ = cat2_str($1, $2); }
		| with_clause select_clause sort_clause
			{ $$ = cat_str(3, $1, $2, $3); }
		| with_clause select_clause opt_sort_clause for_locking_clause opt_select_limit
			{ $$ = cat_str(5, $1, $2, $3, $4, $5); }
		| with_clause select_clause opt_sort_clause select_limit opt_for_locking_clause
			{ $$ = cat_str(5, $1, $2, $3, $4, $5); }
3622
		;
3623

3624 3625
select_clause: simple_select		{ $$ = $1; }
		| select_with_parens		{ $$ = $1; }
Marc G. Fournier's avatar
Marc G. Fournier committed
3626 3627
		;

3628 3629 3630 3631
simple_select:	SELECT opt_distinct target_list
					into_clause from_clause where_clause
					group_clause having_clause
			{ $$ = cat_str(8, make_str("select"), $2, $3, $4, $5, $6, $7, $8); }
3632 3633
		| values_clause
			{ $$ = $1; }
3634 3635 3636 3637 3638 3639
		| select_clause UNION opt_all select_clause
			{ $$ = cat_str(4, $1, make_str("union"), $3, $4); }
		| select_clause INTERSECT opt_all select_clause
			{ $$ = cat_str(4, $1, make_str("intersect"), $3, $4); }
		| select_clause EXCEPT opt_all select_clause
			{ $$ = cat_str(4, $1, make_str("except"), $3, $4); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3640 3641
		;

Michael Meskes's avatar
Michael Meskes committed
3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656
with_clause:
		WITH cte_list			{ $$ = cat2_str(make_str("with"), $2); }
		| WITH RECURSIVE cte_list	{ $$ = cat2_str(make_str("with recursive"), $3); }
		;

cte_list:
		common_table_expr			{ $$ = $1; }
		| cte_list ',' common_table_expr	{ $$ = cat_str(3, $1, make_str(","), $3); }
		;


common_table_expr:  name opt_name_list AS select_with_parens
			{ $$ = cat_str(4, $1, $2, make_str("as"), $4); }
		;

3657 3658 3659 3660 3661
into_clause:  INTO OptTempTableName
		{
			FoundInto = 1;
			$$= cat2_str(make_str("into"), $2);
		}
3662
		| ecpg_into			{ $$ = EMPTY; }
3663
		| /*EMPTY*/			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
3664 3665
		;

Michael Meskes's avatar
Michael Meskes committed
3666 3667 3668 3669 3670 3671 3672
/*
 * Redundancy here is needed to avoid shift/reduce conflicts,
 * since TEMP is not a reserved word.  See also OptTemp.
 *
 * The result is a cons cell (not a true list!) containing
 * a boolean and a table name.
 */
3673
OptTempTableName:  TEMPORARY opt_table qualified_name
3674
			{ $$ = cat_str(3, make_str("temporary"), $2, $3); }
3675
		| TEMP opt_table qualified_name
3676
			{ $$ = cat_str(3, make_str("temp"), $2, $3); }
3677
		| LOCAL TEMPORARY opt_table qualified_name
3678
			{ $$ = cat_str(3, make_str("local temporary"), $3, $4); }
3679
		| LOCAL TEMP opt_table qualified_name
3680
			{ $$ = cat_str(3, make_str("local temp"), $3, $4); }
3681
		| GLOBAL TEMPORARY opt_table qualified_name
3682
			{ $$ = cat_str(3, make_str("global temporary"), $3, $4); }
3683
		| GLOBAL TEMP opt_table qualified_name
3684
			{ $$ = cat_str(3, make_str("global temp"), $3, $4); }
3685
		| TABLE qualified_name
3686
			{ $$ = cat2_str(make_str("table"), $2); }
3687
		| qualified_name
3688 3689
			{ $$ = $1; }
		;
Michael Meskes's avatar
Michael Meskes committed
3690

3691
opt_table:	TABLE				{ $$ = make_str("table"); }
Michael Meskes's avatar
Michael Meskes committed
3692
		| /*EMPTY*/				{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
3693 3694
		;

3695
opt_all:  ALL					{ $$ = make_str("all"); }
Michael Meskes's avatar
Michael Meskes committed
3696
		| /*EMPTY*/				{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
3697 3698
		;

3699 3700 3701 3702 3703 3704 3705 3706
opt_distinct:  DISTINCT
			{ $$ = make_str("distinct"); }
		| DISTINCT ON '(' expr_list ')'
			{ $$ = cat_str(3, make_str("distinct on ("), $4, make_str(")")); }
		| ALL
			{ $$ = make_str("all"); }
		| /*EMPTY*/
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
3707 3708
		;

3709 3710 3711 3712
opt_sort_clause:	sort_clause	{ $$ = $1; }
		| /* EMPTY */		{ $$ = EMPTY; }
		;

3713 3714
sort_clause:  ORDER BY sortby_list
			{ $$ = cat2_str(make_str("order by"), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3715 3716 3717
		;

sortby_list:  sortby					{ $$ = $1; }
Michael Meskes's avatar
Michael Meskes committed
3718
		| sortby_list ',' sortby		{ $$ = cat_str(3, $1, make_str(","), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3719 3720
		;

3721 3722 3723 3724
sortby: a_expr USING qual_all_Op opt_nulls_order
			{ $$ = cat_str(4, $1, make_str("using"), $3, $4); }
		| a_expr opt_asc_desc opt_nulls_order
			{ $$ = cat_str(3, $1, $2, $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
3725 3726
		;

3727 3728
select_limit:	LIMIT select_limit_value OFFSET select_offset_value
		   { $$ = cat_str(4, make_str("limit"), $2, make_str("offset"), $4); }
Michael Meskes's avatar
Michael Meskes committed
3729
		| OFFSET select_offset_value LIMIT select_limit_value
3730 3731 3732 3733 3734
		   { $$ = cat_str(4, make_str("offset"), $2, make_str("limit"), $4); }
		| LIMIT select_limit_value
		   { $$ = cat2_str(make_str("limit"), $2); }
		| OFFSET select_offset_value
		   { $$ = cat2_str(make_str("offset"), $2); }
Michael Meskes's avatar
Michael Meskes committed
3735
		| LIMIT select_limit_value ',' select_offset_value
3736
		   {
3737
		   	mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to backend");
3738 3739
			$$ = cat_str(4, make_str("limit"), $2, make_str(","), $4);
		   }
3740
		;
3741

3742 3743 3744
opt_select_limit:	select_limit	{ $$ = $1; }
		| /*EMPTY*/					{ $$ = EMPTY; }
		;
3745

3746 3747
select_limit_value: a_expr 	{ $$ = $1; }
		| ALL		{ $$ = make_str("all"); }
3748 3749
		;

3750
select_offset_value: a_expr { $$ = $1; }
3751
		;
3752

Marc G. Fournier's avatar
Marc G. Fournier committed
3753 3754 3755 3756 3757 3758 3759
/*
 *	jimmy bell-style recursive queries aren't supported in the
 *	current system.
 *
 *	...however, recursive addattr and rename supported.  make special
 *	cases for these.
 */
Jan Wieck's avatar
Jan Wieck committed
3760
group_clause:  GROUP_P BY expr_list
3761 3762 3763
			{ $$ = cat2_str(make_str("group by"), $3); }
		| /*EMPTY*/
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
3764 3765
		;

3766 3767 3768 3769
having_clause:	HAVING a_expr
			{ $$ = cat2_str(make_str("having"), $2); }
		| /*EMPTY*/
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
3770 3771
		;

3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788
for_locking_clause:
		for_locking_items 	{ $$ = $1; }
		| FOR READ ONLY 	{ $$ = make_str("for read only");}
		;

opt_for_locking_clause:	
		for_locking_clause	{ $$ = $1; }
		| /* EMPTY */   	{ $$ = EMPTY; }
		;

for_locking_items:
		for_locking_item		 	{ $$ = $1; }
		| for_locking_items for_locking_item	{ $$ = cat2_str($1, $2); }
		;

for_locking_item:
		FOR UPDATE locked_rels_list opt_nowait
3789 3790 3791
			{ $$ = cat_str(3, make_str("for update"), $3, $4); }
		| FOR SHARE locked_rels_list opt_nowait
			{ $$ = cat_str(3, make_str("for share"), $3, $4); }
3792 3793
		;

3794
locked_rels_list:
Michael Meskes's avatar
Michael Meskes committed
3795
		OF qualified_name_list	{ $$ = cat2_str(make_str("of"), $2); }
3796
		| /* EMPTY */		{ $$ = EMPTY; }
3797
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
3798

Michael Meskes's avatar
Michael Meskes committed
3799 3800 3801 3802
values_clause:  VALUES ctext_row
			{ $$ = cat2_str(make_str("values"), $2); }
		| values_clause ',' ctext_row
			{ $$ = cat_str(3, $1, make_str(","), $3); }
Michael Meskes's avatar
Michael Meskes committed
3803 3804
		;

Marc G. Fournier's avatar
Marc G. Fournier committed
3805 3806 3807
/*****************************************************************************
 *
 *	clauses common to all Optimizable Stmts:
3808
 *		from_clause - allow list of both JOIN expressions and table names
Michael Meskes's avatar
Michael Meskes committed
3809
 *		where_clause	- qualifications for joins or restrictions
Marc G. Fournier's avatar
Marc G. Fournier committed
3810 3811 3812
 *
 *****************************************************************************/

3813 3814
from_clause:	FROM from_list		{ $$ = cat2_str(make_str("from"), $2); }
		| /* EMPTY */				{ $$ = EMPTY; }
Michael Meskes's avatar
Michael Meskes committed
3815 3816
		;

3817 3818 3819
from_list:	from_list ',' table_ref { $$ = cat_str(3, $1, make_str(","), $3); }
		| table_ref					{ $$ = $1; }
		;
Michael Meskes's avatar
Michael Meskes committed
3820

3821
/*
3822
 * table_ref is where an alias clause can be attached.	Note we cannot make
3823 3824 3825 3826
 * alias_clause have an empty production because that causes parse conflicts
 * between table_ref := '(' joined_table ')' alias_clause
 * and joined_table := '(' joined_table ')'.  So, we must have the
 * redundant-looking productions here instead.
3827 3828 3829 3830
 */
table_ref:	relation_expr
			{ $$ = $1; }
		| relation_expr alias_clause
3831
			{ $$ = cat2_str($1, $2); }
3832 3833 3834
		| func_table
			{ $$ = $1; }
		| func_table alias_clause
3835
		        { $$ = cat2_str($1, $2); }
3836
		| func_table AS '(' TableFuncElementList ')'
3837
			{ $$ = cat_str(4, $1, make_str("as ("), $4, make_str(")")); }
3838
		| func_table AS ColId '(' TableFuncElementList ')'
3839
			{ $$ = cat_str(6, $1, make_str("as"), $3, make_str("("), $5, make_str(")"));}
3840
		| func_table ColId '(' TableFuncElementList ')'
3841
			{ $$ = cat_str(5, $1, $2, make_str("("), $4, make_str(")")); }
3842
		| select_with_parens
3843 3844 3845 3846
			{
				mmerror(PARSE_ERROR, ET_ERROR, "sub-SELECT in FROM must have an alias");
				$$ = $1;
			}
3847
		| select_with_parens alias_clause
3848
			{ $$ = cat2_str($1, $2); }
3849 3850 3851
		| joined_table
			{ $$ = $1; }
		| '(' joined_table ')' alias_clause
3852
			{ $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); }
3853
		;
3854

3855 3856 3857 3858 3859 3860 3861 3862
/*
 * It may seem silly to separate joined_table from table_ref, but there is
 * method in SQL92's madness: if you don't do it this way you get reduce-
 * reduce conflicts, because it's not clear to the parser generator whether
 * to expect alias_clause after ')' or not.  For the same reason we must
 * treat 'JOIN' and 'join_type JOIN' separately, rather than allowing
 * join_type to expand to empty; if we try it, the parser generator can't
 * figure out when to reduce an empty join_type right after table_ref.
3863 3864
 *
 * Note that a CROSS JOIN is the same as an unqualified
3865 3866 3867 3868 3869
 * INNER JOIN, and an INNER JOIN/ON has the same shape
 * but a qualification expression to limit membership.
 * A NATURAL JOIN implicitly matches column names between
 * tables and the shape is determined by which columns are
 * in common. We'll collect columns during the later transformations.
3870
 */
3871

3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884
joined_table:  '(' joined_table ')'
			{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
		| table_ref CROSS JOIN table_ref
			{ $$ = cat_str(3, $1, make_str("cross join"), $4); }
		| table_ref join_type JOIN table_ref join_qual
			{ $$ = cat_str(5, $1, $2, make_str("join"), $4, $5); }
		| table_ref JOIN table_ref join_qual
			{ $$ = cat_str(4, $1, make_str("join"), $3, $4); }
		| table_ref NATURAL join_type JOIN table_ref
			{ $$ = cat_str(5, $1, make_str("natural"), $3, make_str("join"), $5); }
		| table_ref NATURAL JOIN table_ref
			{ $$ = cat_str(3, $1, make_str("natural join"), $4); }
		;
3885

Michael Meskes's avatar
Michael Meskes committed
3886 3887 3888 3889 3890 3891 3892 3893 3894 3895
alias_clause:  AS ColId '(' name_list ')'
			{ $$ = cat_str(5, make_str("as"), $2, make_str("("), $4, make_str(")")); }
		| AS ColId
			{ $$ = cat2_str(make_str("as"), $2); }
		| ColId '(' name_list ')'
			{ $$ = cat_str(4, $1, make_str("("), $3, make_str(")")); }
		| ColId
			{ $$ = $1; }
		;

3896 3897 3898 3899
join_type:	FULL join_outer		{ $$ = cat2_str(make_str("full"), $2); }
		| LEFT join_outer		{ $$ = cat2_str(make_str("left"), $2); }
		| RIGHT join_outer		{ $$ = cat2_str(make_str("right"), $2); }
		| INNER_P				{ $$ = make_str("inner"); }
Michael Meskes's avatar
Michael Meskes committed
3900
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
3901

3902
/* OUTER is just noise... */
3903 3904
join_outer:  OUTER_P			{ $$ = make_str("outer"); }
		| /*EMPTY*/				{ $$ = EMPTY;  /* no qualifiers */ }
Marc G. Fournier's avatar
Marc G. Fournier committed
3905 3906
		;

3907 3908
/* JOIN qualification clauses
 * Possibilities are:
3909 3910 3911
 *	USING ( column list ) allows only unqualified column names,
 *						  which must match between tables.
 *	ON expr allows more general qualifications.
3912
 */
Marc G. Fournier's avatar
Marc G. Fournier committed
3913

3914 3915 3916 3917 3918
join_qual:	USING '(' name_list ')'
			{ $$ = cat_str(3, make_str("using ("), $3, make_str(")")); }
		| ON a_expr
			{ $$ = cat2_str(make_str("on"), $2); }
		;
3919

3920
relation_expr:	qualified_name
3921
			{ /* normal relations */ $$ = $1; }
3922
		| qualified_name '*'
3923
			{ /* inheritance query */ $$ = cat2_str($1, make_str("*")); }
3924
		| ONLY qualified_name
3925 3926 3927
			{ /* inheritance query */ $$ = cat2_str(make_str("only "), $2); }
		| ONLY '(' qualified_name ')'
			{ /* inheritance query */ $$ = cat_str(3, make_str("only ("), $3, make_str(")")); }
3928
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
3929

3930 3931 3932 3933 3934 3935 3936 3937
relation_expr_opt_alias: relation_expr                                 %prec UMINUS
		{ $$ = $1; }
		| relation_expr ColId
		{ $$ = cat2_str($1, $2); }
		| relation_expr AS ColId
		{ $$ = cat_str(3, $1, make_str("as"), $3); }
		;

Michael Meskes's avatar
Michael Meskes committed
3938
func_table:  func_expr 	{ $$ = $1; }
3939
		;
3940

3941
where_clause:  WHERE a_expr		{ $$ = cat2_str(make_str("where"), $2); }
3942 3943 3944
		| /*EMPTY*/				{ $$ = EMPTY;  /* no qualifiers */ }
		;

3945 3946
where_or_current_clause:  WHERE a_expr			{ $$ = cat2_str(make_str("where"), $2); }
		| WHERE CURRENT_P OF name		{ $$ = cat2_str(make_str("where current of"), $4); }
3947
		| WHERE CURRENT_P OF Param		{ $$ = cat2_str(make_str("where current of"), $4); }
3948 3949
		| /*EMPTY*/				{ $$ = EMPTY;  /* no qualifiers */ }
		;
3950

3951
TableFuncElementList: TableFuncElement
3952
			{ $$ = $1; }
3953
		| TableFuncElementList ',' TableFuncElement
3954
			{ $$ = cat_str(3, $1, make_str(","), $3); }
3955 3956 3957
		;

TableFuncElement:	ColId Typename	{ $$ = cat2_str($1, $2); }
3958
		;
3959

3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970
/*****************************************************************************
 *
 *	Type syntax
 *		SQL92 introduces a large amount of type-specific syntax.
 *		Define individual clauses to handle these cases, and use
 *		 the generic case to handle regular type-extensible Postgres syntax.
 *		- thomas 1997-10-10
 *
 *****************************************************************************/

Typename:  SimpleTypename opt_array_bounds
3971
			{ $$ = cat2_str($1, $2.str); }
3972 3973
		| SETOF SimpleTypename opt_array_bounds
			{ $$ = cat_str(3, make_str("setof"), $2, $3); }
3974 3975 3976 3977
		| SimpleTypename ARRAY '[' PosIntConst ']'
			{ $$ = cat_str(4, $1, make_str("array ["), $4, make_str("]")); }
		| SETOF SimpleTypename ARRAY '[' PosIntConst ']'
			{ $$ = cat_str(5, make_str("setof"), $2, make_str("array ["), $5, make_str("]")); }
3978 3979 3980
		;


Michael Meskes's avatar
Michael Meskes committed
3981
opt_array_bounds:  '[' ']' opt_array_bounds
3982
		{
3983
			$$.index1 = make_str("0");
3984 3985 3986
			$$.index2 = $3.index1;
			$$.str = cat2_str(make_str("[]"), $3.str);
		}
Michael Meskes's avatar
Michael Meskes committed
3987
		| '[' Iresult ']' opt_array_bounds
3988
		{
3989
			$$.index1 = strdup($2);
3990
			$$.index2 = $4.index1;
3991
			$$.str = cat_str(4, make_str("["), $2, make_str("]"), $4.str);
3992
		}
Marc G. Fournier's avatar
Marc G. Fournier committed
3993
		| /* EMPTY */
3994
		{
3995 3996
			$$.index1 = make_str("-1");
			$$.index2 = make_str("-1");
3997 3998
			$$.str= EMPTY;
		}
Marc G. Fournier's avatar
Marc G. Fournier committed
3999 4000
		;

4001 4002 4003 4004 4005 4006 4007 4008 4009
Iresult:	PosIntConst		{ $$ = $1; }
		| '(' Iresult ')'	{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
		| Iresult '+' Iresult	{ $$ = cat_str(3, $1, make_str("+"), $3); }
		| Iresult '-' Iresult	{ $$ = cat_str(3, $1, make_str("-"), $3); }
		| Iresult '*' Iresult	{ $$ = cat_str(3, $1, make_str("*"), $3); }
		| Iresult '/' Iresult	{ $$ = cat_str(3, $1, make_str("/"), $3); }
		| Iresult '%' Iresult	{ $$ = cat_str(3, $1, make_str("%"), $3); }
		| Sconst		{ $$ = $1; }
		| ColId			{ $$ = $1; }
4010
		;
Michael Meskes's avatar
Michael Meskes committed
4011

4012 4013 4014 4015 4016
SimpleTypename:  GenericType		{ $$ = $1; }
		| ConstDatetime		{ $$ = $1; }
		| Numeric		{ $$ = $1; }
		| Bit			{ $$ = $1; }
		| Character		{ $$ = $1; }
4017 4018 4019 4020 4021
		| ConstInterval opt_interval
			{ $$ = cat2_str($1, $2); }
		| ConstInterval '(' PosIntConst ')' opt_interval
			{ $$ = cat_str(5, $1, make_str("("), $3, make_str(")"), $5); }
		;
Michael Meskes's avatar
Michael Meskes committed
4022

4023
ConstTypename:	Numeric			{ $$ = $1; }
4024 4025
		| ConstBit		{ $$ = $1; }
		| ConstCharacter	{ $$ = $1; }
4026
		| ConstDatetime		{ $$ = $1; }
Marc G. Fournier's avatar
Marc G. Fournier committed
4027 4028
		;

4029 4030
GenericType:  	type_function_name opt_type_modifiers		{ $$ = cat2_str($1, $2); }
		| type_function_name attrs opt_type_modifiers	{ $$ = cat_str(3, $1, $2, $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4031 4032
		;

4033 4034 4035 4036
opt_type_modifiers: '(' expr_list ')'	{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
		| /* EMPTY */		{ $$ = EMPTY; }
		;
		
Marc G. Fournier's avatar
Marc G. Fournier committed
4037 4038
/* SQL92 numeric data types
 * Check FLOAT() precision limits assuming IEEE floating types.
4039
 * Provide real DECIMAL() and NUMERIC() implementations now - Jan 1998-12-30
Marc G. Fournier's avatar
Marc G. Fournier committed
4040 4041
 * - thomas 1997-09-18
 */
4042
Numeric:  INT_P
4043 4044 4045 4046 4047 4048 4049 4050 4051
			{ $$ = make_str("int"); }
		| INTEGER
			{ $$ = make_str("integer"); }
		| SMALLINT
			{ $$ = make_str("smallint"); }
		| BIGINT
			{ $$ = make_str("bigint"); }
		| REAL
			{ $$ = make_str("real"); }
Jan Wieck's avatar
Jan Wieck committed
4052
		| FLOAT_P opt_float
4053
			{ $$ = cat2_str(make_str("float"), $2); }
4054
		| DOUBLE_P PRECISION
4055
			{ $$ = make_str("double precision"); }
4056
		| DECIMAL_P opt_type_modifiers
4057
			{ $$ = cat2_str(make_str("decimal"), $2); }
4058
		| DEC opt_type_modifiers
4059
			{ $$ = cat2_str(make_str("dec"), $2); }
4060
		| NUMERIC opt_type_modifiers
4061
			{ $$ = cat2_str(make_str("numeric"), $2); }
4062
		| BOOLEAN_P
4063
			{ $$ = make_str("boolean"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4064 4065
		;

4066 4067
opt_float:	'(' PosIntConst ')'
			{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4068
		| /*EMPTY*/
4069
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
4070 4071
		;

Michael Meskes's avatar
Michael Meskes committed
4072 4073 4074 4075
/*
 * SQL92 bit-field data types
 * The following implements BIT() and BIT VARYING().
 */
4076 4077

Bit:	BitWithLength		{ $$ = $1; }
4078 4079
		| BitWithoutLength	{ $$ = $1; }
		;
4080

4081
ConstBit:	BitWithLength	{ $$ = $1; }
4082
		| BitWithoutLength	{ $$ = $1; }
4083 4084
		;

4085
BitWithLength:  BIT opt_varying '(' expr_list ')'
4086
			{ $$ = cat_str(5, make_str("bit"), $2, make_str("("), $4, make_str(")")); }
4087 4088 4089
		;

BitWithoutLength: BIT opt_varying
4090 4091
			{ $$ = cat2_str(make_str("bit"), $2); }
		;
Michael Meskes's avatar
Michael Meskes committed
4092

4093
/*
Michael Meskes's avatar
Michael Meskes committed
4094
 * SQL92 character data types
Marc G. Fournier's avatar
Marc G. Fournier committed
4095 4096 4097
 * The following implements CHAR() and VARCHAR().
 *								- ay 6/95
 */
4098 4099 4100
Character:	CharacterWithLength		{ $$ = $1; }
		| CharacterWithoutLength	{ $$ = $1; }
		;
4101

4102
ConstCharacter:	CharacterWithLength	{ $$ = $1; }
4103
		| CharacterWithoutLength	{ $$ = $1; }
4104 4105 4106
		;

CharacterWithLength: character '(' PosIntConst ')' opt_charset
4107
			{ $$ = cat_str(5, $1, make_str("("), $3, make_str(")"), $5); }
4108 4109 4110
		;

CharacterWithoutLength: character opt_charset
4111
			{ $$ = cat2_str($1, $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4112 4113
		;

4114 4115
character:	CHARACTER opt_varying
			{ $$ = cat2_str(make_str("character"), $2); }
Jan Wieck's avatar
Jan Wieck committed
4116
		| CHAR_P opt_varying
4117 4118 4119 4120 4121
			{ $$ = cat2_str(make_str("char"), $2); }
		| VARCHAR
			{ $$ = make_str("varchar"); }
		| NATIONAL CHARACTER opt_varying
			{ $$ = cat2_str(make_str("national character"), $3); }
Jan Wieck's avatar
Jan Wieck committed
4122
		| NATIONAL CHAR_P opt_varying
4123 4124 4125
			{ $$ = cat2_str(make_str("national char"), $3); }
		| NCHAR opt_varying
			{ $$ = cat2_str(make_str("nchar"), $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4126 4127
		;

4128 4129 4130 4131
opt_varying:  VARYING
			{ $$ = make_str("varying"); }
		| /*EMPTY*/
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
4132 4133
		;

4134 4135 4136 4137
opt_charset:  CHARACTER SET ColId
			{ $$ = cat2_str(make_str("character set"), $3); }
		| /*EMPTY*/
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
4138 4139
		;

4140 4141
ConstDatetime:	TIMESTAMP '(' PosIntConst ')' opt_timezone
			{ $$ = cat_str(4, make_str("timestamp("), $3, make_str(")"), $5); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4142
		| TIMESTAMP opt_timezone
4143
			{ $$ = cat2_str(make_str("timestamp"), $2); }
Michael Meskes's avatar
Michael Meskes committed
4144
		| TIME '(' PosIntConst ')' opt_timezone
4145
			{ $$ = cat_str(4, make_str("time("), $3, make_str(")"), $5); }
Michael Meskes's avatar
Michael Meskes committed
4146
		| TIME opt_timezone
4147
			{ $$ = cat2_str(make_str("time"), $2); }
Michael Meskes's avatar
Michael Meskes committed
4148 4149
		;

4150
ConstInterval:	INTERVAL
4151
			{ $$ = make_str("interval"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4152 4153
		;

4154
opt_timezone:  WITH_TIME ZONE
4155 4156 4157 4158 4159
			{ $$ = make_str("with time zone"); }
		| WITHOUT TIME ZONE
			{ $$ = make_str("without time zone"); }
		| /*EMPTY*/
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
4160 4161
		;

Michael Meskes's avatar
Michael Meskes committed
4162 4163 4164 4165 4166 4167
opt_interval:  YEAR_P				{ $$ = make_str("year"); }
		| MONTH_P			{ $$ = make_str("month"); }
		| DAY_P				{ $$ = make_str("day"); }
		| HOUR_P			{ $$ = make_str("hour"); }
		| MINUTE_P			{ $$ = make_str("minute"); }
		| interval_second		{ $$ = $1; }
4168 4169 4170
		| YEAR_P TO MONTH_P		{ $$ = make_str("year to month"); }
		| DAY_P TO HOUR_P		{ $$ = make_str("day to hour"); }
		| DAY_P TO MINUTE_P		{ $$ = make_str("day to minute"); }
Michael Meskes's avatar
Michael Meskes committed
4171 4172 4173 4174 4175
		| DAY_P TO interval_second	{ $$ = make_str("day to second"); }
		| HOUR_P TO MINUTE_P		{ $$ = make_str("hour to minute"); }
		| MINUTE_P TO interval_second	{ $$ = make_str("minute to second"); }
		| HOUR_P TO interval_second	{ $$ = make_str("hour to second"); }
		| /*EMPTY*/			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
4176 4177
		;

Michael Meskes's avatar
Michael Meskes committed
4178 4179 4180 4181
interval_second:
		SECOND_P			{ $$ = make_str("second"); }
		| SECOND_P '(' PosIntConst ')'	{ $$ = cat_str(3, make_str("second("), $3, make_str(")")); }
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
4182 4183 4184

/*****************************************************************************
 *
Michael Meskes's avatar
Michael Meskes committed
4185
 *	expression grammar
Marc G. Fournier's avatar
Marc G. Fournier committed
4186 4187
 *
 *****************************************************************************/
4188

4189
/* General expressions
Marc G. Fournier's avatar
Marc G. Fournier committed
4190
 * This is the heart of the expression syntax.
Michael Meskes's avatar
Michael Meskes committed
4191 4192 4193 4194 4195 4196 4197 4198 4199 4200
 *
 * We have two expression types: a_expr is the unrestricted kind, and
 * b_expr is a subset that must be used in some places to avoid shift/reduce
 * conflicts.  For example, we can't do BETWEEN as "BETWEEN a_expr AND a_expr"
 * because that use of AND conflicts with AND as a boolean operator.  So,
 * b_expr is used in BETWEEN and we remove boolean keywords from b_expr.
 *
 * Note that '(' a_expr ')' is a b_expr, so an unrestricted expression can
 * always be used by surrounding it with parens.
 *
Michael Meskes's avatar
Michael Meskes committed
4201
 * c_expr is all the productions that are common to a_expr and b_expr;
Michael Meskes's avatar
Michael Meskes committed
4202
 * it's factored out just to eliminate redundant coding.
Marc G. Fournier's avatar
Marc G. Fournier committed
4203 4204
 */

Michael Meskes's avatar
Michael Meskes committed
4205
a_expr:  c_expr
4206
			{ $$ = $1; }
Michael Meskes's avatar
Michael Meskes committed
4207
		| a_expr TYPECAST Typename
4208
			{ $$ = cat_str(3, $1, make_str("::"), $3); }
4209
		| a_expr AT TIME ZONE a_expr
4210
			{ $$ = cat_str(3, $1, make_str("at time zone"), $5); }
Michael Meskes's avatar
Michael Meskes committed
4211
		/*
4212 4213 4214 4215 4216 4217 4218 4219
		 * These operators must be called out explicitly in order to make use
		 * of yacc/bison's automatic operator-precedence handling.  All other
		 * operator names are handled by the generic productions using "Op",
		 * below; and all those operators will have the same precedence.
		 *
		 * If you add more explicitly-known operators, be sure to add them
		 * also to b_expr and to the MathOp list above.
		 */
Michael Meskes's avatar
Michael Meskes committed
4220
		| '+' a_expr %prec UMINUS
4221
			{ $$ = cat2_str(make_str("+"), $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4222
		| '-' a_expr %prec UMINUS
4223
			{ $$ = cat2_str(make_str("-"), $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4224
		| a_expr '+' a_expr
4225
			{ $$ = cat_str(3, $1, make_str("+"), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4226
		| a_expr '-' a_expr
4227
			{ $$ = cat_str(3, $1, make_str("-"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4228
		| a_expr '*' a_expr
4229
			{ $$ = cat_str(3, $1, make_str("*"), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4230
		| a_expr '/' a_expr
4231
			{ $$ = cat_str(3, $1, make_str("/"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4232
		| a_expr '%' a_expr
4233
			{ $$ = cat_str(3, $1, make_str("%"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4234
		| a_expr '^' a_expr
4235
			{ $$ = cat_str(3, $1, make_str("^"), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4236
		| a_expr '<' a_expr
4237
			{ $$ = cat_str(3, $1, make_str("<"), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4238
		| a_expr '>' a_expr
4239
			{ $$ = cat_str(3, $1, make_str(">"), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4240
		| a_expr '=' a_expr
4241
			{ $$ = cat_str(3, $1, make_str("="), $3); }
4242
		| a_expr qual_Op a_expr		%prec Op
4243
			{ $$ = cat_str(3, $1, $2, $3); }
4244
		| qual_Op a_expr		%prec Op
4245
			{ $$ = cat2_str($1, $2); }
4246
		| a_expr qual_Op		%prec POSTFIXOP
4247
			{ $$ = cat2_str($1, $2); }
Michael Meskes's avatar
Michael Meskes committed
4248
		| a_expr AND a_expr
4249
			{ $$ = cat_str(3, $1, make_str("and"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4250
		| a_expr OR a_expr
4251
			{ $$ = cat_str(3, $1, make_str("or"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4252
		| NOT a_expr
4253
			{ $$ = cat2_str(make_str("not"), $2); }
Michael Meskes's avatar
Michael Meskes committed
4254
		| a_expr LIKE a_expr
4255
			{ $$ = cat_str(3, $1, make_str("like"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4256
		| a_expr LIKE a_expr ESCAPE a_expr
4257
			{ $$ = cat_str(5, $1, make_str("like"), $3, make_str("escape"), $5); }
Michael Meskes's avatar
Michael Meskes committed
4258
		| a_expr NOT LIKE a_expr
4259
			{ $$ = cat_str(3, $1, make_str("not like"), $4); }
Michael Meskes's avatar
Michael Meskes committed
4260
		| a_expr NOT LIKE a_expr ESCAPE a_expr
4261
			{ $$ = cat_str(5, $1, make_str("not like"), $4, make_str("escape"), $6); }
Michael Meskes's avatar
Michael Meskes committed
4262
		| a_expr ILIKE a_expr
4263
			{ $$ = cat_str(3, $1, make_str("ilike"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4264
		| a_expr ILIKE a_expr ESCAPE a_expr
4265
			{ $$ = cat_str(5, $1, make_str("ilike"), $3, make_str("escape"), $5); }
Michael Meskes's avatar
Michael Meskes committed
4266
		| a_expr NOT ILIKE a_expr
4267
			{ $$ = cat_str(3, $1, make_str("not ilike"), $4); }
Michael Meskes's avatar
Michael Meskes committed
4268
		| a_expr NOT ILIKE a_expr ESCAPE a_expr
4269
			{ $$ = cat_str(5, $1, make_str("not ilike"), $4, make_str("escape"), $6); }
4270 4271 4272 4273 4274 4275 4276 4277
		| a_expr SIMILAR TO a_expr	%prec SIMILAR
			{ $$ = cat_str(3, $1, make_str("similar to"), $4); }
		| a_expr SIMILAR TO a_expr ESCAPE a_expr
			{ $$ = cat_str(5, $1, make_str("similar to"), $4, make_str("escape"), $6); }
		| a_expr NOT SIMILAR TO a_expr	%prec SIMILAR
			{ $$ = cat_str(3, $1, make_str("not similar to"), $5); }
		| a_expr NOT SIMILAR TO a_expr ESCAPE a_expr
			{ $$ = cat_str(5, $1, make_str("not similar to"), $5, make_str("escape"), $7); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4278
		| a_expr ISNULL
4279
			{ $$ = cat2_str($1, make_str("isnull")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4280
		| a_expr IS NULL_P
4281
			{ $$ = cat2_str($1, make_str("is null")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4282
		| a_expr NOTNULL
4283
			{ $$ = cat2_str($1, make_str("notnull")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4284
		| a_expr IS NOT NULL_P
4285
			{ $$ = cat2_str($1, make_str("is not null")); }
Michael Meskes's avatar
Michael Meskes committed
4286 4287
		| row OVERLAPS row
			{ $$ = cat_str(3, $1, make_str("overlaps"), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4288
		/* IS TRUE, IS FALSE, etc used to be function calls
4289 4290
		 *	but let's make them expressions to allow the optimizer
		 *	a chance to eliminate them if a_expr is a constant string.
Marc G. Fournier's avatar
Marc G. Fournier committed
4291
		 * - thomas 1997-12-22
4292
		 *
4293 4294
		 *	Created BooleanTest Node type, and changed handling
		 *	for NULL inputs
4295
		 * - jec 2001-06-18
Marc G. Fournier's avatar
Marc G. Fournier committed
4296 4297
		 */
		| a_expr IS TRUE_P
4298
			{ $$ = cat2_str($1, make_str("is true")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4299
		| a_expr IS NOT TRUE_P
4300
			{ $$ = cat2_str($1, make_str("is not true")); }
4301
		| a_expr IS FALSE_P
4302
			{ $$ = cat2_str($1, make_str("is false")); }
4303
		| a_expr IS NOT FALSE_P
4304
			{ $$ = cat2_str($1, make_str("is not false")); }
4305
		| a_expr IS UNKNOWN
4306
			{ $$ = cat2_str($1, make_str("is unknown")); }
4307
		| a_expr IS NOT UNKNOWN
4308
			{ $$ = cat2_str($1, make_str("is not unknown")); }
4309
		| a_expr IS DISTINCT FROM a_expr %prec IS
4310
			{ $$ = cat_str(3, $1, make_str("is distinct from"), $5); }
4311 4312
		| a_expr IS NOT DISTINCT FROM a_expr %prec IS
			{ $$ = cat_str(3, $1, make_str("is not distinct from"), $6); }
4313
		| a_expr IS OF '(' type_list ')' %prec IS
4314
			{ $$ = cat_str(4, $1, make_str("is of ("), $5, make_str(")")); }
4315
		| a_expr IS NOT OF '(' type_list ')' %prec IS
4316
			{ $$ = cat_str(4, $1, make_str("is not of ("), $6, make_str(")")); }
4317 4318 4319 4320 4321 4322 4323 4324
		| a_expr BETWEEN opt_asymmetric b_expr AND b_expr	%prec BETWEEN
			{ $$ = cat_str(6, $1, make_str("between"), $3, $4, make_str("and"), $6); }
		| a_expr NOT BETWEEN opt_asymmetric b_expr AND b_expr	%prec BETWEEN
			{ $$ = cat_str(6, $1, make_str("not between"), $4, $5, make_str("and"), $7); }
		| a_expr BETWEEN SYMMETRIC b_expr AND b_expr	%prec BETWEEN
			{ $$ = cat_str(5, $1, make_str("between symmetric"), $4, make_str("and"), $6); }
		| a_expr NOT BETWEEN SYMMETRIC b_expr AND b_expr	%prec BETWEEN
			{ $$ = cat_str(5, $1, make_str("not between symmetric"), $5, make_str("and"), $7); }
Jan Wieck's avatar
Jan Wieck committed
4325
		| a_expr IN_P in_expr
4326
			{ $$ = cat_str(3, $1, make_str("in"), $3); }
Jan Wieck's avatar
Jan Wieck committed
4327
		| a_expr NOT IN_P in_expr
4328
			{ $$ = cat_str(3, $1, make_str("not in"), $4); }
4329
		| a_expr subquery_Op sub_type select_with_parens %prec Op
4330
			{ $$ = cat_str(4, $1, $2, $3, $4); }
4331
		| a_expr subquery_Op sub_type '(' a_expr ')' %prec Op
Michael Meskes's avatar
Michael Meskes committed
4332
			{ $$ = cat_str(6, $1, $2, $3, make_str("("), $5, make_str(")")); }
4333
		| UNIQUE select_with_parens 
4334
			{ $$ = cat2_str(make_str("unique"), $2); }
4335 4336 4337 4338
		| a_expr IS DOCUMENT_P
			{ $$ = cat2_str($1, make_str("is document")); }
		| a_expr IS NOT DOCUMENT_P
			{ $$ = cat2_str($1, make_str("is not document")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4339 4340
		;

4341
/* Restricted expressions
Michael Meskes's avatar
Michael Meskes committed
4342
 *
Marc G. Fournier's avatar
Marc G. Fournier committed
4343
 * b_expr is a subset of the complete expression syntax
Michael Meskes's avatar
Michael Meskes committed
4344
 *
Michael Meskes's avatar
Michael Meskes committed
4345
 * Presently, AND, NOT, IS and IN are the a_expr keywords that would
Michael Meskes's avatar
Michael Meskes committed
4346 4347
 * cause trouble in the places where b_expr is used.  For simplicity, we
 * just eliminate all the boolean-keyword-operator productions from b_expr.
Marc G. Fournier's avatar
Marc G. Fournier committed
4348
 */
Michael Meskes's avatar
Michael Meskes committed
4349
b_expr:  c_expr
4350
			{ $$ = $1; }
Michael Meskes's avatar
Michael Meskes committed
4351
		| b_expr TYPECAST Typename
4352
			{ $$ = cat_str(3, $1, make_str("::"), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4353
		| '-' b_expr %prec UMINUS
4354
			{ $$ = cat2_str(make_str("-"), $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4355
		| b_expr '+' b_expr
4356
			{ $$ = cat_str(3, $1, make_str("+"), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4357
		| b_expr '-' b_expr
4358
			{ $$ = cat_str(3, $1, make_str("-"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4359
		| b_expr '*' b_expr
4360
			{ $$ = cat_str(3, $1, make_str("*"), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4361
		| b_expr '/' b_expr
4362
			{ $$ = cat_str(3, $1, make_str("/"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4363
		| b_expr '%' b_expr
4364
			{ $$ = cat_str(3, $1, make_str("%"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4365
		| b_expr '^' b_expr
4366
			{ $$ = cat_str(3, $1, make_str("^"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4367
		| b_expr '<' b_expr
4368
			{ $$ = cat_str(3, $1, make_str("<"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4369
		| b_expr '>' b_expr
4370
			{ $$ = cat_str(3, $1, make_str(">"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4371
		| b_expr '=' b_expr
4372
			{ $$ = cat_str(3, $1, make_str("="), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4373
		| b_expr Op b_expr
4374
			{ $$ = cat_str(3, $1, $2, $3); }
4375
		| qual_Op b_expr		%prec Op
4376
			{ $$ = cat2_str($1, $2); }
4377
		| b_expr qual_Op		%prec POSTFIXOP
4378
			{ $$ = cat2_str($1, $2); }
4379 4380
		| b_expr IS DISTINCT FROM b_expr %prec IS
			{ $$ = cat_str(3, $1, make_str("is distinct from"), $5); }
4381 4382
		| b_expr IS NOT DISTINCT FROM b_expr %prec IS
			{ $$ = cat_str(3, $1, make_str("is not distinct from"), $6); }
4383 4384 4385 4386
		| b_expr IS OF '(' b_expr ')' %prec IS
			{ $$ = cat_str(4, $1, make_str("is of ("), $5, make_str(")")); }
		| b_expr IS NOT OF '(' b_expr ')' %prec IS
			{ $$ = cat_str(4, $1, make_str("is not of ("), $6, make_str(")")); }
4387 4388 4389 4390
		| b_expr IS DOCUMENT_P
			{ $$ = cat2_str($1, make_str("is document")); }
		| b_expr IS NOT DOCUMENT_P
			{ $$ = cat2_str($1, make_str("is not document")); }
Michael Meskes's avatar
Michael Meskes committed
4391 4392 4393 4394 4395 4396
		;

/*
 * Productions that can be used in both a_expr and b_expr.
 *
 * Note: productions that refer recursively to a_expr or b_expr mostly
4397
 * cannot appear here.	However, it's OK to refer to a_exprs that occur
Michael Meskes's avatar
Michael Meskes committed
4398 4399 4400
 * inside parentheses, such as function arguments; that cannot introduce
 * ambiguity to the b_expr syntax.
 */
4401
c_expr: columnref
4402
			{ $$ = $1;	}
Michael Meskes's avatar
Michael Meskes committed
4403
		| AexprConst
4404
			{ $$ = $1;	}
4405 4406
		| Param opt_indirection
			{ $$ = cat2_str($1, $2); }
4407 4408
		| '(' a_expr ')' opt_indirection
			{ $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); }
Michael Meskes's avatar
Michael Meskes committed
4409
		| case_expr
4410
			{ $$ = $1; }
Michael Meskes's avatar
Michael Meskes committed
4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433
		| func_expr
			{ $$ = $1; }
		| select_with_parens	%prec UMINUS
			{ $$ = $1; }
		| EXISTS select_with_parens
			{ $$ = cat2_str(make_str("exists"), $2); }
		| ARRAY select_with_parens
			{ $$ = cat2_str(make_str("array"), $2); }
		| ARRAY array_expr
			{ $$ = cat2_str(make_str("array"), $2); }
		| row
			{ $$ = $1; }
		;

/*
 * func_expr is split out from c_expr just so that we have a classification
 * for "everything that is a function call or looks like one".  This isn't
 * very important, but it saves us having to document which variants are
 * legal in the backwards-compatible functional-index syntax for CREATE INDEX.
 * (Note that many of the special SQL functions wouldn't actually make any
 * sense as functional index entries, but we ignore that consideration here.)
 */
func_expr:      func_name '(' ')'
4434
			{ $$ = cat2_str($1, make_str("()"));	}
Marc G. Fournier's avatar
Marc G. Fournier committed
4435
		| func_name '(' expr_list ')'
4436
			{ $$ = cat_str(4, $1, make_str("("), $3, make_str(")"));	}
Michael Meskes's avatar
Michael Meskes committed
4437 4438 4439 4440
		| func_name '(' VARIADIC a_expr ')'
			{ $$ = cat_str(4, $1, make_str("( variadic "), $4, make_str(")"));	}
		| func_name '(' expr_list ',' VARIADIC a_expr ')'
			{ $$ = cat_str(6, $1, make_str("("), $3, make_str(", variadic "), $6, make_str(")"));	}
Michael Meskes's avatar
Michael Meskes committed
4441
		| func_name '(' ALL expr_list ')'
4442
			{ $$ = cat_str(4, $1, make_str("( all"), $4, make_str(")"));	}
Michael Meskes's avatar
Michael Meskes committed
4443
		| func_name '(' DISTINCT expr_list ')'
4444
			{ $$ = cat_str(4, $1, make_str("( distinct"), $4, make_str(")"));  }
Michael Meskes's avatar
Michael Meskes committed
4445
		| func_name '(' '*' ')'
4446
			{ $$ = cat2_str($1, make_str("(*)")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4447
		| CURRENT_DATE
4448
			{ $$ = make_str("current_date"); }
4449
		| CURRENT_TIME
4450
			{ $$ = make_str("current_time"); }
4451 4452
		| CURRENT_TIME '(' PosIntConst ')'
			{ $$ = cat_str(3, make_str("current_time ("), $3, make_str(")")); }
4453
		| CURRENT_TIMESTAMP
4454
			{ $$ = make_str("current_timestamp"); }
4455 4456
		| CURRENT_TIMESTAMP '(' PosIntConst ')'
			{ $$ = cat_str(3, make_str("current_timestamp ("), $3, make_str(")")); }
4457
		| LOCALTIME
4458 4459 4460
			{ $$ = make_str("localtime"); }
		| LOCALTIME '(' PosIntConst ')'
			{ $$ = cat_str(3, make_str("localtime ("), $3, make_str(")")); }
4461
		| LOCALTIMESTAMP
4462 4463 4464 4465 4466 4467 4468
			{ $$ = make_str("local_timestamp"); }
		| LOCALTIMESTAMP '(' PosIntConst ')'
			{ $$ = cat_str(3, make_str("locale_timestamp ("), $3, make_str(")")); }
		| CURRENT_ROLE
			{ $$ = make_str("current_role"); }
		| CURRENT_USER
			{ $$ = make_str("current_user"); }
4469
		| SESSION_USER
4470
			{ $$ = make_str("session_user"); }
4471
		| USER
4472
			{ $$ = make_str("user"); }
4473 4474 4475 4476
		| CURRENT_CATALOG
			{ $$ = make_str("current_catalog"); }
		| CURRENT_SCHEMA
			{ $$ = make_str("current_schema"); }
4477 4478
		| CAST '(' a_expr AS Typename ')'
			{ $$ = cat_str(5, make_str("cast("), $3, make_str("as"), $5, make_str(")")); }
Michael Meskes's avatar
Michael Meskes committed
4479
		| EXTRACT '(' extract_list ')'
4480
			{ $$ = cat_str(3, make_str("extract("), $3, make_str(")")); }
4481 4482
		| OVERLAY '(' overlay_list ')'
			{ $$ = cat_str(3, make_str("overlay("), $3, make_str(")")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4483
		| POSITION '(' position_list ')'
4484
			{ $$ = cat_str(3, make_str("position("), $3, make_str(")")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4485
		| SUBSTRING '(' substr_list ')'
4486
			{ $$ = cat_str(3, make_str("substring("), $3, make_str(")")); }
4487 4488
		| TREAT '(' a_expr AS Typename ')'
			{ $$ = cat_str(5, make_str("treat("), $3, make_str("as"), $5, make_str(")")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4489 4490
		/* various trim expressions are defined in SQL92 - thomas 1997-07-19 */
		| TRIM '(' BOTH trim_list ')'
4491
			{ $$ = cat_str(3, make_str("trim(both"), $4, make_str(")")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4492
		| TRIM '(' LEADING trim_list ')'
4493
			{ $$ = cat_str(3, make_str("trim(leading"), $4, make_str(")")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4494
		| TRIM '(' TRAILING trim_list ')'
4495
			{ $$ = cat_str(3, make_str("trim(trailing"), $4, make_str(")")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4496
		| TRIM '(' trim_list ')'
4497
			{ $$ = cat_str(3, make_str("trim("), $3, make_str(")")); }
Michael Meskes's avatar
Michael Meskes committed
4498
		| NULLIF '(' a_expr ',' a_expr ')'
4499
			{ $$ = cat_str(5, make_str("nullif("), $3, make_str(","), $5, make_str(")")); }
Michael Meskes's avatar
Michael Meskes committed
4500 4501
		| COALESCE '(' expr_list ')'
			{ $$ = cat_str(3, make_str("coalesce("), $3, make_str(")")); }
4502 4503 4504 4505
		| GREATEST '(' expr_list ')'
			{ $$ = cat_str(3, make_str("greatest("), $3, make_str(")")); }
		| LEAST '(' expr_list ')'
			{ $$ = cat_str(3, make_str("least("), $3, make_str(")")); }
4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535
		| XMLCONCAT '(' expr_list ')'
			{ $$ = cat_str(3, make_str("xmlconcat("), $3, make_str(")")); }
		| XMLELEMENT '(' NAME_P ColLabel ')'
			{ $$ = cat_str(3, make_str("xmlelement( name"), $4, make_str(")")); }
		| XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ')'
			{ $$ = cat_str(5, make_str("xmlelement( name"), $4, make_str(","), $6, make_str(")")); }
		| XMLELEMENT '(' NAME_P ColLabel ',' expr_list ')'
			{ $$ = cat_str(5, make_str("xmlelement( name"), $4, make_str(","), $6, make_str(")")); }
		| XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ',' expr_list ')'
			{ $$ = cat_str(7, make_str("xmlelement( name"), $4, make_str(","), $6, make_str(","), $8, make_str(")")); }
		| XMLFOREST '(' xml_attribute_list ')'
			{ $$ = cat_str(3, make_str("xmlforest("), $3, make_str(")")); }
		| XMLPARSE '(' document_or_content a_expr xml_whitespace_option ')'
			{ $$ = cat_str(5, make_str("xmlparse("), $3, $4, $5, make_str(")")); }
		| XMLPI '(' NAME_P ColLabel ')'
			{ $$ = cat_str(3, make_str("xmlpi( name"), $4, make_str(")")); }
		| XMLPI '(' NAME_P ColLabel ',' a_expr ')'
			{ $$ = cat_str(5, make_str("xmlpi( name"), $4, make_str(","), $6, make_str(")")); }
		| XMLROOT '(' a_expr ',' xml_root_version opt_xml_root_standalone  ')'
			{ $$ = cat_str(6, make_str("xmlroot("), $3, make_str(","), $5, $6, make_str(")")); }
		;

/*
 * SQL/XML support
 */

xml_root_version: VERSION_P a_expr
			{ $$ = cat2_str(make_str("version"), $2); }
		| VERSION_P NO VALUE_P
			{ $$ = make_str("version no value"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4536
		;
4537

4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571
opt_xml_root_standalone: ',' STANDALONE_P YES_P
				{ $$ = make_str(", standalone yes"); }
			| ',' STANDALONE_P NO
				{ $$ = make_str(", standalone no"); }
			| ',' STANDALONE_P NO VALUE_P
				{ $$ = make_str(", standalone no value"); }
			| /*EMPTY*/
				{ $$ = EMPTY; }
 			;

xml_attributes: 	XMLATTRIBUTES '(' xml_attribute_list ')'
				{ $$ = cat_str(3, make_str("xmlattributes("), $3, make_str(")")); }
			;

xml_attribute_list:	xml_attribute_el
				{ $$ = $1; }
			| xml_attribute_list ',' xml_attribute_el
				{ $$ = cat_str(3, $1, make_str(","), $3); }
			;

xml_attribute_el: a_expr AS ColLabel
			{ $$ = cat_str(3, $1, make_str("as"), $3); }
		| a_expr
			{ $$ = $1; }
		;

document_or_content: DOCUMENT_P		{ $$ = make_str("document"); }
			| CONTENT_P	{ $$ = make_str("content"); }
			;

xml_whitespace_option: PRESERVE WHITESPACE_P 	{ $$ = make_str("preserve whitespace"); }
			| STRIP_P WHITESPACE_P	{ $$ = make_str("strip whitespace"); }
			| /*EMPTY*/		{ $$ = EMPTY; }
			;
Michael Meskes's avatar
Michael Meskes committed
4572

4573
row: ROW '(' expr_list ')'
4574 4575 4576 4577 4578 4579
			{ $$ = cat_str(3, make_str("row ("), $3, make_str(")")); }
		| ROW '(' ')'
			{ $$ = make_str("row()"); }
		| '(' expr_list ',' a_expr ')'
			{ $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")")); }
		;
4580 4581

sub_type:  ANY		{ $$ = make_str("ANY"); }
4582 4583 4584
		| SOME		{ $$ = make_str("SOME"); }
		| ALL		{ $$ = make_str("ALL"); }
		;
4585 4586

all_Op:  Op 				{ $$ = $1; }
4587 4588
		| MathOp			{ $$ = $1; }
		;
4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614

MathOp: '+'				{ $$ = make_str("+"); }
		| '-'			{ $$ = make_str("-"); }
		| '*'			{ $$ = make_str("*"); }
		| '%'			{ $$ = make_str("%"); }
		| '^'			{ $$ = make_str("^"); }
		| '/'			{ $$ = make_str("/"); }
		| '<'			{ $$ = make_str("<"); }
		| '>'			{ $$ = make_str(">"); }
		| '='			{ $$ = make_str("="); }
		;

qual_Op:  Op 				{ $$ = $1; }
		| OPERATOR '(' any_operator ')'	{ $$ = cat_str(3, make_str("operator ("), $3, make_str(")")); }
		;

qual_all_Op:  all_Op 				{ $$ = $1; }
		| OPERATOR '(' any_operator ')'	{ $$ = cat_str(3, make_str("operator ("), $3, make_str(")")); }
		;

subquery_Op:  all_Op 				{ $$ = $1; }
		| OPERATOR '(' any_operator ')'	{ $$ = cat_str(3, make_str("operator ("), $3, make_str(")")); }
		| LIKE 				{ $$ = make_str("like"); }
		| NOT LIKE 			{ $$ = make_str("not like"); }
		| ILIKE 			{ $$ = make_str("ilike"); }
		| NOT ILIKE 			{ $$ = make_str("not ilike"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4615 4616
		;

4617 4618
expr_list:	a_expr
			{ $$ = $1; }
Michael Meskes's avatar
Michael Meskes committed
4619
		| expr_list ',' a_expr
4620
			{ $$ = cat_str(3, $1, make_str(","), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4621 4622
		;

4623
type_list:	 Typename
4624
			{ $$ = $1; }
4625 4626
		| type_list ',' Typename
			{ $$ = cat_str(3, $1, ',', $3); }
4627 4628
		;

Michael Meskes's avatar
Michael Meskes committed
4629 4630 4631 4632 4633
array_expr: '[' expr_list ']'			{ $$ = cat_str(3, make_str("["), $2, make_str("]")); }
		| '[' array_expr_list ']'	{ $$ = cat_str(3, make_str("["), $2, make_str("]")); }
		| '[' ']'			{ $$ = make_str("[]"); }
		;

4634 4635 4636
array_expr_list: array_expr				{ $$ = $1; }
		| array_expr_list ',' array_expr	{ $$ = cat_str(3, $1, make_str(","), $3); }
		;
4637

Michael Meskes's avatar
Michael Meskes committed
4638 4639 4640 4641
extract_list:  extract_arg FROM a_expr
			{ $$ = cat_str(3, $1, make_str("from"), $3); }
		| /* EMPTY */
			{ $$ = EMPTY; }
4642
		;
Tom Lane's avatar
Tom Lane committed
4643

4644
extract_arg:  ident				{ $$ = $1; }
4645 4646 4647 4648 4649 4650 4651
		| YEAR_P				{ $$ = make_str("year"); }
		| MONTH_P				{ $$ = make_str("month"); }
		| DAY_P					{ $$ = make_str("day"); }
		| HOUR_P				{ $$ = make_str("hour"); }
		| MINUTE_P				{ $$ = make_str("minute"); }
		| SECOND_P				{ $$ = make_str("second"); }
		| StringConst			{ $$ = $1; }
Marc G. Fournier's avatar
Marc G. Fournier committed
4652 4653
		;

4654 4655 4656 4657 4658 4659 4660 4661
overlay_list:
		a_expr overlay_placing substr_from substr_for
			{ $$ = cat_str(4, $1, 42, $3, $4); }
		| a_expr overlay_placing substr_from
			{ $$ = cat_str(3, $1, $2, $3); }
		;

overlay_placing:
4662 4663
		PLACING a_expr		{ $$ = cat2_str(make_str("placing"), $2); }
		;
4664

Michael Meskes's avatar
Michael Meskes committed
4665
/* position_list uses b_expr not a_expr to avoid conflict with general IN */
Jan Wieck's avatar
Jan Wieck committed
4666
position_list:	b_expr IN_P b_expr
4667
			{ $$ = cat_str(3, $1, make_str("in"), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4668
		| /* EMPTY */
4669
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
4670 4671
		;

4672
substr_list:  a_expr substr_from substr_for
4673 4674 4675 4676 4677
			{ $$ = cat_str(3, $1, $2, $3); }
		| a_expr substr_for substr_from
			{ $$ = cat_str(3, $1, $2, $3); }
		| a_expr substr_from
			{ $$ = cat2_str($1, $2); }
4678
		| a_expr substr_for
4679
			{ $$ = cat2_str($1, $2); }
4680
		| expr_list
4681
			{ $$ = $1; }
Marc G. Fournier's avatar
Marc G. Fournier committed
4682
		| /* EMPTY */
4683
			{ $$ = EMPTY; }
Marc G. Fournier's avatar
Marc G. Fournier committed
4684 4685
		;

4686
substr_from:  FROM a_expr
4687
			{ $$ = cat2_str(make_str("from"), $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4688 4689
		;

4690
substr_for:  FOR a_expr
4691
			{ $$ = cat2_str(make_str("for"), $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4692 4693
		;

4694 4695
trim_list:	a_expr FROM expr_list
			{ $$ = cat_str(3, $1, make_str("from"), $3); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4696
		| FROM expr_list
4697
			{ $$ = cat2_str(make_str("from"), $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4698
		| expr_list
4699
			{ $$ = $1; }
Marc G. Fournier's avatar
Marc G. Fournier committed
4700 4701
		;

4702
in_expr:  select_with_parens
4703
			{ $$ = $1; }
4704
		| '(' expr_list ')'
4705
			{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4706 4707
		;

4708 4709 4710
/* Case clause
 * Define SQL92-style case clause.
 */
4711
case_expr:	CASE case_arg when_clause_list case_default END_P
4712
			{ $$ = cat_str(5, make_str("case"), $2, $3, $4, make_str("end")); }
4713 4714 4715
		;

when_clause_list:  when_clause_list when_clause
4716 4717 4718 4719
			{ $$ = cat2_str($1, $2); }
		| when_clause
			{ $$ = $1; }
		;
4720

Michael Meskes's avatar
Michael Meskes committed
4721
when_clause:  WHEN a_expr THEN a_expr
4722 4723 4724 4725 4726 4727 4728 4729 4730 4731
			{ $$ = cat_str(4, make_str("when"), $2, make_str("then"), $4); }
		;

case_default:  ELSE a_expr
			{ $$ = cat2_str(make_str("else"), $2); }
		| /*EMPTY*/
			{ $$ = EMPTY; }
		;

case_arg:  a_expr			{ $$ = $1; }
4732
		| /*EMPTY*/		{ $$ = EMPTY; }
4733
		;
4734

4735
columnref: relation_name		{ $$ = $1; }
4736 4737
		| relation_name indirection	{ $$ = cat2_str($1, $2); }
		;
4738

4739
indirection_el:
4740 4741 4742 4743 4744
		'.' attr_name			{ $$ = cat2_str(make_str("."), $2); }
		| '.' '*'			{ $$ = make_str(".*"); }
		| '[' a_expr ']'		{ $$ = cat_str(3, make_str("["), $2, make_str("]")); }
		| '[' a_expr ':' a_expr ']'	{ $$ = cat_str(5, make_str("["), $2, make_str(":"), $4, make_str("]")); }
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
4745

4746
indirection:	indirection_el		{ $$ = $1; }
4747 4748
		| indirection indirection_el	{ $$ = cat2_str($1, $2); }
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
4749

4750
opt_indirection:
4751
		/*EMPTY*/				{ $$ = EMPTY; }
4752
		| opt_indirection indirection_el	{ $$ = cat2_str($1, $2);}
4753
		;
4754

4755
opt_asymmetric: ASYMMETRIC	{ $$ = make_str("asymmetric"); }
4756 4757
		| /*EMPTY*/		{ $$ = EMPTY; }
		;
4758

Michael Meskes's avatar
Michael Meskes committed
4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770
ctext_expr:
		a_expr     	{ $$ = $1; }
		| DEFAULT	{ $$ = make_str("default"); }
		;

ctext_expr_list:
		 ctext_expr				{ $$ = $1; }
		 |  ctext_expr_list ',' ctext_expr	{ $$ = cat_str(3, $1, make_str(","), $3); }
		 ;

ctext_row: '(' ctext_expr_list ')' 	{ $$ = cat_str(3, make_str("("), $2, make_str(")"));};

Marc G. Fournier's avatar
Marc G. Fournier committed
4771 4772
/*****************************************************************************
 *
Michael Meskes's avatar
Michael Meskes committed
4773
 *	target lists for SELECT
Marc G. Fournier's avatar
Marc G. Fournier committed
4774 4775 4776
 *
 *****************************************************************************/

Michael Meskes's avatar
Michael Meskes committed
4777
target_list:  target_list ',' target_el
4778
			{ $$ = cat_str(3, $1, make_str(","), $3);  }
Michael Meskes's avatar
Michael Meskes committed
4779
		| target_el
4780
			{ $$ = $1;	}
Marc G. Fournier's avatar
Marc G. Fournier committed
4781 4782
		;

4783 4784
target_el:	a_expr AS ColLabel
			{ $$ = cat_str(3, $1, make_str("as"), $3); }
Michael Meskes's avatar
Michael Meskes committed
4785 4786 4787 4788 4789 4790 4791 4792
		/*
		 * We support omitting AS only for column labels that aren't
		 * any known keyword.  There is an ambiguity against postfix
		 * operators: is "a ! b" an infix expression, or a postfix
		 * expression and a column label?  We prefer to resolve this
		 * as an infix expression, which we accomplish by assigning
		 * IDENT a precedence higher than POSTFIXOP.
		 */
4793 4794
		| a_expr IDENT
			{ $$ = cat_str(3, $1, make_str("as"), $2); }
Michael Meskes's avatar
Michael Meskes committed
4795
		| a_expr
4796
			{ $$ = $1; }
Marc G. Fournier's avatar
Marc G. Fournier committed
4797
		| '*'
4798
			{ $$ = make_str("*"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4799 4800
		;

Michael Meskes's avatar
Michael Meskes committed
4801 4802
/* INFORMIX workaround, no longer needed
update_target_list:  '(' inf_col_list ')' '=' '(' inf_val_list ')'
4803 4804 4805 4806 4807
		{
			struct inf_compat_col *ptrc;
			struct inf_compat_val *ptrv;
			char *cols = make_str( "(" );
			char *vals = make_str( "(" );
4808

4809
			for (ptrc = informix_col, ptrv = informix_val; ptrc != NULL && ptrv != NULL; ptrc = ptrc->next, ptrv = ptrv->next)
4810
			{
4811
				if ( ptrc->next != NULL )
4812
				{
4813 4814 4815 4816 4817
					cols = cat_str(4, cols, ptrc->name, ptrc->indirection, make_str(",") );
				}
				else
				{
					cols = cat_str(4, cols, ptrc->name, ptrc->indirection, make_str(")") );
4818
				}
4819 4820 4821 4822
				if (ptrv->next != NULL )
					vals = cat_str(3, vals, ptrv->val, make_str("," ) );
				else
					vals = cat_str( 3, vals, ptrv->val, make_str(")") );
4823
			}
4824
			$$ = cat_str( 3, cols, make_str("="), vals );
Michael Meskes's avatar
Michael Meskes committed
4825
		} 
Michael Meskes's avatar
Michael Meskes committed
4826 4827
		;

Michael Meskes's avatar
Michael Meskes committed
4828
inf_col_list: ColId opt_indirection
4829 4830
		{
			struct inf_compat_col *ptr = mm_alloc(sizeof(struct inf_compat_col));
4831

4832 4833 4834 4835 4836 4837 4838 4839
			ptr->name = $1;
			ptr->indirection = $2;
			ptr->next = NULL;
			informix_col = ptr;
		}
		| ColId opt_indirection ',' inf_col_list
		{
			struct inf_compat_col *ptr = mm_alloc(sizeof(struct inf_compat_col));
4840

4841 4842 4843 4844 4845 4846
		        ptr->name = $1;
		        ptr->indirection = $2;
		        ptr->next = informix_col;
		        informix_col = ptr;
		}
		;
4847

4848 4849 4850
inf_val_list: a_expr
		{
			struct inf_compat_val *ptr = mm_alloc(sizeof(struct inf_compat_val));
4851

4852 4853 4854 4855 4856 4857 4858
			ptr->val = $1;
			ptr->next = NULL;
			informix_val = ptr;
		}
		| a_expr ',' inf_val_list
		{
			struct inf_compat_val *ptr = mm_alloc(sizeof(struct inf_compat_val));
4859

4860 4861 4862 4863 4864
		        ptr->val = $1;
		        ptr->next = informix_val;
		        informix_val = ptr;
		}
		;
Michael Meskes's avatar
Michael Meskes committed
4865
*/
4866

Michael Meskes's avatar
Michael Meskes committed
4867 4868
/*****************************************************************************
 *
4869
 *	   Names and constants
Michael Meskes's avatar
Michael Meskes committed
4870 4871 4872
 *
 *****************************************************************************/

4873 4874 4875 4876 4877 4878 4879 4880 4881 4882
relation_name:  SpecialRuleRelation	{ $$ = $1; }
		| ColId	                { $$ = $1; }
		;

qualified_name_list:  qualified_name
				{ $$ = $1; }
		| qualified_name_list ',' qualified_name
				{ $$ = cat_str(3, $1, make_str(","), $3); }
		;

4883 4884
qualified_name: relation_name
		{ $$ = $1; }
4885
		| relation_name indirection
4886
		{ $$ = cat2_str($1, $2); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4887 4888
		;

4889 4890 4891 4892 4893 4894 4895
name_list:  name
			{ $$ = $1; }
		| name_list ',' name
			{ $$ = cat_str(3, $1, make_str(","), $3); }
		;


4896
name:				ColId			{ $$ = $1; };
4897 4898 4899 4900
database_name:		ColId			{ $$ = $1; };
access_method:		ColId			{ $$ = $1; };
attr_name:			ColLabel		{ $$ = $1; };
index_name:			ColId			{ $$ = $1; };
Marc G. Fournier's avatar
Marc G. Fournier committed
4901

4902
file_name:			StringConst		{ $$ = $1; };
Marc G. Fournier's avatar
Marc G. Fournier committed
4903

4904
func_name: type_function_name
4905
			{ $$ = $1; }
4906 4907
		| relation_name indirection
			{ $$ = cat2_str($1, $2); }
4908 4909 4910
		;


Marc G. Fournier's avatar
Marc G. Fournier committed
4911 4912 4913
/* Constants
 * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
 */
4914
AexprConst:  PosAllConst
4915
			{ $$ = $1; }
4916
		| ConstTypename StringConst
4917 4918 4919
			{ $$ = cat2_str($1, $2); }
		| ConstInterval StringConst opt_interval
			{ $$ = cat_str(3, $1, $2, $3); }
4920
		| ConstInterval  '(' PosIntConst ')' StringConst opt_interval
4921
			{ $$ = cat_str(6, $1, make_str("("), $3, make_str(")"), $5, $6); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4922
		| TRUE_P
4923
			{ $$ = make_str("true"); }
Marc G. Fournier's avatar
Marc G. Fournier committed
4924
		| FALSE_P
4925
			{ $$ = make_str("false"); }
Michael Meskes's avatar
Michael Meskes committed
4926
		| NULL_P
4927
			{ $$ = make_str("null"); }
4928
		| civarind
4929
			{ $$ = $1; }
Marc G. Fournier's avatar
Marc G. Fournier committed
4930 4931
		;

4932
Param:   PARAM				{ $$ = make_name();};
4933 4934
Iconst:  ICONST				{ $$ = make_name();};
Fconst:  FCONST				{ $$ = make_name();};
4935 4936
Bconst:  BCONST				{ $$ = make_name();};
Xconst:  XCONST				{ $$ = make_name();};
4937 4938
Sconst:  SCONST
		{
4939
			/* could have been input as '' or $$ */
4940 4941 4942 4943
			$$ = (char *)mm_alloc(strlen($1) + 3);
			$$[0]='\'';
			strcpy($$+1, $1);
			$$[strlen($1)+1]='\'';
4944
			$$[strlen($1)+2]='\0';
4945 4946
			free($1);
		}
4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968
	| ECONST
		{
			/* escaped quote starting with E */
			$$ = (char *)mm_alloc(strlen($1) + 4);
			$$[0]='E';
			$$[1]='\'';
			strcpy($$+2, $1);
			$$[strlen($1)+2]='\'';
			$$[strlen($1)+3]='\0';
			free($1);
		}
	| NCONST
		{
			/* escaped quote starting with rNE */
			$$ = (char *)mm_alloc(strlen($1) + 4);
			$$[0]='N';
			$$[1]='\'';
			strcpy($$+2, $1);
			$$[strlen($1)+2]='\'';
			$$[strlen($1)+3]='\0';
			free($1);
		}
4969 4970 4971 4972 4973
	| DOLCONST
		{
			$$ = $1; 
		}
	;
Marc G. Fournier's avatar
Marc G. Fournier committed
4974

4975
PosIntConst:	Iconst		{ $$ = $1; }
4976
		| civar		{ $$ = $1; }
4977 4978 4979 4980 4981 4982
		;

IntConst:	PosIntConst		{ $$ = $1; }
		| '-' PosIntConst	{ $$ = cat2_str(make_str("-"), $2); }
		;

4983
IntConstVar:	Iconst
4984
		{
4985
	        	char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
4986

4987
			sprintf(length, "%d", (int) strlen($1));
4988
			new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
4989 4990 4991 4992 4993
			$$ = $1;
		}
		| cvariable	{ $$ = $1; }
		;

4994 4995
AllConstVar:	Fconst
		{
4996
		        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
4997

4998
			sprintf(length, "%d", (int) strlen($1));
4999
			new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
5000 5001 5002 5003 5004
			$$ = $1;
		}
		| IntConstVar		{ $$ = $1; }
		| '-' Fconst
		{
5005
		        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
5006
			char *var = cat2_str(make_str("-"), $2);
5007

5008
			sprintf(length, "%d", (int) strlen(var));
5009
			new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
5010 5011 5012 5013
			$$ = var;
		}
		| '-' Iconst
		{
5014
		        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
5015
			char *var = cat2_str(make_str("-"), $2);
5016

5017
			sprintf(length, "%d", (int) strlen(var));
5018
			new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
5019 5020
			$$ = var;
		}
5021
		| Sconst
5022
		{
5023
		        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
5024
			char *var = $1 + 1;
5025

5026 5027
			var[strlen(var) - 1] = '\0';
			sprintf(length, "%d", (int) strlen(var));
5028
			new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
5029 5030 5031 5032
			$$ = var;
		}
		;

5033
StringConst:	Sconst		{ $$ = $1; }
5034
		| civar		{ $$ = $1; }
5035 5036
		;

5037
PosIntStringConst:	Iconst	{ $$ = $1; }
5038
		| Sconst	{ $$ = $1; }
5039
		| civar		{ $$ = $1; }
5040
		;
5041

5042
NumConst:	Fconst			{ $$ = $1; }
5043
		| Iconst		{ $$ = $1; }
5044
		| '-' Fconst		{ $$ = cat2_str(make_str("-"), $2); }
5045
		| '-' Iconst		{ $$ = cat2_str(make_str("-"), $2); }
5046
		| civar			{ $$ = $1; }
5047 5048
		;

5049
AllConst:	Sconst			{ $$ = $1; }
5050
		| NumConst		{ $$ = $1; }
5051 5052
		;

5053 5054 5055 5056 5057 5058 5059 5060 5061
PosAllConst:	Sconst			{ $$ = $1; }
		| Fconst		{ $$ = $1; }
		| Iconst		{ $$ = $1; }
		| Bconst		{ $$ = $1; }
		| Xconst		{ $$ = $1; }
		| func_name Sconst	{ $$ = cat2_str($1, $2); }
		| func_name '(' expr_list ')' Sconst
					{ $$ = cat_str(5, $1, make_str("("), $3, make_str(")"), $5); }
		| civar			{ $$ = $1; }
5062 5063
		;

5064
RoleId:  ColId		{ $$ = $1;};
Marc G. Fournier's avatar
Marc G. Fournier committed
5065

5066
SpecialRuleRelation:  OLD
5067 5068 5069
		{
			if (!QueryIsRule)
				mmerror(PARSE_ERROR, ET_ERROR, "OLD used in non-rule query");
5070

5071 5072
			$$ = make_str("old");
		}
Marc G. Fournier's avatar
Marc G. Fournier committed
5073
		| NEW
5074 5075 5076
		{
			if (!QueryIsRule)
				mmerror(PARSE_ERROR, ET_ERROR, "NEW used in non-rule query");
5077

5078 5079
			$$ = make_str("new");
		}
Marc G. Fournier's avatar
Marc G. Fournier committed
5080 5081 5082 5083 5084 5085 5086
		;

/*
 * and now special embedded SQL stuff
 */

/*
5087
 * the exec sql connect statement: connect to the given database
Marc G. Fournier's avatar
Marc G. Fournier committed
5088
 */
5089
ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user
5090 5091
			{ $$ = cat_str(5, $3, make_str(","), $5, make_str(","), $4); }
		| SQL_CONNECT TO DEFAULT
5092
			{ $$ = make_str("NULL, NULL, NULL, \"DEFAULT\""); }
5093 5094
		  /* also allow ORACLE syntax */
		| SQL_CONNECT ora_user
5095
			{ $$ = cat_str(3, make_str("NULL,"), $2, make_str(", NULL")); }
5096
		| DATABASE connection_target
5097
			{ $$ = cat2_str($2, make_str(", NULL, NULL, NULL")); }
5098
		;
5099

5100
connection_target: opt_database_name opt_server opt_port
5101 5102 5103
		{
			/* old style: dbname[@server][:port] */
			if (strlen($2) > 0 && *($2) != '@')
5104
				mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\", found \"%s\"", $2);
5105 5106 5107 5108 5109 5110
			
			/* C strings need to be handled differently */
			if ($1[0] == '\"')
				$$ = $1;
			else
				$$ = make3_str(make_str("\""), make3_str($1, $2, $3), make_str("\""));
5111
		}
5112
		|  db_prefix ':' server opt_port '/' opt_database_name opt_options
5113 5114 5115
		{
			/* new style: <tcp|unix>:postgresql://server[:port][/dbname] */
			if (strncmp($1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp($1, "tcp:postgresql", strlen("tcp:postgresql")) != 0)
5116
				mmerror(PARSE_ERROR, ET_ERROR, "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported");
5117 5118

			if (strncmp($3, "//", strlen("//")) != 0)
5119
				mmerror(PARSE_ERROR, ET_ERROR, "expected \"://\", found \"%s\"", $3);
5120 5121 5122 5123

			if (strncmp($1, "unix", strlen("unix")) == 0 &&
				strncmp($3 + strlen("//"), "localhost", strlen("localhost")) != 0 &&
				strncmp($3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0)
5124
				mmerror(PARSE_ERROR, ET_ERROR, "unix domain sockets only work on \"localhost\" but not on \"%s\"", $3 + strlen("//"));
5125 5126

			$$ = make3_str(make3_str(make_str("\""), $1, make_str(":")), $3, make3_str(make3_str($4, make_str("/"), $6),	$7, make_str("\"")));
5127
		}
5128 5129 5130 5131
		| char_variable
		{
			$$ = $1;
		}
5132 5133 5134 5135 5136 5137 5138 5139 5140
		| Sconst
		{
			/* We can only process double quoted strings not single quotes ones,
			 * so we change the quotes.
			 * Note, that the rule for Sconst adds these single quotes. */
			$1[0] = '\"';
			$1[strlen($1)-1] = '\"';
			$$ = $1;
		}
5141
		;
5142

5143 5144 5145 5146
opt_database_name: database_name		{ $$ = $1; }
		| /*EMPTY*/			{ $$ = EMPTY; }
		;

5147
db_prefix: ident cvariable
5148 5149
		{
			if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0)
5150
				mmerror(PARSE_ERROR, ET_ERROR, "expected \"postgresql\", found \"%s\"", $2);
5151 5152

			if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0)
5153
				mmerror(PARSE_ERROR, ET_ERROR, "illegal connection type %s", $1);
5154 5155

			$$ = make3_str($1, make_str(":"), $2);
5156
		}
5157
		;
5158

5159
server: Op server_name
5160 5161
		{
			if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0)
5162
				mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\" or \"://\", found \"%s\"", $1);
5163

5164 5165
			$$ = make2_str($1, $2);
		}
5166
		;
5167

5168 5169
opt_server: server			{ $$ = $1; }
		| /*EMPTY*/			{ $$ = EMPTY; }
5170
		;
5171

5172 5173 5174
server_name: ColId					{ $$ = $1; }
		| ColId '.' server_name		{ $$ = make3_str($1, make_str("."), $3); }
		| IP						{ $$ = make_name(); }
5175
		;
5176

5177
opt_port: ':' PosIntConst	{ $$ = make2_str(make_str(":"), $2); }
5178
		| /*EMPTY*/	{ $$ = EMPTY; }
5179
		;
5180

5181
opt_connection_name: AS connection_object	{ $$ = $2; }
5182
		| /*EMPTY*/			{ $$ = make_str("NULL"); }
5183
		;
5184

5185
opt_user: USER ora_user		{ $$ = $2; }
5186
		| /*EMPTY*/			{ $$ = make_str("NULL, NULL"); }
5187
		;
5188 5189

ora_user: user_name
5190 5191 5192 5193 5194 5195 5196 5197 5198
			{ $$ = cat2_str($1, make_str(", NULL")); }
		| user_name '/' user_name
			{ $$ = cat_str(3, $1, make_str(","), $3); }
		| user_name SQL_IDENTIFIED BY user_name
			{ $$ = cat_str(3, $1, make_str(","), $4); }
		| user_name USING user_name
			{ $$ = cat_str(3, $1, make_str(","), $3); }
		;

5199
user_name: RoleId
5200
		{
5201
			if ($1[0] == '\"')
5202
				$$ = $1;
5203
			else
5204
				$$ = make3_str(make_str("\""), $1, make_str("\""));
5205 5206 5207 5208
		}
		| StringConst
		{
			if ($1[0] == '\"')
5209
				$$ = $1;
Michael Meskes's avatar
Michael Meskes committed
5210
			else if ($1[1] == '$') /* variable */
5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222
			{
				enum ECPGttype type = argsinsert->variable->type->type;

				/* if array see what's inside */
				if (type == ECPGt_array)
					type = argsinsert->variable->type->u.element->type;

				/* handle varchars */
				if (type == ECPGt_varchar)
					$$ = make2_str(mm_strdup(argsinsert->variable->name), make_str(".arr"));
				else
					$$ = mm_strdup(argsinsert->variable->name);
5223
			}
5224 5225 5226 5227
			else
				$$ = make3_str(make_str("\""), $1, make_str("\""));
		}
		;
5228

5229
char_variable: cvariable
5230
		{
5231
			/* check if we have a string variable */
5232
			struct variable *p = find_variable($1);
5233
			enum ECPGttype type = p->type->type;
5234

5235 5236
			/* If we have just one character this is not a string */
			if (atol(p->type->size) == 1)
5237
					mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype");
5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254
			else
			{
				/* if array see what's inside */
				if (type == ECPGt_array)
					type = p->type->u.element->type;

				switch (type)
				{
					case ECPGt_char:
					case ECPGt_unsigned_char:
						$$ = $1;
						break;
					case ECPGt_varchar:
						$$ = make2_str($1, make_str(".arr"));
						break;
					default:
						mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype");
5255
						$$ = $1;
5256 5257
						break;
				}
5258
			}
5259
		}
5260
		;
5261

5262
opt_options: Op connect_options
5263 5264
		{
			if (strlen($1) == 0)
5265
				mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
5266

5267
			if (strcmp($1, "?") != 0)
5268
				mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $1);
5269

Michael Meskes's avatar
Michael Meskes committed
5270
			$$ = make2_str(make_str("?"), $2);
5271
		}
5272 5273
		| /*EMPTY*/ 	{ $$ = EMPTY; }
		;
5274

5275 5276 5277 5278 5279 5280 5281 5282
connect_options:  ColId opt_opt_value 
			{ $$ = make2_str($1, $2); }
	| ColId opt_opt_value Op connect_options
			{
				if (strlen($3) == 0)
					mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");

				if (strcmp($3, "&") != 0)
5283
					mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $3);
5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295

				$$ = cat_str(3, make2_str($1, $2), $3, $4);
			}
	;

opt_opt_value: /*EMPTY*/
			{ $$ = EMPTY; }
		| '=' Iconst
			{ $$ = make2_str(make_str("="), $2); }
		| '=' IDENT
			{ $$ = make2_str(make_str("="), $2); }
		;
5296
/*
5297 5298
 * Declare a prepared cursor. The syntax is different from the standard
 * declare statement, so we create a new rule.
5299
 */
5300
ECPGCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR prepared_name
5301 5302 5303
		{
			struct cursor *ptr, *this;
			struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
5304
			const char *con = connection ? connection : "NULL";
5305

5306 5307 5308
			for (ptr = cur; ptr != NULL; ptr = ptr->next)
			{
				if (strcmp($2, ptr->name) == 0)
5309
					/* re-definition is a bug */
5310
					mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" already defined", $2);
5311 5312 5313 5314 5315 5316 5317 5318
			}

			this = (struct cursor *) mm_alloc(sizeof(struct cursor));

			/* initial definition */
			this->next = cur;
			this->name = $2;
			this->connection = connection;
5319
			this->command =  cat_str(6, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for $1"));
5320 5321 5322 5323 5324
			this->argsresult = NULL;

			thisquery->type = &ecpg_query;
			thisquery->brace_level = 0;
			thisquery->next = NULL;
5325 5326
			thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(, , __LINE__)") + strlen(con) + strlen($7));
			sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7);
5327 5328

			this->argsinsert = NULL;
5329
			add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
5330 5331 5332 5333 5334

			cur = this;

			$$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
		}
5335
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
5336

5337 5338 5339 5340 5341 5342
ECPGExecuteImmediateStmt: EXECUTE IMMEDIATE execstring
			{ 
			  /* execute immediate means prepare the statement and
			   * immediately execute it */
			  $$ = $3;
			};
5343
/*
5344 5345 5346 5347 5348
 * variable decalartion outside exec sql declare block
 */
ECPGVarDeclaration: single_vt_declaration;

single_vt_declaration: type_declaration		{ $$ = $1; }
5349
		| var_declaration		{ $$ = $1; }
5350 5351
		;

5352 5353 5354 5355 5356 5357
precision:	NumConst	{ $$ = $1; };

opt_scale:	',' NumConst	{ $$ = $2; }
		| /* EMPTY */	{ $$ = EMPTY; }
		;

5358 5359
ecpg_interval:	opt_interval	{ $$ = $1; }
		| YEAR_P TO MINUTE_P	{ $$ = make_str("year to minute"); }
Michael Meskes's avatar
Michael Meskes committed
5360
		| YEAR_P TO SECOND_P	{ $$ = make_str("year to second"); }
5361
		| DAY_P TO DAY_P		{ $$ = make_str("day to day"); }
5362 5363 5364
		| MONTH_P TO MONTH_P	{ $$ = make_str("month to month"); }
		;

5365
/*
5366
 * variable declaration inside exec sql declare block
5367 5368
 */
ECPGDeclaration: sql_startdeclare
5369
		{ fputs("/* exec sql begin declare section */", yyout); }
5370
		var_type_declarations sql_enddeclare
5371 5372 5373 5374 5375 5376
		{
			fprintf(yyout, "%s/* exec sql end declare section */", $3);
			free($3);
			output_line_number();
		}
		;
5377

5378
sql_startdeclare: ecpgstart BEGIN_P DECLARE SQL_SECTION ';' {};
5379

5380
sql_enddeclare: ecpgstart END_P DECLARE SQL_SECTION ';' {};
5381

5382 5383
var_type_declarations:	/*EMPTY*/			{ $$ = EMPTY; }
		| vt_declarations			{ $$ = $1; }
5384
		| CPP_LINE				{ $$ = $1; }
5385
		;
Michael Meskes's avatar
Michael Meskes committed
5386

5387
vt_declarations:  var_declaration			{ $$ = $1; }
5388
		| type_declaration			{ $$ = $1; }
5389 5390
		| vt_declarations var_declaration	{ $$ = cat2_str($1, $2); }
		| vt_declarations type_declaration	{ $$ = cat2_str($1, $2); }
5391
		| vt_declarations CPP_LINE		{ $$ = cat2_str($1, $2); }
5392
		;
5393

5394 5395
variable_declarations:	var_declaration 	{ $$ = $1; }
		| variable_declarations var_declaration 	{ $$ = cat2_str($1, $2); }
5396 5397 5398 5399 5400 5401 5402 5403
		;

type_declaration: S_TYPEDEF
	{
		/* reset this variable so we see if there was */
		/* an initializer specified */
		initializer = 0;
	}
5404
	var_type opt_pointer ECPGColLabelCommon opt_array_bounds ';'
5405
	{
5406
		add_typedef($5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *$4 ? 1 : 0);
5407

5408
		fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4 ? "*" : "", $5, $6.str);
5409 5410 5411 5412
		output_line_number();
		$$ = make_str("");
	};

5413
var_declaration: storage_declaration
5414
		var_type
5415
		{
5416 5417 5418 5419
			actual_type[struct_level].type_enum = $2.type_enum;
			actual_type[struct_level].type_dimension = $2.type_dimension;
			actual_type[struct_level].type_index = $2.type_index;
			actual_type[struct_level].type_sizeof = $2.type_sizeof;
5420 5421

			actual_startline[struct_level] = hashline_number();
5422
		}
5423
		variable_list ';'
Michael Meskes's avatar
Michael Meskes committed
5424
		{
5425
			$$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, make_str(";\n"));
5426
		}
5427 5428 5429 5430 5431 5432
		| var_type
		{
			actual_type[struct_level].type_enum = $1.type_enum;
			actual_type[struct_level].type_dimension = $1.type_dimension;
			actual_type[struct_level].type_index = $1.type_index;
			actual_type[struct_level].type_sizeof = $1.type_sizeof;
5433

5434 5435
			actual_startline[struct_level] = hashline_number();
		}
5436
		variable_list ';'
5437
		{
5438
			$$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, make_str(";\n"));
5439 5440 5441
		}
		| struct_union_type_with_symbol ';'
		{
5442
			$$ = cat2_str($1, make_str(";"));
5443
		}
5444 5445
		;

5446 5447 5448 5449
opt_bit_field:	':' Iconst	{ $$ =cat2_str(make_str(":"), $2); }
		| /* EMPTY */	{ $$ = EMPTY; }
		;

5450
storage_declaration: storage_clause storage_modifier
5451 5452 5453
			{$$ = cat2_str ($1, $2); }
		| storage_clause		{$$ = $1; }
		| storage_modifier		{$$ = $1; }
5454
		;
5455

5456 5457
storage_clause : S_EXTERN	{ $$ = make_str("extern"); }
		| S_STATIC			{ $$ = make_str("static"); }
5458
		| S_REGISTER		{ $$ = make_str("register"); }
5459
		| S_AUTO			{ $$ = make_str("auto"); }
5460
		;
5461

5462
storage_modifier : S_CONST	{ $$ = make_str("const"); }
5463
		| S_VOLATILE		{ $$ = make_str("volatile"); }
5464
		;
Michael Meskes's avatar
Michael Meskes committed
5465

5466
var_type:	simple_type
5467 5468
		{
			$$.type_enum = $1;
5469
			$$.type_str = mm_strdup(ecpg_type_name($1));
5470 5471
			$$.type_dimension = make_str("-1");
			$$.type_index = make_str("-1");
5472
			$$.type_sizeof = NULL;
5473
		}
5474
		| struct_union_type
5475 5476
		{
			$$.type_str = $1;
5477 5478
			$$.type_dimension = make_str("-1");
			$$.type_index = make_str("-1");
5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489

			if (strncmp($1, "struct", sizeof("struct")-1) == 0)
			{
				$$.type_enum = ECPGt_struct;
				$$.type_sizeof = ECPGstruct_sizeof;
			}
			else
			{
				$$.type_enum = ECPGt_union;
				$$.type_sizeof = NULL;
			}
5490
		}
5491
		| enum_type
5492 5493 5494
		{
			$$.type_str = $1;
			$$.type_enum = ECPGt_int;
5495 5496
			$$.type_dimension = make_str("-1");
			$$.type_index = make_str("-1");
5497
			$$.type_sizeof = NULL;
5498
		}
5499 5500
		| ECPGColLabelCommon '(' precision opt_scale ')'
		{
5501 5502 5503
			if (strcmp($1, "numeric") == 0)
			{
				$$.type_enum = ECPGt_numeric;
5504
				$$.type_str = make_str("numeric");
5505 5506 5507 5508
			}
			else if (strcmp($1, "decimal") == 0)
			{
				$$.type_enum = ECPGt_decimal;
5509
				$$.type_str = make_str("decimal");
5510 5511
			}
			else
5512
			{
5513
				mmerror(PARSE_ERROR, ET_ERROR, "only numeric/decimal have precision/scale argument");
5514 5515 5516
				$$.type_enum = ECPGt_numeric;
				$$.type_str = make_str("numeric");
			}
5517

5518 5519
			$$.type_dimension = make_str("-1");
			$$.type_index = make_str("-1");
5520 5521
			$$.type_sizeof = NULL;
		}
5522
		| ECPGColLabelCommon ecpg_interval
5523
		{
5524
			if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0)
5525
				mmerror (PARSE_ERROR, ET_ERROR, "interval specification not allowed here");
5526

5527 5528 5529 5530 5531 5532 5533
			/*
			 * Check for type names that the SQL grammar treats as
			 * unreserved keywords
			 */
			if (strcmp($1, "varchar") == 0)
			{
				$$.type_enum = ECPGt_varchar;
5534
				$$.type_str = EMPTY; /*make_str("varchar");*/
5535 5536
				$$.type_dimension = make_str("-1");
				$$.type_index = make_str("-1");
5537
				$$.type_sizeof = NULL;
5538 5539 5540 5541 5542
			}
			else if (strcmp($1, "float") == 0)
			{
				$$.type_enum = ECPGt_float;
				$$.type_str = make_str("float");
5543 5544
				$$.type_dimension = make_str("-1");
				$$.type_index = make_str("-1");
5545
				$$.type_sizeof = NULL;
5546 5547 5548 5549 5550
			}
			else if (strcmp($1, "double") == 0)
			{
				$$.type_enum = ECPGt_double;
				$$.type_str = make_str("double");
5551 5552
				$$.type_dimension = make_str("-1");
				$$.type_index = make_str("-1");
5553
				$$.type_sizeof = NULL;
5554
			}
5555 5556 5557
			else if (strcmp($1, "numeric") == 0)
			{
				$$.type_enum = ECPGt_numeric;
5558
				$$.type_str = make_str("numeric");
5559 5560
				$$.type_dimension = make_str("-1");
				$$.type_index = make_str("-1");
5561 5562 5563 5564
				$$.type_sizeof = NULL;
			}
			else if (strcmp($1, "decimal") == 0)
			{
5565
				$$.type_enum = ECPGt_decimal;
5566
				$$.type_str = make_str("decimal");
5567 5568
				$$.type_dimension = make_str("-1");
				$$.type_index = make_str("-1");
5569 5570
				$$.type_sizeof = NULL;
			}
5571 5572 5573
			else if (strcmp($1, "date") == 0)
			{
				$$.type_enum = ECPGt_date;
5574
				$$.type_str = make_str("date");
5575 5576
				$$.type_dimension = make_str("-1");
				$$.type_index = make_str("-1");
5577 5578 5579 5580 5581
				$$.type_sizeof = NULL;
			}
			else if (strcmp($1, "timestamp") == 0)
			{
				$$.type_enum = ECPGt_timestamp;
5582
				$$.type_str = make_str("timestamp");
5583 5584
				$$.type_dimension = make_str("-1");
				$$.type_index = make_str("-1");
5585 5586
				$$.type_sizeof = NULL;
			}
5587 5588
			else if (strcmp($1, "interval") == 0)
			{
5589
				$$.type_enum = ECPGt_interval;
5590
				$$.type_str = make_str("interval");
5591 5592
				$$.type_dimension = make_str("-1");
				$$.type_index = make_str("-1");
5593 5594 5595 5596 5597
				$$.type_sizeof = NULL;
			}
			else if (strcmp($1, "datetime") == 0)
			{
				$$.type_enum = ECPGt_timestamp;
5598
				$$.type_str = make_str("timestamp");
5599 5600
				$$.type_dimension = make_str("-1");
				$$.type_index = make_str("-1");
5601 5602
				$$.type_sizeof = NULL;
			}
5603 5604 5605 5606 5607 5608 5609 5610 5611
			else
			{
				/* this is for typedef'ed types */
				struct typedefs *this = get_typedef($1);

				$$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
				$$.type_enum = this->type->type_enum;
				$$.type_dimension = this->type->type_dimension;
				$$.type_index = this->type->type_index;
5612 5613 5614 5615 5616
				if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
					$$.type_sizeof = this->type->type_sizeof;
				else 
					$$.type_sizeof = cat_str(3, make_str("sizeof("), mm_strdup(this->name), make_str(")"));

5617 5618
				struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
			}
5619
		}
5620 5621 5622
		| s_struct_union_symbol
		{
			/* this is for named structs/unions */
5623 5624
			char *name;
			struct typedefs *this;
5625
			bool forward = (forward_name != NULL && strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
5626 5627 5628 5629 5630 5631

			name = cat2_str($1.su, $1.symbol);
			/* Do we have a forward definition? */
			if (!forward)
			{
				/* No */
5632

5633 5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644
				this = get_typedef(name);
				$$.type_str = mm_strdup(this->name);
				$$.type_enum = this->type->type_enum;
				$$.type_dimension = this->type->type_dimension;
				$$.type_index = this->type->type_index;
				$$.type_sizeof = this->type->type_sizeof;
				struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
				free(name);
			}
			else
			{
				$$.type_str = name;
5645 5646 5647 5648 5649
				$$.type_enum = ECPGt_long;
				$$.type_dimension = make_str("-1");
				$$.type_index = make_str("-1");
				$$.type_sizeof = make_str("");
				struct_member_list[struct_level] = NULL;
5650
			}
5651
		}
5652
		;
5653

5654
enum_type: ENUM_P symbol enum_definition
5655
			{ $$ = cat_str(3, make_str("enum"), $2, $3); }
5656
		| ENUM_P enum_definition
5657
			{ $$ = cat2_str(make_str("enum"), $2); }
5658
		| ENUM_P symbol
5659 5660
			{ $$ = cat2_str(make_str("enum"), $2); }
		;
Michael Meskes's avatar
Michael Meskes committed
5661

5662 5663
enum_definition: '{' c_list '}'
			{ $$ = cat_str(3, make_str("{"), $2, make_str("}")); };
5664

5665 5666 5667 5668
struct_union_type_with_symbol: s_struct_union_symbol
		{
			struct_member_list[struct_level++] = NULL;
			if (struct_level >= STRUCT_DEPTH)
5669
				 mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");
5670
			forward_name = mm_strdup($1.symbol);
5671
		}
5672
		'{' variable_declarations '}'
5673
		{
5674 5675
			struct typedefs *ptr, *this;
			struct this_type su_type;
5676

5677
			ECPGfree_struct_member(struct_member_list[struct_level]);
5678
			struct_member_list[struct_level] = NULL;
5679
			struct_level--;
5680
			if (strncmp($1.su, "struct", sizeof("struct")-1) == 0)
5681
				su_type.type_enum = ECPGt_struct;
5682
			else
5683 5684
				su_type.type_enum = ECPGt_union;
			su_type.type_str = cat2_str($1.su, $1.symbol);
5685 5686
			free(forward_name);
			forward_name = NULL;
5687

5688 5689 5690
			/* This is essantially a typedef but needs the keyword struct/union as well.
			 * So we create the typedef for each struct definition with symbol */
			for (ptr = types; ptr != NULL; ptr = ptr->next)
5691 5692 5693
			{
					if (strcmp(su_type.type_str, ptr->name) == 0)
							/* re-definition is a bug */
5694
							mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" already defined", su_type.type_str);
5695
			}
5696

5697
			this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
5698

5699 5700
			/* initial definition */
			this->next = types;
5701
			this->name = mm_strdup(su_type.type_str);
5702
			this->brace_level = braces_open;
5703 5704 5705 5706 5707 5708 5709
			this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
			this->type->type_enum = su_type.type_enum;
			this->type->type_str = mm_strdup(su_type.type_str);
			this->type->type_dimension = make_str("-1"); /* dimension of array */
			this->type->type_index = make_str("-1");	/* length of string */
			this->type->type_sizeof = ECPGstruct_sizeof;
			this->struct_member_list = struct_member_list[struct_level];
5710 5711 5712

			types = this;
			$$ = cat_str(4, su_type.type_str, make_str("{"), $4, make_str("}"));
5713 5714
		}
		;
5715

5716
struct_union_type: struct_union_type_with_symbol	{ $$ = $1; }
5717 5718 5719 5720
		| s_struct_union
		{
			struct_member_list[struct_level++] = NULL;
			if (struct_level >= STRUCT_DEPTH)
5721
				 mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");
5722 5723
		}
		'{' variable_declarations '}'
5724 5725
		{
			ECPGfree_struct_member(struct_member_list[struct_level]);
5726
			struct_member_list[struct_level] = NULL;
5727
			struct_level--;
5728
			$$ = cat_str(4, $1, make_str("{"), $4, make_str("}"));
5729 5730
		}
		;
5731

5732
s_struct_union_symbol: SQL_STRUCT symbol
5733
		{
5734 5735
			$$.su = make_str("struct");
			$$.symbol = $2;
5736
			ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), make_str(")"));
5737
		}
5738
		| UNION symbol
5739
		{
5740 5741
			$$.su = make_str("union");
			$$.symbol = $2;
5742 5743
		}
		;
5744

5745
s_struct_union: SQL_STRUCT
5746 5747 5748 5749
		{
			ECPGstruct_sizeof = make_str(""); /* This must not be NULL to distinguish from simple types. */
			$$ = make_str("struct");
		}
5750 5751 5752
		| UNION 	{ $$ = make_str("union"); }
		;

5753 5754 5755
simple_type: unsigned_type					{ $$=$1; }
		|	opt_signed signed_type			{ $$=$2; }
		;
5756

5757
unsigned_type: SQL_UNSIGNED SQL_SHORT		{ $$ = ECPGt_unsigned_short; }
5758
		| SQL_UNSIGNED SQL_SHORT INT_P	{ $$ = ECPGt_unsigned_short; }
5759
		| SQL_UNSIGNED						{ $$ = ECPGt_unsigned_int; }
5760
		| SQL_UNSIGNED INT_P				{ $$ = ECPGt_unsigned_int; }
Michael Meskes's avatar
Michael Meskes committed
5761
		| SQL_UNSIGNED SQL_LONG				{ $$ = ECPGt_unsigned_long; }
5762
		| SQL_UNSIGNED SQL_LONG INT_P		{ $$ = ECPGt_unsigned_long; }
5763 5764
		| SQL_UNSIGNED SQL_LONG SQL_LONG
		{
5765
#ifdef HAVE_LONG_LONG_INT_64
5766
			$$ = ECPGt_unsigned_long_long;
5767
#else
5768
			$$ = ECPGt_unsigned_long;
5769
#endif
5770
		}
5771
		| SQL_UNSIGNED SQL_LONG SQL_LONG INT_P
5772
		{
5773
#ifdef HAVE_LONG_LONG_INT_64
5774
			$$ = ECPGt_unsigned_long_long;
5775
#else
5776
			$$ = ECPGt_unsigned_long;
5777
#endif
5778
		}
Jan Wieck's avatar
Jan Wieck committed
5779
		| SQL_UNSIGNED CHAR_P			{ $$ = ECPGt_unsigned_char; }
Michael Meskes's avatar
Michael Meskes committed
5780 5781
		;

5782
signed_type: SQL_SHORT				{ $$ = ECPGt_short; }
5783
		| SQL_SHORT INT_P			{ $$ = ECPGt_short; }
5784
		| INT_P						{ $$ = ECPGt_int; }
5785
		| SQL_LONG					{ $$ = ECPGt_long; }
5786
		| SQL_LONG INT_P			{ $$ = ECPGt_long; }
5787 5788
		| SQL_LONG SQL_LONG
		{
5789
#ifdef HAVE_LONG_LONG_INT_64
5790
			$$ = ECPGt_long_long;
5791
#else
5792
			$$ = ECPGt_long;
5793
#endif
5794
		}
5795
		| SQL_LONG SQL_LONG INT_P
5796
		{
5797
#ifdef HAVE_LONG_LONG_INT_64
5798
			$$ = ECPGt_long_long;
5799
#else
5800
			$$ = ECPGt_long;
5801
#endif
5802 5803
		}
		| SQL_BOOL					{ $$ = ECPGt_bool; }
Jan Wieck's avatar
Jan Wieck committed
5804
		| CHAR_P					{ $$ = ECPGt_char; }
5805
		| DOUBLE_P					{ $$ = ECPGt_double; }
5806
		;
Michael Meskes's avatar
Michael Meskes committed
5807

5808 5809 5810
opt_signed: SQL_SIGNED
		|	/* EMPTY */
		;
Michael Meskes's avatar
Michael Meskes committed
5811

5812 5813 5814 5815 5816
variable_list: variable
			{ $$ = $1; }
		| variable_list ',' variable
			{ $$ = cat_str(3, $1, make_str(","), $3); }
		;
5817

5818
variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initializer
5819 5820
		{
			struct ECPGtype * type;
5821
			char *dimension = $3.index1; /* dimension of array */
5822
			char *length = $3.index2;    /* length of string */
5823
			char dim[14L];
5824
			char *vcn;
5825

5826
			adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1), false);
5827 5828 5829

			switch (actual_type[struct_level].type_enum)
			{
5830 5831
				case ECPGt_struct:
				case ECPGt_union:
5832
					if (atoi(dimension) < 0)
5833
						type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof);
5834
					else
5835
						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);
5836

5837
					$$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
5838 5839 5840
					break;

				case ECPGt_varchar:
5841
					if (atoi(dimension) < 0)
5842
						type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, yylineno);
5843
					else
5844 5845
						type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, yylineno), dimension);
					
5846
					if (strcmp(dimension, "0") == 0 || abs(atoi(dimension)) == 1)
5847
							*dim = '\0';
5848
					else
5849
							sprintf(dim, "[%s]", dimension);
5850 5851
					/* cannot check for atoi <= 0 because a defined constant will yield 0 here as well */
					if (atoi(length) < 0 || strcmp(length, "0") == 0)
5852 5853
						mmerror(PARSE_ERROR, ET_ERROR, "pointer to varchar are not implemented");

5854 5855 5856
					/* make sure varchar struct name is unique by adding linenumer of its definition */
					vcn = (char *) mm_alloc(strlen($2) + sizeof(int) * CHAR_BIT * 10 / 3);
					sprintf(vcn, "%s_%d", $2, yylineno);
5857
					if (strcmp(dimension, "0") == 0)
5858
						$$ = cat_str(7, make2_str(make_str(" struct varchar_"), vcn), make_str(" { int len; char arr["), mm_strdup(length), make_str("]; } *"), mm_strdup($2), $4, $5);
5859
					else
5860
						$$ = cat_str(8, make2_str(make_str(" struct varchar_"), vcn), make_str(" { int len; char arr["), mm_strdup(length), make_str("]; } "), mm_strdup($2), mm_strdup(dim), $4, $5);
5861 5862 5863 5864
					break;

				case ECPGt_char:
				case ECPGt_unsigned_char:
5865
					if (atoi(dimension) == -1)
5866 5867 5868 5869 5870 5871 5872 5873
					{
						int i = strlen($5);

						if (atoi(length) == -1 && i > 0) /* char <var>[] = "string" */
						{
							/* if we have an initializer but no string size set, let's use the initializer's length */
							free(length);
							length = mm_alloc(i+sizeof("sizeof()"));
5874
							sprintf(length, "sizeof(%s)", $5+2);
5875
						}
5876
						type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0);
5877
					}
5878
					else
5879
						type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0), dimension);
5880

5881
					$$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
5882 5883 5884
					break;

				default:
5885
					if (atoi(dimension) < 0)
5886
						type = ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"), 0);
5887
					else
5888
						type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"), 0), dimension);
5889

5890
					$$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
5891
					break;
5892 5893 5894
			}

			if (struct_level == 0)
5895
				new_variable($2, type, braces_open);
5896 5897 5898 5899
			else
				ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]));

			free($2);
5900 5901
		}
		;
5902

5903 5904 5905 5906 5907 5908 5909 5910
opt_initializer: /*EMPTY*/
			{ $$ = EMPTY; }
		| '=' c_term
		{
			initializer = 1;
			$$ = cat2_str(make_str("="), $2);
		}
		;
5911

5912 5913 5914 5915
opt_pointer: /*EMPTY*/				{ $$ = EMPTY; }
		| '*'						{ $$ = make_str("*"); }
		| '*' '*'					{ $$ = make_str("**"); }
		;
5916 5917

/*
5918
 * We try to simulate the correct DECLARE syntax here so we get dynamic SQL
5919 5920
 */
ECPGDeclare: DECLARE STATEMENT ident
5921 5922 5923 5924 5925
		{
			/* this is only supported for compatibility */
			$$ = cat_str(3, make_str("/* declare statement"), $3, make_str("*/"));
		}
		;
5926
/*
5927
 * the exec sql disconnect statement: disconnect from the given database
5928 5929
 */
ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; }
5930
		;
5931

5932
dis_name: connection_object			{ $$ = $1; }
5933
		| CURRENT_P			{ $$ = make_str("\"CURRENT\""); }
5934 5935
		| ALL				{ $$ = make_str("\"ALL\""); }
		| /* EMPTY */			{ $$ = make_str("\"CURRENT\""); }
5936
		;
5937

5938 5939 5940
connection_object: database_name		{ $$ = make3_str(make_str("\""), $1, make_str("\"")); }
		| DEFAULT			{ $$ = make_str("\"DEFAULT\""); }
		| char_variable			{ $$ = $1; }
5941
		;
5942

Michael Meskes's avatar
Michael Meskes committed
5943 5944 5945 5946 5947 5948 5949
execute_rest:	ecpg_using ecpg_into	{ $$ = EMPTY; }
		| ecpg_into ecpg_using	{ $$ = EMPTY; }
		| ecpg_using		{ $$ = EMPTY; }
		| ecpg_into 		{ $$ = EMPTY; }
		| /* EMPTY */		{ $$ = EMPTY; }
		;

5950 5951 5952 5953 5954
execstring: char_variable
			{ $$ = $1; }
		|	CSTRING
			{ $$ = make3_str(make_str("\""), $1, make_str("\"")); }
		;
5955

5956 5957 5958 5959 5960 5961 5962 5963
prepared_name: name	 	{ 
					if ($1[0] == '\"' && $1[strlen($1)-1] == '\"') /* already quoted? */
						$$ = $1;
					else /* not quoted => convert to lowercase */
					{
						int i;

						for (i = 0; i< strlen($1); i++)
5964
							$1[i] = tolower((unsigned char) $1[i]);
5965 5966 5967 5968

						$$ = make3_str(make_str("\""), $1, make_str("\""));
					}
				}
5969
		| char_variable	{ $$ = $1; }
5970
		;
5971

5972 5973 5974 5975
/*
 * the exec sql free command to deallocate a previously
 * prepared statement
 */
5976 5977 5978
ECPGFree:	SQL_FREE name	{ $$ = $2; }
		| SQL_FREE ALL	{ $$ = make_str("all"); }
		;
5979 5980 5981 5982

/*
 * open is an open cursor, at the moment this has to be removed
 */
5983
ECPGOpen: SQL_OPEN name opt_ecpg_using { $$ = $2; };
5984

5985
opt_ecpg_using: /*EMPTY*/	{ $$ = EMPTY; }
Michael Meskes's avatar
Michael Meskes committed
5986 5987 5988 5989
		| ecpg_using		{ $$ = $1; }
		;

ecpg_using:	USING using_list 	{ $$ = EMPTY; }
5990
		| using_descriptor      { $$ = $1; }
5991
		;
5992

5993
using_descriptor: USING opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
5994
		{
5995
			add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator);
5996 5997
			$$ = EMPTY;
		}
5998 5999 6000
		;

into_descriptor: INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
6001
		{
6002
			add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator);
6003 6004 6005
			$$ = EMPTY;
		}
		;
6006

6007 6008
opt_sql: /*EMPTY*/ | SQL_SQL;

Michael Meskes's avatar
Michael Meskes committed
6009
ecpg_into: INTO into_list		{ $$ = EMPTY; }
6010
		| into_descriptor	{ $$ = $1; }
6011
		;
6012

6013 6014 6015 6016
using_list: UsingConst | UsingConst ',' using_list;

UsingConst: AllConst
		{
6017
			if ($1[1] != '$') /* found a constant */
6018
			{
6019
				char *length = mm_alloc(32);
6020

6021
				sprintf(length, "%d", (int) strlen($1));
6022
				add_variable_to_head(&argsinsert, new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator);
6023 6024
			}
		}
6025
		| civarind { $$ = EMPTY; }
6026
		;
6027

6028

6029
/*
6030 6031
 * We accept descibe but do nothing with it so far.
 */
6032
ECPGDescribe: SQL_DESCRIBE INPUT_P name using_descriptor
Michael Meskes's avatar
Michael Meskes committed
6033
	{
6034
		const char *con = connection ? connection : "NULL";
6035
		mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n");
6036 6037
		$$ = (char *) mm_alloc(sizeof("1, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
		sprintf($$, "1, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
6038 6039 6040
	}
	| SQL_DESCRIBE opt_output name using_descriptor
	{
6041
		const char *con = connection ? connection : "NULL";
6042
		mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n");
6043 6044
		$$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
		sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
6045 6046 6047
	}
	| SQL_DESCRIBE opt_output name into_descriptor
	{
6048
		const char *con = connection ? connection : "NULL";
6049
		mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n");
6050 6051
		$$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
		sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
6052 6053
	}
	;
6054

6055 6056 6057
opt_output:	SQL_OUTPUT	{ $$ = make_str("output"); }
	| 	/* EMPTY */	{ $$ = EMPTY; }
	;
6058

Michael Meskes's avatar
Michael Meskes committed
6059 6060
/*
 * dynamic SQL: descriptor based access
6061 6062
 *	originall written by Christof Petig <christof.petig@wtal.de>
 *			and Peter Eisentraut <peter.eisentraut@credativ.de>
Michael Meskes's avatar
Michael Meskes committed
6063 6064
 */

6065 6066 6067 6068
/*
 * allocate a descriptor
 */
ECPGAllocateDescr:     SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
6069 6070 6071 6072 6073
		{
			add_descriptor($3,connection);
			$$ = $3;
		}
		;
6074

6075

Michael Meskes's avatar
Michael Meskes committed
6076 6077 6078
/*
 * deallocate a descriptor
 */
6079
ECPGDeallocateDescr:	DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
Michael Meskes's avatar
Michael Meskes committed
6080 6081 6082
		{
			drop_descriptor($3,connection);
			$$ = $3;
6083 6084
		}
		;
Michael Meskes's avatar
Michael Meskes committed
6085 6086

/*
6087
 * manipulate a descriptor header
Michael Meskes's avatar
Michael Meskes committed
6088 6089
 */

Michael Meskes's avatar
Michael Meskes committed
6090
ECPGGetDescriptorHeader: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems
6091 6092
			{  $$ = $3; }
		;
Michael Meskes's avatar
Michael Meskes committed
6093

6094 6095 6096 6097
ECPGGetDescHeaderItems: ECPGGetDescHeaderItem
		| ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem
		;

6098
ECPGGetDescHeaderItem: cvariable '=' desc_header_item
6099 6100
			{ push_assignment($1, $3); }
		;
Michael Meskes's avatar
Michael Meskes committed
6101

6102 6103 6104

ECPGSetDescriptorHeader: SET SQL_DESCRIPTOR quoted_ident_stringvar ECPGSetDescHeaderItems
			{ $$ = $3; }
6105
		;
6106 6107 6108 6109 6110

ECPGSetDescHeaderItems: ECPGSetDescHeaderItem
		| ECPGSetDescHeaderItems ',' ECPGSetDescHeaderItem
		;

6111
ECPGSetDescHeaderItem: desc_header_item '=' IntConstVar
6112
		{
6113 6114
			push_assignment($3, $1);
		}
6115
		;
Michael Meskes's avatar
Michael Meskes committed
6116

Michael Meskes's avatar
Michael Meskes committed
6117

6118
desc_header_item:	SQL_COUNT			{ $$ = ECPGd_count; }
Michael Meskes's avatar
Michael Meskes committed
6119 6120
		;

6121 6122 6123 6124
/*
 * manipulate a descriptor
 */

Michael Meskes's avatar
Michael Meskes committed
6125
ECPGGetDescriptor:	SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGGetDescItems
6126
			{  $$.str = $5; $$.name = $3; }
6127 6128
		;

Michael Meskes's avatar
Michael Meskes committed
6129
ECPGGetDescItems: ECPGGetDescItem
6130 6131 6132
		| ECPGGetDescItems ',' ECPGGetDescItem
		;

6133
ECPGGetDescItem: cvariable '=' descriptor_item	{ push_assignment($1, $3); };
6134

6135

6136
ECPGSetDescriptor:	SET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGSetDescItems
6137 6138
			{  $$.str = $5; $$.name = $3; }
		;
Michael Meskes's avatar
Michael Meskes committed
6139

6140 6141 6142 6143
ECPGSetDescItems: ECPGSetDescItem
		| ECPGSetDescItems ',' ECPGSetDescItem
		;

6144
ECPGSetDescItem: descriptor_item '=' AllConstVar
6145 6146 6147 6148
		{
			push_assignment($3, $1);
		}
		;
6149 6150 6151


descriptor_item:	SQL_CARDINALITY			{ $$ = ECPGd_cardinality; }
6152
		| DATA_P				{ $$ = ECPGd_data; }
6153 6154
		| SQL_DATETIME_INTERVAL_CODE		{ $$ = ECPGd_di_code; }
		| SQL_DATETIME_INTERVAL_PRECISION 	{ $$ = ECPGd_di_precision; }
6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165
		| SQL_INDICATOR				{ $$ = ECPGd_indicator; }
		| SQL_KEY_MEMBER			{ $$ = ECPGd_key_member; }
		| SQL_LENGTH				{ $$ = ECPGd_length; }
		| NAME_P				{ $$ = ECPGd_name; }
		| SQL_NULLABLE				{ $$ = ECPGd_nullable; }
		| SQL_OCTET_LENGTH			{ $$ = ECPGd_octet; }
		| PRECISION				{ $$ = ECPGd_precision; }
		| SQL_RETURNED_LENGTH			{ $$ = ECPGd_length; }
		| SQL_RETURNED_OCTET_LENGTH		{ $$ = ECPGd_ret_octet; }
		| SQL_SCALE				{ $$ = ECPGd_scale; }
		| TYPE_P				{ $$ = ECPGd_type; }
6166 6167
		;

6168
/*
Michael Meskes's avatar
Michael Meskes committed
6169 6170 6171
 * set/reset the automatic transaction mode, this needs a differnet handling
 * as the other set commands
 */
6172 6173
ECPGSetAutocommit:	SET SQL_AUTOCOMMIT '=' on_off	{ $$ = $4; }
		|  SET SQL_AUTOCOMMIT TO on_off   { $$ = $4; }
6174
		;
Michael Meskes's avatar
Michael Meskes committed
6175

6176 6177 6178
on_off: ON				{ $$ = make_str("on"); }
		| OFF			{ $$ = make_str("off"); }
		;
Michael Meskes's avatar
Michael Meskes committed
6179

6180
/*
6181 6182 6183
 * set the actual connection, this needs a differnet handling as the other
 * set commands
 */
6184 6185 6186
ECPGSetConnection:	SET CONNECTION TO connection_object { $$ = $4; }
		| SET CONNECTION '=' connection_object { $$ = $4; }
		| SET CONNECTION  connection_object { $$ = $3; }
6187
		;
6188 6189 6190 6191

/*
 * define a new type for embedded SQL
 */
6192 6193
ECPGTypedef: TYPE_P
		{
6194 6195 6196
			/* reset this variable so we see if there was */
			/* an initializer specified */
			initializer = 0;
6197
		}
6198
		ECPGColLabelCommon IS var_type opt_array_bounds opt_reference
6199
		{
6200
			add_typedef($3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *$7 ? 1 : 0);
6201

6202 6203 6204 6205
			if (auto_create_c == false)
				$$ = 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("*/"));
			else
				$$ = 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(";"));
6206 6207
		}
		;
6208

6209 6210 6211
opt_reference: SQL_REFERENCE 		{ $$ = make_str("reference"); }
		| /*EMPTY*/		 			{ $$ = EMPTY; }
		;
6212 6213 6214 6215

/*
 * define the type of one variable for embedded SQL
 */
6216 6217
ECPGVar: SQL_VAR
		{
6218 6219 6220
			/* reset this variable so we see if there was */
			/* an initializer specified */
			initializer = 0;
6221
		}
6222
		ColLabel IS var_type opt_array_bounds opt_reference
6223
		{
6224
			struct variable *p = find_variable($3);
6225 6226
			char *dimension = $6.index1;
			char *length = $6.index2;
6227
			struct ECPGtype * type;
6228

6229 6230 6231
			if (($5.type_enum == ECPGt_struct ||
				 $5.type_enum == ECPGt_union) &&
				initializer == 1)
6232
				mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in EXEC SQL VAR command");
6233
			else
6234
			{
6235
				adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false);
6236 6237 6238 6239 6240

				switch ($5.type_enum)
				{
					case ECPGt_struct:
					case ECPGt_union:
6241
						if (atoi(dimension) < 0)
6242
							type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_sizeof);
6243
						else
6244
							type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum,$5.type_sizeof), dimension);
6245 6246 6247
						break;

					case ECPGt_varchar:
6248
						if (atoi(dimension) == -1)
6249
							type = ECPGmake_simple_type($5.type_enum, length, 0);
6250
						else
6251
							type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension);
6252
						break;
6253

6254 6255
					case ECPGt_char:
					case ECPGt_unsigned_char:
6256
						if (atoi(dimension) == -1)
6257
							type = ECPGmake_simple_type($5.type_enum, length, 0);
6258
						else
6259
							type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension);
6260 6261 6262
						break;

					default:
6263
						if (atoi(length) >= 0)
6264
							mmerror(PARSE_ERROR, ET_ERROR, "no multidimensional array support for simple data types");
6265

6266
						if (atoi(dimension) < 0)
6267
							type = ECPGmake_simple_type($5.type_enum, make_str("1"), 0);
6268
						else
6269
							type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, make_str("1"), 0), dimension);
6270 6271 6272 6273 6274 6275 6276 6277 6278 6279
						break;
				}

				ECPGfree_type(p->type);
				p->type = type;
			}

			$$ = 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("*/"));
		}
		;
6280

Marc G. Fournier's avatar
Marc G. Fournier committed
6281
/*
6282
 * whenever statement: decide what to do in case of error/no data found
6283
 * according to SQL standards we lack: SQLSTATE, CONSTRAINT and SQLEXCEPTION
Marc G. Fournier's avatar
Marc G. Fournier committed
6284
 */
Michael Meskes's avatar
Michael Meskes committed
6285
ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action
6286 6287 6288
		{
			when_error.code = $<action>3.code;
			when_error.command = $<action>3.command;
6289
			$$ = cat_str(3, make_str("/* exec sql whenever sqlerror "), $3.str, make_str("; */"));
6290 6291 6292 6293 6294
		}
		| SQL_WHENEVER NOT SQL_FOUND action
		{
			when_nf.code = $<action>4.code;
			when_nf.command = $<action>4.command;
6295
			$$ = cat_str(3, make_str("/* exec sql whenever not found "), $4.str, make_str("; */"));
6296 6297 6298 6299 6300
		}
		| SQL_WHENEVER SQL_SQLWARNING action
		{
			when_warn.code = $<action>3.code;
			when_warn.command = $<action>3.command;
6301
			$$ = cat_str(3, make_str("/* exec sql whenever sql_warning "), $3.str, make_str("; */"));
6302 6303
		}
		;
6304

Michael Meskes's avatar
Michael Meskes committed
6305
action : CONTINUE_P
6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332 6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352
		{
			$<action>$.code = W_NOTHING;
			$<action>$.command = NULL;
			$<action>$.str = make_str("continue");
		}
		| SQL_SQLPRINT
		{
			$<action>$.code = W_SQLPRINT;
			$<action>$.command = NULL;
			$<action>$.str = make_str("sqlprint");
		}
		| SQL_STOP
		{
			$<action>$.code = W_STOP;
			$<action>$.command = NULL;
			$<action>$.str = make_str("stop");
		}
		| SQL_GOTO name
		{
			$<action>$.code = W_GOTO;
			$<action>$.command = strdup($2);
			$<action>$.str = cat2_str(make_str("goto "), $2);
		}
		| SQL_GO TO name
		{
			$<action>$.code = W_GOTO;
			$<action>$.command = strdup($3);
			$<action>$.str = cat2_str(make_str("goto "), $3);
		}
		| DO name '(' c_args ')'
		{
			$<action>$.code = W_DO;
			$<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
			$<action>$.str = cat2_str(make_str("do"), mm_strdup($<action>$.command));
		}
		| DO SQL_BREAK
		{
			$<action>$.code = W_BREAK;
			$<action>$.command = NULL;
			$<action>$.str = make_str("break");
		}
		| SQL_CALL name '(' c_args ')'
		{
			$<action>$.code = W_DO;
			$<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
			$<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
		}
6353
		| SQL_CALL name
6354 6355
		{
			$<action>$.code = W_DO;
6356
			$<action>$.command = cat2_str($2, make_str("()"));
6357 6358
			$<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
		}
6359
		;
6360

6361
/* some other stuff for ecpg */
Michael Meskes's avatar
Michael Meskes committed
6362

6363
/* additional unreserved keywords */
6364 6365 6366 6367 6368
ECPGKeywords: ECPGKeywords_vanames	{ $$ = $1; }
		| ECPGKeywords_rest 	{ $$ = $1; }
		;

ECPGKeywords_vanames:  SQL_BREAK		{ $$ = make_str("break"); }
6369 6370 6371
		| SQL_CALL						{ $$ = make_str("call"); }
		| SQL_CARDINALITY				{ $$ = make_str("cardinality"); }
		| SQL_COUNT						{ $$ = make_str("count"); }
Michael Meskes's avatar
Michael Meskes committed
6372 6373
		| SQL_DATETIME_INTERVAL_CODE	{ $$ = make_str("datetime_interval_code"); }
		| SQL_DATETIME_INTERVAL_PRECISION	{ $$ = make_str("datetime_interval_precision"); }
6374 6375 6376 6377 6378 6379 6380 6381 6382
		| SQL_FOUND						{ $$ = make_str("found"); }
		| SQL_GO						{ $$ = make_str("go"); }
		| SQL_GOTO						{ $$ = make_str("goto"); }
		| SQL_IDENTIFIED				{ $$ = make_str("identified"); }
		| SQL_INDICATOR				{ $$ = make_str("indicator"); }
		| SQL_KEY_MEMBER			{ $$ = make_str("key_member"); }
		| SQL_LENGTH				{ $$ = make_str("length"); }
		| SQL_NULLABLE				{ $$ = make_str("nullable"); }
		| SQL_OCTET_LENGTH			{ $$ = make_str("octet_length"); }
Michael Meskes's avatar
Michael Meskes committed
6383
		| SQL_RETURNED_LENGTH		{ $$ = make_str("returned_length"); }
6384
		| SQL_RETURNED_OCTET_LENGTH	{ $$ = make_str("returned_octet_length"); }
6385 6386
		| SQL_SCALE					{ $$ = make_str("scale"); }
		| SQL_SECTION				{ $$ = make_str("section"); }
6387
		| SQL_SQL				{ $$ = make_str("sql"); }
6388 6389 6390 6391
		| SQL_SQLERROR				{ $$ = make_str("sqlerror"); }
		| SQL_SQLPRINT				{ $$ = make_str("sqlprint"); }
		| SQL_SQLWARNING			{ $$ = make_str("sqlwarning"); }
		| SQL_STOP					{ $$ = make_str("stop"); }
6392
		;
6393

6394 6395 6396 6397 6398 6399
ECPGKeywords_rest:  SQL_CONNECT		{ $$ = make_str("connect"); }
		| SQL_DESCRIBE				{ $$ = make_str("describe"); }
		| SQL_DISCONNECT			{ $$ = make_str("disconnect"); }
		| SQL_OPEN					{ $$ = make_str("open"); }
		| SQL_VAR					{ $$ = make_str("var"); }
		| SQL_WHENEVER				{ $$ = make_str("whenever"); }
Michael Meskes's avatar
Michael Meskes committed
6400 6401
		;

6402
/* additional keywords that can be SQL type names (but not ECPGColLabels) */
6403
ECPGTypeName:  SQL_BOOL				{ $$ = make_str("bool"); }
6404 6405 6406 6407 6408 6409
		| SQL_LONG					{ $$ = make_str("long"); }
		| SQL_OUTPUT				{ $$ = make_str("output"); }
		| SQL_SHORT					{ $$ = make_str("short"); }
		| SQL_STRUCT				{ $$ = make_str("struct"); }
		| SQL_SIGNED				{ $$ = make_str("signed"); }
		| SQL_UNSIGNED				{ $$ = make_str("unsigned"); }
Michael Meskes's avatar
Michael Meskes committed
6410 6411
		;

6412
symbol: ColLabel					{ $$ = $1; }
6413 6414
		;

6415
/*
6416 6417 6418 6419
 * Name classification hierarchy.
 *
 * IDENT is the lexeme returned by the lexer for identifiers that match
 * no known keyword.  In most cases, we can accept certain keywords as
6420
 * names, not only IDENTs.	We prefer to accept as many such keywords
6421 6422 6423 6424 6425
 * as possible to minimize the impact of "reserved words" on programmers.
 * So, we divide names into several possible classes.  The classification
 * is chosen in part to make keywords acceptable as names wherever possible.
 */

6426
ECPGColId:ident					{ $$ = $1; }
6427 6428
		| ECPGunreserved_interval	{ $$ = $1; }
		| ECPGunreserved_con		{ $$ = $1; }
6429 6430 6431 6432 6433
		| col_name_keyword		{ $$ = $1; }
		| ECPGKeywords			{ $$ = $1; }
		| ECPGCKeywords			{ $$ = $1; }
		| CHAR_P			{ $$ = make_str("char"); }
		| VALUES			{ $$ = make_str("values"); }
6434
		;
6435 6436
/* Column identifier --- names that can be column, table, etc names.
 */
6437
ColId:	ident					{ $$ = $1; }
6438
		| unreserved_keyword		{ $$ = $1; }
6439 6440 6441 6442 6443
		| col_name_keyword		{ $$ = $1; }
		| ECPGKeywords			{ $$ = $1; }
		| ECPGCKeywords			{ $$ = $1; }
		| CHAR_P			{ $$ = make_str("char"); }
		| VALUES			{ $$ = make_str("values"); }
6444
		;
6445
/* Type/function identifier --- names that can be type names.
6446
 */
6447
type_function_name:	ident					{ $$ = $1; }
6448
		| unreserved_keyword		{ $$ = $1; }
6449
		| type_func_name_keyword		{ $$ = $1; }
6450 6451
		| ECPGKeywords				{ $$ = $1; }
		| ECPGTypeName				{ $$ = $1; }
6452
		| ECPGCKeywords				{ $$ = $1; }
6453 6454 6455 6456
		;

/* Column label --- allowed labels in "AS" clauses.
 * This presently includes *all* Postgres keywords.
6457
 */
6458
ColLabel:  ECPGColLabel				{ $$ = $1; }
6459 6460 6461 6462 6463 6464 6465
		| ECPGTypeName			{ $$ = $1; }
		| CHAR_P			{ $$ = make_str("char"); }
		| INPUT_P			{ $$ = make_str("input"); }
		| INT_P				{ $$ = make_str("int"); }
		| UNION				{ $$ = make_str("union"); }
		| TO				{ $$ = make_str("to"); }
		| ECPGCKeywords			{ $$ = $1; }
6466
		| ECPGunreserved_interval	{ $$ = $1; }
6467 6468
		;

6469
ECPGColLabelCommon:  ident			{ $$ = $1; }
6470
		| col_name_keyword		{ $$ = $1; }
6471
		| type_func_name_keyword	{ $$ = $1; }
6472 6473
		| ECPGKeywords_vanames		{ $$ = $1; }
		;
6474

6475
ECPGColLabel:  ECPGColLabelCommon	{ $$ = $1; }
6476 6477 6478
		| reserved_keyword		{ $$ = $1; }
		| ECPGunreserved		{ $$ = $1; }
		| ECPGKeywords_rest		{ $$ = $1; }
6479 6480
		;

6481
ECPGCKeywords: S_AUTO			{ $$ = make_str("auto"); }
6482 6483 6484 6485 6486 6487
		| S_CONST				{ $$ = make_str("const"); }
		| S_EXTERN				{ $$ = make_str("extern"); }
		| S_REGISTER			{ $$ = make_str("register"); }
		| S_STATIC				{ $$ = make_str("static"); }
		| S_TYPEDEF				{ $$ = make_str("typedef"); }
		| S_VOLATILE			{ $$ = make_str("volatile"); }
6488
		;
6489

6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500
/*
 * Keyword classification lists.  Generally, every keyword present in
 * the Postgres grammar should appear in exactly one of these lists.
 *
 * Put a new keyword into the first list that it can go into without causing
 * shift or reduce conflicts.  The earlier lists define "less reserved"
 * categories of keywords.
 */

/* "Unreserved" keywords --- available for use as any kind of name.
 */
6501 6502 6503 6504 6505 6506
/* The following symbols must be excluded from ECPGColLabel and directly included into ColLabel
   to enable C variables to get names from ECPGColLabel:
   DAY_P, HOUR_P, MINUTE_P, MONTH_P, SECOND_P, YEAR_P
 */
unreserved_keyword: ECPGunreserved_interval | ECPGunreserved;

6507
ECPGunreserved_interval: DAY_P			{ $$ = make_str("day"); }
6508 6509 6510 6511 6512 6513
		| HOUR_P			{ $$ = make_str("hour"); }
		| MINUTE_P			{ $$ = make_str("minute"); }
		| MONTH_P			{ $$ = make_str("month"); }
		| SECOND_P			{ $$ = make_str("second"); }
		| YEAR_P			{ $$ = make_str("year"); }
		;
6514

6515
/* The following symbol must be excluded from var_name but still included in ColId
6516
   to enable ecpg special postgresql variables with this name:  CONNECTION
6517 6518 6519 6520
 */
ECPGunreserved:	ECPGunreserved_con		{ $$ = $1; }
		| CONNECTION			{ $$ = make_str("connection"); }
		;
6521

6522
ECPGunreserved_con:	  ABORT_P			{ $$ = make_str("abort"); }
6523
		| ABSOLUTE_P		{ $$ = make_str("absolute"); }
6524 6525
		| ACCESS			{ $$ = make_str("access"); }
		| ACTION			{ $$ = make_str("action"); }
6526
		| ADD_P				{ $$ = make_str("add"); }
6527
		| ADMIN				{ $$ = make_str("admin"); }
6528 6529
		| AFTER				{ $$ = make_str("after"); }
		| AGGREGATE			{ $$ = make_str("aggregate"); }
6530
		| ALSO				{ $$ = make_str("also"); }
6531
		| ALTER				{ $$ = make_str("alter"); }
6532
		| ALWAYS			{ $$ = make_str("always"); }
6533
		| ASSERTION			{ $$ = make_str("assertion"); }
6534
		| ASSIGNMENT		{ $$ = make_str("assignment"); }
6535 6536 6537 6538 6539 6540 6541
		| AT				{ $$ = make_str("at"); }
		| BACKWARD			{ $$ = make_str("backward"); }
		| BEFORE			{ $$ = make_str("before"); }
		| BEGIN_P			{ $$ = make_str("begin"); }
		| BY				{ $$ = make_str("by"); }
		| CACHE				{ $$ = make_str("cache"); }
		| CASCADE			{ $$ = make_str("cascade"); }
6542
		| CASCADED			{ $$ = make_str("cascaded"); }
6543
		| CHAIN				{ $$ = make_str("chain"); }
6544 6545
		| CHARACTERISTICS	{ $$ = make_str("characteristics"); }
		| CHECKPOINT		{ $$ = make_str("checkpoint"); }
6546 6547 6548 6549 6550 6551
		| CLASS				{ $$ = make_str("class"); }
		| CLOSE				{ $$ = make_str("close"); }
		| CLUSTER			{ $$ = make_str("cluster"); }
		| COMMENT			{ $$ = make_str("comment"); }
		| COMMIT			{ $$ = make_str("commit"); }
		| COMMITTED			{ $$ = make_str("committed"); }
Michael Meskes's avatar
Michael Meskes committed
6552
		| CONCURRENTLY		{ $$ = make_str("concurrently"); }
6553
		| CONFIGURATION		{ $$ = make_str("configuration"); }
6554 6555
/*		| CONNECTION		{ $$ = make_str("connection"); }*/
		| CONSTRAINTS		{ $$ = make_str("constraints"); }
6556
		| CONTENT_P		{ $$ = make_str("content"); }
Michael Meskes's avatar
Michael Meskes committed
6557
		| CONTINUE_P		{ $$ = make_str("continue"); }
6558
		| CONVERSION_P		{ $$ = make_str("conversion"); }
6559
		| COPY				{ $$ = make_str("copy"); }
6560
		| COST				{ $$ = make_str("cost"); }
6561
		| CREATEDB			{ $$ = make_str("createdb"); }
6562 6563
		| CREATEROLE		{ $$ = make_str("createrole"); }
		| CREATEUSER		{ $$ = make_str("createuser"); }
6564
		| CSV				{ $$ = make_str("csv"); }
Michael Meskes's avatar
Michael Meskes committed
6565
		| CTYPE			{ $$ = make_str("ctype"); }
6566 6567
		| CURSOR			{ $$ = make_str("cursor"); }
		| CYCLE				{ $$ = make_str("cycle"); }
6568
		| DATA_P			{ $$ = make_str("data"); }
6569
		| DATABASE			{ $$ = make_str("database"); }
6570
/*		| DAY_P				{ $$ = make_str("day"); }*/
6571
		| DEALLOCATE		{ $$ = make_str("deallocate"); }
6572
		| DECLARE			{ $$ = make_str("declare"); }
6573
		| DEFAULTS			{ $$ = make_str("defaults"); }
6574 6575 6576
		| DEFERRED			{ $$ = make_str("deferred"); }
		| DELETE_P			{ $$ = make_str("delete"); }
		| DELIMITER			{ $$ = make_str("delimiter"); }
6577
		| DELIMITERS		{ $$ = make_str("delimiters"); }
6578
		| DICTIONARY		{ $$ = make_str("dictionary"); }
6579
		| DISABLE_P			{ $$ = make_str("disable"); }
6580
		| DISCARD			{ $$ = make_str("discard"); }
6581
		| DOCUMENT_P			{ $$ = make_str("document"); }
6582 6583 6584 6585
		| DOMAIN_P			{ $$ = make_str("domain"); }
		| DOUBLE_P			{ $$ = make_str("double"); }
		| DROP				{ $$ = make_str("drop"); }
		| EACH				{ $$ = make_str("each"); }
6586
		| ENABLE_P			{ $$ = make_str("enable"); }
6587 6588
		| ENCODING			{ $$ = make_str("encoding"); }
		| ENCRYPTED			{ $$ = make_str("encrypted"); }
6589
/*		| ENUM_P			{ $$ = make_str("enum"); }*/
6590
		| ESCAPE			{ $$ = make_str("escape"); }
6591
		| EXCLUDING			{ $$ = make_str("excluding"); }
6592 6593 6594
		| EXCLUSIVE			{ $$ = make_str("exclusive"); }
		| EXECUTE			{ $$ = make_str("execute"); }
		| EXPLAIN			{ $$ = make_str("explain"); }
6595 6596
		| EXTERNAL			{ $$ = make_str("external"); }
		| FAMILY			{ $$ = make_str("family"); }
6597 6598 6599 6600 6601 6602
		| FETCH				{ $$ = make_str("fetch"); }
		| FIRST_P			{ $$ = make_str("first"); }
		| FORCE				{ $$ = make_str("force"); }
		| FORWARD			{ $$ = make_str("forward"); }
		| FUNCTION			{ $$ = make_str("function"); }
		| GLOBAL			{ $$ = make_str("global"); }
6603
		| GRANTED			{ $$ = make_str("granted"); }
6604
		| HANDLER			{ $$ = make_str("handler"); }
6605
		| HEADER_P			{ $$ = make_str("header"); }
6606
		| HOLD				{ $$ = make_str("hold"); }
6607
/*		| HOUR_P			{ $$ = make_str("hour"); }*/
Michael Meskes's avatar
Michael Meskes committed
6608
		| IDENTITY_P			{ $$ = make_str("identity"); }
6609
		| IF_P				{ $$ = make_str("if"); }
6610 6611
		| IMMEDIATE			{ $$ = make_str("immediate"); }
		| IMMUTABLE			{ $$ = make_str("immutable"); }
6612
		| IMPLICIT_P		{ $$ = make_str("implicit"); }
6613
		| INCLUDING			{ $$ = make_str("including"); }
6614 6615
		| INCREMENT			{ $$ = make_str("increment"); }
		| INDEX				{ $$ = make_str("index"); }
6616
		| INDEXES			{ $$ = make_str("indexes"); }
6617
		| INHERIT			{ $$ = make_str("inherit"); }
6618
		| INHERITS			{ $$ = make_str("inherits"); }
6619
		| INSENSITIVE		{ $$ = make_str("insensitive"); }
6620 6621 6622 6623
		| INSERT			{ $$ = make_str("insert"); }
		| INSTEAD			{ $$ = make_str("instead"); }
		| ISOLATION			{ $$ = make_str("isolation"); }
		| KEY				{ $$ = make_str("key"); }
6624
		| LANCOMPILER		{ $$ = make_str("lancompiler"); }
6625
		| LANGUAGE			{ $$ = make_str("language"); }
6626
		| LARGE_P			{ $$ = make_str("large"); }
6627 6628 6629 6630 6631 6632 6633
		| LAST_P			{ $$ = make_str("last"); }
		| LEVEL				{ $$ = make_str("level"); }
		| LISTEN			{ $$ = make_str("listen"); }
		| LOAD				{ $$ = make_str("load"); }
		| LOCAL				{ $$ = make_str("local"); }
		| LOCATION			{ $$ = make_str("location"); }
		| LOCK_P			{ $$ = make_str("lock"); }
6634
		| LOGIN_P			{ $$ = make_str("login"); }
6635
		| MAPPING			{ $$ = make_str("mapping"); }
6636 6637
		| MATCH				{ $$ = make_str("match"); }
		| MAXVALUE			{ $$ = make_str("maxvalue"); }
6638
/*		| MINUTE_P			{ $$ = make_str("minute"); }*/
6639 6640
		| MINVALUE			{ $$ = make_str("minvalue"); }
		| MODE				{ $$ = make_str("mode"); }
6641
/*		| MONTH_P			{ $$ = make_str("month"); }*/
6642
		| MOVE				{ $$ = make_str("move"); }
6643
		| NAME_P			{ $$ = make_str("name"); }
6644 6645 6646
		| NAMES				{ $$ = make_str("names"); }
		| NEXT				{ $$ = make_str("next"); }
		| NO				{ $$ = make_str("no"); }
6647 6648 6649
		| NOCREATEDB		{ $$ = make_str("nocreatedb"); }
		| NOCREATEROLE		{ $$ = make_str("nocreaterole"); }
		| NOCREATEUSER		{ $$ = make_str("nocreateuser"); }
6650
		| NOINHERIT			{ $$ = make_str("noinherit"); }
6651 6652
		| NOLOGIN_P 		{ $$ = make_str("nologin"); }
		| NOSUPERUSER		{ $$ = make_str("nosuperuser"); }
6653 6654
		| NOTHING			{ $$ = make_str("nothing"); }
		| NOTIFY			{ $$ = make_str("notify"); }
Michael Meskes's avatar
Michael Meskes committed
6655
		| NOWAIT			{ $$ = make_str("nowait"); }
6656
		| NULLS_P			{ $$ = make_str("nulls"); }
6657
		| OBJECT_P			{ $$ = make_str("object"); }
6658 6659 6660 6661
		| OF				{ $$ = make_str("of"); }
		| OIDS				{ $$ = make_str("oids"); }
		| OPERATOR			{ $$ = make_str("operator"); }
		| OPTION			{ $$ = make_str("option"); }
6662
		| OWNED				{ $$ = make_str("owned"); }
6663
		| OWNER				{ $$ = make_str("owner"); }
6664
		| PARSER			{ $$ = make_str("parser"); }
6665 6666
		| PARTIAL			{ $$ = make_str("partial"); }
		| PASSWORD			{ $$ = make_str("password"); }
6667
		| PLANS				{ $$ = make_str("plans"); }
6668
		| PREPARE			{ $$ = make_str("prepare"); }
6669
		| PREPARED			{ $$ = make_str("prepared"); }
6670 6671
		| PRESERVE			{ $$ = make_str("preserver"); }
		| PRIOR				{ $$ = make_str("prior"); }
6672 6673
		| PRIVILEGES		{ $$ = make_str("privileges"); }
		| PROCEDURAL		{ $$ = make_str("procedural"); }
6674
		| PROCEDURE			{ $$ = make_str("procedure"); }
6675
		| QUOTE				{ $$ = make_str("quote"); }
6676
		| READ				{ $$ = make_str("read"); }
6677
		| REASSIGN			{ $$ = make_str("reassign"); }
6678
		| RECHECK			{ $$ = make_str("recheck"); }
Michael Meskes's avatar
Michael Meskes committed
6679
		| RECURSIVE			{ $$ = make_str("recursive"); }
6680
		| REINDEX			{ $$ = make_str("reindex"); }
6681
		| RELATIVE_P		{ $$ = make_str("relative"); }
Michael Meskes's avatar
Michael Meskes committed
6682
		| RELEASE			{ $$ = make_str("release"); }
6683
		| RENAME			{ $$ = make_str("rename"); }
6684
		| REPEATABLE		{ $$ = make_str("repeatable"); }
6685
		| REPLACE			{ $$ = make_str("replace"); }
6686
		| REPLICA			{ $$ = make_str("replica"); }
6687 6688 6689 6690 6691
		| RESET				{ $$ = make_str("reset"); }
		| RESTART			{ $$ = make_str("restart"); }
		| RESTRICT			{ $$ = make_str("restrict"); }
		| RETURNS			{ $$ = make_str("returns"); }
		| REVOKE			{ $$ = make_str("revoke"); }
6692
		| ROLE				{ $$ = make_str("role"); }
6693 6694 6695
		| ROLLBACK			{ $$ = make_str("rollback"); }
		| ROWS				{ $$ = make_str("rows"); }
		| RULE				{ $$ = make_str("rule"); }
Michael Meskes's avatar
Michael Meskes committed
6696
		| SAVEPOINT			{ $$ = make_str("savepoint"); }
6697 6698
		| SCHEMA			{ $$ = make_str("schema"); }
		| SCROLL			{ $$ = make_str("scroll"); }
6699
		| SEARCH			{ $$ = make_str("search"); }
6700
/*		| SECOND_P			{ $$ = make_str("second"); }*/
6701
		| SEQUENCE			{ $$ = make_str("sequence"); }
6702
		| SERIALIZABLE		{ $$ = make_str("serializable"); }
6703 6704 6705 6706 6707 6708
		| SESSION			{ $$ = make_str("session"); }
		| SET				{ $$ = make_str("set"); }
		| SHARE				{ $$ = make_str("share"); }
		| SHOW				{ $$ = make_str("show"); }
		| SIMPLE			{ $$ = make_str("simple"); }
		| STABLE			{ $$ = make_str("stable"); }
6709
		| STANDALONE_P			{ $$ = make_str("standalone"); }
6710 6711
		| START				{ $$ = make_str("start"); }
		| STATEMENT			{ $$ = make_str("statement"); }
6712
		| STATISTICS		{ $$ = make_str("statistics"); }
6713 6714 6715 6716
		| STDIN				{ $$ = make_str("stdin"); }
		| STDOUT			{ $$ = make_str("stdout"); }
		| STORAGE			{ $$ = make_str("storage"); }
		| STRICT_P			{ $$ = make_str("strict"); }
6717 6718
		| STRIP_P			{ $$ = make_str("strip"); }
		| SUPERUSER_P		{ $$ = make_str("superuser"); }
6719
		| SYSTEM_P			{ $$ = make_str("system"); }
6720
		| SYSID				{ $$ = make_str("sysid"); }
6721
		| TABLESPACE		{ $$ = make_str("tablespace"); }
6722 6723 6724
		| TEMP				{ $$ = make_str("temp"); }
		| TEMPLATE			{ $$ = make_str("template"); }
		| TEMPORARY			{ $$ = make_str("temporary"); }
6725
		| TEXT_P			{ $$ = make_str("text"); }
6726
		| TRANSACTION		{ $$ = make_str("transaction"); }
6727 6728 6729 6730
		| TRIGGER			{ $$ = make_str("trigger"); }
		| TRUNCATE			{ $$ = make_str("truncate"); }
		| TRUSTED			{ $$ = make_str("trusted"); }
		| TYPE_P			{ $$ = make_str("type"); }
6731 6732
		| UNCOMMITTED		{ $$ = make_str("uncommitted"); }
		| UNENCRYPTED		{ $$ = make_str("unencrypted"); }
6733 6734 6735 6736 6737 6738
		| UNKNOWN			{ $$ = make_str("unknown"); }
		| UNLISTEN			{ $$ = make_str("unlisten"); }
		| UNTIL				{ $$ = make_str("until"); }
		| UPDATE			{ $$ = make_str("update"); }
		| VACUUM			{ $$ = make_str("vacuum"); }
		| VALID				{ $$ = make_str("valid"); }
6739 6740
		| VALIDATOR			{ $$ = make_str("validator"); }
		| VALUE_P			{ $$ = make_str("value"); }
6741
		| VARYING			{ $$ = make_str("varying"); }
6742
		| VERSION_P			{ $$ = make_str("version"); }
6743
		| VIEW				{ $$ = make_str("view"); }
6744 6745
		| VOLATILE			{ $$ = make_str("volatile"); }
		| WHITESPACE_P			{ $$ = make_str("whitespace"); }
6746 6747 6748
		| WITHOUT			{ $$ = make_str("without"); }
		| WORK				{ $$ = make_str("work"); }
		| WRITE  			{ $$ = make_str("write"); }
6749 6750
		| XML_P  			{ $$ = make_str("xml"); }
		| YES_P  			{ $$ = make_str("yes"); }
6751
/*		| YEAR_P			{ $$ = make_str("year"); }*/
6752
		| ZONE				{ $$ = make_str("zone"); }
6753 6754
		;

6755
/* Column identifier --- keywords that can be column, table, etc names.
6756
 *
6757 6758 6759
 * Many of these keywords will in fact be recognized as type or function
 * names too; but they have special productions for the purpose, and so
 * can't be treated as "generic" type or function names.
6760
 *
6761 6762 6763
 * The type names appearing here are not usable as function names
 * because they can be followed by '(' in typename productions, which
 * looks too much like a function call for an LR(1) parser.
6764
 */
6765
col_name_keyword:
6766 6767
		BIGINT			{ $$ = make_str("bigint");}
		| BIT			{ $$ = make_str("bit"); }
6768
/* CHAR must be excluded from ECPGColLabel because of conflict with UNSIGNED
Jan Wieck's avatar
Jan Wieck committed
6769
		| CHAR_P		{ $$ = make_str("char"); }
6770
 */
6771 6772 6773
		| CHARACTER		{ $$ = make_str("character"); }
		| COALESCE		{ $$ = make_str("coalesce"); }
		| DEC			{ $$ = make_str("dec"); }
6774
		| DECIMAL_P		{ $$ = make_str("decimal"); }
6775 6776
		| EXISTS		{ $$ = make_str("exists"); }
		| EXTRACT		{ $$ = make_str("extract"); }
Jan Wieck's avatar
Jan Wieck committed
6777
		| FLOAT_P		{ $$ = make_str("float"); }
6778
		| GREATEST		{ $$ = make_str("greatest"); }
6779
		| INOUT			{ $$ = make_str("inout"); }
6780
/* INT must be excluded from ECPGColLabel because of conflict
6781
		| INT_P			{ $$ = make_str("int"); }
6782 6783 6784
 */
		| INTEGER 		{ $$ = make_str("integer"); }
		| INTERVAL		{ $$ = make_str("interval"); }
6785
		| LEAST			{ $$ = make_str("least"); }
6786
		| NATIONAL		{ $$ = make_str("national"); }
6787 6788 6789 6790
		| NCHAR			{ $$ = make_str("nchar"); }
		| NONE			{ $$ = make_str("none"); }
		| NULLIF		{ $$ = make_str("nullif"); }
		| NUMERIC		{ $$ = make_str("numeric"); }
6791 6792
		| OUT_P			{ $$ = make_str("out"); }
		| OVERLAY		{ $$ = make_str("overlay"); }
6793
		| POSITION		{ $$ = make_str("position"); }
6794
		| PRECISION		{ $$ = make_str("precision"); }
6795
		| REAL			{ $$ = make_str("real"); }
6796
		| ROW 			{ $$ = make_str("row"); }
6797 6798 6799 6800 6801
		| SETOF			{ $$ = make_str("setof"); }
		| SMALLINT		{ $$ = make_str("smallint"); }
		| SUBSTRING		{ $$ = make_str("substring"); }
		| TIME			{ $$ = make_str("time"); }
		| TIMESTAMP		{ $$ = make_str("timestamp"); }
6802
		| TREAT    		{ $$ = make_str("treat"); }
6803
		| TRIM			{ $$ = make_str("trim"); }
6804 6805
		/* VALUES creates a shift/reduce problem if listed here
		| VALUES		{ $$ = make_str("values"); } */
6806
		| VARCHAR		{ $$ = make_str("varchar"); }
6807 6808 6809 6810 6811 6812 6813 6814
		| XMLATTRIBUTES		{ $$ = make_str("xmlattributes"); }
		| XMLCONCAT		{ $$ = make_str("xmlconcat"); }
		| XMLELEMENT		{ $$ = make_str("xmlelement"); }
		| XMLFOREST		{ $$ = make_str("xmlforest"); }
		| XMLPARSE		{ $$ = make_str("xmlparse"); }
		| XMLPI			{ $$ = make_str("xmlpi"); }
		| XMLROOT		{ $$ = make_str("xmlroot"); }
		| XMLSERIALIZE		{ $$ = make_str("xmlserialize"); }
6815 6816
		;

6817
/* Function identifier --- keywords that can be function names.
6818
 *
6819 6820 6821 6822 6823 6824
 * Most of these are keywords that are used as operators in expressions;
 * in general such keywords can't be column names because they would be
 * ambiguous with variables, but they are unambiguous as function identifiers.
 *
 * Do not include POSITION, SUBSTRING, etc here since they have explicit
 * productions in a_expr to support the goofy SQL9x argument syntax.
6825
 *	- thomas 2000-11-28
6826
 */
6827
type_func_name_keyword:
6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847
		  AUTHORIZATION		{ $$ = make_str("authorization"); }
		| BETWEEN		{ $$ = make_str("between"); }
		| BINARY		{ $$ = make_str("binary"); }
		| CROSS			{ $$ = make_str("cross"); }
		| FREEZE		{ $$ = make_str("freeze"); }
		| FULL			{ $$ = make_str("full"); }
		| ILIKE			{ $$ = make_str("ilike"); }
		| INNER_P		{ $$ = make_str("inner"); }
		| IS			{ $$ = make_str("is"); }
		| ISNULL		{ $$ = make_str("isnull"); }
		| JOIN			{ $$ = make_str("join"); }
		| LEFT			{ $$ = make_str("left"); }
		| LIKE			{ $$ = make_str("like"); }
		| NATURAL		{ $$ = make_str("natural"); }
		| NOTNULL		{ $$ = make_str("notnull"); }
		| OUTER_P		{ $$ = make_str("outer"); }
		| OVERLAPS		{ $$ = make_str("overlaps"); }
		| RIGHT			{ $$ = make_str("right"); }
		| SIMILAR		{ $$ = make_str("similar"); }
		| VERBOSE		{ $$ = make_str("verbose"); }
6848 6849
		;

6850 6851 6852 6853 6854 6855 6856
/* Reserved keyword --- these keywords are usable only as a ColLabel.
 *
 * Keywords appear here if they could not be distinguished from variable,
 * type, or function names in some contexts.  Don't put things here unless
 * forced to.
 */
reserved_keyword:
6857 6858 6859 6860 6861 6862 6863 6864
		  ALL				{ $$ = make_str("all"); }
		| ANALYSE			{ $$ = make_str("analyse"); } /* British */
		| ANALYZE			{ $$ = make_str("analyze"); }
		| AND				{ $$ = make_str("and"); }
		| ANY				{ $$ = make_str("any"); }
		| ARRAY				{ $$ = make_str("array"); }
		| AS				{ $$ = make_str("as"); }
		| ASC				{ $$ = make_str("asc"); }
6865
		| ASYMMETRIC		{ $$ = make_str("asymmetric"); }
6866 6867 6868 6869 6870 6871
		| BOTH				{ $$ = make_str("both"); }
		| CASE				{ $$ = make_str("case"); }
		| CAST				{ $$ = make_str("cast"); }
		| CHECK				{ $$ = make_str("check"); }
		| COLLATE			{ $$ = make_str("collate"); }
		| COLUMN			{ $$ = make_str("column"); }
6872
		| CONSTRAINT		{ $$ = make_str("constraint"); }
6873
		| CREATE			{ $$ = make_str("create"); }
6874
		| CURRENT_P                     { $$ = make_str("current"); }
6875
		| CURRENT_CATALOG	{ $$ = make_str("current_catalog"); }
6876 6877 6878 6879
		| CURRENT_DATE		{ $$ = make_str("current_date"); }
		| CURRENT_TIME		{ $$ = make_str("current_time"); }
		| CURRENT_TIMESTAMP	{ $$ = make_str("current_timestamp"); }
		| CURRENT_ROLE		{ $$ = make_str("current_role"); }
6880
		| CURRENT_SCHEMA	{ $$ = make_str("current_schema"); }
6881
		| CURRENT_USER		{ $$ = make_str("current_user"); }
6882
		| DEFAULT			{ $$ = make_str("default"); }
6883
		| DEFERRABLE		{ $$ = make_str("deferrable"); }
6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896
		| DESC				{ $$ = make_str("desc"); }
		| DISTINCT			{ $$ = make_str("distinct"); }
		| DO				{ $$ = make_str("do"); }
		| ELSE				{ $$ = make_str("else"); }
		| END_P				{ $$ = make_str("end"); }
		| EXCEPT			{ $$ = make_str("except"); }
		| FALSE_P			{ $$ = make_str("false"); }
		| FOR				{ $$ = make_str("for"); }
		| FOREIGN			{ $$ = make_str("foreign"); }
		| FROM				{ $$ = make_str("from"); }
		| GRANT				{ $$ = make_str("grant"); }
		| GROUP_P			{ $$ = make_str("group"); }
		| HAVING			{ $$ = make_str("having"); }
6897
		| IN_P				{ $$ = make_str("in"); }
6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913
		| INITIALLY			{ $$ = make_str("initially"); }
		| INTERSECT			{ $$ = make_str("intersect"); }
		| INTO				{ $$ = make_str("into"); }
		| LEADING			{ $$ = make_str("leading"); }
		| LIMIT				{ $$ = make_str("limit"); }
		| NEW				{ $$ = make_str("new"); }
		| NOT				{ $$ = make_str("not"); }
		| NULL_P			{ $$ = make_str("null"); }
		| OFF				{ $$ = make_str("off"); }
		| OFFSET			{ $$ = make_str("offset"); }
		| OLD				{ $$ = make_str("old"); }
		| ON				{ $$ = make_str("on"); }
		| ONLY				{ $$ = make_str("only"); }
		| OR				{ $$ = make_str("or"); }
		| ORDER				{ $$ = make_str("order"); }
		| PRIMARY			{ $$ = make_str("primary"); }
6914 6915
		| REFERENCES			{ $$ = make_str("references"); }
		| RETURNING			{ $$ = make_str("returning"); }
6916
		| SELECT			{ $$ = make_str("select"); }
6917
		| SESSION_USER			{ $$ = make_str("session_user"); }
6918
		| SOME				{ $$ = make_str("some"); }
6919
		| SYMMETRIC			{ $$ = make_str("symmetric"); }
6920 6921
		| TABLE				{ $$ = make_str("table"); }
		| THEN				{ $$ = make_str("then"); }
6922
/* TO must be excluded from ECPGColLabel because of a conflict in variable name parsing
6923
		| TO				{ $$ = make_str("to"); }
6924
 */
6925 6926
		| TRAILING			{ $$ = make_str("trailing"); }
		| TRUE_P			{ $$ = make_str("true"); }
6927
/* UNION must be excluded from ECPGColLabel because of conflict with s_union
6928
		| UNION				{ $$ = make_str("union"); }
6929
 */
6930 6931 6932
		| UNIQUE			{ $$ = make_str("unique"); }
		| USER				{ $$ = make_str("user"); }
		| USING				{ $$ = make_str("using"); }
6933
		| VARIADIC			{ $$ = make_str("variadic"); }
6934 6935
		| WHEN				{ $$ = make_str("when"); }
		| WHERE				{ $$ = make_str("where"); }
Michael Meskes's avatar
Michael Meskes committed
6936
		| WITH				{ $$ = make_str("with"); }
6937 6938
		;

Marc G. Fournier's avatar
Marc G. Fournier committed
6939

6940 6941
into_list : coutputvariable | into_list ',' coutputvariable
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
6942

6943 6944 6945 6946
ecpgstart: SQL_START	{
				reset_variables();
				pacounter = 1;
			}
6947
		;
6948

6949 6950 6951
c_args: /*EMPTY*/		{ $$ = EMPTY; }
		| c_list		{ $$ = $1; }
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
6952

6953
coutputvariable: cvariable indicator
6954
			{ add_variable_to_head(&argsresult, find_variable($1), find_variable($2)); }
6955
		| cvariable
6956
			{ add_variable_to_head(&argsresult, find_variable($1), &no_indicator); }
6957
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
6958

6959

6960
civarind: cvariable indicator
6961 6962 6963 6964
		{
			if (find_variable($2)->type->type == ECPGt_array)
				mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input");

6965
			add_variable_to_head(&argsinsert, find_variable($1), find_variable($2));
6966
			$$ = create_questionmarks($1, false);
6967 6968
		}
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
6969

6970
civar: cvariable
6971 6972 6973 6974
		{
			add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
			$$ = create_questionmarks($1, false);
		}
6975
		;
6976

6977 6978
indicator: cvariable				{ check_indicator((find_variable($1))->type); $$ = $1; }
		| SQL_INDICATOR cvariable	{ check_indicator((find_variable($2))->type); $$ = $2; }
6979 6980
		| SQL_INDICATOR name		{ check_indicator((find_variable($2))->type); $$ = $2; }
		;
Marc G. Fournier's avatar
Marc G. Fournier committed
6981

6982
cvariable:	CVARIABLE
6983 6984 6985 6986
		{
			/* As long as multidimensional arrays are not implemented we have to check for those here */
			char *ptr = $1;
			int brace_open=0, brace = false;
6987

6988 6989 6990 6991
			for (; *ptr; ptr++)
			{
				switch (*ptr)
				{
6992 6993
					case '[':
							if (brace)
6994
								mmerror(PARSE_ERROR, ET_FATAL, "no multidimensional array support for simple data types");
6995 6996
							brace_open++;
							break;
6997 6998 6999 7000
					case ']':
							brace_open--;
							if (brace_open == 0)
								brace = true;
7001 7002
							break;
					case '\t':
7003 7004 7005 7006 7007
					case ' ':
							break;
					default:
							if (brace_open == 0)
								brace = false;
7008 7009 7010 7011 7012 7013
							break;
				}
			}
			$$ = $1;
		}
		;
7014
ident: IDENT				{ $$ = $1; }
7015
		| CSTRING		{ $$ = make3_str(make_str("\""), $1, make_str("\"")); }
7016
		;
Michael Meskes's avatar
Michael Meskes committed
7017

7018
quoted_ident_stringvar: name
7019 7020 7021 7022
			{ $$ = make3_str(make_str("\""), $1, make_str("\"")); }
		| char_variable
			{ $$ = make3_str(make_str("("), $1, make_str(")")); }
		;
7023

Marc G. Fournier's avatar
Marc G. Fournier committed
7024 7025 7026
/*
 * C stuff
 */
7027

7028
c_stuff_item: c_anything			{ $$ = $1; }
7029
		| '(' ')'			{ $$ = make_str("()"); }
7030 7031 7032
		| '(' c_stuff ')'
			{ $$ = cat_str(3, make_str("("), $2, make_str(")")); }
		;
7033

7034
c_stuff: c_stuff_item			{ $$ = $1; }
7035 7036 7037
		| c_stuff c_stuff_item
			{ $$ = cat2_str($1, $2); }
		;
Michael Meskes's avatar
Michael Meskes committed
7038

7039 7040
c_list: c_term				{ $$ = $1; }
		| c_list ',' c_term	{ $$ = cat_str(3, $1, make_str(","), $3); }
7041
		;
Michael Meskes's avatar
Michael Meskes committed
7042

7043 7044
c_term:  c_stuff			{ $$ = $1; }
		| '{' c_list '}'	{ $$ = cat_str(3, make_str("{"), $2, make_str("}")); }
7045
		;
7046

7047 7048 7049 7050 7051
c_thing:	c_anything		{ $$ = $1; }
		|	'('		{ $$ = make_str("("); }
		|	')'		{ $$ = make_str(")"); }
		|	','		{ $$ = make_str(","); }
		|	';'		{ $$ = make_str(";"); }
7052 7053
		;

7054
c_anything:  IDENT				{ $$ = $1; }
Michael Meskes's avatar
Michael Meskes committed
7055 7056 7057 7058 7059 7060 7061 7062 7063 7064 7065 7066
		| CSTRING			{ $$ = make3_str(make_str("\""), $1, make_str("\"")); }
		| Iconst			{ $$ = $1; }
		| Fconst			{ $$ = $1; }
		| Sconst			{ $$ = $1; }
		| '*'				{ $$ = make_str("*"); }
		| '+'				{ $$ = make_str("+"); }
		| '-'				{ $$ = make_str("-"); }
		| '/'				{ $$ = make_str("/"); }
		| '%'				{ $$ = make_str("%"); }
		| NULL_P			{ $$ = make_str("NULL"); }
		| S_ADD				{ $$ = make_str("+="); }
		| S_AND				{ $$ = make_str("&&"); }
7067
		| S_ANYTHING			{ $$ = make_name(); }
Michael Meskes's avatar
Michael Meskes committed
7068 7069 7070 7071
		| S_AUTO			{ $$ = make_str("auto"); }
		| S_CONST			{ $$ = make_str("const"); }
		| S_DEC				{ $$ = make_str("--"); }
		| S_DIV				{ $$ = make_str("/="); }
7072
		| S_DOTPOINT			{ $$ = make_str(".*"); }
Michael Meskes's avatar
Michael Meskes committed
7073 7074 7075 7076 7077
		| S_EQUAL			{ $$ = make_str("=="); }
		| S_EXTERN			{ $$ = make_str("extern"); }
		| S_INC				{ $$ = make_str("++"); }
		| S_LSHIFT			{ $$ = make_str("<<"); }
		| S_MEMBER			{ $$ = make_str("->"); }
7078
		| S_MEMPOINT			{ $$ = make_str("->*"); }
Michael Meskes's avatar
Michael Meskes committed
7079 7080 7081 7082
		| S_MOD				{ $$ = make_str("%="); }
		| S_MUL				{ $$ = make_str("*="); }
		| S_NEQUAL			{ $$ = make_str("!="); }
		| S_OR				{ $$ = make_str("||"); }
7083
		| S_REGISTER			{ $$ = make_str("register"); }
Michael Meskes's avatar
Michael Meskes committed
7084 7085 7086 7087
		| S_RSHIFT			{ $$ = make_str(">>"); }
		| S_STATIC			{ $$ = make_str("static"); }
		| S_SUB				{ $$ = make_str("-="); }
		| S_TYPEDEF			{ $$ = make_str("typedef"); }
7088
		| S_VOLATILE			{ $$ = make_str("volatile"); }
Michael Meskes's avatar
Michael Meskes committed
7089
		| SQL_BOOL			{ $$ = make_str("bool"); }
7090
		| ENUM_P			{ $$ = make_str("enum"); }
Michael Meskes's avatar
Michael Meskes committed
7091 7092 7093 7094 7095 7096 7097
		| HOUR_P			{ $$ = make_str("hour"); }
		| INT_P				{ $$ = make_str("int"); }
		| SQL_LONG			{ $$ = make_str("long"); }
		| MINUTE_P			{ $$ = make_str("minute"); }
		| MONTH_P			{ $$ = make_str("month"); }
		| SECOND_P			{ $$ = make_str("second"); }
		| SQL_SHORT			{ $$ = make_str("short"); }
7098 7099 7100
		| SQL_SIGNED			{ $$ = make_str("signed"); }
		| SQL_STRUCT			{ $$ = make_str("struct"); }
		| SQL_UNSIGNED			{ $$ = make_str("unsigned"); }
Michael Meskes's avatar
Michael Meskes committed
7101 7102 7103
		| YEAR_P			{ $$ = make_str("year"); }
		| CHAR_P			{ $$ = make_str("char"); }
		| FLOAT_P			{ $$ = make_str("float"); }
Michael Meskes's avatar
Michael Meskes committed
7104
		| TO				{ $$ = make_str("to"); }
Michael Meskes's avatar
Michael Meskes committed
7105 7106 7107 7108 7109
		| UNION				{ $$ = make_str("union"); }
		| VARCHAR			{ $$ = make_str("varchar"); }
		| '['				{ $$ = make_str("["); }
		| ']'				{ $$ = make_str("]"); }
		| '='				{ $$ = make_str("="); }
7110
		| ':' 				{ $$ = make_str(":"); }
7111
		;
7112 7113

%%
7114

7115
void base_yyerror(const char * error)
7116 7117 7118
{
	char buf[1024];

7119
	snprintf(buf,sizeof buf, _("%s at or near \"%s\""), error, token_start ? token_start : yytext);
7120
	buf[sizeof(buf)-1]=0;
7121
	mmerror(PARSE_ERROR, ET_ERROR, buf);
7122
}
7123

7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134
void parser_init(void)
{
 /* This function is empty. It only exists for compatibility with the backend parser right now. */
}

/*
 * Must undefine base_yylex before including pgc.c, since we want it
 * to create the function base_yylex not filtered_base_yylex.
 */
#undef base_yylex

7135
#include "pgc.c"