X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;ds=sidebyside;f=src%2Finterfaces%2Fecpg%2Fpreproc%2Fpreproc.y;h=b0d126e9bad26281ef7ac3a0ba7a2146aaebd24f;hb=44d5be0e5308e951c0c5dc522b4bcacf2bcbc476;hp=9b0c01f4f5ee823eff9e44a8bbecc13ced059618;hpb=eebad1a74f7ced1f23256dde7c11df64e760c6ab;p=postgresql diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 9b0c01f4f5..b0d126e9ba 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -1,10 +1,26 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.286 2004/06/11 17:32:39 momjian Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.373 2008/10/04 21:56:55 tgl Exp $ */ /* Copyright comment */ %{ #include "postgres_fe.h" #include "extern.h" +#include + +/* 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 /* * Variables containing simple states. @@ -12,12 +28,13 @@ int struct_level = 0; int braces_open; /* brace level counter */ int ecpg_informix_var = 0; -char errortext[128]; char *connection = NULL; char *input_filename = NULL; static int QueryIsRule = 0, FoundInto = 0; static int initializer = 0; +static int pacounter = 1; +static char pacounter_buffer[sizeof(int) * CHAR_BIT * 10 / 3]; /* a rough guess at the size we need */ static struct this_type actual_type[STRUCT_DEPTH]; static char *actual_startline[STRUCT_DEPTH]; @@ -30,41 +47,55 @@ static char *ECPGstruct_sizeof = NULL; /* for forward declarations we have to store some data as well */ static char *forward_name = NULL; -struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, NULL, {NULL}}; +struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, NULL, NULL, {NULL}, 0}; struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL}; -struct ECPGtype ecpg_query = {ECPGt_char_variable, 0L, NULL, {NULL}}; - -static struct inf_compat_col -{ - char *name; - char *indirection; - struct inf_compat_col *next; -} *informix_col; - -static struct inf_compat_val -{ - char *val; - struct inf_compat_val *next; -} *informix_val; +struct ECPGtype ecpg_query = {ECPGt_char_variable, NULL, NULL, {NULL}, 0}; /* * Handle parsing errors and warnings */ void -mmerror(int error_code, enum errortype type, char * error) +mmerror(int error_code, enum errortype type, char * error, ...) { + va_list ap; + + /* internationalize the error message string */ + error = _(error); + + fprintf(stderr, "%s:%d: ", input_filename, yylineno); + + switch(type) + { + case ET_WARNING: + fprintf(stderr, _("WARNING: ")); + break; + case ET_ERROR: + case ET_FATAL: + fprintf(stderr, _("ERROR: ")); + break; + } + + va_start(ap, error); + vfprintf(stderr, error, ap); + va_end(ap); + + fprintf(stderr, "\n"); + switch(type) { case ET_WARNING: - fprintf(stderr, "%s:%d: WARNING: %s\n", input_filename, yylineno, error); break; case ET_ERROR: - fprintf(stderr, "%s:%d: ERROR: %s\n", input_filename, yylineno, error); ret_value = error_code; break; case ET_FATAL: - fprintf(stderr, "%s:%d: ERROR: %s\n", input_filename, yylineno, error); + if (yyin) + fclose(yyin); + if (yyout) + fclose(yyout); + if (unlink(output_filename) != 0 && *output_filename != '-') + fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename); exit(error_code); } } @@ -159,11 +190,11 @@ create_questionmarks(char *name, bool array) int count; char *result = EMPTY; - /* 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 + /* 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 * so we don't have to worry here. */ - + if (p->type->type == ECPGt_struct || (array && p->type->type == ECPGt_array && p->type->u.element->type == ECPGt_struct)) { struct ECPGstruct_member *m; @@ -179,7 +210,10 @@ create_questionmarks(char *name, bool array) count = 1; for (; count > 0; count --) - result = cat2_str(result, make_str("? , ")); + { + sprintf(pacounter_buffer, "$%d", pacounter++); + result = cat_str(3, result, strdup(pacounter_buffer), make_str(" , ")); + } /* removed the trailing " ," */ @@ -191,10 +225,16 @@ static char * adjust_informix(struct arguments *list) { /* Informix accepts DECLARE with variables that are out of scope when OPEN is called. - * This breaks standard and leads to some very dangerous programming. + * for instance you can declare variables in a function, and then subsequently use them + * { + * declare_vars(); + * exec sql ... which uses vars declared in the above function + * + * This breaks standard and leads to some very dangerous programming. * Since they do, we have to work around and accept their syntax as well. * But we will do so ONLY in Informix mode. - * We have to change the variables to our own struct and just store the pointer instead of the variable */ + * We have to change the variables to our own struct and just store the pointer instead of the variable + */ struct arguments *ptr; char *result = make_str(""); @@ -203,41 +243,46 @@ adjust_informix(struct arguments *list) { char temp[20]; /* this should be sufficient unless you have 8 byte integers */ char *original_var; - + /* change variable name to "ECPG_informix_get_var()" */ original_var = ptr->variable->name; sprintf(temp, "%d))", ecpg_informix_var); - - if ((ptr->variable->type->type != ECPGt_char && ptr->variable->type->type != ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1) + + 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) + { + 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); + sprintf(temp, "%d, (", ecpg_informix_var++); + } + 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) { - ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ECPGtype_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->size), 0); + 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); sprintf(temp, "%d, (", ecpg_informix_var++); } else { - ptr->variable = new_variable(cat_str(4, make_str("*("), mm_strdup(ECPGtype_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), 0); + 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); sprintf(temp, "%d, &(", ecpg_informix_var++); } - + /* create call to "ECPG_informix_set_var(, . )" */ result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n")); - + /* now the indicator if there is one */ if (ptr->indicator->type->type != ECPGt_NO_INDICATOR) { /* change variable name to "ECPG_informix_get_var()" */ original_var = ptr->indicator->name; sprintf(temp, "%d))", ecpg_informix_var); - + /* create call to "ECPG_informix_set_var(, . )" */ if (atoi(ptr->indicator->type->size) > 1) { - ptr->indicator = new_variable(cat_str(4, make_str("("), mm_strdup(ECPGtype_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), 0); + 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); sprintf(temp, "%d, (", ecpg_informix_var++); } else { - ptr->indicator = new_variable(cat_str(4, make_str("*("), mm_strdup(ECPGtype_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), 0); + 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); 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")); @@ -261,13 +306,13 @@ add_additional_variables(char *name, bool insert) if (ptr == NULL) { - snprintf(errortext, sizeof(errortext), "trying to access an undeclared cursor %s\n", name); - mmerror(PARSE_ERROR, ET_ERROR, errortext); + mmerror(PARSE_ERROR, ET_ERROR, "trying to access an undeclared cursor \"%s\"\n", name); return NULL; } + if (insert) { - /* add all those input variables that were given earlier + /* add all those input variables that were given earlier * note that we have to append here but have to keep the existing order */ for (p = ptr->argsinsert; p; p = p->next) add_variable_to_tail(&argsinsert, p->variable, p->indicator); @@ -276,11 +321,59 @@ add_additional_variables(char *name, bool insert) /* add all those output variables that were given earlier */ for (p = ptr->argsresult; p; p = p->next) add_variable_to_tail(&argsresult, p->variable, p->indicator); - + return ptr; } + +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) + mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in typedef command"); + else + { + for (ptr = types; ptr != NULL; ptr = ptr->next) + { + if (strcmp(name, ptr->name) == 0) + /* re-definition is a bug */ + mmerror(PARSE_ERROR, ET_ERROR, "type %s already defined", name); + } + 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) + mmerror(PARSE_ERROR, ET_ERROR, "no multidimensional array support for simple data types"); + + types = this; + } +} %} +%name-prefix="base_yy" +%locations + %union { double dval; char *str; @@ -293,23 +386,24 @@ add_additional_variables(char *name, bool insert) enum ECPGdtype dtype_enum; struct fetch_desc descriptor; struct su_symbol struct_union; + struct prep prep; } /* special embedded SQL token */ %token SQL_ALLOCATE SQL_AUTOCOMMIT SQL_BOOL SQL_BREAK - SQL_CALL SQL_CARDINALITY SQL_CONNECT SQL_CONNECTION - SQL_CONTINUE SQL_COUNT SQL_CURRENT SQL_DATA + SQL_CALL SQL_CARDINALITY SQL_CONNECT + SQL_COUNT SQL_DATA SQL_DATETIME_INTERVAL_CODE SQL_DATETIME_INTERVAL_PRECISION SQL_DESCRIBE - SQL_DESCRIPTOR SQL_DISCONNECT SQL_ENUM SQL_FOUND - SQL_FREE SQL_GO SQL_GOTO SQL_IDENTIFIED + SQL_DESCRIPTOR SQL_DISCONNECT SQL_FOUND + SQL_FREE SQL_GET SQL_GO SQL_GOTO SQL_IDENTIFIED SQL_INDICATOR SQL_KEY_MEMBER SQL_LENGTH - SQL_LONG SQL_NAME SQL_NULLABLE SQL_OCTET_LENGTH - SQL_OPEN SQL_OUTPUT SQL_RELEASE SQL_REFERENCE + SQL_LONG SQL_NULLABLE SQL_OCTET_LENGTH + SQL_OPEN SQL_OUTPUT SQL_REFERENCE 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 - SQL_STRUCT SQL_UNSIGNED SQL_VALUE SQL_VAR SQL_WHENEVER + SQL_STRUCT SQL_UNSIGNED SQL_VAR SQL_WHENEVER /* C token */ %token S_ADD S_AND S_ANYTHING S_AUTO S_CONST S_DEC S_DIV @@ -322,88 +416,104 @@ add_additional_variables(char *name, bool insert) %token TYPECAST /* ordinary key words in alphabetical order */ -%token ABORT_P ABSOLUTE_P ACCESS ACTION ADD AFTER - AGGREGATE ALL ALSO ALTER ANALYSE ANALYZE AND ANY ARRAY AS ASC - ASSERTION ASSIGNMENT AT AUTHORIZATION +%token ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER + AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC + ASSERTION ASSIGNMENT ASYMMETRIC AT AUTHORIZATION - BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT - BOOLEAN_P BOTH BY + BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT + BOOLEAN_P BOTH BY - CACHE CALLED CASCADE CASE CAST CHAIN CHAR_P + CACHE CALLED CASCADE CASCADED CASE CAST CHAIN CHAR_P CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT - COMMITTED CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY - CREATE CREATEDB CREATEUSER CROSS CSV CURRENT_DATE CURRENT_TIME - CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE + COMMITTED CONCURRENTLY CONFIGURATION CONNECTION CONSTRAINT CONSTRAINTS + CONTENT_P CONTINUE_P CONVERSION_P COPY COST CREATE CREATEDB + CREATEROLE CREATEUSER CROSS CSV CTYPE CURRENT_P CURRENT_DATE CURRENT_ROLE + CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE + + DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS + DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS DESC + DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP + + EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EXCEPT EXCLUSIVE EXCLUDING + EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT - DATABASE DAY_P DEALLOCATE DEC DECIMAL_P DECLARE DEFAULT DEFAULTS - DEFERRABLE DEFERRED DEFINER DELETE_P DELIMITER DELIMITERS - DESC DISTINCT DO DOMAIN_P DOUBLE_P DROP - EACH ELSE ENCODING ENCRYPTED END_P ESCAPE EXCEPT EXCLUSIVE EXCLUDING - EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT + FALSE_P FAMILY FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD FREEZE FROM + FULL FUNCTION - FALSE_P FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD FREEZE FROM - FULL FUNCTION + GLOBAL GRANT GRANTED GREATEST GROUP_P - GET GLOBAL GRANT GROUP_P - HANDLER HAVING HOLD HOUR_P + HANDLER HAVING HEADER_P HOLD HOUR_P - ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT - INDEX INHERITS INITIALLY INNER_P INOUT INPUT_P - INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT - INTERVAL INTO INVOKER IS ISNULL ISOLATION + 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 - JOIN + JOIN - KEY + KEY - LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEFT LEVEL LIKE LIMIT LISTEN - LOAD LOCAL LOCATION LOCK_P + LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEAST LEFT LEVEL + LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION + LOCK_P LOGIN_P - MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE + MAPPING MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE - NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB - NOCREATEUSER NONE NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P - NULLIF NUMERIC + NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB + NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER + NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OR ORDER - OUT_P OUTER_P OVERLAPS OVERLAY OWNER + OUT_P OUTER_P OVERLAPS OVERLAY OWNED OWNER - PARTIAL PASSWORD PATH_P PENDANT PLACING POSITION - PRECISION PRESERVE PREPARE PRIMARY PRIOR PRIVILEGES PROCEDURAL PROCEDURE + PARSER PARTIAL PASSWORD PLACING PLANS POSITION + PRECISION PRESERVE PREPARE PREPARED PRIMARY + PRIOR PRIVILEGES PROCEDURAL PROCEDURE QUOTE - READ REAL RECHECK REFERENCES REINDEX RELATIVE_P RENAME REPEATABLE REPLACE - RESET RESTART RESTRICT RETURNS REVOKE RIGHT ROLLBACK ROW ROWS RULE + READ REAL REASSIGN RECHECK RECURSIVE REFERENCES REINDEX RELATIVE_P RELEASE RENAME + REPEATABLE REPLACE REPLICA RESET RESTART RESTRICT RETURNING RETURNS REVOKE + RIGHT ROLE ROLLBACK ROW ROWS RULE + + SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE + SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE + 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 + + TABLE TABLESPACE TEMP TEMPLATE TEMPORARY TEXT_P THEN TIME TIMESTAMP TO + TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P TRUNCATE TRUSTED TYPE_P + + UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL + UPDATE USER USING + + VACUUM VALID VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING + VERBOSE VERSION_P VIEW VOLATILE + WHEN WHERE WHITESPACE_P WITH WITHOUT WORK WRITE - SCHEMA SCROLL SECOND_P SECURITY SELECT SEQUENCE SERIALIZABLE - SESSION SESSION_USER SET SETOF SHARE SHOW SIMILAR SIMPLE SMALLINT SOME - STABLE START STATEMENT STATISTICS STDIN STDOUT STORAGE STRICT_P - SUBSTRING SYSID + XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLFOREST XMLPARSE + XMLPI XMLROOT XMLSERIALIZE - TABLE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP TO TOAST - TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P TRUNCATE TRUSTED TYPE_P - UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL UPDATE USAGE - USER USING + YEAR_P YES_P - VACUUM VALID VALUES VARCHAR VARYING VERBOSE VERSION VIEW VOLATILE - WHEN WHERE WITH WITHOUT WORK WRITE - YEAR_P - ZONE + ZONE /* 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. */ -%token UNIONJOIN +%token NULLS_FIRST NULLS_LAST WITH_CASCADED WITH_LOCAL WITH_CHECK -/* Special keywords, not in the query language - see the "lex" file */ -%token IDENT SCONST Op CSTRING CVARIABLE CPP_LINE IP BCONST XCONST +/* Special token types, not actually keywords - see the "lex" file */ +%token IDENT SCONST Op CSTRING CVARIABLE CPP_LINE IP BCONST +%token XCONST DOLCONST ECONST NCONST %token ICONST PARAM %token FCONST /* precedence: lowest to highest */ +%nonassoc SET /* see relation_expr_opt_alias */ %left UNION EXCEPT %left INTERSECT %left OR @@ -416,8 +526,9 @@ add_additional_variables(char *name, bool insert) %nonassoc OVERLAPS %nonassoc BETWEEN %nonassoc IN_P -%left POSTFIXOP /* dummy for postfix Op rules */ -%left Op OPERATOR /* multi-character ops and user-defined operators */ +%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 */ %nonassoc NOTNULL %nonassoc ISNULL %nonassoc IS NULL_P TRUE_P FALSE_P UNKNOWN @@ -431,39 +542,41 @@ add_additional_variables(char *name, bool insert) %left '(' ')' %left TYPECAST %left '.' -%left JOIN UNIONJOIN CROSS LEFT FULL RIGHT INNER_P NATURAL +%left JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL +/* kluge to keep xml_whitespace_option from causing shift/reduce conflicts */ +%right PRESERVE STRIP_P -%type Iconst Fconst Sconst TransactionStmt CreateStmt UserId +%type Iconst Fconst Sconst TransactionStmt CreateStmt RoleId %type CreateAsElement OptCreateAs CreateAsList CreateAsStmt %type comment_text ConstraintDeferrabilitySpec TableElementList %type key_match ColLabel SpecialRuleRelation ColId columnDef %type ColConstraint ColConstraintElem drop_type Bconst Iresult -%type TableConstraint OptTableElementList Xconst opt_transaction -%type ConstraintElem key_actions ColQualList type_name -%type target_list target_el update_target_list alias_clause -%type update_target_el qualified_name database_name alter_using -%type access_method attr_name index_name name func_name -%type file_name AexprConst c_expr ConstTypename var_list +%type TableConstraint OptTableElementList Xconst opt_transaction +%type ConstraintElem key_actions ColQualList cluster_index_specification +%type target_list target_el alias_clause type_func_name_keyword +%type qualified_name database_name alter_using type_function_name +%type access_method attr_name index_name name func_name opt_restart_seqs +%type file_name AexprConst c_expr ConstTypename var_list %type a_expr b_expr TruncateStmt CommentStmt OnCommitOption opt_by -%type opt_indirection expr_list extract_list extract_arg +%type opt_indirection expr_list extract_list extract_arg OptSeqOptList %type position_list substr_list substr_from alter_column_default %type trim_list in_expr substr_for attrs TableFuncElement -%type Typename SimpleTypename Numeric opt_float opt_numeric -%type opt_decimal Character character opt_varying opt_charset +%type Typename SimpleTypename Numeric opt_float DiscardStmt +%type Character character opt_varying opt_charset enum_val_list %type opt_timezone opt_interval table_ref fetch_direction -%type row_descriptor ConstDatetime AlterDomainStmt AlterSeqStmt +%type ConstDatetime AlterDomainStmt AlterSeqStmt table_func_column %type SelectStmt into_clause OptTemp ConstraintAttributeSpec %type opt_table opt_all sort_clause sortby_list ConstraintAttr %type sortby qualified_name_list name_list ColId_or_Sconst %type group_clause having_clause from_clause opt_distinct opt_hold %type join_outer where_clause relation_expr sub_type arg_class -%type opt_column_list insert_rest InsertStmt WithOidsAs param_name -%type columnList DeleteStmt LockStmt UpdateStmt DeclareCursorStmt -%type NotifyStmt columnElem UnlistenStmt TableElement rowdefinition +%type opt_column_list insert_rest InsertStmt param_name +%type columnList DeleteStmt UpdateStmt DeclareCursorStmt +%type NotifyStmt columnElem UnlistenStmt TableElement fetch_count %type copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary -%type FetchStmt from_in CreateOpClassStmt like_including_defaults +%type FetchStmt from_in CreateOpClassStmt returning_clause %type ClosePortalStmt DropStmt VacuumStmt AnalyzeStmt opt_verbose -%type opt_full func_arg OptWithOids opt_freeze alter_table_cmd +%type opt_full func_arg OptWith opt_freeze alter_table_cmd %type analyze_keyword opt_name_list ExplainStmt index_params %type index_elem opt_class access_method_clause alter_table_cmds %type index_opt_unique IndexStmt func_return ConstInterval @@ -471,24 +584,24 @@ add_additional_variables(char *name, bool insert) %type def_elem def_list definition DefineStmt select_with_parens %type opt_instead event RuleActionList opt_using CreateAssertStmt %type RuleActionStmtOrEmpty RuleActionMulti func_as reindex_type -%type RuleStmt opt_column oper_argtypes NumConst -%type MathOp RemoveFuncStmt aggr_argtype for_update_clause +%type RuleStmt opt_column oper_argtypes NumConst var_name +%type MathOp RemoveFuncStmt ECPGunreserved_con opt_database_name %type RemoveAggrStmt opt_procedural select_no_parens CreateCastStmt -%type RemoveOperStmt RenameStmt all_Op opt_Trusted opt_lancompiler +%type RemoveOperStmt RenameStmt all_Op opt_trusted opt_lancompiler %type VariableSetStmt var_value zone_value VariableShowStmt %type VariableResetStmt AlterTableStmt from_list overlay_list -%type user_list OptUserList OptUserElem relation_name -%type CreateUserStmt AlterUserStmt CreateSeqStmt OptSeqList -%type OptSeqElem TriggerForSpec TriggerForOpt TriggerForType +%type relation_name OptTableSpace LockStmt opt_lock table_func_column_list +%type CreateUserStmt AlterUserStmt CreateSeqStmt SeqOptList +%type SeqOptElem TriggerForSpec TriggerForOpt TriggerForType %type DropTrigStmt TriggerOneEvent TriggerEvents RuleActionStmt %type TriggerActionTime CreateTrigStmt DropPLangStmt DropCastStmt %type CreatePLangStmt TriggerFuncArgs TriggerFuncArg simple_select %type ViewStmt LoadStmt CreatedbStmt createdb_opt_item ExplainableStmt %type createdb_opt_list opt_encoding OptInherit opt_equal -%type AlterUserSetStmt privilege_list privilege privilege_target -%type opt_grant_grant_option opt_revoke_grant_option cursor_options +%type privilege_list privilege privilege_target opt_if_exists +%type opt_grant_grant_option cursor_options DropOwnedStmt %type transaction_mode_list_or_empty transaction_mode_list -%type function_with_argtypes_list function_with_argtypes +%type function_with_argtypes_list function_with_argtypes IntConstVar %type DropdbStmt ClusterStmt grantee RevokeStmt Bit DropOpClassStmt %type GrantStmt privileges PosAllConst constraints_set_list %type ConstraintsSetStmt AllConst CreateDomainStmt opt_nowait @@ -496,67 +609,84 @@ add_additional_variables(char *name, bool insert) %type select_clause opt_select_limit select_limit_value opt_recheck %type ConstraintTimeSpec AlterDatabaseSetStmt DropAssertStmt %type select_offset_value ReindexStmt join_type opt_boolean -%type join_qual update_list joined_table opclass_item fetch_count -%type opt_lock lock_type OptGroupList OptGroupElem array_expr_list +%type join_qual joined_table opclass_item relation_expr_opt_alias +%type lock_type array_expr_list ReassignOwnedStmt for_locking_item %type OptConstrFromTable OptTempTableName StringConst array_expr -%type constraints_set_mode comment_type opt_empty_parentheses +%type constraints_set_mode comment_type opt_check_option %type CreateGroupStmt AlterGroupStmt DropGroupStmt key_delete %type opt_force key_update CreateSchemaStmt PosIntStringConst %type IntConst PosIntConst grantee_list func_type opt_or_replace -%type select_limit opt_for_update_clause CheckPointStmt +%type select_limit CheckPointStmt ECPGColId old_aggr_list %type OptSchemaName OptSchemaEltList schema_stmt opt_drop_behavior %type handler_name any_name_list any_name opt_as insert_column_list -%type columnref dotted_name function_name insert_target_el -%type insert_target_list insert_column_item DropRuleStmt -%type createfunc_opt_item set_rest var_list_or_default +%type columnref values_clause AllConstVar prep_type_clause ExecuteStmt +%type insert_column_item DropRuleStmt ctext_expr execute_param_clause +%type createfunc_opt_item set_rest %type CreateFunctionStmt createfunc_opt_list func_table %type DropUserStmt copy_from copy_opt_list copy_opt_item %type opt_oids TableLikeClause key_action opt_definition -%type cast_context row r_expr qual_Op qual_all_Op opt_default +%type cast_context row qual_Op qual_all_Op opt_default %type CreateConversionStmt any_operator opclass_item_list %type iso_level type_list CharacterWithLength ConstCharacter %type CharacterWithoutLength BitWithLength BitWithoutLength %type ConstBit GenericType TableFuncElementList opt_analyze -%type opt_sort_clause transaction_access_mode subquery_Op +%type opt_sort_clause subquery_Op transaction_mode_item %type ECPGWhenever ECPGConnect connection_target ECPGOpen -%type indicator ECPGExecute ECPGPrepare ecpg_using ecpg_into +%type indicator ecpg_using ecpg_into DeallocateStmt %type storage_declaration storage_clause opt_initializer c_anything %type variable_list variable c_thing c_term ECPGKeywords_vanames %type opt_pointer ECPGDisconnect dis_name storage_modifier -%type ECPGRelease execstring server_name ECPGVarDeclaration +%type execstring server_name ECPGVarDeclaration func_expr %type connection_object opt_server opt_port c_stuff c_stuff_item %type user_name opt_user char_variable ora_user ident opt_reference %type var_type_declarations quoted_ident_stringvar ECPGKeywords_rest -%type db_prefix server opt_options opt_connection_name c_list +%type db_prefix server connect_options opt_options opt_connection_name c_list %type ECPGSetConnection ECPGTypedef c_args ECPGKeywords ECPGCKeywords -%type enum_type civar civarind ECPGCursorStmt ECPGDeallocate -%type ECPGFree ECPGDeclare ECPGVar opt_at enum_definition +%type enum_type civar civarind ECPGCursorStmt PreparableStmt +%type ECPGFree ECPGDeclare ECPGVar at enum_definition opt_opt_value %type struct_union_type s_struct_union vt_declarations execute_rest %type var_declaration type_declaration single_vt_declaration %type ECPGSetAutocommit on_off variable_declarations ECPGDescribe %type ECPGAllocateDescr ECPGDeallocateDescr symbol opt_output -%type ECPGGetDescriptorHeader ECPGColLabel single_var_declaration +%type ECPGGetDescriptorHeader ECPGColLabel SetResetClause AlterUserSetStmt %type reserved_keyword unreserved_keyword ecpg_interval opt_ecpg_using -%type col_name_keyword func_name_keyword precision opt_scale -%type ECPGTypeName using_list ECPGColLabelCommon UsingConst -%type inf_val_list inf_col_list using_descriptor into_descriptor -%type ecpg_into_using prepared_name struct_union_type_with_symbol -%type ECPGunreserved ECPGunreserved_interval cvariable -%type AlterDatabaseOwnerStmt +%type col_name_keyword precision opt_scale ECPGExecuteImmediateStmt +%type ECPGTypeName using_list ECPGColLabelCommon UsingConst +%type using_descriptor into_descriptor opt_nulls_order opt_asc_desc +%type prepared_name struct_union_type_with_symbol OptConsTableSpace +%type ECPGunreserved ECPGunreserved_interval cvariable opt_bit_field +%type AlterOwnerStmt OptTableSpaceOwner CreateTableSpaceStmt +%type DropTableSpaceStmt indirection indirection_el ECPGSetDescriptorHeader +%type AlterDatabaseStmt CreateRoleStmt OptRoleList AlterRoleStmt AlterRoleSetStmt +%type DropRoleStmt add_drop opt_validator common_func_opt_item +%type opt_grant_admin_option AlterFunctionStmt alterfunc_opt_list opt_restrict +%type AlterObjectSchemaStmt alterdb_opt_list for_locking_clause opt_for_locking_clause +%type locked_rels_list opt_granted_by RevokeRoleStmt alterdb_opt_item using_clause +%type GrantRoleStmt opt_asymmetric aggr_args old_aggr_definition +%type old_aggr_elem for_locking_items TableLikeOptionList TableLikeOption +%type set_target_list set_clause_list set_clause multiple_set_clause +%type ctext_expr_list ctext_row single_set_clause set_target opt_type_modifiers +%type opclass_drop_list opclass_drop DropOpFamilyStmt opt_opfamily +%type CreateOpFamilyStmt AlterOpFamilyStmt create_as_target +%type xml_attributes xml_attribute_list document_or_content xml_whitespace_option +%type opt_xml_root_standalone xml_root_version xml_attribute_el +%type where_or_current_clause AlterTSConfigurationStmt AlterTSDictionaryStmt %type s_struct_union_symbol -%type ECPGGetDescriptor +%type ECPGGetDescriptor ECPGSetDescriptor %type simple_type signed_type unsigned_type %type descriptor_item desc_header_item -%type var_type +%type var_type + +%type PrepareStmt %type action -%type opt_array_bounds +%type opt_array_bounds %% prog: statements; @@ -565,22 +695,22 @@ statements: /*EMPTY*/ | statements statement ; -statement: ecpgstart opt_at stmt ';' { connection = NULL; } +statement: ecpgstart at stmt ';' { connection = NULL; } | ecpgstart stmt ';' | ecpgstart ECPGVarDeclaration { fprintf(yyout, "%s", $2); - free($2); + free($2); output_line_number(); } | ECPGDeclaration | c_thing { fprintf(yyout, "%s", $1); free($1); } | CPP_LINE { fprintf(yyout, "%s", $1); free($1); } | '{' { braces_open++; fputs("{", yyout); } - | '}' { remove_variables(braces_open--); fputs("}", yyout); } + | '}' { remove_typedefs(braces_open); remove_variables(braces_open--); fputs("}", yyout); } ; -opt_at: AT connection_target +at: AT connection_object { connection = $2; /* @@ -590,106 +720,142 @@ opt_at: AT connection_target */ if (argsinsert != NULL) argsinsert = NULL; - }; - -stmt: AlterDatabaseSetStmt { output_statement($1, 0, connection); } - | AlterDatabaseOwnerStmt { output_statement($1, 0, connection); } - | AlterDomainStmt { output_statement($1, 0, connection); } - | AlterGroupStmt { output_statement($1, 0, connection); } - | AlterSeqStmt { output_statement($1, 0, connection); } - | AlterTableStmt { output_statement($1, 0, connection); } - | AlterUserSetStmt { output_statement($1, 0, connection); } - | AlterUserStmt { output_statement($1, 0, connection); } - | AnalyzeStmt { output_statement($1, 0, connection); } - | CheckPointStmt { output_statement($1, 0, connection); } + } + ; + +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); } + | AlterTSConfigurationStmt { output_statement($1, 0, ECPGst_normal); } + | AlterTSDictionaryStmt { output_statement($1, 0, ECPGst_normal); } + | AlterUserStmt { output_statement($1, 0, ECPGst_normal); } + | AlterUserSetStmt { output_statement($1, 0, ECPGst_normal); } + | AnalyzeStmt { output_statement($1, 0, ECPGst_normal); } + | CheckPointStmt { output_statement($1, 0, ECPGst_normal); } | ClosePortalStmt { if (INFORMIX_MODE) { - /* Informix also has a CLOSE DATABASE command that - essantially works like a DISCONNECT CURRENT - as far as I know. */ + /* + * Informix also has a CLOSE DATABASE command that + * essantially works like a DISCONNECT CURRENT + * as far as I know. + */ if (pg_strcasecmp($1+strlen("close "), "database") == 0) { if (connection) - mmerror(PARSE_ERROR, ET_ERROR, "no at option for close database statement.\n"); - + mmerror(PARSE_ERROR, ET_ERROR, "no at option for close database statement\n"); + fprintf(yyout, "{ ECPGdisconnect(__LINE__, \"CURRENT\");"); - whenever_action(2); - free($1); + whenever_action(2); + free($1); } else - output_statement($1, 0, connection); + output_statement($1, 0, ECPGst_normal); } else - output_statement($1, 0, connection); + 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) + mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement\n"); + + output_deallocate_prepare_statement($1); } - | ClusterStmt { output_statement($1, 0, connection); } - | CommentStmt { output_statement($1, 0, connection); } - | ConstraintsSetStmt { output_statement($1, 0, connection); } - | CopyStmt { output_statement($1, 0, connection); } - | CreateAsStmt { output_statement($1, 0, connection); } - | CreateAssertStmt { output_statement($1, 0, connection); } - | CreateCastStmt { output_statement($1, 0, connection); } - | CreateConversionStmt { output_statement($1, 0, connection); } - | CreateDomainStmt { output_statement($1, 0, connection); } - | CreateFunctionStmt { output_statement($1, 0, connection); } - | CreateGroupStmt { output_statement($1, 0, connection); } - | CreatePLangStmt { output_statement($1, 0, connection); } - | CreateOpClassStmt { output_statement($1, 0, connection); } - | CreateSchemaStmt { output_statement($1, 0, connection); } - | CreateSeqStmt { output_statement($1, 0, connection); } - | CreateStmt { output_statement($1, 0, connection); } - | CreateTrigStmt { output_statement($1, 0, connection); } - | CreateUserStmt { output_statement($1, 0, connection); } - | CreatedbStmt { output_statement($1, 0, connection); } - /*| DeallocateStmt { output_statement($1, 0, connection); }*/ | DeclareCursorStmt { output_simple_statement($1); } - | DefineStmt { output_statement($1, 0, connection); } - | DeleteStmt { output_statement($1, 1, connection); } - | DropAssertStmt { output_statement($1, 0, connection); } - | DropCastStmt { output_statement($1, 0, connection); } - | DropGroupStmt { output_statement($1, 0, connection); } - | DropOpClassStmt { output_statement($1, 0, connection); } - | DropPLangStmt { output_statement($1, 0, connection); } - | DropRuleStmt { output_statement($1, 0, connection); } - | DropStmt { output_statement($1, 0, connection); } - | DropTrigStmt { output_statement($1, 0, connection); } - | DropUserStmt { output_statement($1, 0, connection); } - | DropdbStmt { output_statement($1, 0, connection); } - | ExplainStmt { output_statement($1, 0, connection); } -/* | ExecuteStmt { output_statement($1, 0, connection); }*/ - | FetchStmt { output_statement($1, 1, connection); } - | GrantStmt { output_statement($1, 0, connection); } - | IndexStmt { output_statement($1, 0, connection); } - | InsertStmt { output_statement($1, 1, connection); } - | ListenStmt { output_statement($1, 0, connection); } - | LoadStmt { output_statement($1, 0, connection); } - | LockStmt { output_statement($1, 0, connection); } - | NotifyStmt { output_statement($1, 0, connection); } -/* | PrepareStmt { output_statement($1, 0, connection); }*/ - | ReindexStmt { output_statement($1, 0, connection); } - | RemoveAggrStmt { output_statement($1, 0, connection); } - | RemoveOperStmt { output_statement($1, 0, connection); } - | RemoveFuncStmt { output_statement($1, 0, connection); } - | RenameStmt { output_statement($1, 0, connection); } - | RevokeStmt { output_statement($1, 0, connection); } - | RuleStmt { output_statement($1, 0, connection); } - | SelectStmt { output_statement($1, 1, connection); } + | 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); } + | ExecuteStmt { output_statement($1, 1, ECPGst_execute); } + | 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); } | TransactionStmt { fprintf(yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1); whenever_action(2); free($1); } - | TruncateStmt { output_statement($1, 0, connection); } - | UnlistenStmt { output_statement($1, 0, connection); } - | UpdateStmt { output_statement($1, 1, connection); } - | VacuumStmt { output_statement($1, 0, connection); } - | VariableSetStmt { output_statement($1, 0, connection); } - | VariableShowStmt { output_statement($1, 0, connection); } - | VariableResetStmt { output_statement($1, 0, connection); } - | ViewStmt { output_statement($1, 0, connection); } + | 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); } | ECPGAllocateDescr { fprintf(yyout,"ECPGallocate_desc(__LINE__, %s);",$1); @@ -699,7 +865,7 @@ stmt: AlterDatabaseSetStmt { output_statement($1, 0, connection); } | ECPGConnect { if (connection) - mmerror(PARSE_ERROR, ET_ERROR, "no at option for connect statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for connect statement\n"); fprintf(yyout, "{ ECPGconnect(__LINE__, %d, %s, %d); ", compat, $1, autocommit); reset_variables(); @@ -710,18 +876,10 @@ stmt: AlterDatabaseSetStmt { output_statement($1, 0, connection); } { output_simple_statement($1); } - | ECPGDeallocate - { - if (connection) - mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement.\n"); - fprintf(yyout, "{ ECPGdeallocate(__LINE__, %d, %s);", compat, $1); - whenever_action(2); - free($1); - } | ECPGDeallocateDescr { if (connection) - mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement\n"); fprintf(yyout,"ECPGdeallocate_desc(__LINE__, %s);",$1); whenever_action(0); free($1); @@ -737,27 +895,28 @@ stmt: AlterDatabaseSetStmt { output_statement($1, 0, connection); } fputs("ECPGt_EORT);", yyout); fprintf(yyout, "}"); output_line_number(); - + /* whenever_action(2); */ free($1); } | ECPGDisconnect { if (connection) - mmerror(PARSE_ERROR, ET_ERROR, "no at option for disconnect statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for disconnect statement\n"); fprintf(yyout, "{ ECPGdisconnect(__LINE__, %s);", $1 ? $1 : "\"CURRENT\""); whenever_action(2); free($1); } - | ECPGExecute - { - output_statement($1, 0, connection); - } + | ECPGExecuteImmediateStmt { output_statement($1, 0, ECPGst_exec_immediate); } | ECPGFree { - fprintf(yyout, "{ ECPGdeallocate(__LINE__, %d, \"%s\");", compat, $1); + const char *con = connection ? connection : "NULL"; + if (strcmp($1, "all")) + fprintf(yyout, "{ ECPGdeallocate(__LINE__, %d, %s, \"%s\");", compat, con, $1); + else + fprintf(yyout, "{ ECPGdeallocate_all(__LINE__, %d, %s);", compat, con); whenever_action(2); free($1); @@ -780,19 +939,12 @@ stmt: AlterDatabaseSetStmt { output_statement($1, 0, connection); } struct cursor *ptr; if ((ptr = add_additional_variables($1, true)) != NULL) - output_statement(mm_strdup(ptr->command), 0, ptr->connection ? mm_strdup(ptr->connection) : NULL); - ptr->opened = true; - } - | ECPGPrepare - { - if (connection) - mmerror(PARSE_ERROR, ET_ERROR, "no at option for prepare statement.\n"); - - fprintf(yyout, "{ ECPGprepare(__LINE__, %s);", $1); - whenever_action(2); - free($1); + { + connection = ptr->connection ? mm_strdup(ptr->connection) : NULL; + output_statement(mm_strdup(ptr->command), 0, 0); + ptr->opened = true; + } } - | ECPGRelease { /* output already done */ } | ECPGSetAutocommit { fprintf(yyout, "{ ECPGsetcommit(__LINE__, \"%s\", %s);", $1, connection ? connection : "NULL"); @@ -802,16 +954,29 @@ stmt: AlterDatabaseSetStmt { output_statement($1, 0, connection); } | ECPGSetConnection { if (connection) - mmerror(PARSE_ERROR, ET_ERROR, "no at option for set connection statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for set connection statement\n"); fprintf(yyout, "{ ECPGsetconn(__LINE__, %s);", $1); whenever_action(2); free($1); } + | 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); + } | ECPGTypedef { if (connection) - mmerror(PARSE_ERROR, ET_ERROR, "no at option for typedef statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for typedef statement\n"); fprintf(yyout, "%s", $1); free($1); @@ -820,14 +985,14 @@ stmt: AlterDatabaseSetStmt { output_statement($1, 0, connection); } | ECPGVar { if (connection) - mmerror(PARSE_ERROR, ET_ERROR, "no at option for var statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for var statement\n"); output_simple_statement($1); } | ECPGWhenever { if (connection) - mmerror(PARSE_ERROR, ET_ERROR, "no at option for whenever statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for whenever statement\n"); output_simple_statement($1); } @@ -840,144 +1005,165 @@ stmt: AlterDatabaseSetStmt { output_statement($1, 0, connection); } /***************************************************************************** * - * Create a new Postgres DBMS user + * Create a new Postgres DBMS role * * *****************************************************************************/ -CreateUserStmt: CREATE USER UserId opt_with OptUserList - { $$ = cat_str(4, make_str("create user"), $3, make_str("with"), $5); } +CreateRoleStmt: CREATE ROLE RoleId opt_with OptRoleList + { $$ = cat_str(4, make_str("create role"), $3, make_str("with"), $5); } ; opt_with: WITH { $$ = make_str("with"); } | /*EMPTY*/ { $$ = EMPTY; } ; +/* + * 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); } + | PASSWORD NULL_P { $$ = make_str("password null"); } + | 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"); } + | INHERIT { $$ = make_str("inherit"); } + | NOINHERIT { $$ = make_str("noinherit"); } + | CREATEDB { $$ = make_str("createdb"); } + | NOCREATEDB { $$ = make_str("nocreatedb"); } + | CREATEROLE { $$ = make_str("createrole"); } + | NOCREATEROLE { $$ = make_str("nocreaterole"); } + | LOGIN_P { $$ = make_str("login"); } + | NOLOGIN_P { $$ = make_str("nologin"); } + | 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); } + | IN_P ROLE name_list { $$ = cat2_str(make_str("in role"), $3); } + | IN_P GROUP_P name_list { $$ = cat2_str(make_str("in group"), $3); } + ; /***************************************************************************** * - * Alter a postgresql DBMS user - * + * Create a new Postgres DBMS user (role with implied login ability) * *****************************************************************************/ -AlterUserStmt: ALTER USER UserId OptUserList - { $$ = cat_str(3, make_str("alter user"), $3, $4); } - | ALTER USER UserId WITH OptUserList - { $$ = cat_str(4, make_str("alter user"), $3, make_str("with"), $5); } - ; +CreateUserStmt: + CREATE USER RoleId opt_with OptRoleList + {$$ = cat_str(4, make_str("create user"), $3, $4, $5); } + ; -AlterUserSetStmt: ALTER USER UserId SET set_rest - { $$ = cat_str(4, make_str("alter user"), $3, make_str("set"), $5); } - | ALTER USER UserId VariableResetStmt - { $$ = cat_str(3, make_str("alter user"), $3, $4); } - ; + /***************************************************************************** + * + * Alter a postgresql DBMS role + * + * + *****************************************************************************/ -/***************************************************************************** - * - * Drop a postgresql DBMS user - * - * - *****************************************************************************/ -DropUserStmt: DROP USER user_list - { $$ = cat2_str(make_str("drop user"), $3);} + AlterRoleStmt: ALTER ROLE RoleId opt_with OptRoleList + { $$ = cat_str(4, make_str("alter role"), $3, $4, $5); } ; -/* - * Options for CREATE USER and ALTER USER - */ -OptUserList: OptUserList OptUserElem { $$ = cat2_str($1, $2); } - | /* EMPTY */ { $$ = EMPTY; } - ; - -OptUserElem: PASSWORD Sconst - { $$ = cat2_str(make_str("password"), $2); } - | SYSID PosIntConst - { $$ = cat2_str(make_str("sysid"), $2); } - | CREATEDB - { $$ = make_str("createdb"); } - | NOCREATEDB - { $$ = make_str("nocreatedb"); } - | CREATEUSER - { $$ = make_str("createuser"); } - | NOCREATEUSER - { $$ = make_str("nocreateuser"); } - | IN_P GROUP_P user_list - { $$ = cat2_str(make_str("in group"), $3); } - | VALID UNTIL Sconst - { $$ = cat2_str(make_str("valid until"), $3); } - ; - -user_list: user_list ',' UserId - { $$ = cat_str(3, $1, make_str(","), $3); } - | UserId - { $$ = $1; } + AlterRoleSetStmt: ALTER ROLE RoleId SetResetClause + { $$ = cat_str(3, make_str("alter role"), $3, $4); } ; -/***************************************************************************** - * - * Create a postgresql group - * - * - ****************************************************************************/ -CreateGroupStmt: CREATE GROUP_P UserId OptGroupList - { $$ = cat_str(3, make_str("create group"), $3, $4); } - | CREATE GROUP_P UserId WITH OptGroupList - { $$ = cat_str(4, make_str("create group"), $3, make_str("with"), $5); } + /***************************************************************************** + * + * Alter a postgresql DBMS user + * + *****************************************************************************/ + + AlterUserStmt: ALTER USER RoleId opt_with OptRoleList + { $$ = cat_str(4, make_str("alter user"), $3, $4, $5); }; + + AlterUserSetStmt: ALTER USER RoleId SetResetClause + { $$ = cat_str(3, make_str("alter user"), $3, $4); } ; -/* - * Options for CREATE GROUP - */ -OptGroupList: OptGroupList OptGroupElem { $$ = cat2_str($1, $2); } - | /* EMPTY */ { $$ = EMPTY; } + /***************************************************************************** + * + * Drop a postgresql DBMS role + * + * + *****************************************************************************/ + DropRoleStmt: DROP ROLE name_list + { $$ = cat2_str(make_str("drop role"), $3);} + | DROP ROLE IF_P EXISTS name_list + { $$ = cat2_str(make_str("drop role if exists"), $5);} + ; + + /***************************************************************************** + * + * Drop a postgresql DBMS user + * + * + *****************************************************************************/ + DropUserStmt: DROP USER name_list + { $$ = cat2_str(make_str("drop user"), $3);} + | DROP USER IF_P EXISTS name_list + { $$ = cat2_str(make_str("drop user if exists"), $5);} + ; -OptGroupElem: USER user_list - { $$ = cat2_str(make_str("user"), $2); } - | SYSID PosIntConst - { $$ = cat2_str(make_str("sysid"), $2); } + /***************************************************************************** + * + * Create a postgresql group + * + * + ****************************************************************************/ + CreateGroupStmt: CREATE GROUP_P RoleId opt_with OptRoleList + { $$ = cat_str(4, make_str("create group"), $3, $4, $5); } ; + /***************************************************************************** + * + * Alter a postgresql group + * + * + *****************************************************************************/ + AlterGroupStmt: ALTER GROUP_P RoleId add_drop USER name_list + { $$ = cat_str(5, make_str("alter group"), $3, $4, make_str("user"), $6); } + ; -/***************************************************************************** - * - * Alter a postgresql group - * - * - *****************************************************************************/ -AlterGroupStmt: ALTER GROUP_P UserId ADD USER user_list - { $$ = cat_str(4, make_str("alter group"), $3, make_str("add user"), $6); } - | ALTER GROUP_P UserId DROP USER user_list - { $$ = cat_str(4, make_str("alter group"), $3, make_str("drop user"), $6); } + add_drop: ADD_P { $$ = make_str("add"); } + | DROP { $$ = make_str("drop"); } ; -/***************************************************************************** - * - * Drop a postgresql group - * - * - *****************************************************************************/ -DropGroupStmt: DROP GROUP_P UserId + /***************************************************************************** + * + * Drop a postgresql group + * + * + *****************************************************************************/ + DropGroupStmt: DROP GROUP_P name_list { $$ = cat2_str(make_str("drop group"), $3); } + | DROP GROUP_P IF_P EXISTS name_list + { $$ = cat2_str(make_str("drop group if exists"), $5); } ; -/***************************************************************************** - * - * Manipulate a schema - * - * - *****************************************************************************/ + /***************************************************************************** + * + * Manipulate a schema + * + * + *****************************************************************************/ -CreateSchemaStmt: CREATE SCHEMA UserId OptSchemaName AUTHORIZATION UserId OptSchemaEltList - { $$ = cat_str(6, make_str("create schema"), $3, $4, make_str("authorization"), $6, $7); } + CreateSchemaStmt: CREATE SCHEMA OptSchemaName AUTHORIZATION RoleId OptSchemaEltList + { $$ = 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); } ; -OptSchemaName: ColId { $$ = $1; } - | /* EMPTY */ { $$ = EMPTY; } - ; + OptSchemaName: ColId { $$ = $1; } + | /* EMPTY */ { $$ = EMPTY; } + ; OptSchemaEltList: OptSchemaEltList schema_stmt { $$ = cat2_str($1, $2); } | /* EMPTY */ { $$ = EMPTY; } @@ -988,12 +1174,12 @@ OptSchemaEltList: OptSchemaEltList schema_stmt { $$ = cat2_str($1, $2); * statement (in addition to by themselves). */ schema_stmt: CreateStmt { $$ = $1; } - | IndexStmt { $$ = $1; } - | CreateSeqStmt { $$ = $1; } - | CreateTrigStmt { $$ = $1; } - | GrantStmt { $$ = $1; } - | ViewStmt { $$ = $1; } - ; + | IndexStmt { $$ = $1; } + | CreateSeqStmt { $$ = $1; } + | CreateTrigStmt { $$ = $1; } + | GrantStmt { $$ = $1; } + | ViewStmt { $$ = $1; } + ; @@ -1013,10 +1199,18 @@ VariableSetStmt: SET set_rest { $$ = cat2_str(make_str("set session"), $3 ); } ; -set_rest: ColId TO var_list_or_default +set_rest: /* Generic SET syntaxes: */ + var_name TO var_list { $$ = cat_str(3, $1, make_str("to"), $3); } - | ColId "=" var_list_or_default - { $$ = cat_str(3, $1, make_str("="), $3); } + | var_name "=" var_list + { $$ = cat_str(3, $1, make_str("="), $3); } + | 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: */ | TIME ZONE zone_value { $$ = cat2_str(make_str("time zone"), $3); } | TRANSACTION transaction_mode_list @@ -1025,18 +1219,21 @@ set_rest: ColId TO var_list_or_default { $$ = cat2_str(make_str("session characteristics as transaction"), $5); } | NAMES opt_encoding { $$ = cat2_str(make_str("names"), $2); } + | ROLE ColId_or_Sconst + { $$ = cat2_str(make_str("role"), $2); } | SESSION AUTHORIZATION ColId_or_Sconst { $$ = cat2_str(make_str("session authorization"), $3); } | SESSION AUTHORIZATION DEFAULT { $$ = make_str("session authorization default"); } + | XML_P OPTION document_or_content + { $$ = cat2_str(make_str("xml option"), $3); } ; -var_list_or_default: var_list - { $$ = $1; } - | DEFAULT - { $$ = make_str("default"); } +var_name: ECPGColId { $$ = $1; } + | var_name '.' ColId { $$ = cat_str(3, $1, make_str("."), $3); } ; + var_list: var_value { $$ = $1; } | var_list ',' var_value @@ -1044,14 +1241,23 @@ var_list: var_value ; iso_level: READ UNCOMMITTED { $$ = make_str("read uncommitted"); } - | READ COMMITTED { $$ = make_str("read committed"); } - | REPEATABLE READ { $$ = make_str("repeatable read"); } - | SERIALIZABLE { $$ = make_str("serializable"); } + | READ COMMITTED { $$ = make_str("read committed"); } + | REPEATABLE READ { $$ = make_str("repeatable read"); } + | SERIALIZABLE { $$ = make_str("serializable"); } ; var_value: opt_boolean { $$ = $1; } - | AllConst { $$ = $1; } - | ColId { $$ = $1; } + | 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; + } + | ColId { $$ = $1; } ; opt_boolean: TRUE_P { $$ = make_str("true"); } @@ -1088,19 +1294,22 @@ ColId_or_Sconst: ColId { $$ = $1; } | StringConst { $$ = $1; } ; -VariableShowStmt: SHOW ColId +VariableShowStmt: SHOW var_name ecpg_into { $$ = cat2_str(make_str("show"), $2); } - | SHOW TIME ZONE + | SHOW TIME ZONE ecpg_into { $$ = make_str("show time zone"); } - | SHOW TRANSACTION ISOLATION LEVEL + | SHOW TRANSACTION ISOLATION LEVEL ecpg_into { $$ = make_str("show transaction isolation level"); } - | SHOW SESSION AUTHORIZATION + | SHOW SESSION AUTHORIZATION ecpg_into { $$ = make_str("show session authorization"); } | SHOW ALL - { $$ = make_str("show all"); } + { + mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL not implemented"); + $$ = EMPTY; + } ; -VariableResetStmt: RESET ColId +VariableResetStmt: RESET var_name { $$ = cat2_str(make_str("reset"), $2); } | RESET TIME ZONE { $$ = make_str("reset time zone"); } @@ -1112,13 +1321,19 @@ VariableResetStmt: RESET ColId { $$ = make_str("reset all"); } ; +/* SetResetClause allows SET or RESET without LOCAL */ +SetResetClause: + SET set_rest { $$ = cat2_str(make_str("set"), $2); } + | VariableResetStmt { $$ = $1; } + ; + 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"); } - | name_list + | qualified_name_list { $$ = $1; } ; @@ -1132,16 +1347,28 @@ constraints_set_mode: DEFERRED { $$ = make_str("deferred"); } CheckPointStmt: CHECKPOINT { $$= make_str("checkpoint"); } ; +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"); } + ; /***************************************************************************** * - * ALTER TABLE variations + * ALTER [ TABLE | INDEX | SEQUENCE | VIEW ] variations * *****************************************************************************/ AlterTableStmt: ALTER TABLE relation_expr alter_table_cmds { $$ = cat_str(3, make_str("alter table"), $3, $4); } + | 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); } ; alter_table_cmds: @@ -1150,48 +1377,97 @@ alter_table_cmds: ; alter_table_cmd: - ADD opt_column columnDef -/* ALTER TABLE ADD [COLUMN] */ +/* ALTER TABLE ADD [COLUMN] */ + ADD_P opt_column columnDef { $$ = cat_str(3, make_str("add"), $2, $3); } -/* ALTER TABLE ALTER [COLUMN] {SET DEFAULT |DROP DEFAULT} */ +/* ALTER TABLE ALTER [COLUMN] {SET DEFAULT |DROP DEFAULT} */ | ALTER opt_column ColId alter_column_default { $$ = cat_str(4, make_str("alter"), $2, $3, $4); } -/* ALTER TABLE ALTER [COLUMN] DROP NOT NULL */ +/* ALTER TABLE ALTER [COLUMN] DROP NOT NULL */ | ALTER opt_column ColId DROP NOT NULL_P { $$ = cat_str(4, make_str("alter"), $2, $3, make_str("drop not null")); } -/* ALTER TABLE ALTER [COLUMN] SET NOT NULL */ +/* ALTER TABLE ALTER [COLUMN] SET NOT NULL */ | ALTER opt_column ColId SET NOT NULL_P { $$ = cat_str(4, make_str("alter"), $2, $3, make_str("set not null")); } -/* ALTER TABLE ALTER [COLUMN] SET STATISTICS */ +/* ALTER TABLE ALTER [COLUMN] SET STATISTICS */ | ALTER opt_column ColId SET STATISTICS PosIntConst { $$ = cat_str(5, make_str("alter"), $2, $3, make_str("set statistics"), $6); } -/* ALTER TABLE ALTER [COLUMN] SET STORAGE */ +/* ALTER TABLE ALTER [COLUMN] SET STORAGE */ | ALTER opt_column ColId SET STORAGE ColId { $$ = cat_str(5, make_str("alter"), $2, $3, make_str("set storage"), $6); } -/* ALTER TABLE DROP [COLUMN] {RESTRICT|CASCADE} */ +/* ALTER TABLE DROP [COLUMN] {RESTRICT|CASCADE} */ | DROP opt_column ColId opt_drop_behavior { $$ = cat_str(4, make_str("drop"), $2, $3, $4); } -/* ALTER TABLE ALTER [COLUMN] TYPE [ USING ] */ +/* ALTER TABLE ALTER [COLUMN] TYPE [ USING ] */ | ALTER opt_column ColId TYPE_P Typename alter_using { $$ = cat_str(6, make_str("alter"), $2, $3, make_str("type"), $5, $6); } -/* ALTER TABLE ADD CONSTRAINT ... */ - | ADD TableConstraint +/* ALTER TABLE ADD CONSTRAINT ... */ + | ADD_P TableConstraint { $$ = cat_str(2, make_str("add"), $2); } -/* ALTER TABLE DROP CONSTRAINT ... */ +/* ALTER TABLE DROP CONSTRAINT ... */ | DROP CONSTRAINT name opt_drop_behavior { $$ = cat_str(3, make_str("drop constraint"), $3, $4); } -/* ALTER TABLE SET WITHOUT OIDS */ +/* ALTER TABLE SET WITHOUT OIDS */ | SET WITHOUT OIDS { $$ = make_str("set without oids"); } - /* ALTER TABLE CREATE TOAST TABLE */ - | CREATE TOAST TABLE - { $$ = make_str("create toast table"); } -/* ALTER TABLE OWNER TO UserId */ - | OWNER TO UserId - { $$ = cat_str(2, make_str("owner to"), $3); } /* ALTER TABLE CLUSTER ON */ | CLUSTER ON name { $$ = cat_str(2, make_str("cluster on"), $3); } +/* ALTER TABLE SET WITHOUT CLUSTER */ + | SET WITHOUT CLUSTER + { $$ = make_str("set without cluster"); } +/* ALTER TABLE ENABLE TRIGGER */ + | ENABLE_P TRIGGER name + { $$ = cat2_str(make_str("enable trigger"), $3); } +/* ALTER TABLE ENABLE ALWAYS TRIGGER */ + | ENABLE_P ALWAYS TRIGGER name + { $$ = cat2_str(make_str("enable always trigger"), $4); } +/* ALTER TABLE ENABLE REPLICA TRIGGER */ + | ENABLE_P REPLICA TRIGGER name + { $$ = cat2_str(make_str("enable replica trigger"), $4); } +/* ALTER TABLE ENABLE TRIGGER ALL */ + | ENABLE_P TRIGGER ALL + { $$ = make_str("enable trigger all"); } +/* ALTER TABLE ENABLE TRIGGER USER */ + | ENABLE_P TRIGGER USER + { $$ = make_str("enable trigger user"); } +/* ALTER TABLE DISABLE TRIGGER */ + | DISABLE_P TRIGGER name + { $$ = cat2_str(make_str("disable trigger"), $3); } +/* ALTER TABLE DISABLE TRIGGER ALL */ + | DISABLE_P TRIGGER ALL + { $$ = make_str("disable trigger all"); } +/* ALTER TABLE DISABLE TRIGGER USER */ + | DISABLE_P TRIGGER USER + { $$ = make_str("disable trigger user"); } +/* ALTER TABLE ENABLE RULE */ + | ENABLE_P RULE name + { $$ = cat2_str(make_str("enable rule"), $3); } +/* ALTER TABLE ENABLE ALWAYS RULE */ + | ENABLE_P ALWAYS RULE name + { $$ = cat2_str(make_str("enable always rule"), $4); } +/* ALTER TABLE ENABLE REPLICA RULE */ + | ENABLE_P REPLICA RULE name + { $$ = cat2_str(make_str("enable replica rule"), $4); } +/* ALTER TABLE DISABLE RULE */ + | DISABLE_P RULE name + { $$ = cat2_str(make_str("disable rule"), $3); } +/* ALTER TABLE ALTER INHERITS ADD */ + | INHERIT qualified_name + { $$ = cat2_str(make_str("inherit"), $2); } +/* ALTER TABLE NO INHERITS */ + | NO INHERIT qualified_name + { $$ = cat2_str(make_str("no inherit"), $3); } + /* ALTER OWNER TO RoleId */ + | OWNER TO RoleId + { $$ = cat2_str(make_str("owner to"), $3); } + /* ALTER SET TABLESPACE */ + | SET TABLESPACE name + { $$ = cat2_str(make_str("set tablespace"), $3); } + | SET definition + { $$ = cat2_str(make_str("set"), $2); } + | RESET definition + { $$ = cat2_str(make_str("reset"), $2); } ; alter_column_default: @@ -1199,15 +1475,15 @@ alter_column_default: | DROP DEFAULT { $$ = make_str("drop default"); } ; -opt_drop_behavior: CASCADE { $$ = make_str("cascade"); } - | RESTRICT { $$ = make_str("restrict"); } +opt_drop_behavior: CASCADE { $$ = make_str("cascade"); } + | RESTRICT { $$ = make_str("restrict"); } | /* EMPTY */ { $$ = EMPTY; } ; -alter_using: USING a_expr { $$ = cat2_str(make_str("using"), $2); } - | /* EMPTY */ { $$ = EMPTY; } +alter_using: USING a_expr { $$ = cat2_str(make_str("using"), $2); } + | /* EMPTY */ { $$ = EMPTY; } ; - + /***************************************************************************** * * QUERY : @@ -1216,34 +1492,37 @@ alter_using: USING a_expr { $$ = cat2_str(make_str("using"), $2); } *****************************************************************************/ ClosePortalStmt: CLOSE name - { - $$ = cat2_str(make_str("close"), $2); - } + { $$ = cat2_str(make_str("close"), $2); } + | CLOSE ALL + { $$ = make_str("close all"); } ; -/***************************************************************************** - * - * QUERY : - * COPY [BINARY] FROM/TO - * [USING DELIMITERS ] - * - *****************************************************************************/ - CopyStmt: COPY opt_binary qualified_name opt_oids copy_from copy_file_name copy_delimiter opt_with copy_opt_list - { $$ = cat_str(9, make_str("copy"), $2, $3, $4, $5, $6, $7, $8, $9); } + { + if (strcmp($5, "to") == 0 && strcmp($6, "stdin") == 0) + mmerror(PARSE_ERROR, ET_ERROR, "copy to stdin not possible\n"); + else if (strcmp($5, "from") == 0 && strcmp($6, "stdout") == 0) + mmerror(PARSE_ERROR, ET_ERROR, "copy from stdout not possible\n"); + else if (strcmp($5, "from") == 0 && strcmp($6, "stdin") == 0) + mmerror(PARSE_ERROR, ET_WARNING, "copy from stdin not implemented\n"); + + $$ = cat_str(9, make_str("copy"), $2, $3, $4, $5, $6, $7, $8, $9); + } + | COPY select_with_parens TO copy_file_name opt_with copy_opt_list + { + if (strcmp($4, "stdin") == 0) + mmerror(PARSE_ERROR, ET_ERROR, "copy to stdin is not possible\n"); + + $$ = cat_str(6, make_str("copy"), $2, make_str("to"), $4, $5, $6); + } ; copy_from: TO { $$ = make_str("to"); } | FROM { $$ = make_str("from"); } ; -/* - * copy_file_name NULL indicates stdio is used. Whether stdin or stdout is - * used depends on the direction. (It really doesn't make sense to copy from - * stdout. We silently correct the "typo". - AY 9/94 - */ -copy_file_name: StringConst { $$ = $1; } +copy_file_name: StringConst { $$ = $1; } | STDIN { $$ = make_str("stdin"); } | STDOUT { $$ = make_str("stdout"); } ; @@ -1259,6 +1538,7 @@ copy_opt_item: BINARY { $$ = make_str("binary"); } | NULL_P opt_as StringConst { $$ = cat_str(3, make_str("null"), $2, $3); } | CSV { $$ = make_str("csv"); } + | HEADER_P { $$ = make_str("header"); } | QUOTE opt_as Sconst { $$ = cat_str(3, make_str("quote"), $2, $3); } | ESCAPE opt_as Sconst @@ -1267,7 +1547,7 @@ copy_opt_item: BINARY { $$ = make_str("binary"); } { $$ = cat2_str(make_str("force quote"), $3); } | FORCE NOT NULL_P columnList { $$ = cat2_str(make_str("force not null"), $4); } - + ; opt_binary: BINARY { $$ = make_str("binary"); } @@ -1300,11 +1580,11 @@ opt_using: USING { $$ = make_str("using"); } *****************************************************************************/ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' - OptInherit OptWithOids OnCommitOption - { $$ = cat_str(10, make_str("create"), $2, make_str("table"), $4, make_str("("), $6, make_str(")"), $8, $9, $10); } + OptInherit OptWith OnCommitOption OptTableSpace + { $$ = cat_str(11, make_str("create"), $2, make_str("table"), $4, make_str("("), $6, make_str(")"), $8, $9, $10, $11); } | CREATE OptTemp TABLE qualified_name OF qualified_name - '(' OptTableElementList ')' OptWithOids OnCommitOption - { $$ = cat_str(11, make_str("create"), $2, make_str("table"), $4, make_str("of"), $6, make_str("("), $8, make_str(")"), $10, $11); } + '(' OptTableElementList ')' OptWith OnCommitOption OptTableSpace + { $$ = cat_str(12, make_str("create"), $2, make_str("table"), $4, make_str("of"), $6, make_str("("), $8, make_str(")"), $10, $11, $12); } ; /* @@ -1313,12 +1593,12 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' */ OptTemp: TEMPORARY { $$ = make_str("temporary"); } - | TEMP { $$ = make_str("temp"); } + | TEMP { $$ = make_str("temp"); } | LOCAL TEMPORARY { $$ = make_str("local temporary"); } | LOCAL TEMP { $$ = make_str("local temp"); } | GLOBAL TEMPORARY { $$ = make_str("global temporary"); } | GLOBAL TEMP { $$ = make_str("global temp"); } - | /*EMPTY*/ { $$ = EMPTY; } + | /*EMPTY*/ { $$ = EMPTY; } ; @@ -1338,10 +1618,8 @@ TableElement: columnDef { $$ = $1; } | TableConstraint { $$ = $1; } ; -columnDef: ColId Typename ColQualList - { - $$ = cat_str(3, $1, $2, $3); - } +columnDef: ColId Typename ColQualList + {$$ = cat_str(3, $1, $2, $3); } ; ColQualList: ColQualList ColConstraint { $$ = cat2_str($1,$2); } @@ -1369,10 +1647,10 @@ ColConstraintElem: NOT NULL_P { $$ = make_str("not null"); } | NULL_P { $$ = make_str("null"); } - | UNIQUE - { $$ = make_str("unique"); } - | PRIMARY KEY - { $$ = make_str("primary key"); } + | 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); } | CHECK '(' a_expr ')' { $$ = cat_str(3, make_str("check ("), $3, make_str(")")); } | DEFAULT b_expr @@ -1393,22 +1671,28 @@ ColConstraintElem: NOT NULL_P * there is no parsing conflict. */ ConstraintAttr: DEFERRABLE { $$ = make_str("deferrable"); } - | NOT DEFERRABLE { $$ = make_str("not deferrable"); } + | NOT DEFERRABLE { $$ = make_str("not deferrable"); } | INITIALLY DEFERRED { $$ = make_str("initially deferred"); } | INITIALLY IMMEDIATE { $$ = make_str("initially immediate"); } ; -TableLikeClause: LIKE qualified_name like_including_defaults - { - $$ = cat_str(3, make_str("like"), $2, $3); - } +TableLikeClause: LIKE qualified_name TableLikeOptionList + {$$ = cat_str(3, make_str("like"), $2, $3); } + ; + +TableLikeOptionList: TableLikeOptionList TableLikeOption + { $$ = cat2_str($1, $2); } + | /* EMPTY */ { $$ = EMPTY; } ; -like_including_defaults: +TableLikeOption: INCLUDING DEFAULTS { $$ = make_str("including defaults"); } - | EXCLUDING DEFAULTS { $$ = make_str("excluding defaults"); } - | /* EMPTY */ { $$ = EMPTY; } - ; + | EXCLUDING DEFAULTS { $$ = make_str("excluding defaults"); } + | INCLUDING CONSTRAINTS { $$ = make_str("including constraints"); } + | EXCLUDING CONSTRAINTS { $$ = make_str("excluding constraints"); } + | INCLUDING INDEXES { $$ = make_str("including indexes"); } + | EXCLUDING INDEXES { $$ = make_str("excluding indexes"); } + ; /* ConstraintElem specifies constraint syntax which is not embedded into * a column definition. ColConstraintElem specifies the embedded form. @@ -1422,24 +1706,24 @@ TableConstraint: CONSTRAINT name ConstraintElem ConstraintElem: CHECK '(' a_expr ')' { $$ = cat_str(3, make_str("check("), $3, make_str(")")); } - | UNIQUE '(' columnList ')' - { $$ = cat_str(3, make_str("unique("), $3, make_str(")")); } - | PRIMARY KEY '(' columnList ')' - { $$ = cat_str(3, make_str("primary key("), $4, make_str(")")); } + | 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); } | 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); } ; opt_column_list: '(' columnList ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); } - | /*EMPTY*/ { $$ = EMPTY; } - ; + | /*EMPTY*/ { $$ = EMPTY; } + ; columnList: columnList ',' columnElem - { $$ = cat_str(3, $1, make_str(","), $3); } - | columnElem - { $$ = $1; } - ; + { $$ = cat_str(3, $1, make_str(","), $3); } + | columnElem + { $$ = $1; } + ; columnElem: ColId { $$ = $1; } ; @@ -1448,7 +1732,7 @@ key_match: MATCH FULL { $$ = make_str("match full"); } | MATCH PARTIAL { - mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported FOREIGN KEY/MATCH PARTIAL will be passed to backend"); + mmerror(PARSE_ERROR, ET_WARNING, "currently unsupported FOREIGN KEY/MATCH PARTIAL will be passed to backend"); $$ = make_str("match partial"); } | /*EMPTY*/ @@ -1470,7 +1754,7 @@ key_update: ON UPDATE key_action { $$ = cat2_str(make_str("on update"), $3); } ; -key_action: NO ACTION { $$ = make_str("no action"); } +key_action: NO ACTION { $$ = make_str("no action"); } | RESTRICT { $$ = make_str("restrict"); } | CASCADE { $$ = make_str("cascade"); } | SET DEFAULT { $$ = make_str("set default"); } @@ -1483,46 +1767,47 @@ OptInherit: INHERITS '(' qualified_name_list ')' { $$ = EMPTY; } ; -OptWithOids: WITH OIDS { $$ = make_str("with oids"); } - | WITHOUT OIDS { $$ = make_str("without oids"); } - | /*EMPTY*/ { $$ = EMPTY; } +OptWith: WITH definition { $$ = cat2_str(make_str("with"), $2); } + | WITH OIDS { $$ = make_str("with oids"); } + | WITHOUT OIDS { $$ = make_str("without oids"); } + | /*EMPTY*/ { $$ = EMPTY; } ; -OnCommitOption: ON COMMIT DROP { $$ = make_str("on commit drop"); } +OnCommitOption: ON COMMIT DROP { $$ = make_str("on commit drop"); } | ON COMMIT DELETE_P ROWS { $$ = make_str("on commit delete rows"); } | ON COMMIT PRESERVE ROWS { $$ = make_str("on commit preserve rows"); } - | /*EMPTY*/ { $$ = EMPTY; } + | /*EMPTY*/ { $$ = EMPTY; } + ; + +OptTableSpace: TABLESPACE name { $$ = cat2_str(make_str("tablespace"), $2); } + | /*EMPTY*/ { $$ = EMPTY; } ; +OptConsTableSpace: USING INDEX TABLESPACE name { $$ = cat2_str(make_str("using index tablespace"), $4); } + | /*EMPTY*/ { $$ = EMPTY; } + ; /* * Note: CREATE TABLE ... AS SELECT ... is just another spelling for * SELECT ... INTO. */ -CreateAsStmt: CREATE OptTemp TABLE qualified_name OptCreateAs WithOidsAs AS +CreateAsStmt: CREATE OptTemp TABLE create_as_target AS { FoundInto = 0; } SelectStmt { if (FoundInto == 1) - mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE / AS SELECT may not specify INTO"); + mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE / AS SELECT cannot specify INTO"); - $$ = cat_str(8, make_str("create"), $2, make_str("table"), $4, $5, $6, make_str("as"), $9); + $$ = cat_str(6, make_str("create"), $2, make_str("table"), $4, make_str("as"), $7); } ; -/* - * To avoid a shift/reduce conflict in CreateAsStmt, we need to - * include the 'AS' terminal in the parsing of WITH/WITHOUT - * OIDS. Unfortunately that means this production is effectively a - * duplicate of OptWithOids. - */ -WithOidsAs: - WITH OIDS AS { $$ = make_str("with oids as"); } - | WITHOUT OIDS AS { $$ = make_str("without oids as"); } - | AS { $$ = make_str("as"); } - ; - +create_as_target: qualified_name OptCreateAs OptWith OnCommitOption OptTableSpace + { + $$ = cat_str(5, $1, $2, $3, $4, $5); + } + ; OptCreateAs: '(' CreateAsList ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); } @@ -1547,19 +1832,23 @@ CreateAsElement: ColId { $$ = $1; } * *****************************************************************************/ -CreateSeqStmt: CREATE OptTemp SEQUENCE qualified_name OptSeqList - { $$ = cat_str(4, make_str("create"), $2, make_str("sequence"), $4, $5); } +CreateSeqStmt: CREATE OptTemp SEQUENCE qualified_name OptSeqOptList + { $$ = cat_str(5, make_str("create"), $2, make_str("sequence"), $4, $5); } ; -AlterSeqStmt: ALTER SEQUENCE qualified_name OptSeqList +AlterSeqStmt: ALTER SEQUENCE relation_expr SeqOptList { $$ = cat_str(3,make_str("alter sequence"), $3, $4); } ; -OptSeqList: OptSeqList OptSeqElem { $$ = cat2_str($1, $2); } - | /*EMPTY*/ { $$ = EMPTY; } +OptSeqOptList: SeqOptList { $$ = $1; } + | /*EMPTY*/ { $$ = EMPTY; } + ; + +SeqOptList: SeqOptElem { $$ = $1; } + | SeqOptList SeqOptElem { $$ = cat2_str($1, $2); } ; -OptSeqElem: CACHE NumConst +SeqOptElem: CACHE NumConst { $$ = cat2_str(make_str("cache"), $2); } | CYCLE { $$ = make_str("cycle"); } @@ -1575,8 +1864,12 @@ OptSeqElem: CACHE NumConst { $$ = make_str("no maxvalue"); } | NO MINVALUE { $$ = make_str("no minvalue"); } + | OWNED BY any_name + { $$ = cat2_str(make_str("owned by"), $3); } | START opt_with NumConst { $$ = cat_str(3, make_str("start"), $2, $3); } + | RESTART + { $$ = make_str("restart"); } | RESTART opt_with NumConst { $$ = cat_str(3, make_str("restart"), $2, $3); } ; @@ -1593,25 +1886,30 @@ opt_by: BY { $$ = make_str("by"); } * *****************************************************************************/ -CreatePLangStmt: CREATE opt_Trusted opt_procedural LANGUAGE ColId_or_Sconst - HANDLER handler_name opt_lancompiler - { $$ = cat_str(8, make_str("create"), $2, $3, make_str("language"), $5, make_str("handler"), $7, $8); } +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); } ; -opt_Trusted: TRUSTED { $$ = make_str("trusted"); } +opt_trusted: TRUSTED { $$ = make_str("trusted"); } | /*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 '('). - * Work around by using name and dotted_name separately. + * Work around by using simple names instead. */ -handler_name: name - { $$ = $1; } - | dotted_name - { $$ = $1; /* XXX changing soon */ } - ; +handler_name: name { $$ = $1; } + | name attrs { $$ = cat2_str($1, $2); } + ; +opt_validator: VALIDATOR handler_name + { $$ = cat2_str(make_str("validator"), $2); } + | /*EMPTY*/ + { $$ = ""; } + ; opt_lancompiler: LANCOMPILER StringConst { $$ = cat2_str(make_str("lancompiler"), $2); } | /*EMPTY*/ @@ -1620,12 +1918,47 @@ opt_lancompiler: LANCOMPILER StringConst DropPLangStmt: DROP opt_procedural LANGUAGE StringConst opt_drop_behavior { $$ = cat_str(5, make_str("drop"), $2, make_str("language"), $4, $5); } + | 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); } ; opt_procedural: PROCEDURAL { $$ = make_str("prcedural"); } | /*EMPTY*/ { $$ = EMPTY; } ; +/***************************************************************************** + * + * 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 + * + * No need for drop behaviour as we cannot implement dependencies for + * objects in other databases; we can only support RESTRICT. + * + ****************************************************************************/ + + +DropTableSpaceStmt: DROP TABLESPACE name + { $$ = cat2_str(make_str("drop tablespace"), $3); } + | DROP TABLESPACE IF_P EXISTS name + { $$ = cat2_str(make_str("drop tablespace if exists"), $5); } + ; + + /***************************************************************************** * * QUERIES : @@ -1635,13 +1968,11 @@ opt_procedural: PROCEDURAL { $$ = make_str("prcedural"); } *****************************************************************************/ CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON - qualified_name TriggerForSpec - EXECUTE PROCEDURE - name '(' TriggerFuncArgs ')' + qualified_name TriggerForSpec EXECUTE PROCEDURE name + '(' TriggerFuncArgs ')' { $$ = 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 - qualified_name OptConstrFromTable - ConstraintAttributeSpec + qualified_name OptConstrFromTable ConstraintAttributeSpec 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(")")); } @@ -1691,7 +2022,7 @@ TriggerFuncArg: PosAllConst { $$ = $1; } ; OptConstrFromTable: /* Empty */ { $$ = EMPTY; } - | FROM qualified_name { $$ = cat2_str(make_str("from"), $2); } + | FROM qualified_name { $$ = cat2_str(make_str("from"), $2); } ; ConstraintAttributeSpec: ConstraintDeferrabilitySpec { $$ = $1; } @@ -1710,6 +2041,10 @@ ConstraintAttributeSpec: ConstraintDeferrabilitySpec { $$ = $1; } $$ = cat2_str($1, $2); } + | /* EMPTY */ + { + $$ = EMPTY; + } ; ConstraintDeferrabilitySpec: NOT DEFERRABLE @@ -1726,6 +2061,8 @@ ConstraintTimeSpec: INITIALLY IMMEDIATE DropTrigStmt: DROP TRIGGER name ON qualified_name opt_drop_behavior { $$ = cat_str(5, make_str("drop trigger"), $3, make_str("on"), $5, $6); } + | 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); } ; /***************************************************************************** @@ -1736,19 +2073,19 @@ DropTrigStmt: DROP TRIGGER name ON qualified_name opt_drop_behavior * *****************************************************************************/ CreateAssertStmt: CREATE ASSERTION name - 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); - } + 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); + } ; DropAssertStmt: DROP ASSERTION name - { - mmerror(PARSE_ERROR, ET_ERROR, "DROP ASSERTION is not yet supported"); - $$ = cat2_str(make_str("drop assertion"), $3); - } - ; + { + mmerror(PARSE_ERROR, ET_ERROR, "DROP ASSERTION is not yet supported"); + $$ = cat2_str(make_str("drop assertion"), $3); + } + ; /***************************************************************************** @@ -1758,18 +2095,28 @@ DropAssertStmt: DROP ASSERTION name * *****************************************************************************/ -DefineStmt: CREATE AGGREGATE func_name definition +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 { $$ = cat_str(3, make_str("create aggregate"), $3, $4); } | CREATE OPERATOR all_Op definition { $$ = cat_str(3, make_str("create operator"), $3, $4); } | CREATE TYPE_P any_name definition { $$ = cat_str(3, make_str("create type"), $3, $4); } - | CREATE TYPE_P any_name AS rowdefinition - { $$ = cat_str(4, make_str("create type"), $3, make_str("as"), $5); } - ; - -rowdefinition: '(' TableFuncElementList ')' - { $$ = cat_str(3, make_str("("), $2, make_str(")"));} + | 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(")")); } + | 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(")")); } + | 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); } ; definition: '(' def_list ')' @@ -1785,21 +2132,40 @@ def_elem: ColLabel '=' def_arg { $$ = cat_str(3, $1, make_str("="), $3); } ; /* Note: any simple identifier will be returned as a type name! */ -def_arg: func_return { $$ = $1; } - | qual_all_Op { $$ = $1; } - | AllConst { $$ = $1; } +def_arg: func_type { $$ = $1; } + | reserved_keyword { $$ = $1; } + | qual_all_Op { $$ = $1; } + | AllConst { $$ = $1; } ; -CreateOpClassStmt: CREATE OPERATOR CLASS any_name opt_default FOR TYPE_P Typename - USING access_method AS opclass_item_list - { - $$ = cat_str(9, make_str("create operator class"), $4, $5, make_str("for type"), $8, make_str("using"), $10, make_str("as"), $12); - } - ; +aggr_args: '(' type_list ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); } + | '(' '*' ')' { $$ = 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); } + ; + +enum_val_list: StringConst { $$ = $1; } + | enum_val_list ',' StringConst { $$ = cat_str(3, $1, make_str(","), $3);} + ; + +CreateOpClassStmt: CREATE OPERATOR CLASS any_name opt_default FOR TYPE_P Typename + USING access_method opt_opfamily AS opclass_item_list + { + $$ = cat_str(10, make_str("create operator class"), $4, $5, make_str("for type"), $8, make_str("using"), $10, $11, make_str("as"), $13); + } + ; opclass_item_list: opclass_item { $$ = $1; } - | opclass_item_list ',' opclass_item { $$ = cat_str(3, $1, make_str(","), $3); } - ; + | opclass_item_list ',' opclass_item { $$ = cat_str(3, $1, make_str(","), $3); } + ; opclass_item: OPERATOR PosIntConst any_operator opt_recheck { $$ = cat_str(4, make_str("operator"), $2, $3, $4); } @@ -1807,65 +2173,136 @@ opclass_item: OPERATOR PosIntConst any_operator opt_recheck { $$ = cat_str(7, make_str("operator"), $2, $3, make_str("("), $5, make_str(")"), $7); } | FUNCTION PosIntConst func_name func_args { $$ = cat_str(4, make_str("function"), $2, $3, $4); } + | FUNCTION PosIntConst '(' type_list ')' func_name func_args + { $$ = cat_str(7, make_str("function"), $2, make_str("("), $4, make_str(")"), $6, $7); } | STORAGE Typename { $$ = cat2_str(make_str("storage"), $2); } ; opt_default: DEFAULT { $$ = make_str("default"); } - | /*EMPTY*/ { $$ = EMPTY; } - ; + | /*EMPTY*/ { $$ = EMPTY; } + ; -opt_recheck: RECHECK { $$ = make_str("recheck"); } - | /*EMPTY*/ { $$ = EMPTY; } - ; +opt_opfamily: FAMILY any_name { $$ = cat2_str(make_str("family"), $2); } + | /*EMPTY*/ { $$ = EMPTY; } + ; + +opt_recheck: RECHECK { + mmerror(PARSE_ERROR, ET_WARNING, "no longer supported RECHECK OPTION will be passed to backend"); + $$ = make_str("recheck"); + } + | /*EMPTY*/ { $$ = EMPTY; } + ; + +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(")")); } + ; 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); } + | 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); } + ; + +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); } + ; + +/***************************************************************************** + * + * QUERY: + * + * DROP OWNED BY username [, username ...] [ RESTRICT | CASCADE ] + * REASSIGN OWNED BY username [, username ...] TO username + * + *****************************************************************************/ +DropOwnedStmt: + DROP OWNED BY name_list opt_drop_behavior + {$$ = cat_str(3, make_str("drop owned by"), $4, $5); } + ; + +ReassignOwnedStmt: + REASSIGN OWNED BY name_list TO name + {$$ = cat_str(4, make_str("reassign owned by"), $4, make_str("to"), $6); } ; /***************************************************************************** * * QUERY: * - * DROP itemtype itemname [, itemname ...] + * DROP itemtype [ IF EXISTS ] itemname [, itemname ...] [ RESTRICT | CASCADE ] * *****************************************************************************/ -DropStmt: DROP drop_type any_name_list opt_drop_behavior +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); } + | DROP drop_type any_name_list opt_drop_behavior { $$ = cat_str(4, make_str("drop"), $2, $3, $4); } ; -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"); } +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"); } ; any_name_list: any_name - { $$ = $1; } - | any_name_list ',' any_name - { $$ = cat_str(3, $1, make_str(","), $3); } - ; + { $$ = $1; } + | any_name_list ',' any_name + { $$ = cat_str(3, $1, make_str(","), $3); } + ; + +any_name: ColId { $$ = $1; } + | ColId attrs { $$ = cat2_str($1, $2); } + ; + +attrs: '.' attr_name { $$ = cat2_str(make_str("."), $2); } + | attrs '.' attr_name { $$ = cat_str(3, $1, make_str("."), $3); } + ; -any_name: ColId - { $$ = $1; } - | dotted_name - { $$ = $1; } - ; /***************************************************************************** * * QUERY: - * truncate table relname + * truncate table relname1, relname2, .... * *****************************************************************************/ -TruncateStmt: TRUNCATE opt_table qualified_name - { $$ = cat_str(3, make_str("truncate table"), $2, $3); } +TruncateStmt: TRUNCATE opt_table qualified_name_list opt_restart_seqs opt_drop_behavior + { $$ = cat_str(5, make_str("truncate table"), $2, $3, $4, $5); } ; +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; } + ; + /***************************************************************************** * * QUERY: @@ -1874,47 +2311,47 @@ TruncateStmt: TRUNCATE opt_table qualified_name *****************************************************************************/ /* This is different from the backend as we try to be compatible with many other - * embedded SQL implementations. So we accept their syntax as well and + * embedded SQL implementations. So we accept their syntax as well and * translate it to the PGSQL syntax. */ - -FetchStmt: FETCH fetch_direction from_in name ecpg_into_using + +FetchStmt: FETCH fetch_direction from_in name ecpg_into { add_additional_variables($4, false); $$ = cat_str(4, make_str("fetch"), $2, $3, $4); } - | FETCH fetch_direction name ecpg_into_using + | FETCH fetch_direction name ecpg_into { add_additional_variables($3, false); $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3); } - | FETCH from_in name ecpg_into_using + | FETCH from_in name ecpg_into { - add_additional_variables($3, false); + add_additional_variables($3, false); $$ = cat_str(3, make_str("fetch"), $2, $3); } - | FETCH name ecpg_into_using + | FETCH name ecpg_into { - add_additional_variables($2, false); + add_additional_variables($2, false); $$ = cat2_str(make_str("fetch"), $2); } | FETCH fetch_direction from_in name { - add_additional_variables($4, false); + add_additional_variables($4, false); $$ = cat_str(4, make_str("fetch"), $2, $3, $4); } | FETCH fetch_direction name { - add_additional_variables($3, false); + add_additional_variables($3, false); $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3); } - | FETCH from_in name + | FETCH from_in name { add_additional_variables($3, false); $$ = cat_str(3, make_str("fetch"), $2, $3); } - | FETCH name + | FETCH name { - add_additional_variables($2, false); + add_additional_variables($2, false); $$ = cat2_str(make_str("fetch"), $2); } | MOVE fetch_direction from_in name @@ -1939,8 +2376,16 @@ fetch_direction: NEXT { $$ = make_str("next"); } | BACKWARD ALL { $$ = make_str("backward all"); } ; -fetch_count: IntConst { $$ = $1; } - ; +fetch_count: IntConst { + if ($1[1] == '$') + { + /* a variable here has to be replaced on the client side, thus we have to use '$0' here */ + $$ = make_str("$0"); + free($1); + } + else + $$ = $1; + } from_in: IN_P { $$ = make_str("in"); } | FROM { $$ = make_str("from"); } @@ -1948,8 +2393,8 @@ from_in: IN_P { $$ = make_str("in"); } CommentStmt: COMMENT ON comment_type name IS comment_text { $$ = cat_str(5, make_str("comment on"), $3, $4, make_str("is"), $6); } - | COMMENT ON AGGREGATE func_name '(' aggr_argtype ')' IS comment_text - { $$ = cat_str(6, make_str("comment on aggregate"), $4, make_str("("), $6, make_str(") is"), $9); } + | COMMENT ON AGGREGATE func_name aggr_args IS comment_text + { $$ = cat_str(5, make_str("comment on aggregate"), $4, $5, make_str("is"), $7); } | COMMENT ON FUNCTION func_name func_args IS comment_text { $$ = cat_str(5, make_str("comment on function"), $4, $5, make_str("is"), $7); } | COMMENT ON OPERATOR all_Op '(' oper_argtypes ')' IS comment_text @@ -1962,24 +2407,36 @@ CommentStmt: COMMENT ON comment_type name IS comment_text { $$ = cat_str(4, make_str("comment on rule"), $4, make_str("is"), $6); } | 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); } + | 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); } | 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); } + | 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); } ; comment_type: COLUMN { $$ = make_str("column"); } - | 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"); } - | CONVERSION_P { $$ = make_str("conversion"); } + | 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"); } + | CONVERSION_P { $$ = make_str("conversion"); } + | TABLESPACE { $$ = make_str("tablespace"); } + | ROLE { $$ = make_str("role"); } ; comment_text: StringConst { $$ = $1; } @@ -1997,11 +2454,10 @@ GrantStmt: GRANT privileges ON privilege_target TO grantee_list opt_grant_grant_ { $$ = cat_str(7, make_str("grant"), $2, make_str("on"), $4, make_str("to"), $6, $7); } ; -RevokeStmt: REVOKE opt_revoke_grant_option privileges ON privilege_target FROM grantee_list opt_drop_behavior - { - $$ = cat_str(9, make_str("revoke"), $2, $3, make_str("on"), $5, make_str("from"), $7, $8); - } - +RevokeStmt: REVOKE privileges ON privilege_target FROM grantee_list opt_drop_behavior + {$$ = cat_str(7, make_str("revoke"), $2, make_str("on"), $4, make_str("from"), $6, $7); } + | REVOKE GRANT OPTION FOR privileges ON privilege_target FROM grantee_list opt_drop_behavior + {$$ = cat_str(7, make_str("revoke grant option for"), $5, make_str("on"), $7, make_str("from"), $9, $10); } ; privileges: ALL PRIVILEGES { $$ = make_str("all privileges"); } @@ -2016,23 +2472,17 @@ privilege_list: privilege ; privilege: SELECT { $$ = make_str("select"); } - | INSERT { $$ = make_str("insert"); } - | UPDATE { $$ = make_str("update"); } - | DELETE_P { $$ = make_str("delete"); } - | RULE { $$ = make_str("rule"); } | REFERENCES { $$ = make_str("references"); } - | TRIGGER { $$ = make_str("trigger"); } - | EXECUTE { $$ = make_str("execute"); } - | USAGE { $$ = make_str("usage"); } | CREATE { $$ = make_str("create"); } - | TEMPORARY { $$ = make_str("temporary"); } - | TEMP { $$ = make_str("temp"); } + | ColId { $$ = $1; } ; privilege_target: qualified_name_list { $$ = $1; } | TABLE qualified_name_list { $$ = cat2_str(make_str("table"), $2); } + | SEQUENCE qualified_name_list + { $$ = cat2_str(make_str("sequence"), $2); } | FUNCTION function_with_argtypes_list { $$ = cat2_str(make_str("function"), $2); } | DATABASE name_list @@ -2041,6 +2491,8 @@ privilege_target: qualified_name_list { $$ = cat2_str(make_str("language") , $2); } | SCHEMA name_list { $$ = cat2_str(make_str("schema") , $2); } + | TABLESPACE name_list + { $$ = cat2_str(make_str("tablespace") , $2); } ; grantee_list: grantee @@ -2049,24 +2501,16 @@ grantee_list: grantee { $$ = cat_str(3, $1, make_str(","), $3); } ; -grantee: ColId { $$ = $1; } - | GROUP_P ColId { $$ = cat2_str(make_str("group"), $2); } +grantee: RoleId { $$ = $1; } + | GROUP_P RoleId { $$ = cat2_str(make_str("group"), $2); } ; opt_grant_grant_option: WITH GRANT OPTION { - mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported GRANT/WITH GRANT OPTION will be passed to backend"); + mmerror(PARSE_ERROR, ET_WARNING, "currently unsupported GRANT/WITH GRANT OPTION will be passed to backend"); $$ = make_str("with grant option"); } - | /*EMPTY*/ { $$ = EMPTY; } - ; - -opt_revoke_grant_option: GRANT OPTION FOR - { - mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported REVOKE/GRANT OPTION FOR will be passed to backend"); - $$ = make_str("grant option for"); - } - | /*EMPTY*/ { $$ = EMPTY; } + | /*EMPTY*/ { $$ = EMPTY; } ; function_with_argtypes_list: function_with_argtypes @@ -2077,18 +2521,49 @@ function_with_argtypes_list: function_with_argtypes function_with_argtypes: func_name func_args { $$ = cat2_str($1, $2); }; +/***************************************************************************** + * + * GRANT and REVOKE ROLE statements + * + *****************************************************************************/ + +GrantRoleStmt: + 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); } + ; + +RevokeRoleStmt: + 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); } + ; + +opt_grant_admin_option: WITH ADMIN OPTION { $$ = make_str("with admin option"); } + | /*EMPTY*/ { $$ = EMPTY; } + ; + +opt_granted_by: GRANTED BY RoleId { $$ = cat2_str(make_str("granted by"), $3); } + | /*EMPTY*/ { $$ = EMPTY; } + ; + /***************************************************************************** * * QUERY: - * create index on - * [ using ] "(" ( | using ] )+ ")" - * [ where ] + * 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. * *****************************************************************************/ IndexStmt: CREATE index_opt_unique INDEX index_name ON qualified_name - access_method_clause '(' index_params ')' where_clause - { $$ = cat_str(11, make_str("create"), $2, make_str("index"), $4, make_str("on"), $6, $7, make_str("("), $9, make_str(")"), $11); } + 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); } + | 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); } ; index_opt_unique: UNIQUE { $$ = make_str("unique"); } @@ -2105,22 +2580,38 @@ index_params: index_elem { $$ = $1; } | index_params ',' index_elem { $$ = cat_str(3, $1, make_str(","), $3); } ; -index_elem: attr_name opt_class - { $$ = cat2_str($1, $2); } - | func_name '(' expr_list ')' opt_class - { $$ = cat_str(5, $1, make_str("("), $3, ")", $5); } - | '(' a_expr ')' opt_class - { $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); } - ; +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); } + ; opt_class: any_name { $$ = $1; } | USING any_name { $$ = cat2_str(make_str("using"), $2); } | /*EMPTY*/ { $$ = EMPTY; } ; +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; } + ; + CreateFunctionStmt: CREATE opt_or_replace FUNCTION func_name func_args RETURNS func_return createfunc_opt_list opt_definition { $$ = cat_str(8, make_str("create"), $2, make_str("function"), $4, $5, make_str("returns"), $7, $8); } + | 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); } + | CREATE opt_or_replace FUNCTION func_name func_args + createfunc_opt_list opt_definition + { $$ = cat_str(6, make_str("create"), $2, make_str("function"), $4, $5, $6, $7); } ; opt_or_replace: OR REPLACE { $$ = make_str("or replace"); } @@ -2139,25 +2630,18 @@ func_args_list: func_arg { $$ = cat_str(3, $1, make_str(","), $3); } ; -func_arg: arg_class param_name func_type { $$ = cat_str(3, $1, $2, $3); } - | arg_class func_type { $$ = cat2_str($1, $2); } +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; } ; -arg_class: IN_P { $$ = make_str("in"); } - | OUT_P - { - mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported CREATE FUNCTION/OUT will be passed to backend"); - - $$ = make_str("out"); - } - | INOUT - { - mmerror(PARSE_ERROR, ET_WARNING, "Currently unsupported CREATE FUNCTION/INOUT will be passed to backend"); - - $$ = make_str("inout"); - } - | /*EMPTY*/ - { $$ = EMPTY; } +arg_class: IN_P { $$ = make_str("in"); } + | OUT_P { $$ = make_str("out"); } + | INOUT { $$ = make_str("inout"); } + | IN_P OUT_P { $$ = make_str("in out"); } + | VARIADIC { $$ = make_str("variadic"); } ; func_as: StringConst @@ -2166,7 +2650,7 @@ func_as: StringConst { $$ = cat_str(3, $1, make_str(","), $3); } ; -param_name: function_name { $$ = $1; }; +param_name: type_function_name { $$ = $1; }; func_return: func_type { @@ -2180,8 +2664,10 @@ func_return: func_type func_type: Typename { $$ = $1; } - | type_name attrs '%' TYPE_P + | type_function_name attrs '%' TYPE_P { $$ = cat_str(3, $1, $2, make_str("% type")); } + | SETOF type_function_name attrs '%' TYPE_P + { $$ = cat_str(4, make_str("setof"), $2, $3, make_str("% type")); } ; @@ -2191,22 +2677,19 @@ createfunc_opt_list: createfunc_opt_item { $$ = cat2_str($1, $2); } ; -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: + 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"); } | IMMUTABLE { $$ = make_str("immutable"); } | STABLE { $$ = make_str("stable"); } | VOLATILE { $$ = make_str("volatile"); } - | 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"); } | EXTERNAL SECURITY DEFINER { $$ = make_str("external security definer"); } | EXTERNAL SECURITY INVOKER @@ -2215,41 +2698,80 @@ createfunc_opt_item: AS func_as { $$ = make_str("security definer"); } | SECURITY INVOKER { $$ = make_str("security invoker"); } + | COST NumConst + { $$ = cat2_str(make_str("cost"), $2); } + | ROWS NumConst + { $$ = cat2_str(make_str("rows"), $2); } + | SetResetClause + { $$ = $1; } + ; + +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; } ; opt_definition: WITH definition { $$ = cat2_str(make_str("with"), $2); } - | /*EMPTY*/ { $$ = EMPTY; } - ; + | /*EMPTY*/ { $$ = EMPTY; } + ; + +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); } + ; + +AlterFunctionStmt: + ALTER FUNCTION function_with_argtypes alterfunc_opt_list opt_restrict + { $$ = cat_str(4, make_str("alter function"), $3, $4, $5); } + ; + +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"); } + | /*EMPTY*/ { $$ = EMPTY; } + ; /***************************************************************************** * * QUERY: * * DROP FUNCTION funcname (arg1, arg2, ...) - * DROP AGGREGATE aggname (aggtype) + * DROP AGGREGATE (arg1, ...) [ RESTRICT | CASCADE ] * DROP OPERATOR opname (leftoperand_typ rightoperand_typ) * *****************************************************************************/ RemoveFuncStmt: DROP FUNCTION func_name func_args opt_drop_behavior { $$ = cat_str(4, make_str("drop function"), $3, $4, $5); } + | DROP FUNCTION IF_P EXISTS func_name func_args opt_drop_behavior + { $$ = cat_str(4, make_str("drop function if exists"), $5, $6, $7); } ; -RemoveAggrStmt: DROP AGGREGATE func_name '(' aggr_argtype ')' opt_drop_behavior - { $$ = cat_str(6, make_str("drop aggregate"), $3, make_str("("), $5, make_str(")"), $7); } +RemoveAggrStmt: DROP AGGREGATE func_name aggr_args opt_drop_behavior + { $$ = cat_str(4, make_str("drop aggregate"), $3, $4, $5); } + | DROP AGGREGATE IF_P EXISTS func_name aggr_args opt_drop_behavior + { $$ = cat_str(4, make_str("drop aggregate if exists"), $5, $6, $7); } ; -aggr_argtype: Typename { $$ = $1; } - | '*' { $$ = make_str("*"); } - ; - - RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')' opt_drop_behavior { $$ = cat_str(6, make_str("drop operator"), $3, make_str("("), $5, make_str(")"), $7); } + | DROP OPERATOR IF_P EXISTS any_operator '(' oper_argtypes ')' opt_drop_behavior + { $$ = cat_str(6, make_str("drop operator if exists"), $5, make_str("("), $7, make_str(")"), $9); } ; oper_argtypes: Typename - { mmerror(PARSE_ERROR, ET_ERROR, "parser: argument type missing (use NONE for unary operators)"); } + { + mmerror(PARSE_ERROR, ET_ERROR, "parser: argument type missing (use NONE for unary operators)"); + $$ = make_str("none"); + } | Typename ',' Typename { $$ = cat_str(3, $1, make_str(","), $3); } | NONE ',' Typename /* left unary */ @@ -2259,16 +2781,16 @@ oper_argtypes: Typename ; any_operator: - all_Op - { $$ = $1; } - | ColId '.' any_operator - { $$ = cat_str(3, $1, make_str("."), $3); } - ; + all_Op + { $$ = $1; } + | ColId '.' any_operator + { $$ = cat_str(3, $1, make_str("."), $3); } + ; CreateCastStmt: CREATE CAST '(' Typename AS Typename ')' WITH FUNCTION function_with_argtypes cast_context { $$ = cat_str(6, make_str("create cast ("), $4, make_str("as"), $6, make_str(") with function"), $10); } - | CREATE CAST '(' Typename AS Typename ')' + | CREATE CAST '(' Typename AS Typename ')' WITHOUT FUNCTION cast_context { $$ = cat_str(6, make_str("create cast ("), $4, make_str("as"), $6, make_str(") without function"), $10); } ; @@ -2278,8 +2800,12 @@ cast_context: AS ASSIGNMENT { $$ = make_str("as assignment"); } ; -DropCastStmt: DROP CAST '(' Typename AS Typename ')' opt_drop_behavior - { $$ = cat_str(6, make_str("drop cast ("), $4, make_str("as"), $6, make_str(")"), $8); } +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; } ; /***************************************************************************** @@ -2291,6 +2817,8 @@ DropCastStmt: DROP CAST '(' Typename AS Typename ')' opt_drop_behavior *****************************************************************************/ ReindexStmt: REINDEX reindex_type qualified_name opt_force { $$ = cat_str(4, make_str("reindex"), $2, $3, $4); } + | REINDEX SYSTEM_P name opt_force + { $$ = cat_str(3, make_str("reindex system"), $3, $4); } | REINDEX DATABASE name opt_force { $$ = cat_str(3, make_str("reindex database"), $3, $4); } ; @@ -2311,36 +2839,115 @@ opt_force: FORCE { $$ = make_str("force"); } * *****************************************************************************/ -RenameStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' RENAME TO name - { $$ = cat_str(6, make_str("alter aggregate"), $3, make_str("("), $5, make_str(") rename to"), $9); } - | ALTER CONVERSION_P any_name RENAME TO name +RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name + { $$ = cat_str(5, make_str("alter aggregate"), $3, $4, make_str("rename to"), $7); } + | ALTER CONVERSION_P any_name RENAME TO name { $$ = cat_str(4, make_str("alter conversion"), $3, make_str("rename to"), $6); } - | ALTER DATABASE database_name RENAME TO database_name + | ALTER DATABASE database_name RENAME TO database_name { $$ = cat_str(4, make_str("alter database"), $3, make_str("rename to"), $6); } - | ALTER FUNCTION func_name func_args RENAME TO name - { $$ = cat_str(5, make_str("alter function"), $3, $4, make_str("rename to"), $7); } - | ALTER GROUP_P UserId RENAME TO UserId + | ALTER FUNCTION function_with_argtypes RENAME TO name + { $$ = cat_str(4, make_str("alter function"), $3, make_str("rename to"), $6); } + | ALTER GROUP_P RoleId RENAME TO RoleId { $$ = cat_str(4, make_str("alter group"), $3, make_str("rename to"), $6); } - | ALTER LANGUAGE name RENAME TO name - { $$ = cat_str(4, make_str("alter language"), $3, make_str("rename to"), $6); } - | ALTER OPERATOR CLASS any_name USING access_method RENAME TO name + | ALTER opt_procedural LANGUAGE name RENAME TO name + { $$ = cat_str(6, make_str("alter"), $2, make_str("language"), $4, make_str("rename to"), $7); } + | ALTER OPERATOR CLASS any_name USING access_method RENAME TO name { $$ = cat_str(6, make_str("alter operator class"), $4, make_str("using"), $6, make_str("rename to"), $9); } - | ALTER SCHEMA name RENAME TO name + | 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); } + | ALTER SCHEMA name RENAME TO name { $$ = cat_str(4, make_str("alter schema"), $3, make_str("rename to"), $6); } - | ALTER TABLE relation_expr RENAME TO name + | ALTER TABLE relation_expr RENAME TO name { $$ = cat_str(4, make_str("alter table"), $3, make_str("rename to"), $6); } - | ALTER TABLE relation_expr RENAME opt_column name TO name + | ALTER TABLE relation_expr SET SCHEMA name + { $$ = cat_str(4, make_str("alter table"), $3, make_str("set schema"), $6); } + | 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); } + | ALTER INDEX relation_expr RENAME TO name + { $$ = cat_str(4, make_str("alter index"), $3, make_str("rename to"), $6); } + | ALTER TABLE relation_expr RENAME opt_column name TO name { $$ = cat_str(7, make_str("alter table"), $3, make_str("rename"), $5, $6, make_str("to"), $8); } - | ALTER TRIGGER name ON relation_expr RENAME TO name + | ALTER TRIGGER name ON relation_expr RENAME TO name { $$ = cat_str(6, make_str("alter trigger"), $3, make_str("on"), $5, make_str("rename to"), $8); } - | ALTER USER UserId RENAME TO UserId + | ALTER USER RoleId RENAME TO RoleId { $$ = cat_str(4, make_str("alter user"), $3, make_str("rename to"), $6); } + | ALTER TABLESPACE name RENAME TO name + { $$ = cat_str(4, make_str("alter tablespace"), $3, make_str("rename to"), $6); } + | 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); } + | ALTER TYPE_P any_name RENAME TO name + { $$ = cat_str(4, make_str("alter type"), $3, make_str("rename to"), $6); } ; opt_column: COLUMN { $$ = make_str("column"); } | /*EMPTY*/ { $$ = EMPTY; } ; +/***************************************************************************** + * + * ALTER THING name SET SCHEMA name + * + *****************************************************************************/ + +AlterObjectSchemaStmt: + ALTER AGGREGATE func_name aggr_args SET SCHEMA name + { $$ = cat_str(5, make_str("alter aggregate"), $3, $4, make_str("set schema"), $7); } + | ALTER DOMAIN_P any_name SET SCHEMA name + { $$ = cat_str(4, make_str("alter domain"), $3, make_str("set schema"), $6); } + | ALTER FUNCTION function_with_argtypes SET SCHEMA name + { $$ = cat_str(4, make_str("alter function"), $3, make_str("set schema"), $6); } + | ALTER SEQUENCE relation_expr SET SCHEMA name + { $$ = cat_str(4, make_str("alter sequence"), $3, make_str("set schema"), $6); } + | ALTER VIEW relation_expr SET SCHEMA name + { $$ = 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); } + ; + +/***************************************************************************** + * + * ALTER THING name OWNER TO newname + * + *****************************************************************************/ + +AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId + { $$ = cat_str(5, make_str("alter aggregate"), $3, $4, make_str("owner to"), $7); } + | ALTER CONVERSION_P any_name OWNER TO RoleId + { $$ = cat_str(4, make_str("alter conversion"), $3, make_str("owner to"), $6); } + | ALTER DATABASE database_name OWNER TO RoleId + { $$ = cat_str(4, make_str("alter database"), $3, make_str("owner to"), $6); } + | ALTER DOMAIN_P database_name OWNER TO RoleId + { $$ = cat_str(4, make_str("alter domain"), $3, make_str("owner to"), $6); } + | ALTER FUNCTION function_with_argtypes OWNER TO RoleId + { $$ = cat_str(4, make_str("alter function"), $3, make_str("owner to"), $6); } + | ALTER opt_procedural LANGUAGE name OWNER TO RoleId + { $$ = cat_str(6, make_str("alter"), $2, make_str("language"), $4, make_str("owner to"), $7); } + | ALTER OPERATOR any_operator '(' oper_argtypes ')' OWNER TO RoleId + { $$ = cat_str(6, make_str("alter operator"), $3, make_str("("), $5, make_str(") owner to"), $9); } + | ALTER OPERATOR CLASS any_name USING access_method OWNER TO RoleId + { $$ = cat_str(6, make_str("alter operator class"), $4, make_str("using"), $6, make_str("owner to"), $9); } + | 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); } + | ALTER SCHEMA name OWNER TO RoleId + { $$ = cat_str(4, make_str("alter schema"), $3, make_str("owner to"), $6); } + | ALTER TYPE_P any_name OWNER TO RoleId + { $$ = cat_str(4, make_str("alter type"), $3, make_str("owner to"), $6); } + | ALTER TABLESPACE name OWNER TO RoleId + { $$ = cat_str(4, make_str("alter tablespace"), $3, make_str("owner to"), $6); } + | 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); } + ; + /***************************************************************************** * @@ -2378,15 +2985,16 @@ RuleActionStmt: SelectStmt ; RuleActionStmtOrEmpty: RuleActionStmt { $$ = $1; } - | /*EMPTY*/ { $$ = EMPTY; } - ; + | /*EMPTY*/ { $$ = EMPTY; } + ; /* change me to select, update, etc. some day */ event: SELECT { $$ = make_str("select"); } | UPDATE { $$ = make_str("update"); } | DELETE_P { $$ = make_str("delete"); } | INSERT { $$ = make_str("insert"); } - ; + | TRUNCATE { $$ = make_str("truncate"); } + ; opt_instead: INSTEAD { $$ = make_str("instead"); } | ALSO { $$ = make_str("also"); } @@ -2394,7 +3002,9 @@ opt_instead: INSTEAD { $$ = make_str("instead"); } ; DropRuleStmt: DROP RULE name ON qualified_name opt_drop_behavior - { $$ = cat_str(5, make_str("drop rule"), $3, make_str("on"), $5, $6);} + { $$ = cat_str(5, make_str("drop rule"), $3, make_str("on"), $5, $6);} + | 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);} ; /***************************************************************************** @@ -2405,15 +3015,15 @@ DropRuleStmt: DROP RULE name ON qualified_name opt_drop_behavior * *****************************************************************************/ -NotifyStmt: NOTIFY qualified_name - { $$ = cat2_str(make_str("notify"), $2); } +NotifyStmt: NOTIFY ColId + { $$ = cat2_str(make_str("notify"), $2); } ; -ListenStmt: LISTEN qualified_name - { $$ = cat2_str(make_str("listen"), $2); } +ListenStmt: LISTEN ColId + { $$ = cat2_str(make_str("listen"), $2); } ; -UnlistenStmt: UNLISTEN qualified_name +UnlistenStmt: UNLISTEN ColId { $$ = cat2_str(make_str("unlisten"), $2); } | UNLISTEN '*' { $$ = make_str("unlisten *"); } @@ -2428,51 +3038,82 @@ UnlistenStmt: UNLISTEN qualified_name * (also older versions END / ABORT) * *****************************************************************************/ -TransactionStmt: ABORT_P opt_transaction { $$ = make_str("rollback"); } +TransactionStmt: ABORT_P opt_transaction { $$ = make_str("rollback"); } | 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); } - | COMMIT opt_transaction { $$ = make_str("commit"); } - | END_P opt_transaction { $$ = make_str("commit"); } - | ROLLBACK opt_transaction { $$ = make_str("rollback"); } - ; - -opt_transaction: WORK { $$ = EMPTY; } + | COMMIT opt_transaction { $$ = make_str("commit"); } + | END_P opt_transaction { $$ = make_str("commit"); } + | ROLLBACK opt_transaction { $$ = make_str("rollback"); } + | SAVEPOINT ColId { $$ = cat2_str(make_str("savepoint"), $2); } + | RELEASE SAVEPOINT ColId { $$ = cat2_str(make_str("release savepoint"), $3); } + | 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); } + | 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); } + ; + +opt_transaction: WORK { $$ = EMPTY; } | TRANSACTION { $$ = EMPTY; } | /*EMPTY*/ { $$ = EMPTY; } ; +transaction_mode_item: + ISOLATION LEVEL iso_level + { $$ = cat2_str(make_str("isolation level"), $3); } + | READ ONLY { $$ = make_str("read only"); } + | READ WRITE { $$ = make_str("read write"); } + ; + transaction_mode_list: - ISOLATION LEVEL iso_level - { $$ = cat2_str(make_str("isolation level"), $3); } - | transaction_access_mode - { $$ = $1; } - | ISOLATION LEVEL iso_level transaction_access_mode - { $$ = cat_str(3, make_str("isolation level"), $3, $4); } - | transaction_access_mode ISOLATION LEVEL iso_level - { $$ = cat_str(3, $1, make_str("isolation level"), $4); } - ; - + 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); } + ; + transaction_mode_list_or_empty: - transaction_mode_list { $$ = $1; } - | /* EMPTY */ { $$ = EMPTY; } - ; + transaction_mode_list { $$ = $1; } + | /* EMPTY */ { $$ = EMPTY; } + ; -transaction_access_mode: - READ ONLY { $$ = make_str("read only"); } - | READ WRITE { $$ = make_str("read write"); } - ; - /***************************************************************************** * - * QUERY: - * define view '('target-list ')' [where ] + * QUERY: + * CREATE [ OR REPLACE ] [ TEMP ] VIEW '('target-list ')' + * AS [ WITH [ CASCADED | LOCAL ] CHECK OPTION ] * *****************************************************************************/ -ViewStmt: CREATE opt_or_replace VIEW qualified_name opt_column_list AS SelectStmt - { $$ = cat_str(7, make_str("create"), $2, make_str("view"), $4, $5, make_str("as"), $7); } +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); } ; +/* + * We use merged tokens here to avoid creating shift/reduce conflicts against + * a whole lot of other uses of WITH. + */ +opt_check_option: + WITH_CHECK OPTION + { + mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented"); + $$ = EMPTY; + } + | WITH_CASCADED CHECK OPTION + { + mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented"); + $$ = EMPTY; + } + | WITH_LOCAL CHECK OPTION + { + mmerror(PARSE_ERROR, ET_ERROR, "WITH CHECK OPTION not implemented"); + $$ = EMPTY; + } + | /* EMPTY */ + { $$ = EMPTY; } + ; /***************************************************************************** * @@ -2505,7 +3146,11 @@ createdb_opt_list: createdb_opt_item { $$ = cat2_str($1, $2); } ; -createdb_opt_item: LOCATION opt_equal StringConst +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 { $$ = cat_str(3,make_str("location"), $2, $3); } | LOCATION opt_equal DEFAULT { $$ = cat_str(3, make_str("location"), $2, make_str("default")); } @@ -2517,6 +3162,8 @@ createdb_opt_item: LOCATION opt_equal StringConst { $$ = cat_str(3, make_str("encoding"), $2, $3); } | ENCODING opt_equal DEFAULT { $$ = cat_str(3, make_str("encoding"), $2, make_str("default")); } + | CONNECTION LIMIT opt_equal PosIntConst + { $$ = cat_str(3, make_str("connection limit"), $3, $4); } | OWNER opt_equal name { $$ = cat_str(3, make_str("owner"), $2, $3); } | OWNER opt_equal DEFAULT @@ -2535,23 +3182,34 @@ opt_equal: '=' { $$ = make_str("="); } * *****************************************************************************/ -AlterDatabaseOwnerStmt: ALTER DATABASE database_name OWNER TO UserId - { $$ = cat_str(4, make_str("alter database"), $3, make_str("owner to"), $6); } -AlterDatabaseSetStmt: ALTER DATABASE database_name SET set_rest - { $$ = cat_str(4, make_str("alter database"), $3, make_str("set"), $5); } - | ALTER DATABASE database_name VariableResetStmt +AlterDatabaseStmt: ALTER DATABASE database_name opt_with alterdb_opt_list + { $$ = cat_str(4, make_str("alter database"), $3, $4, $5); } + ; + +AlterDatabaseSetStmt: ALTER DATABASE database_name SetResetClause { $$ = cat_str(3, make_str("alter database"), $3, $4); } ; +alterdb_opt_list: + alterdb_opt_list alterdb_opt_item { $$ = cat2_str($1, $2);} + | /* EMPTY */ { $$ = EMPTY; } + ; + +alterdb_opt_item: + CONNECTION LIMIT opt_equal PosIntConst { $$ = cat_str(3, make_str("connection limit"), $3, $4); } + ; + /***************************************************************************** * - * DROP DATABASE + * DROP DATABASE [ IF EXISTS ] * * *****************************************************************************/ DropdbStmt: DROP DATABASE database_name { $$ = cat2_str(make_str("drop database"), $3); } + | DROP DATABASE IF_P EXISTS database_name + { $$ = cat2_str(make_str("drop database if exists"), $5); } ; @@ -2562,35 +3220,53 @@ DropdbStmt: DROP DATABASE database_name *****************************************************************************/ CreateDomainStmt: CREATE DOMAIN_P any_name opt_as Typename ColQualList - { - $$ = cat_str(55555, make_str("create domain"), $3, $4, $5, $6); - } + { + $$ = cat_str(5, make_str("create domain"), $3, $4, $5, $6); + } ; AlterDomainStmt: - 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 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); } - | ALTER DOMAIN_P any_name OWNER TO UserId - { $$ = cat_str(4, make_str("alter domain"), $3, make_str("owner to"), $6); } - ; - + 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); } + ; + opt_as: AS {$$ = make_str("as"); } - | /* EMPTY */ {$$ = EMPTY; } - ; + | /* EMPTY */ {$$ = EMPTY; } + ; + +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); } + ; CreateConversionStmt: - 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); } - ; + 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); } + ; /***************************************************************************** * @@ -2601,14 +3277,18 @@ CreateConversionStmt: * *****************************************************************************/ -ClusterStmt: CLUSTER index_name ON qualified_name - { $$ = cat_str(4, make_str("cluster"), $2, make_str("on"), $4); } - | CLUSTER qualified_name - { $$ = cat2_str(make_str("cluster"), $2); } - | CLUSTER - { $$ = make_str("cluster"); } - ; +ClusterStmt: CLUSTER qualified_name cluster_index_specification + { $$ = cat_str(3,make_str("cluster"), $2, $3); } + | CLUSTER + { $$ = make_str("cluster"); } + | CLUSTER qualified_name ON qualified_name + { $$ = cat_str(4, make_str("cluster"), $2, make_str("on"), $4); } + ; +cluster_index_specification: + USING index_name { $$ = cat2_str(make_str("using"), $2); } + | /*EMPTY*/ { $$ = EMPTY; } + ; /***************************************************************************** * @@ -2633,7 +3313,7 @@ AnalyzeStmt: analyze_keyword opt_verbose ; analyze_keyword: ANALYZE { $$ = make_str("analyze"); } - | ANALYSE { $$ = make_str("analyse"); } + | ANALYSE { $$ = make_str("analyse"); } ; opt_verbose: VERBOSE { $$ = make_str("verbose"); } @@ -2669,54 +3349,60 @@ ExplainStmt: EXPLAIN opt_analyze opt_verbose ExplainableStmt ExplainableStmt: SelectStmt | InsertStmt - | UpdateStmt + | UpdateStmt | DeleteStmt | DeclareCursorStmt - /* | ExecuteStmt */ - ; + | ExecuteStmt + ; opt_analyze: - analyze_keyword { $$ = $1; } - | /* EMPTY */ { $$ = EMPTY; } - ; - -/* - -conflicts with ecpg + analyze_keyword { $$ = $1; } + | /* EMPTY */ { $$ = EMPTY; } + ; -PrepareStmt: PREPARE name prep_type_clause AS PreparableStmt - { $$ = cat_str(5, make_str("prepare"), $2, $3, make_str("as"), $5); } +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; + } ; PreparableStmt: - SelectStmt - | InsertStmt - | UpdateStmt - | DeleteStmt - ; + SelectStmt + | InsertStmt + | UpdateStmt + | DeleteStmt + ; -prep_type_clause: '(' prep_type_list ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); } - | /* EMPTY * / { $$ = EMPTY; } +prep_type_clause: '(' type_list ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); } + | /* EMPTY */ { $$ = EMPTY; } ; -prep_type_list: Typename { $$ = $1; } - | prep_type_list ',' Typename { $$ = cat_str(3, $1, make_str(","), $3); } - ; - -ExecuteStmt: EXECUTE name execute_param_clause - { $$ = cat_str(3, make_str("execute"), $2, $3); } - | CREATE OptTemp TABLE qualified_name OptCreateAs AS EXECUTE name execute_param_clause - { $$ = cat_str(8, make_str("create"), $2, make_str("table"), $4, $5, make_str("as execute"), $8, $9); } - +ExecuteStmt: EXECUTE prepared_name execute_param_clause execute_rest /* execute_rest is an ecpg addon */ + { + /* $$ = cat_str(3, make_str("ECPGprepared_statement("), connection, $2, make_str("__LINE__)"));*/ + $$ = $2; + } + | CREATE OptTemp TABLE create_as_target AS + EXECUTE prepared_name execute_param_clause + { $$ = cat_str(7, make_str("create"), $2, make_str("table"), $4, make_str("as execute"), $7, $8); } ; execute_param_clause: '(' expr_list ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); } - | /* EMPTY * / { $$ = EMPTY; } - ; + | /* EMPTY */ { $$ = EMPTY; } + ; -DeallocateStmt: DEALLOCATE name { $$ = cat2_str(make_str("deallocate"), $2); } - | DEALLOCATE PREPARE name { $$ = cat2_str(make_str("deallocate prepare"), $3); } - ; -*/ +DeallocateStmt: DEALLOCATE prepared_name { $$ = $2; } + | DEALLOCATE PREPARE prepared_name { $$ = $3; } + | DEALLOCATE ALL { $$ = make_str("all"); } + | DEALLOCATE PREPARE ALL { $$ = make_str("all"); } + ; /***************************************************************************** * @@ -2725,20 +3411,17 @@ DeallocateStmt: DEALLOCATE name { $$ = cat2_str(make_str("deallocate"), $2); } * *****************************************************************************/ -InsertStmt: INSERT INTO qualified_name insert_rest - { $$ = cat_str(3, make_str("insert into"), $3, $4); } +InsertStmt: INSERT INTO qualified_name insert_rest returning_clause + { $$ = cat_str(4, make_str("insert into"), $3, $4, $5); } ; -insert_rest: VALUES '(' insert_target_list ')' - { $$ = cat_str(3, make_str("values("), $3, make_str(")")); } - | DEFAULT VALUES - { $$ = make_str("default values"); } - | SelectStmt +insert_rest: + SelectStmt { $$ = $1; } - | '(' insert_column_list ')' VALUES '(' insert_target_list ')' - { $$ = cat_str(5, make_str("("), $2, make_str(") values ("), $6, make_str(")")); } | '(' insert_column_list ')' SelectStmt { $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); } + | DEFAULT VALUES + { $$ = make_str("default values"); } ; insert_column_list: insert_column_list ',' insert_column_item @@ -2751,6 +3434,9 @@ insert_column_item: ColId opt_indirection { $$ = cat2_str($1, $2); } ; +returning_clause: RETURNING target_list { $$ = cat2_str(make_str("returning"), $2); } + | /* EMPTY */ { $$ = EMPTY; } + ; /***************************************************************************** * @@ -2759,8 +3445,12 @@ insert_column_item: ColId opt_indirection * *****************************************************************************/ -DeleteStmt: DELETE_P FROM relation_expr where_clause - { $$ = cat_str(3, make_str("delete from"), $3, $4); } +DeleteStmt: DELETE_P FROM relation_expr_opt_alias using_clause where_or_current_clause returning_clause + { $$ = cat_str(5, make_str("delete from"), $3, $4, $5, $6); } + ; + +using_clause: USING from_list { $$ = cat2_str(make_str("using"), $2); } + | /* EMPTY */ { $$ = EMPTY; } ; LockStmt: LOCK_P opt_table qualified_name_list opt_lock opt_nowait @@ -2794,13 +3484,37 @@ opt_nowait: NOWAIT { $$ = make_str("nowait"); } * *****************************************************************************/ -UpdateStmt: UPDATE relation_expr - SET update_target_list +UpdateStmt: UPDATE relation_expr_opt_alias + SET set_clause_list from_clause - where_clause - {$$ = cat_str(6, make_str("update"), $2, make_str("set"), $4, $5, $6); } + where_or_current_clause + returning_clause + {$$ = cat_str(7, make_str("update"), $2, make_str("set"), $4, $5, $6, $7); } + ; + +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); } + ; /***************************************************************************** * @@ -2815,11 +3529,8 @@ DeclareCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt for (ptr = cur; ptr != NULL; ptr = ptr->next) { if (strcmp($2, ptr->name) == 0) - { - /* re-definition is a bug */ - snprintf(errortext, sizeof(errortext), "cursor %s already defined", $2); - mmerror(PARSE_ERROR, ET_ERROR, errortext); - } + /* re-definition is a bug */ + mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" already defined", $2); } this = (struct cursor *) mm_alloc(sizeof(struct cursor)); @@ -2843,20 +3554,23 @@ DeclareCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt ; cursor_options: /* EMPTY */ { $$ = EMPTY; } - | 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")); } - ; + | 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")); } + ; + +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"); } + ; -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"); } - ; - /***************************************************************************** * * QUERY: @@ -2880,9 +3594,9 @@ select_no_parens: simple_select { $$ = $1; } | select_clause sort_clause { $$ = cat2_str($1, $2); } - | select_clause opt_sort_clause for_update_clause opt_select_limit + | select_clause opt_sort_clause for_locking_clause opt_select_limit { $$ = cat_str(4, $1, $2, $3, $4); } - | select_clause opt_sort_clause select_limit opt_for_update_clause + | select_clause opt_sort_clause select_limit opt_for_locking_clause { $$ = cat_str(4, $1, $2, $3, $4); } ; @@ -2894,6 +3608,8 @@ 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); } + | values_clause + { $$ = $1; } | select_clause UNION opt_all select_clause { $$ = cat_str(4, $1, make_str("union"), $3, $4); } | select_clause INTERSECT opt_all select_clause @@ -2907,7 +3623,7 @@ into_clause: INTO OptTempTableName FoundInto = 1; $$= cat2_str(make_str("into"), $2); } - | ecpg_into_using { $$ = EMPTY; } + | ecpg_into { $$ = EMPTY; } | /*EMPTY*/ { $$ = EMPTY; } ; @@ -2966,14 +3682,10 @@ sortby_list: sortby { $$ = $1; } | sortby_list ',' sortby { $$ = cat_str(3, $1, make_str(","), $3); } ; -sortby: a_expr USING qual_all_Op - { $$ = cat_str(3, $1, make_str("using"), $3); } - | a_expr ASC - { $$ = cat2_str($1, make_str("asc")); } - | a_expr DESC - { $$ = cat2_str($1, make_str("desc")); } - | a_expr - { $$ = $1; } +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); } ; select_limit: LIMIT select_limit_value OFFSET select_offset_value @@ -2985,7 +3697,10 @@ select_limit: LIMIT select_limit_value OFFSET select_offset_value | OFFSET select_offset_value { $$ = cat2_str(make_str("offset"), $2); } | LIMIT select_limit_value ',' select_offset_value - { mmerror(PARSE_ERROR, ET_WARNING, "No longer supported LIMIT #,# syntax passed to backend."); } + { + mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to backend"); + $$ = cat_str(4, make_str("limit"), $2, make_str(","), $4); + } ; opt_select_limit: select_limit { $$ = $1; } @@ -2996,7 +3711,7 @@ select_limit_value: a_expr { $$ = $1; } | ALL { $$ = make_str("all"); } ; -select_offset_value: a_expr { $$ = $1; } +select_offset_value: a_expr { $$ = $1; } ; /* @@ -3018,18 +3733,37 @@ having_clause: HAVING a_expr { $$ = EMPTY; } ; -for_update_clause: FOR UPDATE update_list - { $$ = make_str("for update"); } - | FOR READ ONLY - { $$ = make_str("for read only"); } +for_locking_clause: + for_locking_items { $$ = $1; } + | FOR READ ONLY { $$ = make_str("for read only");} ; -opt_for_update_clause: for_update_clause { $$ = $1; } - | /* EMPTY */ { $$ = EMPTY; } +opt_for_locking_clause: + for_locking_clause { $$ = $1; } + | /* EMPTY */ { $$ = EMPTY; } ; -update_list: OF name_list { $$ = cat2_str(make_str("of"), $2); } - | /* 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 + { $$ = 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); } + ; + +locked_rels_list: + OF name_list { $$ = cat2_str(make_str("of"), $2); } + | /* EMPTY */ { $$ = EMPTY; } + ; + +values_clause: VALUES ctext_row + { $$ = cat2_str(make_str("values"), $2); } + | values_clause ',' ctext_row + { $$ = cat_str(3, $1, make_str(","), $3); } ; /***************************************************************************** @@ -3058,25 +3792,28 @@ from_list: from_list ',' table_ref { $$ = cat_str(3, $1, make_str(","), $3); } table_ref: relation_expr { $$ = $1; } | relation_expr alias_clause - { $$= cat2_str($1, $2); } + { $$ = cat2_str($1, $2); } | func_table { $$ = $1; } | func_table alias_clause - { $$= cat2_str($1, $2); } + { $$ = cat2_str($1, $2); } | func_table AS '(' TableFuncElementList ')' - { $$=cat_str(4, $1, make_str("as ("), $4, make_str(")")); } + { $$ = cat_str(4, $1, make_str("as ("), $4, make_str(")")); } | func_table AS ColId '(' TableFuncElementList ')' - { $$=cat_str(6, $1, make_str("as"), $3, make_str("("), $5, make_str(")"));} + { $$ = cat_str(6, $1, make_str("as"), $3, make_str("("), $5, make_str(")"));} | func_table ColId '(' TableFuncElementList ')' - { $$=cat_str(5, $1, $2, make_str("("), $4, make_str(")")); } + { $$ = cat_str(5, $1, $2, make_str("("), $4, make_str(")")); } | select_with_parens - {mmerror(PARSE_ERROR, ET_ERROR, "sub-SELECT in FROM must have an alias");} + { + mmerror(PARSE_ERROR, ET_ERROR, "sub-SELECT in FROM must have an alias"); + $$ = $1; + } | select_with_parens alias_clause - { $$=cat2_str($1, $2); } + { $$ = cat2_str($1, $2); } | joined_table { $$ = $1; } | '(' joined_table ')' alias_clause - { $$=cat_str(4, make_str("("), $2, make_str(")"), $4); } + { $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); } ; /* @@ -3100,8 +3837,6 @@ 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 UNIONJOIN table_ref - { $$ = cat_str(3, $1, make_str("unionjoin"), $3); } | 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 @@ -3156,24 +3891,35 @@ relation_expr: qualified_name { /* inheritance query */ $$ = cat_str(3, make_str("only ("), $3, make_str(")")); } ; -func_table: func_name '(' ')' - { $$ = cat2_str($1, make_str("()")); } - | func_name '(' expr_list ')' - { $$ = cat_str(4, $1, make_str("("), $3, make_str(")")); } - ; +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); } + ; + +func_table: func_expr { $$ = $1; } + ; where_clause: WHERE a_expr { $$ = cat2_str(make_str("where"), $2); } | /*EMPTY*/ { $$ = EMPTY; /* no qualifiers */ } ; +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); } + | WHERE CURRENT_P OF PARAM { $$ = make_str("where current of param"); } + | /*EMPTY*/ { $$ = EMPTY; /* no qualifiers */ } + ; + TableFuncElementList: TableFuncElement - { $$ = $1; } + { $$ = $1; } | TableFuncElementList ',' TableFuncElement { $$ = cat_str(3, $1, make_str(","), $3); } ; TableFuncElement: ColId Typename { $$ = cat2_str($1, $2); } - ; + ; /***************************************************************************** * @@ -3236,20 +3982,22 @@ SimpleTypename: GenericType { $$ = $1; } { $$ = cat2_str($1, $2); } | ConstInterval '(' PosIntConst ')' opt_interval { $$ = cat_str(5, $1, make_str("("), $3, make_str(")"), $5); } - | type_name attrs - { $$ = cat2_str($1, $2);} ; -ConstTypename: GenericType { $$ = $1; } - | ConstDatetime { $$ = $1; } - | Numeric { $$ = $1; } +ConstTypename: Numeric { $$ = $1; } | ConstBit { $$ = $1; } | ConstCharacter { $$ = $1; } + | ConstDatetime { $$ = $1; } ; -GenericType: type_name { $$ = $1; } +GenericType: type_function_name opt_type_modifiers { $$ = cat2_str($1, $2); } + | type_function_name attrs opt_type_modifiers { $$ = cat_str(3, $1, $2, $3); } ; +opt_type_modifiers: '(' expr_list ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); } + | /* EMPTY */ { $$ = EMPTY; } + ; + /* SQL92 numeric data types * Check FLOAT() precision limits assuming IEEE floating types. * Provide real DECIMAL() and NUMERIC() implementations now - Jan 1998-12-30 @@ -3269,11 +4017,11 @@ Numeric: INT_P { $$ = cat2_str(make_str("float"), $2); } | DOUBLE_P PRECISION { $$ = make_str("double precision"); } - | DECIMAL_P opt_decimal + | DECIMAL_P opt_type_modifiers { $$ = cat2_str(make_str("decimal"), $2); } - | DEC opt_decimal + | DEC opt_type_modifiers { $$ = cat2_str(make_str("dec"), $2); } - | NUMERIC opt_numeric + | NUMERIC opt_type_modifiers { $$ = cat2_str(make_str("numeric"), $2); } | BOOLEAN_P { $$ = make_str("boolean"); } @@ -3285,36 +4033,20 @@ opt_float: '(' PosIntConst ')' { $$ = EMPTY; } ; -opt_numeric: '(' PosIntConst ',' PosIntConst ')' - { $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")")); } - | '(' PosIntConst ')' - { $$ = cat_str(3, make_str("("), $2, make_str(")")); } - | /*EMPTY*/ - { $$ = EMPTY; } - ; - -opt_decimal: '(' PosIntConst ',' PosIntConst ')' - { $$ = cat_str(5, make_str("("), $2, make_str(","), $4, make_str(")")); } - | '(' PosIntConst ')' - { $$ = cat_str(3, make_str("("), $2, make_str(")")); } - | /*EMPTY*/ - { $$ = EMPTY; } - ; - /* * SQL92 bit-field data types * The following implements BIT() and BIT VARYING(). */ Bit: BitWithLength { $$ = $1; } - | BitWithoutLength { $$ = $1; } - ; + | BitWithoutLength { $$ = $1; } + ; ConstBit: BitWithLength { $$ = $1; } - | BitWithoutLength { $$ = $1; } + | BitWithoutLength { $$ = $1; } ; -BitWithLength: BIT opt_varying '(' PosIntConst ')' +BitWithLength: BIT opt_varying '(' expr_list ')' { $$ = cat_str(5, make_str("bit"), $2, make_str("("), $4, make_str(")")); } ; @@ -3332,7 +4064,7 @@ Character: CharacterWithLength { $$ = $1; } ; ConstCharacter: CharacterWithLength { $$ = $1; } - | CharacterWithoutLength { $$ = $1; } + | CharacterWithoutLength { $$ = $1; } ; CharacterWithLength: character '(' PosIntConst ')' opt_charset @@ -3414,80 +4146,6 @@ opt_interval: YEAR_P { $$ = make_str("year"); } * *****************************************************************************/ -/* Expressions using row descriptors - * Define row_descriptor to allow yacc to break the reduce/reduce conflict - * with singleton expressions. - */ -r_expr: row IN_P select_with_parens - { $$ = cat_str(3, $1, make_str("in"), $3); } - | row NOT IN_P select_with_parens - { $$ = cat_str(3, $1, make_str("not in"), $4); } - | row subquery_Op sub_type select_with_parens %prec Op - { $$ = cat_str(4, $1, $2, $3, $4); } - | row subquery_Op select_with_parens %prec Op - { $$ = cat_str(3, $1, $2, $3); } - | row subquery_Op row %prec Op - { $$ = cat_str(3, $1, $2, $3); } - | row IS NULL_P - { $$ = cat2_str($1, make_str("is null")); } - | row IS NOT NULL_P - { $$ = cat2_str($1, make_str("is not null")); } - | row OVERLAPS row - { $$ = cat_str(3, $1, make_str("overlaps"), $3); } - | row IS DISTINCT FROM row %prec IS - { $$ = cat_str(3, $1, make_str("is distinct from"), $5); } - ; - -row: ROW '(' row_descriptor ')' - { $$ = cat_str(3, make_str("row ("), $3, make_str(")")); } - | ROW '(' a_expr ')' - { $$ = cat_str(3, make_str("row ("), $3, make_str(")")); } - | ROW '(' ')' - { $$ = make_str("row()"); } - | '(' row_descriptor ')' - { $$ = cat_str(3, make_str("("), $2, make_str(")")); } - ; - -row_descriptor: expr_list ',' a_expr - { $$ = cat_str(3, $1, make_str(","), $3); } - ; - -sub_type: ANY { $$ = make_str("ANY"); } - | SOME { $$ = make_str("SOME"); } - | ALL { $$ = make_str("ALL"); } - ; - -all_Op: Op { $$ = $1; } - | MathOp { $$ = $1; } - ; - -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"); } - ; - /* General expressions * This is the heart of the expression syntax. * @@ -3508,7 +4166,7 @@ a_expr: c_expr { $$ = $1; } | a_expr TYPECAST Typename { $$ = cat_str(3, $1, make_str("::"), $3); } - | a_expr AT TIME ZONE c_expr + | a_expr AT TIME ZONE a_expr { $$ = cat_str(3, $1, make_str("at time zone"), $5); } /* * These operators must be called out explicitly in order to make use @@ -3523,14 +4181,6 @@ a_expr: c_expr { $$ = cat2_str(make_str("+"), $2); } | '-' a_expr %prec UMINUS { $$ = cat2_str(make_str("-"), $2); } - | '%' a_expr - { $$ = cat2_str(make_str("%"), $2); } - | '^' a_expr - { $$ = cat2_str(make_str("^"), $2); } - | a_expr '%' - { $$ = cat2_str($1, make_str("%")); } - | a_expr '^' - { $$ = cat2_str($1, make_str("^")); } | a_expr '+' a_expr { $$ = cat_str(3, $1, make_str("+"), $3); } | a_expr '-' a_expr @@ -3593,6 +4243,8 @@ a_expr: c_expr { $$ = cat2_str($1, make_str("notnull")); } | a_expr IS NOT NULL_P { $$ = cat2_str($1, make_str("is not null")); } + | row OVERLAPS row + { $$ = cat_str(3, $1, make_str("overlaps"), $3); } /* IS TRUE, IS FALSE, etc used to be function calls * but let's make them expressions to allow the optimizer * a chance to eliminate them if a_expr is a constant string. @@ -3616,14 +4268,20 @@ a_expr: c_expr { $$ = cat2_str($1, make_str("is not unknown")); } | a_expr IS DISTINCT FROM a_expr %prec IS { $$ = cat_str(3, $1, make_str("is distinct from"), $5); } + | a_expr IS NOT DISTINCT FROM a_expr %prec IS + { $$ = cat_str(3, $1, make_str("is not distinct from"), $6); } | a_expr IS OF '(' type_list ')' %prec IS { $$ = cat_str(4, $1, make_str("is of ("), $5, make_str(")")); } | a_expr IS NOT OF '(' type_list ')' %prec IS { $$ = cat_str(4, $1, make_str("is not of ("), $6, make_str(")")); } - | a_expr BETWEEN b_expr AND b_expr %prec BETWEEN - { $$ = cat_str(5, $1, make_str("between"), $3, make_str("and"), $5); } - | a_expr NOT BETWEEN b_expr AND b_expr %prec BETWEEN - { $$ = cat_str(5, $1, make_str("not between"), $4, make_str("and"), $6); } + | 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); } | a_expr IN_P in_expr { $$ = cat_str(3, $1, make_str("in"), $3); } | a_expr NOT IN_P in_expr @@ -3632,10 +4290,12 @@ a_expr: c_expr { $$ = cat_str(4, $1, $2, $3, $4); } | a_expr subquery_Op sub_type '(' a_expr ')' %prec Op { $$ = cat_str(6, $1, $2, $3, make_str("("), $5, make_str(")")); } - | UNIQUE select_with_parens %prec Op + | UNIQUE select_with_parens { $$ = cat2_str(make_str("unique"), $2); } - | r_expr - { $$ = $1; } + | 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")); } ; /* Restricted expressions @@ -3652,14 +4312,6 @@ b_expr: c_expr { $$ = cat_str(3, $1, make_str("::"), $3); } | '-' b_expr %prec UMINUS { $$ = cat2_str(make_str("-"), $2); } - | '%' b_expr - { $$ = cat2_str(make_str("%"), $2); } - | '^' b_expr - { $$ = cat2_str(make_str("^"), $2); } - | b_expr '%' - { $$ = cat2_str($1, make_str("%")); } - | b_expr '^' - { $$ = cat2_str($1, make_str("^")); } | b_expr '+' b_expr { $$ = cat_str(3, $1, make_str("+"), $3); } | b_expr '-' b_expr @@ -3686,10 +4338,16 @@ b_expr: c_expr { $$ = cat2_str($1, $2); } | b_expr IS DISTINCT FROM b_expr %prec IS { $$ = cat_str(3, $1, make_str("is distinct from"), $5); } + | b_expr IS NOT DISTINCT FROM b_expr %prec IS + { $$ = cat_str(3, $1, make_str("is not distinct from"), $6); } | 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(")")); } + | 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")); } ; /* @@ -3704,18 +4362,42 @@ c_expr: columnref { $$ = $1; } | AexprConst { $$ = $1; } - | PARAM attrs opt_indirection - { $$ = cat_str(3, make_str("param"), $2, $3); } - | '(' a_expr ')' attrs opt_indirection - { $$ = cat_str(5, make_str("("), $2, make_str(")"), $4, $5); } + | PARAM opt_indirection + { $$ = cat2_str(make_str("param"), $2); } | '(' a_expr ')' opt_indirection { $$ = cat_str(4, make_str("("), $2, make_str(")"), $4); } | case_expr { $$ = $1; } - | func_name '(' ')' + | 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 '(' ')' { $$ = cat2_str($1, make_str("()")); } | func_name '(' expr_list ')' { $$ = cat_str(4, $1, make_str("("), $3, make_str(")")); } + | 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(")")); } | func_name '(' ALL expr_list ')' { $$ = cat_str(4, $1, make_str("( all"), $4, make_str(")")); } | func_name '(' DISTINCT expr_list ')' @@ -3724,20 +4406,30 @@ c_expr: columnref { $$ = cat2_str($1, make_str("(*)")); } | CURRENT_DATE { $$ = make_str("current_date"); } - | CURRENT_TIME opt_empty_parentheses - { $$ = cat2_str(make_str("current_time"), $2); } - | CURRENT_TIME '(' PosIntConst ')' + | CURRENT_TIME { $$ = make_str("current_time"); } - | CURRENT_TIMESTAMP opt_empty_parentheses - { $$ = cat2_str(make_str("current_timestamp"), $2); } - | CURRENT_TIMESTAMP '(' PosIntConst ')' + | CURRENT_TIME '(' PosIntConst ')' + { $$ = cat_str(3, make_str("current_time ("), $3, make_str(")")); } + | CURRENT_TIMESTAMP { $$ = make_str("current_timestamp"); } - | CURRENT_USER opt_empty_parentheses - { $$ = cat2_str(make_str("current_user"), $2); } - | SESSION_USER opt_empty_parentheses - { $$ = cat2_str(make_str("session_user"), $2); } - | USER opt_empty_parentheses - { $$ = cat2_str(make_str("user"), $2); } + | CURRENT_TIMESTAMP '(' PosIntConst ')' + { $$ = cat_str(3, make_str("current_timestamp ("), $3, make_str(")")); } + | LOCALTIME + { $$ = make_str("localtime"); } + | LOCALTIME '(' PosIntConst ')' + { $$ = cat_str(3, make_str("localtime ("), $3, make_str(")")); } + | LOCALTIMESTAMP + { $$ = 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"); } + | SESSION_USER + { $$ = make_str("session_user"); } + | USER + { $$ = make_str("user"); } | CAST '(' a_expr AS Typename ')' { $$ = cat_str(5, make_str("cast("), $3, make_str("as"), $5, make_str(")")); } | EXTRACT '(' extract_list ')' @@ -3759,29 +4451,123 @@ c_expr: columnref { $$ = cat_str(3, make_str("trim(trailing"), $4, make_str(")")); } | TRIM '(' trim_list ')' { $$ = cat_str(3, make_str("trim("), $3, make_str(")")); } - | CONVERT '(' a_expr USING any_name ')' - { $$ = cat_str(5, make_str("convert("), $3, make_str("using"), $5, make_str(")"));} - | CONVERT '(' expr_list ')' - { $$ = cat_str(3, make_str("convert("), $3, make_str(")")); } - | 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); } + | NULLIF '(' a_expr ',' a_expr ')' + { $$ = cat_str(5, make_str("nullif("), $3, make_str(","), $5, make_str(")")); } + | COALESCE '(' expr_list ')' + { $$ = cat_str(3, make_str("coalesce("), $3, make_str(")")); } + | GREATEST '(' expr_list ')' + { $$ = cat_str(3, make_str("greatest("), $3, make_str(")")); } + | LEAST '(' expr_list ')' + { $$ = cat_str(3, make_str("least("), $3, make_str(")")); } + | 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(")")); } ; + /* - * This used to use ecpg_expr, but since there is no shift/reduce conflict - * anymore, we can remove ecpg_expr. - MM + * SQL/XML support */ -opt_indirection: '[' a_expr ']' opt_indirection - { $$ = cat_str(4, make_str("["), $2, make_str("]"), $4); } - | '[' a_expr ':' a_expr ']' opt_indirection - { $$ = cat_str(6, make_str("["), $2, make_str(":"), $4, make_str("]"), $6); } - | /* EMPTY */ - { $$ = EMPTY; } + +xml_root_version: VERSION_P a_expr + { $$ = cat2_str(make_str("version"), $2); } + | VERSION_P NO VALUE_P + { $$ = make_str("version no value"); } + ; + +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; } + ; + +row: ROW '(' expr_list ')' + { $$ = 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(")")); } + ; + +sub_type: ANY { $$ = make_str("ANY"); } + | SOME { $$ = make_str("SOME"); } + | ALL { $$ = make_str("ALL"); } + ; + +all_Op: Op { $$ = $1; } + | MathOp { $$ = $1; } + ; + +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"); } ; expr_list: a_expr @@ -3790,29 +4576,26 @@ expr_list: a_expr { $$ = cat_str(3, $1, make_str(","), $3); } ; -extract_list: extract_arg FROM a_expr - { $$ = cat_str(3, $1, make_str("from"), $3); } - | /* EMPTY */ - { $$ = EMPTY; } +type_list: Typename + { $$ = $1; } + | type_list ',' Typename + { $$ = cat_str(3, $1, ',', $3); } ; -type_list: type_list ',' Typename - { $$ = cat_str(3, $1, ',', $3); } - | Typename - { $$ = $1; } +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("[]"); } ; array_expr_list: array_expr { $$ = $1; } | array_expr_list ',' array_expr { $$ = cat_str(3, $1, make_str(","), $3); } ; - -array_expr: '[' expr_list ']' { $$ = cat_str(3, make_str("["), $2, make_str("]")); } - | '[' array_expr_list ']' { $$ = cat_str(3, make_str("["), $2, make_str("]")); } +extract_list: extract_arg FROM a_expr + { $$ = cat_str(3, $1, make_str("from"), $3); } + | /* EMPTY */ + { $$ = EMPTY; } ; -/* Allow delimited string SCONST in extract_arg as an SQL extension. - * - thomas 2001-04-12 - */ extract_arg: ident { $$ = $1; } | YEAR_P { $$ = make_str("year"); } @@ -3832,8 +4615,8 @@ overlay_list: ; overlay_placing: - PLACING a_expr { $$ = cat2_str(make_str("placing"), $2); } - ; + PLACING a_expr { $$ = cat2_str(make_str("placing"), $2); } + ; /* position_list uses b_expr not a_expr to avoid conflict with general IN */ position_list: b_expr IN_P b_expr @@ -3880,25 +4663,9 @@ in_expr: select_with_parens /* Case clause * Define SQL92-style case clause. - * Allow all four forms described in the standard: - * - Full specification - * CASE WHEN a = b THEN c ... ELSE d END - * - Implicit argument - * CASE a WHEN b THEN c ... ELSE d END - * - Conditional NULL - * NULLIF(x,y) - * same as CASE WHEN x = y THEN NULL ELSE x END - * - Conditional substitution from list, use first non-null argument - * COALESCE(a,b,...) - * same as CASE WHEN a IS NOT NULL THEN a WHEN b IS NOT NULL THEN b ... END - * - thomas 1998-11-09 */ case_expr: CASE case_arg when_clause_list case_default END_P { $$ = cat_str(5, make_str("case"), $2, $3, $4, make_str("end")); } - | NULLIF '(' a_expr ',' a_expr ')' - { $$ = cat_str(5, make_str("nullif("), $3, make_str(","), $5, make_str(")")); } - | COALESCE '(' expr_list ')' - { $$ = cat_str(3, make_str("coalesce("), $3, make_str(")")); } ; when_clause_list: when_clause_list when_clause @@ -3918,89 +4685,106 @@ case_default: ELSE a_expr ; case_arg: a_expr { $$ = $1; } - | /*EMPTY*/ { $$ = EMPTY; } + | /*EMPTY*/ { $$ = EMPTY; } ; -columnref: relation_name opt_indirection - { $$ = cat2_str($1, $2); } - | dotted_name opt_indirection - { $$ = cat2_str($1, $2); } - ; +columnref: relation_name { $$ = $1; } + | relation_name indirection { $$ = cat2_str($1, $2); } + ; -dotted_name: relation_name attrs - { $$ = cat2_str($1, $2); } +indirection_el: + '.' 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("]")); } ; -attrs: '.' attr_name - { $$ = cat2_str(make_str("."), $2); } - | '.' '*' - { $$ = make_str(".*"); } - | '.' attr_name attrs - { $$ = cat_str(3, make_str("."), $2, $3); } +indirection: indirection_el { $$ = $1; } + | indirection indirection_el { $$ = cat2_str($1, $2); } ; -opt_empty_parentheses: '(' ')' { $$ = make_str("()"); } - | /*EMPTY*/ { $$ = EMPTY; } +opt_indirection: + /*EMPTY*/ { $$ = EMPTY; } + | opt_indirection indirection_el { $$ = cat2_str($1, $2);} ; +opt_asymmetric: ASYMMETRIC { $$ = make_str("asymmetric"); } + | /*EMPTY*/ { $$ = EMPTY; } + ; + +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(")"));}; /***************************************************************************** * - * target lists + * target lists for SELECT * *****************************************************************************/ -/* Target lists as found in SELECT ... and INSERT VALUES ( ... ) */ target_list: target_list ',' target_el { $$ = cat_str(3, $1, make_str(","), $3); } | target_el { $$ = $1; } ; -/* AS is not optional because shift/red conflict with unary ops */ target_el: a_expr AS ColLabel { $$ = cat_str(3, $1, make_str("as"), $3); } + /* + * 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. + */ + | a_expr IDENT + { $$ = cat_str(3, $1, make_str("as"), $2); } | a_expr { $$ = $1; } | '*' { $$ = make_str("*"); } ; -/* Target list as found in UPDATE table SET ... */ -update_target_list: update_target_list ',' update_target_el - { $$ = cat_str(3, $1, make_str(","),$3); } - | '(' inf_col_list ')' '=' '(' inf_val_list ')' +/* INFORMIX workaround, no longer needed +update_target_list: '(' inf_col_list ')' '=' '(' inf_val_list ')' + { + struct inf_compat_col *ptrc; + struct inf_compat_val *ptrv; + char *cols = make_str( "(" ); + char *vals = make_str( "(" ); + + for (ptrc = informix_col, ptrv = informix_val; ptrc != NULL && ptrv != NULL; ptrc = ptrc->next, ptrv = ptrv->next) { - struct inf_compat_col *ptrc; - struct inf_compat_val *ptrv; - char *cols = make_str( "(" ); - char *vals = make_str( "(" ); - - for (ptrc = informix_col, ptrv = informix_val; ptrc != NULL && ptrv != NULL; ptrc = ptrc->next, ptrv = ptrv->next) + if ( ptrc->next != NULL ) { - if ( ptrc->next != NULL ) - { - cols = cat_str(4, cols, ptrc->name, ptrc->indirection, make_str(",") ); - } - else - { - cols = cat_str(4, cols, ptrc->name, ptrc->indirection, make_str(")") ); - } - if (ptrv->next != NULL ) - vals = cat_str(3, vals, ptrv->val, make_str("," ) ); - else - vals = cat_str( 3, vals, ptrv->val, make_str(")") ); + cols = cat_str(4, cols, ptrc->name, ptrc->indirection, make_str(",") ); + } + else + { + cols = cat_str(4, cols, ptrc->name, ptrc->indirection, make_str(")") ); } - $$ = cat_str( 3, cols, make_str("="), vals ); + if (ptrv->next != NULL ) + vals = cat_str(3, vals, ptrv->val, make_str("," ) ); + else + vals = cat_str( 3, vals, ptrv->val, make_str(")") ); } - | update_target_el - { $$ = $1; } + $$ = cat_str( 3, cols, make_str("="), vals ); + } ; inf_col_list: ColId opt_indirection { struct inf_compat_col *ptr = mm_alloc(sizeof(struct inf_compat_col)); - + ptr->name = $1; ptr->indirection = $2; ptr->next = NULL; @@ -4009,18 +4793,18 @@ inf_col_list: ColId opt_indirection | ColId opt_indirection ',' inf_col_list { struct inf_compat_col *ptr = mm_alloc(sizeof(struct inf_compat_col)); - + ptr->name = $1; ptr->indirection = $2; ptr->next = informix_col; informix_col = ptr; } ; - + inf_val_list: a_expr { struct inf_compat_val *ptr = mm_alloc(sizeof(struct inf_compat_val)); - + ptr->val = $1; ptr->next = NULL; informix_val = ptr; @@ -4028,29 +4812,13 @@ inf_val_list: a_expr | a_expr ',' inf_val_list { struct inf_compat_val *ptr = mm_alloc(sizeof(struct inf_compat_val)); - + ptr->val = $1; ptr->next = informix_val; informix_val = ptr; } ; - -update_target_el: ColId opt_indirection '=' a_expr - { $$ = cat_str(4, $1, $2, make_str("="), $4); } - | ColId opt_indirection '=' DEFAULT - { $$ = cat_str(3, $1, $2, make_str("= default")); } - ; - -insert_target_list: insert_target_list ',' insert_target_el - { $$ = cat_str(3, $1, make_str(","), $3); } - | insert_target_el - { $$ = $1; } - ; - -insert_target_el: target_el { $$ = $1; } - | DEFAULT { $$ = make_str("default"); } - ; - +*/ /***************************************************************************** * @@ -4070,8 +4838,8 @@ qualified_name_list: qualified_name qualified_name: relation_name { $$ = $1; } - | dotted_name - { $$ = $1; } + | relation_name indirection + { $$ = cat2_str($1, $2); } ; name_list: name @@ -4082,25 +4850,17 @@ name_list: name name: ColId { $$ = $1; }; -database_name: ColId { $$ = $1; }; -access_method: ColId { $$ = $1; }; -attr_name: ColId { $$ = $1; }; -index_name: ColId { $$ = $1; }; +database_name: ColId { $$ = $1; }; +access_method: ColId { $$ = $1; }; +attr_name: ColLabel { $$ = $1; }; +index_name: ColId { $$ = $1; }; -file_name: StringConst { $$ = $1; }; +file_name: StringConst { $$ = $1; }; -/* func_name will soon return a List ... but not yet */ -/* -func_name: function_name - { $$ = list_make1(makeString($1)); } - | dotted_name - { $$ = $1; } - ; -*/ -func_name: function_name - { $$ = $1; } - | dotted_name +func_name: type_function_name { $$ = $1; } + | relation_name indirection + { $$ = cat2_str($1, $2); } ; @@ -4115,8 +4875,6 @@ AexprConst: PosAllConst { $$ = cat_str(3, $1, $2, $3); } | ConstInterval '(' PosIntConst ')' StringConst opt_interval { $$ = cat_str(6, $1, make_str("("), $3, make_str(")"), $5, $6); } - | PARAM opt_indirection - { $$ = cat2_str(make_str("param"), $2); } | TRUE_P { $$ = make_str("true"); } | FALSE_P @@ -4133,14 +4891,41 @@ Bconst: BCONST { $$ = make_name();}; Xconst: XCONST { $$ = make_name();}; Sconst: SCONST { + /* could have been input as '' or $$ */ $$ = (char *)mm_alloc(strlen($1) + 3); $$[0]='\''; - strcpy($$+1, $1); - $$[strlen($1)+2]='\0'; + strcpy($$+1, $1); $$[strlen($1)+1]='\''; + $$[strlen($1)+2]='\0'; free($1); } - ; + | 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); + } + | DOLCONST + { + $$ = $1; + } + ; PosIntConst: Iconst { $$ = $1; } | civar { $$ = $1; } @@ -4150,19 +4935,69 @@ IntConst: PosIntConst { $$ = $1; } | '-' PosIntConst { $$ = cat2_str(make_str("-"), $2); } ; +IntConstVar: Iconst + { + char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); + + sprintf(length, "%d", (int) strlen($1)); + new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0); + $$ = $1; + } + | cvariable { $$ = $1; } + ; + +AllConstVar: Fconst + { + char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); + + sprintf(length, "%d", (int) strlen($1)); + new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0); + $$ = $1; + } + | IntConstVar { $$ = $1; } + | '-' Fconst + { + char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); + char *var = cat2_str(make_str("-"), $2); + + sprintf(length, "%d", (int) strlen(var)); + new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); + $$ = var; + } + | '-' Iconst + { + char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); + char *var = cat2_str(make_str("-"), $2); + + sprintf(length, "%d", (int) strlen(var)); + new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); + $$ = var; + } + | Sconst + { + char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); + char *var = $1 + 1; + + var[strlen(var) - 1] = '\0'; + sprintf(length, "%d", (int) strlen(var)); + new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); + $$ = var; + } + ; + StringConst: Sconst { $$ = $1; } | civar { $$ = $1; } ; PosIntStringConst: Iconst { $$ = $1; } - | Sconst { $$ = $1; } + | Sconst { $$ = $1; } | civar { $$ = $1; } ; NumConst: Fconst { $$ = $1; } | Iconst { $$ = $1; } | '-' Fconst { $$ = cat2_str(make_str("-"), $2); } - | '-' Iconst { $$ = cat2_str(make_str("-"), $2); } + | '-' Iconst { $$ = cat2_str(make_str("-"), $2); } | civar { $$ = $1; } ; @@ -4170,15 +5005,18 @@ AllConst: Sconst { $$ = $1; } | NumConst { $$ = $1; } ; -PosAllConst: Sconst { $$ = $1; } - | Fconst { $$ = $1; } - | Iconst { $$ = $1; } - | Bconst { $$ = $1; } - | Xconst { $$ = $1; } - | civar { $$ = $1; } +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; } ; -UserId: ColId { $$ = $1;}; +RoleId: ColId { $$ = $1;}; SpecialRuleRelation: OLD { @@ -4206,77 +5044,68 @@ SpecialRuleRelation: OLD ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user { $$ = cat_str(5, $3, make_str(","), $5, make_str(","), $4); } | SQL_CONNECT TO DEFAULT - { $$ = make_str("NULL,NULL,NULL,\"DEFAULT\""); } + { $$ = make_str("NULL, NULL, NULL, \"DEFAULT\""); } /* also allow ORACLE syntax */ | SQL_CONNECT ora_user - { $$ = cat_str(3, make_str("NULL,"), $2, make_str(",NULL")); } + { $$ = cat_str(3, make_str("NULL,"), $2, make_str(", NULL")); } | DATABASE connection_target - { $$ = cat2_str($2, make_str(",NULL,NULL,NULL")); } + { $$ = cat2_str($2, make_str(", NULL, NULL, NULL")); } ; -connection_target: database_name opt_server opt_port +connection_target: opt_database_name opt_server opt_port { /* old style: dbname[@server][:port] */ if (strlen($2) > 0 && *($2) != '@') - { - snprintf(errortext, sizeof(errortext), - "Expected '@', found '%s'", $2); - mmerror(PARSE_ERROR, ET_ERROR, errortext); - } - - $$ = make3_str(make_str("\""), make3_str($1, $2, $3), make_str("\"")); + mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\", found \"%s\"", $2); + + /* C strings need to be handled differently */ + if ($1[0] == '\"') + $$ = $1; + else + $$ = make3_str(make_str("\""), make3_str($1, $2, $3), make_str("\"")); } - | db_prefix ':' server opt_port '/' database_name opt_options + | db_prefix ':' server opt_port '/' opt_database_name opt_options { /* new style: :postgresql://server[:port][/dbname] */ if (strncmp($1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp($1, "tcp:postgresql", strlen("tcp:postgresql")) != 0) - { - snprintf(errortext, sizeof(errortext), "only protocols 'tcp' and 'unix' and database type 'postgresql' are supported"); - mmerror(PARSE_ERROR, ET_ERROR, errortext); - } + mmerror(PARSE_ERROR, ET_ERROR, "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported"); if (strncmp($3, "//", strlen("//")) != 0) - { - snprintf(errortext, sizeof(errortext), "Expected '://', found '%s'", $3); - mmerror(PARSE_ERROR, ET_ERROR, errortext); - } + mmerror(PARSE_ERROR, ET_ERROR, "expected \"://\", found \"%s\"", $3); 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) - { - snprintf(errortext, sizeof(errortext), "unix domain sockets only work on 'localhost' but not on '%9.9s'", $3 + strlen("//")); - mmerror(PARSE_ERROR, ET_ERROR, errortext); - } + mmerror(PARSE_ERROR, ET_ERROR, "unix domain sockets only work on \"localhost\" but not on \"%s\"", $3 + strlen("//")); $$ = make3_str(make3_str(make_str("\""), $1, make_str(":")), $3, make3_str(make3_str($4, make_str("/"), $6), $7, make_str("\""))); } - | Sconst + | char_variable { - if ($1[0] == '\"') - $$ = $1; - else - $$ = make3_str(make_str("\""), $1, make_str("\"")); + $$ = $1; } - | char_variable + | 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; } ; +opt_database_name: database_name { $$ = $1; } + | /*EMPTY*/ { $$ = EMPTY; } + ; + db_prefix: ident cvariable { if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0) - { - snprintf(errortext, sizeof(errortext), "Expected 'postgresql', found '%s'", $2); - mmerror(PARSE_ERROR, ET_ERROR, errortext); - } + mmerror(PARSE_ERROR, ET_ERROR, "expected \"postgresql\", found \"%s\"", $2); if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0) - { - snprintf(errortext, sizeof(errortext), "Illegal connection type %s", $1); - mmerror(PARSE_ERROR, ET_ERROR, errortext); - } + mmerror(PARSE_ERROR, ET_ERROR, "illegal connection type %s", $1); $$ = make3_str($1, make_str(":"), $2); } @@ -4285,10 +5114,7 @@ db_prefix: ident cvariable server: Op server_name { if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0) - { - snprintf(errortext, sizeof(errortext), "Expected '@' or '://', found '%s'", $1); - mmerror(PARSE_ERROR, ET_ERROR, errortext); - } + mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\" or \"://\", found \"%s\"", $1); $$ = make2_str($1, $2); } @@ -4304,15 +5130,15 @@ server_name: ColId { $$ = $1; } ; opt_port: ':' PosIntConst { $$ = make2_str(make_str(":"), $2); } - | /*EMPTY*/ { $$ = EMPTY; } + | /*EMPTY*/ { $$ = EMPTY; } ; -opt_connection_name: AS connection_target { $$ = $2; } +opt_connection_name: AS connection_object { $$ = $2; } | /*EMPTY*/ { $$ = make_str("NULL"); } ; opt_user: USER ora_user { $$ = $2; } - | /*EMPTY*/ { $$ = make_str("NULL,NULL"); } + | /*EMPTY*/ { $$ = make_str("NULL, NULL"); } ; ora_user: user_name @@ -4325,7 +5151,7 @@ ora_user: user_name { $$ = cat_str(3, $1, make_str(","), $3); } ; -user_name: UserId +user_name: RoleId { if ($1[0] == '\"') $$ = $1; @@ -4336,7 +5162,7 @@ user_name: UserId { if ($1[0] == '\"') $$ = $1; - else if (strcmp($1, " ?") == 0) /* variable */ + else if ($1[1] == '$') /* variable */ { enum ECPGttype type = argsinsert->variable->type->type; @@ -4381,28 +5207,47 @@ char_variable: cvariable break; default: mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype"); + $$ = $1; break; } } } ; -opt_options: Op ColId +opt_options: Op connect_options { if (strlen($1) == 0) mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement"); if (strcmp($1, "?") != 0) - { - snprintf(errortext, sizeof(errortext), "unrecognised token '%s'", $1); - mmerror(PARSE_ERROR, ET_ERROR, errortext); - } + mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $1); $$ = make2_str(make_str("?"), $2); } | /*EMPTY*/ { $$ = EMPTY; } ; +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) + mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $3); + + $$ = 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); } + ; /* * Declare a prepared cursor. The syntax is different from the standard * declare statement, so we create a new rule. @@ -4411,15 +5256,13 @@ ECPGCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR prepared_name { struct cursor *ptr, *this; struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable)); + const char *con = connection ? connection : "NULL"; for (ptr = cur; ptr != NULL; ptr = ptr->next) { if (strcmp($2, ptr->name) == 0) - { - /* re-definition is a bug */ - snprintf(errortext, sizeof(errortext), "cursor %s already defined", $2); - mmerror(PARSE_ERROR, ET_ERROR, errortext); - } + /* re-definition is a bug */ + mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" already defined", $2); } this = (struct cursor *) mm_alloc(sizeof(struct cursor)); @@ -4428,76 +5271,39 @@ ECPGCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR prepared_name this->next = cur; this->name = $2; this->connection = connection; - this->command = cat_str(6, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for ?")); + this->command = cat_str(6, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for $1")); this->argsresult = NULL; thisquery->type = &ecpg_query; thisquery->brace_level = 0; - thisquery->next = NULL; - thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement()") + strlen($7)); - sprintf(thisquery->name, "ECPGprepared_statement(%s)", $7); - - this->argsinsert = NULL; - add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator); - - cur = this; - - $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/")); - } - ; - -/* - * the exec sql deallocate prepare command to deallocate a previously - * prepared statement - */ -ECPGDeallocate: DEALLOCATE PREPARE prepared_name - { $$ = $3; } - | DEALLOCATE prepared_name - { $$ = $2; } - ; - -/* - * variable decalartion outside exec sql declare block - */ -ECPGVarDeclaration: single_vt_declaration; - -single_vt_declaration: type_declaration { $$ = $1; } - | single_var_declaration { $$ = $1; } - ; - -single_var_declaration: storage_declaration - var_type - { - 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; - - actual_startline[struct_level] = hashline_number(); - } - variable_list ';' - { - $$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, make_str(";\n")); - } - | 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; - - actual_startline[struct_level] = hashline_number(); - } - variable_list ';' - { - $$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, make_str(";\n")); - } - | struct_union_type_with_symbol ';' - { - $$ = cat2_str($1, make_str(";")); + thisquery->next = NULL; + thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(, , __LINE__)") + strlen(con) + strlen($7)); + sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7); + + this->argsinsert = NULL; + add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator); + + cur = this; + + $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/")); } ; +ECPGExecuteImmediateStmt: EXECUTE IMMEDIATE execstring + { + /* execute immediate means prepare the statement and + * immediately execute it */ + $$ = $3; + }; +/* + * variable decalartion outside exec sql declare block + */ +ECPGVarDeclaration: single_vt_declaration; + +single_vt_declaration: type_declaration { $$ = $1; } + | var_declaration { $$ = $1; } + ; + precision: NumConst { $$ = $1; }; opt_scale: ',' NumConst { $$ = $2; } @@ -4507,7 +5313,7 @@ opt_scale: ',' NumConst { $$ = $2; } ecpg_interval: opt_interval { $$ = $1; } | YEAR_P TO MINUTE_P { $$ = make_str("year to minute"); } | YEAR_P TO SECOND_P { $$ = make_str("year to second"); } - | DAY_P TO DAY_P { $$ = make_str("day to day"); } + | DAY_P TO DAY_P { $$ = make_str("day to day"); } | MONTH_P TO MONTH_P { $$ = make_str("month to month"); } ; @@ -4530,16 +5336,18 @@ sql_enddeclare: ecpgstart END_P DECLARE SQL_SECTION ';' {}; var_type_declarations: /*EMPTY*/ { $$ = EMPTY; } | vt_declarations { $$ = $1; } + | CPP_LINE { $$ = $1; } ; vt_declarations: var_declaration { $$ = $1; } | type_declaration { $$ = $1; } | vt_declarations var_declaration { $$ = cat2_str($1, $2); } | vt_declarations type_declaration { $$ = cat2_str($1, $2); } + | vt_declarations CPP_LINE { $$ = cat2_str($1, $2); } ; -variable_declarations: var_declaration { $$ = $1; } - | variable_declarations var_declaration { $$ = cat2_str($1, $2); } +variable_declarations: var_declaration { $$ = $1; } + | variable_declarations var_declaration { $$ = cat2_str($1, $2); } ; type_declaration: S_TYPEDEF @@ -4550,55 +5358,9 @@ type_declaration: S_TYPEDEF } var_type opt_pointer ECPGColLabelCommon opt_array_bounds ';' { - /* add entry to list */ - struct typedefs *ptr, *this; - char * dimension = $6.index1; - char * length = $6.index2; - - if (($3.type_enum == ECPGt_struct || - $3.type_enum == ECPGt_union) && - initializer == 1) - { - mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in typedef command"); - - } - else - { - for (ptr = types; ptr != NULL; ptr = ptr->next) - { - if (strcmp($5, ptr->name) == 0) - { - /* re-definition is a bug */ - snprintf(errortext, sizeof(errortext), "Type %s already defined", $5); - mmerror(PARSE_ERROR, ET_ERROR, errortext); - } - } - adjust_array($3.type_enum, &dimension, &length, $3.type_dimension, $3.type_index, *$4?1:0, true); - - this = (struct typedefs *) mm_alloc(sizeof(struct typedefs)); - - /* initial definition */ - this->next = types; - this->name = $5; - this->type = (struct this_type *) mm_alloc(sizeof(struct this_type)); - this->type->type_enum = $3.type_enum; - this->type->type_str = mm_strdup($5); - 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 = ($3.type_enum == ECPGt_struct || $3.type_enum == ECPGt_union) ? - struct_member_list[struct_level] : NULL; + add_typedef($5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *$4 ? 1 : 0); - if ($3.type_enum != ECPGt_varchar && - $3.type_enum != ECPGt_char && - $3.type_enum != ECPGt_unsigned_char && - atoi(this->type->type_index) >= 0) - mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types"); - - types = this; - } - - fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4?"*":"", $5, $6.str); + fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4 ? "*" : "", $5, $6.str); output_line_number(); $$ = make_str(""); }; @@ -4623,7 +5385,7 @@ var_declaration: storage_declaration 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; - + actual_startline[struct_level] = hashline_number(); } variable_list ';' @@ -4636,34 +5398,30 @@ var_declaration: storage_declaration } ; +opt_bit_field: ':' Iconst { $$ =cat2_str(make_str(":"), $2); } + | /* EMPTY */ { $$ = EMPTY; } + ; + storage_declaration: storage_clause storage_modifier - { - $$ = cat2_str ($1, $2); - } - | storage_clause - { - $$ = $1; - } - | storage_modifier - { - $$ = $1; - } + {$$ = cat2_str ($1, $2); } + | storage_clause {$$ = $1; } + | storage_modifier {$$ = $1; } ; -storage_clause : S_EXTERN { $$ = make_str("extern"); } - | S_STATIC { $$ = make_str("static"); } +storage_clause : S_EXTERN { $$ = make_str("extern"); } + | S_STATIC { $$ = make_str("static"); } | S_REGISTER { $$ = make_str("register"); } - | S_AUTO { $$ = make_str("auto"); } + | S_AUTO { $$ = make_str("auto"); } ; -storage_modifier : S_CONST { $$ = make_str("const"); } +storage_modifier : S_CONST { $$ = make_str("const"); } | S_VOLATILE { $$ = make_str("volatile"); } ; var_type: simple_type { $$.type_enum = $1; - $$.type_str = mm_strdup(ECPGtype_name($1)); + $$.type_str = mm_strdup(ecpg_type_name($1)); $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; @@ -4707,11 +5465,11 @@ var_type: simple_type } else { - mmerror(PARSE_ERROR, ET_ERROR, "Only numeric/decimal have precision/scale argument"); + mmerror(PARSE_ERROR, ET_ERROR, "only numeric/decimal have precision/scale argument"); $$.type_enum = ECPGt_numeric; $$.type_str = make_str("numeric"); } - + $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; @@ -4719,8 +5477,8 @@ var_type: simple_type | ECPGColLabelCommon ecpg_interval { if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0) - mmerror (PARSE_ERROR, ET_ERROR, "Interval specification not allowed here "); - + mmerror (PARSE_ERROR, ET_ERROR, "interval specification not allowed here"); + /* * Check for type names that the SQL grammar treats as * unreserved keywords @@ -4806,7 +5564,11 @@ var_type: simple_type $$.type_enum = this->type->type_enum; $$.type_dimension = this->type->type_dimension; $$.type_index = this->type->type_index; - $$.type_sizeof = this->type->type_sizeof; + 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(")")); + struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); } } @@ -4822,7 +5584,7 @@ var_type: simple_type if (!forward) { /* No */ - + this = get_typedef(name); $$.type_str = mm_strdup(this->name); $$.type_enum = this->type->type_enum; @@ -4835,20 +5597,20 @@ var_type: simple_type else { $$.type_str = name; - $$.type_enum = ECPGt_long; - $$.type_dimension = make_str("-1"); - $$.type_index = make_str("-1"); - $$.type_sizeof = make_str(""); - struct_member_list[struct_level] = NULL; + $$.type_enum = ECPGt_long; + $$.type_dimension = make_str("-1"); + $$.type_index = make_str("-1"); + $$.type_sizeof = make_str(""); + struct_member_list[struct_level] = NULL; } } ; -enum_type: SQL_ENUM symbol enum_definition +enum_type: ENUM_P symbol enum_definition { $$ = cat_str(3, make_str("enum"), $2, $3); } - | SQL_ENUM enum_definition + | ENUM_P enum_definition { $$ = cat2_str(make_str("enum"), $2); } - | SQL_ENUM symbol + | ENUM_P symbol { $$ = cat2_str(make_str("enum"), $2); } ; @@ -4859,14 +5621,14 @@ struct_union_type_with_symbol: s_struct_union_symbol { struct_member_list[struct_level++] = NULL; if (struct_level >= STRUCT_DEPTH) - mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure/union definition"); + mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition"); forward_name = mm_strdup($1.symbol); - } + } '{' variable_declarations '}' { struct typedefs *ptr, *this; struct this_type su_type; - + ECPGfree_struct_member(struct_member_list[struct_level]); struct_member_list[struct_level] = NULL; struct_level--; @@ -4877,31 +5639,29 @@ struct_union_type_with_symbol: s_struct_union_symbol su_type.type_str = cat2_str($1.su, $1.symbol); free(forward_name); forward_name = NULL; - + /* 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) - { - if (strcmp(su_type.type_str, ptr->name) == 0) - { - /* re-definition is a bug */ - snprintf(errortext, sizeof(errortext), "Type %s already defined", su_type.type_str); - mmerror(PARSE_ERROR, ET_ERROR, errortext); - } - } - - this = (struct typedefs *) mm_alloc(sizeof(struct typedefs)); - - /* initial definition */ - this->next = types; + { + if (strcmp(su_type.type_str, ptr->name) == 0) + /* re-definition is a bug */ + mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" already defined", su_type.type_str); + } + + this = (struct typedefs *) mm_alloc(sizeof(struct typedefs)); + + /* initial definition */ + this->next = types; this->name = mm_strdup(su_type.type_str); - 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]; + this->brace_level = braces_open; + 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]; types = this; $$ = cat_str(4, su_type.type_str, make_str("{"), $4, make_str("}")); @@ -4913,7 +5673,7 @@ struct_union_type: struct_union_type_with_symbol { $$ = $1; } { struct_member_list[struct_level++] = NULL; if (struct_level >= STRUCT_DEPTH) - mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure/union definition"); + mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition"); } '{' variable_declarations '}' { @@ -4928,7 +5688,7 @@ s_struct_union_symbol: SQL_STRUCT symbol { $$.su = make_str("struct"); $$.symbol = $2; - ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), make_str(")")); + ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), make_str(")")); } | UNION symbol { @@ -4937,7 +5697,7 @@ s_struct_union_symbol: SQL_STRUCT symbol } ; -s_struct_union: SQL_STRUCT +s_struct_union: SQL_STRUCT { ECPGstruct_sizeof = make_str(""); /* This must not be NULL to distinguish from simple types. */ $$ = make_str("struct"); @@ -4976,7 +5736,7 @@ unsigned_type: SQL_UNSIGNED SQL_SHORT { $$ = ECPGt_unsigned_short; } signed_type: SQL_SHORT { $$ = ECPGt_short; } | SQL_SHORT INT_P { $$ = ECPGt_short; } - | INT_P { $$ = ECPGt_int; } + | INT_P { $$ = ECPGt_int; } | SQL_LONG { $$ = ECPGt_long; } | SQL_LONG INT_P { $$ = ECPGt_long; } | SQL_LONG SQL_LONG @@ -5010,12 +5770,13 @@ variable_list: variable { $$ = cat_str(3, $1, make_str(","), $3); } ; -variable: opt_pointer ECPGColLabel opt_array_bounds opt_initializer +variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initializer { struct ECPGtype * type; char *dimension = $3.index1; /* dimension of array */ char *length = $3.index2; /* length of string */ char dim[14L]; + char *vcn; 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); @@ -5028,45 +5789,60 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_initializer else 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); - $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4); + $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5); break; case ECPGt_varchar: if (atoi(dimension) < 0) - type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length); + type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, yylineno); else - type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension); - + type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, yylineno), dimension); + if (strcmp(dimension, "0") == 0 || abs(atoi(dimension)) == 1) *dim = '\0'; - else + else sprintf(dim, "[%s]", dimension); - if (strcmp(length, "0") == 0) + /* cannot check for atoi <= 0 because a defined constant will yield 0 here as well */ + if (atoi(length) < 0 || strcmp(length, "0") == 0) mmerror(PARSE_ERROR, ET_ERROR, "pointer to varchar are not implemented"); + /* 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); if (strcmp(dimension, "0") == 0) - $$ = cat_str(6, make2_str(make_str(" struct varchar_"), mm_strdup($2)), make_str(" { int len; char arr["), mm_strdup(length), make_str("]; } *"), mm_strdup($2), $4); + $$ = 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); else - $$ = cat_str(7, make2_str(make_str(" struct varchar_"), mm_strdup($2)), make_str(" { int len; char arr["), mm_strdup(length), make_str("]; } "), mm_strdup($2), mm_strdup(dim), $4); + $$ = 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); break; case ECPGt_char: case ECPGt_unsigned_char: if (atoi(dimension) == -1) - type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length); + { + int i = strlen($5); + + if (atoi(length) == -1 && i > 0) /* char [] = "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()")); + sprintf(length, "sizeof(%s)", $5+2); + } + type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0); + } else - type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension); + type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0), dimension); - $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4); + $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5); break; default: if (atoi(dimension) < 0) - type = ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1")); + type = ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"), 0); else - type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1")), dimension); + type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"), 0), dimension); - $$ = cat_str(4, $1, mm_strdup($2), $3.str, $4); + $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5); break; } @@ -5108,48 +5884,15 @@ ECPGDeclare: DECLARE STATEMENT ident ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; } ; -dis_name: connection_object { $$ = $1; } - | SQL_CURRENT { $$ = make_str("\"CURRENT\""); } - | ALL { $$ = make_str("\"ALL\""); } - | /*EMPTY*/ { $$ = make_str("\"CURRENT\""); } - ; - -connection_object: connection_target { $$ = $1; } - | DEFAULT { $$ = make_str("\"DEFAULT\""); } +dis_name: connection_object { $$ = $1; } + | CURRENT_P { $$ = make_str("\"CURRENT\""); } + | ALL { $$ = make_str("\"ALL\""); } + | /* EMPTY */ { $$ = make_str("\"CURRENT\""); } ; -/* - * execute a given string as sql command - */ -ECPGExecute : EXECUTE IMMEDIATE execstring - { - struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable)); - - thisquery->type = &ecpg_query; - thisquery->brace_level = 0; - thisquery->next = NULL; - thisquery->name = $3; - - add_variable_to_head(&argsinsert, thisquery, &no_indicator); - - $$ = make_str("?"); - } - | EXECUTE prepared_name - { - struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable)); - - thisquery->type = &ecpg_query; - thisquery->brace_level = 0; - thisquery->next = NULL; - thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement()") + strlen($2)); - sprintf(thisquery->name, "ECPGprepared_statement(%s)", $2); - - add_variable_to_head(&argsinsert, thisquery, &no_indicator); - } - execute_rest - { - $$ = make_str("?"); - } +connection_object: database_name { $$ = make3_str(make_str("\""), $1, make_str("\"")); } + | DEFAULT { $$ = make_str("\"DEFAULT\""); } + | char_variable { $$ = $1; } ; execute_rest: ecpg_using ecpg_into { $$ = EMPTY; } @@ -5165,7 +5908,19 @@ execstring: char_variable { $$ = make3_str(make_str("\""), $1, make_str("\"")); } ; -prepared_name: name { $$ = make3_str(make_str("\""), $1, make_str("\"")); } +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++) + $1[i] = tolower((unsigned char) $1[i]); + + $$ = make3_str(make_str("\""), $1, make_str("\"")); + } + } | char_variable { $$ = $1; } ; @@ -5173,187 +5928,198 @@ prepared_name: name { $$ = make3_str(make_str("\""), $1, make_str("\"")); } * the exec sql free command to deallocate a previously * prepared statement */ -ECPGFree: SQL_FREE name { $$ = $2; }; +ECPGFree: SQL_FREE name { $$ = $2; } + | SQL_FREE ALL { $$ = make_str("all"); } + ; /* * open is an open cursor, at the moment this has to be removed */ ECPGOpen: SQL_OPEN name opt_ecpg_using { $$ = $2; }; -opt_ecpg_using: /*EMPTY*/ { $$ = EMPTY; } +opt_ecpg_using: /*EMPTY*/ { $$ = EMPTY; } | ecpg_using { $$ = $1; } ; ecpg_using: USING using_list { $$ = EMPTY; } + | using_descriptor { $$ = $1; } ; using_descriptor: USING opt_sql SQL_DESCRIPTOR quoted_ident_stringvar { - add_variable_to_head(&argsresult, descriptor_variable($4,0), &no_indicator); + add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator); $$ = EMPTY; } ; into_descriptor: INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar { - add_variable_to_head(&argsresult, descriptor_variable($4,0), &no_indicator); + add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator); $$ = EMPTY; } ; - -opt_sql: /*EMPTY*/ | SQL_SQL; -ecpg_into_using: ecpg_into { $$ = EMPTY; } - | using_descriptor { $$ = $1; } - ; +opt_sql: /*EMPTY*/ | SQL_SQL; ecpg_into: INTO into_list { $$ = EMPTY; } | into_descriptor { $$ = $1; } ; - + using_list: UsingConst | UsingConst ',' using_list; UsingConst: AllConst { - if ($1[1] != '?') /* found a constant */ + if ($1[1] != '$') /* found a constant */ { char *length = mm_alloc(32); sprintf(length, "%d", (int) strlen($1)); - add_variable_to_head(&argsinsert, new_variable($1, ECPGmake_simple_type(ECPGt_const, length), 0), &no_indicator); + add_variable_to_head(&argsinsert, new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator); } } + | civarind { $$ = EMPTY; } ; + /* - * As long as the prepare statement is not supported by the backend, we will - * try to simulate it here so we get dynamic SQL - * - * It is supported now but not usable yet by ecpg. - */ -ECPGPrepare: PREPARE prepared_name FROM execstring - { $$ = cat_str(3, $2, make_str(","), $4); } - ; -/* * We accept descibe but do nothing with it so far. */ -ECPGDescribe: SQL_DESCRIBE INPUT_P name using_descriptor +ECPGDescribe: SQL_DESCRIBE INPUT_P name using_descriptor { - mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement.\n"); - $$ = (char *) mm_alloc(sizeof("1, ECPGprepared_statement(\"\")") + strlen($3)); - sprintf($$, "1, ECPGprepared_statement(\"%s\")", $3); + const char *con = connection ? connection : "NULL"; + mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n"); + $$ = (char *) mm_alloc(sizeof("1, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3)); + sprintf($$, "1, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3); } | SQL_DESCRIBE opt_output name using_descriptor { - mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement.\n"); - $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(\"\")") + strlen($3)); - sprintf($$, "0, ECPGprepared_statement(\"%s\")", $3); + const char *con = connection ? connection : "NULL"; + mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n"); + $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3)); + sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3); } | SQL_DESCRIBE opt_output name into_descriptor { - mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement.\n"); - $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(\"\")") + strlen($3)); - sprintf($$, "0, ECPGprepared_statement(\"%s\")", $3); + const char *con = connection ? connection : "NULL"; + mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n"); + $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3)); + sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3); } ; opt_output: SQL_OUTPUT { $$ = make_str("output"); } | /* EMPTY */ { $$ = EMPTY; } ; - + /* * dynamic SQL: descriptor based access - * written by Christof Petig + * originall written by Christof Petig + * and Peter Eisentraut */ /* - * deallocate a descriptor + * allocate a descriptor */ -ECPGDeallocateDescr: DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar +ECPGAllocateDescr: SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar { - drop_descriptor($3,connection); + add_descriptor($3,connection); $$ = $3; } ; + /* - * allocate a descriptor + * deallocate a descriptor */ -ECPGAllocateDescr: SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar +ECPGDeallocateDescr: DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar { - add_descriptor($3,connection); + drop_descriptor($3,connection); $$ = $3; - }; + } + ; /* - * read from descriptor + * manipulate a descriptor header */ +ECPGGetDescriptorHeader: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems + { $$ = $3; } + ; + +ECPGGetDescHeaderItems: ECPGGetDescHeaderItem + | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem + ; + ECPGGetDescHeaderItem: cvariable '=' desc_header_item { push_assignment($1, $3); } ; -desc_header_item: SQL_COUNT { $$ = ECPGd_count; } + +ECPGSetDescriptorHeader: SET SQL_DESCRIPTOR quoted_ident_stringvar ECPGSetDescHeaderItems + { $$ = $3; } ; -ECPGGetDescItem: cvariable '=' descriptor_item { push_assignment($1, $3); }; +ECPGSetDescHeaderItems: ECPGSetDescHeaderItem + | ECPGSetDescHeaderItems ',' ECPGSetDescHeaderItem + ; -descriptor_item: SQL_CARDINALITY { $$ = ECPGd_cardinality; } - | SQL_DATA { $$ = ECPGd_data; } - | SQL_DATETIME_INTERVAL_CODE { $$ = ECPGd_di_code; } - | SQL_DATETIME_INTERVAL_PRECISION { $$ = ECPGd_di_precision; } - | SQL_INDICATOR { $$ = ECPGd_indicator; } - | SQL_KEY_MEMBER { $$ = ECPGd_key_member; } - | SQL_LENGTH { $$ = ECPGd_length; } - | SQL_NAME { $$ = 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; } +ECPGSetDescHeaderItem: desc_header_item '=' IntConstVar + { + push_assignment($3, $1); + } ; -ECPGGetDescHeaderItems: ECPGGetDescHeaderItem - | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem + +desc_header_item: SQL_COUNT { $$ = ECPGd_count; } + ; + +/* + * manipulate a descriptor + */ + +ECPGGetDescriptor: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGGetDescItems + { $$.str = $5; $$.name = $3; } ; ECPGGetDescItems: ECPGGetDescItem | ECPGGetDescItems ',' ECPGGetDescItem ; -ECPGGetDescriptorHeader: GET SQL_DESCRIPTOR quoted_ident_stringvar - ECPGGetDescHeaderItems - { $$ = $3; } - ; +ECPGGetDescItem: cvariable '=' descriptor_item { push_assignment($1, $3); }; -ECPGGetDescriptor: GET SQL_DESCRIPTOR quoted_ident_stringvar SQL_VALUE cvariable ECPGGetDescItems - { $$.str = $5; $$.name = $3; } - | GET SQL_DESCRIPTOR quoted_ident_stringvar SQL_VALUE Iconst ECPGGetDescItems + +ECPGSetDescriptor: SET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGSetDescItems { $$.str = $5; $$.name = $3; } ; -/* - * for compatibility with ORACLE we will also allow the keyword RELEASE - * after a transaction statement to disconnect from the database. - */ +ECPGSetDescItems: ECPGSetDescItem + | ECPGSetDescItems ',' ECPGSetDescItem + ; -ECPGRelease: TransactionStmt SQL_RELEASE +ECPGSetDescItem: descriptor_item '=' AllConstVar { - if (strcmp($1, "begin") == 0) - mmerror(PARSE_ERROR, ET_ERROR, "RELEASE does not make sense when beginning a transaction"); - - fprintf(yyout, "ECPGtrans(__LINE__, %s, \"%s\");", - connection ? connection : "NULL", $1); - whenever_action(0); - fprintf(yyout, "ECPGdisconnect(__LINE__, %s);", - connection ? connection : "\"CURRENT\""); - whenever_action(0); - free($1); + push_assignment($3, $1); } ; + +descriptor_item: SQL_CARDINALITY { $$ = ECPGd_cardinality; } + | SQL_DATA { $$ = ECPGd_data; } + | SQL_DATETIME_INTERVAL_CODE { $$ = ECPGd_di_code; } + | SQL_DATETIME_INTERVAL_PRECISION { $$ = ECPGd_di_precision; } + | 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; } + ; + /* * set/reset the automatic transaction mode, this needs a differnet handling * as the other set commands @@ -5370,9 +6136,9 @@ on_off: ON { $$ = make_str("on"); } * set the actual connection, this needs a differnet handling as the other * set commands */ -ECPGSetConnection: SET SQL_CONNECTION TO connection_object { $$ = $4; } - | SET SQL_CONNECTION '=' connection_object { $$ = $4; } - | SET SQL_CONNECTION connection_object { $$ = $3; } +ECPGSetConnection: SET CONNECTION TO connection_object { $$ = $4; } + | SET CONNECTION '=' connection_object { $$ = $4; } + | SET CONNECTION connection_object { $$ = $3; } ; /* @@ -5386,51 +6152,7 @@ ECPGTypedef: TYPE_P } ECPGColLabelCommon IS var_type opt_array_bounds opt_reference { - /* add entry to list */ - struct typedefs *ptr, *this; - char *dimension = $6.index1; - char *length = $6.index2; - - if (($5.type_enum == ECPGt_struct || - $5.type_enum == ECPGt_union) && - initializer == 1) - mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL TYPE command"); - else - { - for (ptr = types; ptr != NULL; ptr = ptr->next) - { - if (strcmp($3, ptr->name) == 0) - { - /* re-definition is a bug */ - snprintf(errortext, sizeof(errortext), "Type %s already defined", $3); - mmerror(PARSE_ERROR, ET_ERROR, errortext); - } - } - - adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false); - - this = (struct typedefs *) mm_alloc(sizeof(struct typedefs)); - - /* initial definition */ - this->next = types; - this->name = $3; - this->type = (struct this_type *) mm_alloc(sizeof(struct this_type)); - this->type->type_enum = $5.type_enum; - this->type->type_str = mm_strdup($3); - 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 = ($5.type_enum == ECPGt_struct || $5.type_enum == ECPGt_union) ? - struct_member_list[struct_level] : NULL; - - if ($5.type_enum != ECPGt_varchar && - $5.type_enum != ECPGt_char && - $5.type_enum != ECPGt_unsigned_char && - atoi(this->type->type_index) >= 0) - mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types"); - - types = this; - } + add_typedef($3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *$7 ? 1 : 0); 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("*/")); @@ -5462,7 +6184,7 @@ ECPGVar: SQL_VAR if (($5.type_enum == ECPGt_struct || $5.type_enum == ECPGt_union) && initializer == 1) - mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL VAR command"); + mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in EXEC SQL VAR command"); else { adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false); @@ -5479,27 +6201,27 @@ ECPGVar: SQL_VAR case ECPGt_varchar: if (atoi(dimension) == -1) - type = ECPGmake_simple_type($5.type_enum, length); + type = ECPGmake_simple_type($5.type_enum, length, 0); else - type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length), dimension); + type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension); break; case ECPGt_char: case ECPGt_unsigned_char: if (atoi(dimension) == -1) - type = ECPGmake_simple_type($5.type_enum, length); + type = ECPGmake_simple_type($5.type_enum, length, 0); else - type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length), dimension); + type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension); break; default: if (atoi(length) >= 0) - mmerror(PARSE_ERROR, ET_ERROR, "No multidimensional array support for simple data types"); + mmerror(PARSE_ERROR, ET_ERROR, "no multidimensional array support for simple data types"); if (atoi(dimension) < 0) - type = ECPGmake_simple_type($5.type_enum, make_str("1")); + type = ECPGmake_simple_type($5.type_enum, make_str("1"), 0); else - type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, make_str("1")), dimension); + type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, make_str("1"), 0), dimension); break; } @@ -5519,23 +6241,23 @@ ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action { when_error.code = $3.code; when_error.command = $3.command; - $$ = cat_str(3, make_str("/* exec sql whenever sqlerror "), $3.str, make_str("; */\n")); + $$ = cat_str(3, make_str("/* exec sql whenever sqlerror "), $3.str, make_str("; */")); } | SQL_WHENEVER NOT SQL_FOUND action { when_nf.code = $4.code; when_nf.command = $4.command; - $$ = cat_str(3, make_str("/* exec sql whenever not found "), $4.str, make_str("; */\n")); + $$ = cat_str(3, make_str("/* exec sql whenever not found "), $4.str, make_str("; */")); } | SQL_WHENEVER SQL_SQLWARNING action { when_warn.code = $3.code; when_warn.command = $3.command; - $$ = cat_str(3, make_str("/* exec sql whenever sql_warning "), $3.str, make_str("; */\n")); + $$ = cat_str(3, make_str("/* exec sql whenever sql_warning "), $3.str, make_str("; */")); } ; -action : SQL_CONTINUE +action : CONTINUE_P { $$.code = W_NOTHING; $$.command = NULL; @@ -5583,10 +6305,10 @@ action : SQL_CONTINUE $$.command = cat_str(4, $2, make_str("("), $4, make_str(")")); $$.str = cat2_str(make_str("call"), mm_strdup($$.command)); } - | SQL_CALL name + | SQL_CALL name { $$.code = W_DO; - $$.command = cat_str(3, $2, make_str("("), make_str(")")); + $$.command = cat2_str($2, make_str("()")); $$.str = cat2_str(make_str("call"), mm_strdup($$.command)); } ; @@ -5599,53 +6321,51 @@ ECPGKeywords: ECPGKeywords_vanames { $$ = $1; } ; ECPGKeywords_vanames: SQL_BREAK { $$ = make_str("break"); } - | SQL_CALL { $$ = make_str("call"); } - | SQL_CARDINALITY { $$ = make_str("cardinality"); } - | SQL_CONTINUE { $$ = make_str("continue"); } - | SQL_COUNT { $$ = make_str("count"); } - | SQL_DATA { $$ = make_str("data"); } + | SQL_CALL { $$ = make_str("call"); } + | SQL_CARDINALITY { $$ = make_str("cardinality"); } + | SQL_COUNT { $$ = make_str("count"); } + | SQL_DATA { $$ = make_str("data"); } | SQL_DATETIME_INTERVAL_CODE { $$ = make_str("datetime_interval_code"); } | SQL_DATETIME_INTERVAL_PRECISION { $$ = make_str("datetime_interval_precision"); } - | 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_NAME { $$ = make_str("name"); } - | SQL_NULLABLE { $$ = make_str("nullable"); } - | SQL_OCTET_LENGTH { $$ = make_str("octet_length"); } - | SQL_RELEASE { $$ = make_str("release"); } + | 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"); } | SQL_RETURNED_LENGTH { $$ = make_str("returned_length"); } | SQL_RETURNED_OCTET_LENGTH { $$ = make_str("returned_octet_length"); } - | SQL_SCALE { $$ = make_str("scale"); } - | SQL_SECTION { $$ = make_str("section"); } - | SQL_SQLERROR { $$ = make_str("sqlerror"); } - | SQL_SQLPRINT { $$ = make_str("sqlprint"); } - | SQL_SQLWARNING { $$ = make_str("sqlwarning"); } - | SQL_STOP { $$ = make_str("stop"); } + | SQL_SCALE { $$ = make_str("scale"); } + | SQL_SECTION { $$ = make_str("section"); } + | SQL_SQL { $$ = make_str("sql"); } + | SQL_SQLERROR { $$ = make_str("sqlerror"); } + | SQL_SQLPRINT { $$ = make_str("sqlprint"); } + | SQL_SQLWARNING { $$ = make_str("sqlwarning"); } + | SQL_STOP { $$ = make_str("stop"); } ; - -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"); } + +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"); } ; /* additional keywords that can be SQL type names (but not ECPGColLabels) */ ECPGTypeName: SQL_BOOL { $$ = make_str("bool"); } - | 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"); } + | 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"); } ; -symbol: ColLabel { $$ = $1; } +symbol: ColLabel { $$ = $1; } ; /* @@ -5659,34 +6379,35 @@ symbol: ColLabel { $$ = $1; } * is chosen in part to make keywords acceptable as names wherever possible. */ +ECPGColId:ident { $$ = $1; } + | ECPGunreserved_interval { $$ = $1; } + | ECPGunreserved_con { $$ = $1; } + | col_name_keyword { $$ = $1; } + | ECPGKeywords { $$ = $1; } + | ECPGCKeywords { $$ = $1; } + | CHAR_P { $$ = make_str("char"); } + | VALUES { $$ = make_str("values"); } + ; /* Column identifier --- names that can be column, table, etc names. */ -ColId: ident { $$ = $1; } - | unreserved_keyword { $$ = $1; } - | col_name_keyword { $$ = $1; } - | ECPGKeywords { $$ = $1; } - | ECPGCKeywords { $$ = $1; } - | CHAR_P { $$ = make_str("char"); } +ColId: ident { $$ = $1; } + | unreserved_keyword { $$ = $1; } + | col_name_keyword { $$ = $1; } + | ECPGKeywords { $$ = $1; } + | ECPGCKeywords { $$ = $1; } + | CHAR_P { $$ = make_str("char"); } + | VALUES { $$ = make_str("values"); } ; - -/* Type identifier --- names that can be type names. +/* Type/function identifier --- names that can be type names. */ -type_name: ident { $$ = $1; } - | unreserved_keyword { $$ = $1; } +type_function_name: ident { $$ = $1; } + | unreserved_keyword { $$ = $1; } + | type_func_name_keyword { $$ = $1; } | ECPGKeywords { $$ = $1; } | ECPGTypeName { $$ = $1; } | ECPGCKeywords { $$ = $1; } ; -/* Function identifier --- names that can be function names. - */ -function_name: ident { $$ = $1; } - | unreserved_keyword { $$ = $1; } - | func_name_keyword { $$ = $1; } - | ECPGKeywords { $$ = $1; } - | ECPGCKeywords { $$ = $1; } - ; - /* Column label --- allowed labels in "AS" clauses. * This presently includes *all* Postgres keywords. */ @@ -5701,27 +6422,27 @@ ColLabel: ECPGColLabel { $$ = $1; } | ECPGunreserved_interval { $$ = $1; } ; -ECPGColLabelCommon: ident { $$ = $1; } - | col_name_keyword { $$ = $1; } - | func_name_keyword { $$ = $1; } - | ECPGKeywords_vanames { $$ = $1; } - ; - -ECPGColLabel: ECPGColLabelCommon { $$ = $1; } - | reserved_keyword { $$ = $1; } - | ECPGunreserved { $$ = $1; } - | ECPGKeywords_rest { $$ = $1; } +ECPGColLabelCommon: ident { $$ = $1; } + | col_name_keyword { $$ = $1; } + | type_func_name_keyword { $$ = $1; } + | ECPGKeywords_vanames { $$ = $1; } + ; + +ECPGColLabel: ECPGColLabelCommon { $$ = $1; } + | reserved_keyword { $$ = $1; } + | ECPGunreserved { $$ = $1; } + | ECPGKeywords_rest { $$ = $1; } ; ECPGCKeywords: S_AUTO { $$ = make_str("auto"); } - | 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"); } + | 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"); } ; - + /* * Keyword classification lists. Generally, every keyword present in * the Postgres grammar should appear in exactly one of these lists. @@ -5739,24 +6460,34 @@ ECPGCKeywords: S_AUTO { $$ = make_str("auto"); } */ unreserved_keyword: ECPGunreserved_interval | ECPGunreserved; -ECPGunreserved_interval: DAY_P { $$ = make_str("day"); } +ECPGunreserved_interval: DAY_P { $$ = make_str("day"); } | 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"); } ; - -ECPGunreserved: ABORT_P { $$ = make_str("abort"); } - | ABSOLUTE_P { $$ = make_str("absolute"); } + +/* The following symbol must be excluded from var_name but still included in ColId + to enable ecpg special postgresql variables with this name: CONNECTION + */ +ECPGunreserved: ECPGunreserved_con { $$ = $1; } + | CONNECTION { $$ = make_str("connection"); } + ; + +ECPGunreserved_con: ABORT_P { $$ = make_str("abort"); } + | ABSOLUTE_P { $$ = make_str("absolute"); } | ACCESS { $$ = make_str("access"); } | ACTION { $$ = make_str("action"); } - | ADD { $$ = make_str("add"); } + | ADD_P { $$ = make_str("add"); } + | ADMIN { $$ = make_str("admin"); } | AFTER { $$ = make_str("after"); } | AGGREGATE { $$ = make_str("aggregate"); } + | ALSO { $$ = make_str("also"); } | ALTER { $$ = make_str("alter"); } + | ALWAYS { $$ = make_str("always"); } | ASSERTION { $$ = make_str("assertion"); } - | ASSIGNMENT { $$ = make_str("assignment"); } + | ASSIGNMENT { $$ = make_str("assignment"); } | AT { $$ = make_str("at"); } | BACKWARD { $$ = make_str("backward"); } | BEFORE { $$ = make_str("before"); } @@ -5764,65 +6495,87 @@ ECPGunreserved: ABORT_P { $$ = make_str("abort"); } | BY { $$ = make_str("by"); } | CACHE { $$ = make_str("cache"); } | CASCADE { $$ = make_str("cascade"); } + | CASCADED { $$ = make_str("cascaded"); } | CHAIN { $$ = make_str("chain"); } - | CHARACTERISTICS { $$ = make_str("characteristics"); } - | CHECKPOINT { $$ = make_str("checkpoint"); } + | CHARACTERISTICS { $$ = make_str("characteristics"); } + | CHECKPOINT { $$ = make_str("checkpoint"); } | CLASS { $$ = make_str("class"); } | CLOSE { $$ = make_str("close"); } | CLUSTER { $$ = make_str("cluster"); } | COMMENT { $$ = make_str("comment"); } | COMMIT { $$ = make_str("commit"); } | COMMITTED { $$ = make_str("committed"); } - | CONSTRAINTS { $$ = make_str("constraints"); } - | CONVERSION_P { $$ = make_str("conversion"); } + | CONCURRENTLY { $$ = make_str("concurrently"); } + | CONFIGURATION { $$ = make_str("configuration"); } +/* | CONNECTION { $$ = make_str("connection"); }*/ + | CONSTRAINTS { $$ = make_str("constraints"); } + | CONTENT_P { $$ = make_str("content"); } + | CONTINUE_P { $$ = make_str("continue"); } + | CONVERSION_P { $$ = make_str("conversion"); } | COPY { $$ = make_str("copy"); } + | COST { $$ = make_str("cost"); } | CREATEDB { $$ = make_str("createdb"); } - | CREATEUSER { $$ = make_str("createuser"); } + | CREATEROLE { $$ = make_str("createrole"); } + | CREATEUSER { $$ = make_str("createuser"); } | CSV { $$ = make_str("csv"); } | CURSOR { $$ = make_str("cursor"); } | CYCLE { $$ = make_str("cycle"); } | DATABASE { $$ = make_str("database"); } /* | DAY_P { $$ = make_str("day"); }*/ - | DEALLOCATE { $$ = make_str("deallocate"); } + | DEALLOCATE { $$ = make_str("deallocate"); } | DECLARE { $$ = make_str("declare"); } | DEFAULTS { $$ = make_str("defaults"); } | DEFERRED { $$ = make_str("deferred"); } | DELETE_P { $$ = make_str("delete"); } | DELIMITER { $$ = make_str("delimiter"); } - | DELIMITERS { $$ = make_str("delimiters"); } + | DELIMITERS { $$ = make_str("delimiters"); } + | DICTIONARY { $$ = make_str("dictionary"); } + | DISABLE_P { $$ = make_str("disable"); } + | DISCARD { $$ = make_str("discard"); } + | DOCUMENT_P { $$ = make_str("document"); } | DOMAIN_P { $$ = make_str("domain"); } | DOUBLE_P { $$ = make_str("double"); } | DROP { $$ = make_str("drop"); } | EACH { $$ = make_str("each"); } + | ENABLE_P { $$ = make_str("enable"); } | ENCODING { $$ = make_str("encoding"); } | ENCRYPTED { $$ = make_str("encrypted"); } +/* | ENUM_P { $$ = make_str("enum"); }*/ | ESCAPE { $$ = make_str("escape"); } | EXCLUDING { $$ = make_str("excluding"); } | EXCLUSIVE { $$ = make_str("exclusive"); } | EXECUTE { $$ = make_str("execute"); } | EXPLAIN { $$ = make_str("explain"); } + | EXTERNAL { $$ = make_str("external"); } + | FAMILY { $$ = make_str("family"); } | 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"); } + | GRANTED { $$ = make_str("granted"); } | HANDLER { $$ = make_str("handler"); } + | HEADER_P { $$ = make_str("header"); } | HOLD { $$ = make_str("hold"); } /* | HOUR_P { $$ = make_str("hour"); }*/ + | IDENTITY_P { $$ = make_str("identity"); } + | IF_P { $$ = make_str("if"); } | IMMEDIATE { $$ = make_str("immediate"); } | IMMUTABLE { $$ = make_str("immutable"); } - | IMPLICIT_P { $$ = make_str("implicit"); } + | IMPLICIT_P { $$ = make_str("implicit"); } | INCLUDING { $$ = make_str("including"); } | INCREMENT { $$ = make_str("increment"); } | INDEX { $$ = make_str("index"); } + | INDEXES { $$ = make_str("indexes"); } + | INHERIT { $$ = make_str("inherit"); } | INHERITS { $$ = make_str("inherits"); } - | INSENSITIVE { $$ = make_str("insensitive"); } + | INSENSITIVE { $$ = make_str("insensitive"); } | INSERT { $$ = make_str("insert"); } | INSTEAD { $$ = make_str("instead"); } | ISOLATION { $$ = make_str("isolation"); } | KEY { $$ = make_str("key"); } - | LANCOMPILER { $$ = make_str("lancompiler"); } + | LANCOMPILER { $$ = make_str("lancompiler"); } | LANGUAGE { $$ = make_str("language"); } | LARGE_P { $$ = make_str("large"); } | LAST_P { $$ = make_str("last"); } @@ -5832,6 +6585,8 @@ ECPGunreserved: ABORT_P { $$ = make_str("abort"); } | LOCAL { $$ = make_str("local"); } | LOCATION { $$ = make_str("location"); } | LOCK_P { $$ = make_str("lock"); } + | LOGIN_P { $$ = make_str("login"); } + | MAPPING { $$ = make_str("mapping"); } | MATCH { $$ = make_str("match"); } | MAXVALUE { $$ = make_str("maxvalue"); } /* | MINUTE_P { $$ = make_str("minute"); }*/ @@ -5839,90 +6594,114 @@ ECPGunreserved: ABORT_P { $$ = make_str("abort"); } | MODE { $$ = make_str("mode"); } /* | MONTH_P { $$ = make_str("month"); }*/ | MOVE { $$ = make_str("move"); } + | NAME_P { $$ = make_str("name"); } | NAMES { $$ = make_str("names"); } | NEXT { $$ = make_str("next"); } | NO { $$ = make_str("no"); } - | NOCREATEDB { $$ = make_str("nocreatedb"); } - | NOCREATEUSER { $$ = make_str("nocreateuser"); } + | NOCREATEDB { $$ = make_str("nocreatedb"); } + | NOCREATEROLE { $$ = make_str("nocreaterole"); } + | NOCREATEUSER { $$ = make_str("nocreateuser"); } + | NOINHERIT { $$ = make_str("noinherit"); } + | NOLOGIN_P { $$ = make_str("nologin"); } + | NOSUPERUSER { $$ = make_str("nosuperuser"); } | NOTHING { $$ = make_str("nothing"); } | NOTIFY { $$ = make_str("notify"); } + | NOWAIT { $$ = make_str("nowait"); } + | NULLS_P { $$ = make_str("nulls"); } | OBJECT_P { $$ = make_str("object"); } | OF { $$ = make_str("of"); } | OIDS { $$ = make_str("oids"); } | OPERATOR { $$ = make_str("operator"); } | OPTION { $$ = make_str("option"); } + | OWNED { $$ = make_str("owned"); } | OWNER { $$ = make_str("owner"); } + | PARSER { $$ = make_str("parser"); } | PARTIAL { $$ = make_str("partial"); } | PASSWORD { $$ = make_str("password"); } - | PATH_P { $$ = make_str("path"); } - | PENDANT { $$ = make_str("pendant"); } + | PLANS { $$ = make_str("plans"); } | PREPARE { $$ = make_str("prepare"); } + | PREPARED { $$ = make_str("prepared"); } | PRESERVE { $$ = make_str("preserver"); } | PRIOR { $$ = make_str("prior"); } - | PRIVILEGES { $$ = make_str("privileges"); } - | PROCEDURAL { $$ = make_str("procedural"); } + | PRIVILEGES { $$ = make_str("privileges"); } + | PROCEDURAL { $$ = make_str("procedural"); } | PROCEDURE { $$ = make_str("procedure"); } | QUOTE { $$ = make_str("quote"); } | READ { $$ = make_str("read"); } + | REASSIGN { $$ = make_str("reassign"); } | RECHECK { $$ = make_str("recheck"); } | REINDEX { $$ = make_str("reindex"); } - | RELATIVE_P { $$ = make_str("relative"); } + | RELATIVE_P { $$ = make_str("relative"); } + | RELEASE { $$ = make_str("release"); } | RENAME { $$ = make_str("rename"); } - | REPEATABLE { $$ = make_str("repeatable"); } + | REPEATABLE { $$ = make_str("repeatable"); } | REPLACE { $$ = make_str("replace"); } + | REPLICA { $$ = make_str("replica"); } | RESET { $$ = make_str("reset"); } | RESTART { $$ = make_str("restart"); } | RESTRICT { $$ = make_str("restrict"); } | RETURNS { $$ = make_str("returns"); } | REVOKE { $$ = make_str("revoke"); } + | ROLE { $$ = make_str("role"); } | ROLLBACK { $$ = make_str("rollback"); } | ROWS { $$ = make_str("rows"); } | RULE { $$ = make_str("rule"); } + | SAVEPOINT { $$ = make_str("savepoint"); } | SCHEMA { $$ = make_str("schema"); } | SCROLL { $$ = make_str("scroll"); } + | SEARCH { $$ = make_str("search"); } /* | SECOND_P { $$ = make_str("second"); }*/ | SEQUENCE { $$ = make_str("sequence"); } - | SERIALIZABLE { $$ = make_str("serializable"); } + | SERIALIZABLE { $$ = make_str("serializable"); } | SESSION { $$ = make_str("session"); } | SET { $$ = make_str("set"); } | SHARE { $$ = make_str("share"); } | SHOW { $$ = make_str("show"); } | SIMPLE { $$ = make_str("simple"); } | STABLE { $$ = make_str("stable"); } + | STANDALONE_P { $$ = make_str("standalone"); } | START { $$ = make_str("start"); } | STATEMENT { $$ = make_str("statement"); } - | STATISTICS { $$ = make_str("statistics"); } + | STATISTICS { $$ = make_str("statistics"); } | STDIN { $$ = make_str("stdin"); } | STDOUT { $$ = make_str("stdout"); } | STORAGE { $$ = make_str("storage"); } | STRICT_P { $$ = make_str("strict"); } + | STRIP_P { $$ = make_str("strip"); } + | SUPERUSER_P { $$ = make_str("superuser"); } + | SYSTEM_P { $$ = make_str("system"); } | SYSID { $$ = make_str("sysid"); } + | TABLESPACE { $$ = make_str("tablespace"); } | TEMP { $$ = make_str("temp"); } | TEMPLATE { $$ = make_str("template"); } | TEMPORARY { $$ = make_str("temporary"); } - | TOAST { $$ = make_str("toast"); } - | TRANSACTION { $$ = make_str("transaction"); } + | TEXT_P { $$ = make_str("text"); } + | TRANSACTION { $$ = make_str("transaction"); } | TRIGGER { $$ = make_str("trigger"); } | TRUNCATE { $$ = make_str("truncate"); } | TRUSTED { $$ = make_str("trusted"); } | TYPE_P { $$ = make_str("type"); } - | UNCOMMITTED { $$ = make_str("uncommitted"); } - | UNENCRYPTED { $$ = make_str("unencrypted"); } + | UNCOMMITTED { $$ = make_str("uncommitted"); } + | UNENCRYPTED { $$ = make_str("unencrypted"); } | UNKNOWN { $$ = make_str("unknown"); } | UNLISTEN { $$ = make_str("unlisten"); } | UNTIL { $$ = make_str("until"); } | UPDATE { $$ = make_str("update"); } - | USAGE { $$ = make_str("usage"); } | VACUUM { $$ = make_str("vacuum"); } | VALID { $$ = make_str("valid"); } - | VALUES { $$ = make_str("values"); } + | VALIDATOR { $$ = make_str("validator"); } + | VALUE_P { $$ = make_str("value"); } | VARYING { $$ = make_str("varying"); } - | VERSION { $$ = make_str("version"); } + | VERSION_P { $$ = make_str("version"); } | VIEW { $$ = make_str("view"); } + | VOLATILE { $$ = make_str("volatile"); } + | WHITESPACE_P { $$ = make_str("whitespace"); } | WITH { $$ = make_str("with"); } | WITHOUT { $$ = make_str("without"); } | WORK { $$ = make_str("work"); } | WRITE { $$ = make_str("write"); } + | XML_P { $$ = make_str("xml"); } + | YES_P { $$ = make_str("yes"); } /* | YEAR_P { $$ = make_str("year"); }*/ | ZONE { $$ = make_str("zone"); } ; @@ -5945,18 +6724,19 @@ col_name_keyword: */ | CHARACTER { $$ = make_str("character"); } | COALESCE { $$ = make_str("coalesce"); } - | CONVERT { $$ = make_str("convert"); } | DEC { $$ = make_str("dec"); } | DECIMAL_P { $$ = make_str("decimal"); } | EXISTS { $$ = make_str("exists"); } | EXTRACT { $$ = make_str("extract"); } | FLOAT_P { $$ = make_str("float"); } + | GREATEST { $$ = make_str("greatest"); } | INOUT { $$ = make_str("inout"); } /* INT must be excluded from ECPGColLabel because of conflict | INT_P { $$ = make_str("int"); } */ | INTEGER { $$ = make_str("integer"); } | INTERVAL { $$ = make_str("interval"); } + | LEAST { $$ = make_str("least"); } | NATIONAL { $$ = make_str("national"); } | NCHAR { $$ = make_str("nchar"); } | NONE { $$ = make_str("none"); } @@ -5975,7 +6755,17 @@ col_name_keyword: | TIMESTAMP { $$ = make_str("timestamp"); } | TREAT { $$ = make_str("treat"); } | TRIM { $$ = make_str("trim"); } + /* VALUES creates a shift/reduce problem if listed here + | VALUES { $$ = make_str("values"); } */ | VARCHAR { $$ = make_str("varchar"); } + | 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"); } ; /* Function identifier --- keywords that can be function names. @@ -5988,7 +6778,7 @@ col_name_keyword: * productions in a_expr to support the goofy SQL9x argument syntax. * - thomas 2000-11-28 */ -func_name_keyword: +type_func_name_keyword: AUTHORIZATION { $$ = make_str("authorization"); } | BETWEEN { $$ = make_str("between"); } | BINARY { $$ = make_str("binary"); } @@ -6026,20 +6816,23 @@ reserved_keyword: | ARRAY { $$ = make_str("array"); } | AS { $$ = make_str("as"); } | ASC { $$ = make_str("asc"); } + | ASYMMETRIC { $$ = make_str("asymmetric"); } | BOTH { $$ = make_str("both"); } | CASE { $$ = make_str("case"); } | CAST { $$ = make_str("cast"); } | CHECK { $$ = make_str("check"); } | COLLATE { $$ = make_str("collate"); } | COLUMN { $$ = make_str("column"); } - | CONSTRAINT { $$ = make_str("constraint"); } + | CONSTRAINT { $$ = make_str("constraint"); } | CREATE { $$ = make_str("create"); } - | CURRENT_DATE { $$ = make_str("current_date"); } - | CURRENT_TIME { $$ = make_str("current_time"); } - | CURRENT_TIMESTAMP { $$ = make_str("current_timestamp"); } - | CURRENT_USER { $$ = make_str("current_user"); } + | CURRENT_P { $$ = make_str("current"); } + | CURRENT_DATE { $$ = make_str("current_date"); } + | CURRENT_TIME { $$ = make_str("current_time"); } + | CURRENT_TIMESTAMP { $$ = make_str("current_timestamp"); } + | CURRENT_ROLE { $$ = make_str("current_role"); } + | CURRENT_USER { $$ = make_str("current_user"); } | DEFAULT { $$ = make_str("default"); } - | DEFERRABLE { $$ = make_str("deferrable"); } + | DEFERRABLE { $$ = make_str("deferrable"); } | DESC { $$ = make_str("desc"); } | DISTINCT { $$ = make_str("distinct"); } | DO { $$ = make_str("do"); } @@ -6061,7 +6854,6 @@ reserved_keyword: | LIMIT { $$ = make_str("limit"); } | NEW { $$ = make_str("new"); } | NOT { $$ = make_str("not"); } - | NOWAIT { $$ = make_str("nowait"); } | NULL_P { $$ = make_str("null"); } | OFF { $$ = make_str("off"); } | OFFSET { $$ = make_str("offset"); } @@ -6072,9 +6864,11 @@ reserved_keyword: | ORDER { $$ = make_str("order"); } | PRIMARY { $$ = make_str("primary"); } | REFERENCES { $$ = make_str("references"); } + | RETURNING { $$ = make_str("returning"); } | SELECT { $$ = make_str("select"); } | SESSION_USER { $$ = make_str("session_user"); } | SOME { $$ = make_str("some"); } + | SYMMETRIC { $$ = make_str("symmetric"); } | TABLE { $$ = make_str("table"); } | THEN { $$ = make_str("then"); } /* TO must be excluded from ECPGColLabel because of a conflict in variable name parsing @@ -6088,6 +6882,7 @@ reserved_keyword: | UNIQUE { $$ = make_str("unique"); } | USER { $$ = make_str("user"); } | USING { $$ = make_str("using"); } + | VARIADIC { $$ = make_str("variadic"); } | WHEN { $$ = make_str("when"); } | WHERE { $$ = make_str("where"); } ; @@ -6096,7 +6891,10 @@ reserved_keyword: into_list : coutputvariable | into_list ',' coutputvariable ; -ecpgstart: SQL_START { reset_variables(); } +ecpgstart: SQL_START { + reset_variables(); + pacounter = 1; + } ; c_args: /*EMPTY*/ { $$ = EMPTY; } @@ -6121,10 +6919,10 @@ civarind: cvariable indicator ; civar: cvariable - { - add_variable_to_head(&argsinsert, find_variable($1), &no_indicator); - $$ = create_questionmarks($1, false); - } + { + add_variable_to_head(&argsinsert, find_variable($1), &no_indicator); + $$ = create_questionmarks($1, false); + } ; indicator: cvariable { check_indicator((find_variable($1))->type); $$ = $1; } @@ -6132,37 +6930,40 @@ indicator: cvariable { check_indicator((find_variable($1))->type); $$ = $1; } | SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; } ; -cvariable: CVARIABLE +cvariable: CVARIABLE { /* As long as multidimensional arrays are not implemented we have to check for those here */ char *ptr = $1; int brace_open=0, brace = false; - + for (; *ptr; ptr++) { switch (*ptr) { - case '[': if (brace) - { - mmerror(PARSE_ERROR, ET_FATAL, "No multidimensional array support for simple data types"); - } + case '[': + if (brace) + mmerror(PARSE_ERROR, ET_FATAL, "no multidimensional array support for simple data types"); brace_open++; break; - case ']': brace_open--; - if (brace_open == 0) brace = true; + case ']': + brace_open--; + if (brace_open == 0) + brace = true; break; case '\t': - case ' ': break; - default: if (brace_open == 0) brace = false; + case ' ': + break; + default: + if (brace_open == 0) + brace = false; break; } } - $$ = $1; } ; -ident: IDENT { $$ = $1; } - | CSTRING { $$ = make3_str(make_str("\""), $1, make_str("\"")); } +ident: IDENT { $$ = $1; } + | CSTRING { $$ = make3_str(make_str("\""), $1, make_str("\"")); } ; quoted_ident_stringvar: name @@ -6181,7 +6982,7 @@ c_stuff_item: c_anything { $$ = $1; } { $$ = cat_str(3, make_str("("), $2, make_str(")")); } ; -c_stuff: c_stuff_item { $$ = $1; } +c_stuff: c_stuff_item { $$ = $1; } | c_stuff c_stuff_item { $$ = cat2_str($1, $2); } ; @@ -6194,11 +6995,11 @@ c_term: c_stuff { $$ = $1; } | '{' c_list '}' { $$ = cat_str(3, make_str("{"), $2, make_str("}")); } ; -c_thing: c_anything { $$ = $1; } - | '(' { $$ = make_str("("); } - | ')' { $$ = make_str(")"); } - | ',' { $$ = make_str(","); } - | ';' { $$ = make_str(";"); } +c_thing: c_anything { $$ = $1; } + | '(' { $$ = make_str("("); } + | ')' { $$ = make_str(")"); } + | ',' { $$ = make_str(","); } + | ';' { $$ = make_str(";"); } ; c_anything: IDENT { $$ = $1; } @@ -6237,7 +7038,7 @@ c_anything: IDENT { $$ = $1; } | S_TYPEDEF { $$ = make_str("typedef"); } | S_VOLATILE { $$ = make_str("volatile"); } | SQL_BOOL { $$ = make_str("bool"); } - | SQL_ENUM { $$ = make_str("enum"); } + | ENUM_P { $$ = make_str("enum"); } | HOUR_P { $$ = make_str("hour"); } | INT_P { $$ = make_str("int"); } | SQL_LONG { $$ = make_str("long"); } @@ -6257,17 +7058,29 @@ c_anything: IDENT { $$ = $1; } | '[' { $$ = make_str("["); } | ']' { $$ = make_str("]"); } | '=' { $$ = make_str("="); } + | ':' { $$ = make_str(":"); } ; %% -void yyerror( char * error) +void base_yyerror(const char * error) { char buf[1024]; - snprintf(buf,sizeof buf,"%s at or near \"%s\"", error, token_start ? token_start : yytext); + snprintf(buf,sizeof buf, _("%s at or near \"%s\""), error, token_start ? token_start : yytext); buf[sizeof(buf)-1]=0; mmerror(PARSE_ERROR, ET_ERROR, buf); } +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 + #include "pgc.c"