/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.9 2009/06/10 23:11:52 petere Exp $ */ statements: /*EMPTY*/ | statements statement ; statement: ecpgstart at stmt ';' { connection = NULL; } | ecpgstart stmt ';' | ecpgstart ECPGVarDeclaration { fprintf(yyout, "%s", $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_typedefs(braces_open); remove_variables(braces_open--); fputs("}", yyout); } ; CreateAsStmt: CREATE OptTemp TABLE create_as_target AS {FoundInto = 0;} SelectStmt opt_with_data { if (FoundInto == 1) mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE AS cannot specify INTO"); $$ = cat_str(6, make_str("create"), $2, make_str("table"), $4, make_str("as"), $7); } ; RuleStmt: CREATE opt_or_replace RULE name AS {QueryIsRule = 1;} ON event TO qualified_name where_clause DO opt_instead RuleActionList { QueryIsRule=0; $$ = cat_str(12, make_str("create"), $2, make_str("rule"), $4, make_str("as on"), $8, make_str("to"), $10, $11, make_str("do"), $13, $14); } ; at: AT connection_object { connection = $2; /* * Do we have a variable as connection target? * Remove the variable from the variable * list or else it will be used twice */ if (argsinsert != NULL) argsinsert = NULL; } ; /* * the exec sql connect statement: connect to the given database */ 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\""); } /* also allow ORACLE syntax */ | SQL_CONNECT ora_user { $$ = cat_str(3, make_str("NULL,"), $2, make_str(", NULL")); } | DATABASE connection_target { $$ = cat2_str($2, make_str(", NULL, NULL, NULL")); } ; connection_target: opt_database_name opt_server opt_port { /* old style: dbname[@server][:port] */ if (strlen($2) > 0 && *($2) != '@') 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 '/' 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) mmerror(PARSE_ERROR, ET_ERROR, "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported"); if (strncmp($3, "//", strlen("//")) != 0) 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) 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("\""))); } | char_variable { $$ = $1; } | ecpg_sconst { /* We can only process double quoted strings not single quotes ones, * so we change the quotes. * Note, that the rule for ecpg_sconst adds these single quotes. */ $1[0] = '\"'; $1[strlen($1)-1] = '\"'; $$ = $1; } ; opt_database_name: database_name { $$ = $1; } | /*EMPTY*/ { $$ = EMPTY; } ; db_prefix: ecpg_ident cvariable { if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0) mmerror(PARSE_ERROR, ET_ERROR, "expected \"postgresql\", found \"%s\"", $2); if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0) mmerror(PARSE_ERROR, ET_ERROR, "invalid connection type: %s", $1); $$ = make3_str($1, make_str(":"), $2); } ; server: Op server_name { if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0) mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\" or \"://\", found \"%s\"", $1); $$ = make2_str($1, $2); } ; opt_server: server { $$ = $1; } | /*EMPTY*/ { $$ = EMPTY; } ; server_name: ColId { $$ = $1; } | ColId '.' server_name { $$ = make3_str($1, make_str("."), $3); } | IP { $$ = make_name(); } ; opt_port: ':' Iconst { $$ = make2_str(make_str(":"), $2); } | /*EMPTY*/ { $$ = EMPTY; } ; opt_connection_name: AS connection_object { $$ = $2; } | /*EMPTY*/ { $$ = make_str("NULL"); } ; opt_user: USER ora_user { $$ = $2; } | /*EMPTY*/ { $$ = make_str("NULL, NULL"); } ; ora_user: user_name { $$ = cat2_str($1, make_str(", NULL")); } | user_name '/' user_name { $$ = cat_str(3, $1, make_str(","), $3); } | user_name SQL_IDENTIFIED BY user_name { $$ = cat_str(3, $1, make_str(","), $4); } | user_name USING user_name { $$ = cat_str(3, $1, make_str(","), $3); } ; user_name: RoleId { if ($1[0] == '\"') $$ = $1; else $$ = make3_str(make_str("\""), $1, make_str("\"")); } | ecpg_sconst { if ($1[0] == '\"') $$ = $1; else $$ = make3_str(make_str("\""), $1, make_str("\"")); } | civar { enum ECPGttype type = argsinsert->variable->type->type; /* if array see what's inside */ if (type == ECPGt_array) type = argsinsert->variable->type->u.element->type; /* handle varchars */ if (type == ECPGt_varchar) $$ = make2_str(mm_strdup(argsinsert->variable->name), make_str(".arr")); else $$ = mm_strdup(argsinsert->variable->name); } ; char_variable: cvariable { /* check if we have a string variable */ struct variable *p = find_variable($1); enum ECPGttype type = p->type->type; /* If we have just one character this is not a string */ if (atol(p->type->size) == 1) mmerror(PARSE_ERROR, ET_ERROR, "invalid data type"); else { /* if array see what's inside */ if (type == ECPGt_array) type = p->type->u.element->type; switch (type) { case ECPGt_char: case ECPGt_unsigned_char: $$ = $1; break; case ECPGt_varchar: $$ = make2_str($1, make_str(".arr")); break; default: mmerror(PARSE_ERROR, ET_ERROR, "invalid data type"); $$ = $1; break; } } } ; opt_options: Op connect_options { if (strlen($1) == 0) mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement"); if (strcmp($1, "?") != 0) 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); } | '=' ecpg_ident { $$ = make2_str(make_str("="), $2); } | '=' civar { $$ = make2_str(make_str("="), $2); } ; 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; } ; /* * Declare a prepared cursor. The syntax is different from the standard * declare statement, so we create a new rule. */ 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 */ mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" is already defined", $2); } this = (struct cursor *) mm_alloc(sizeof(struct cursor)); /* initial definition */ 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 $1")); this->argsresult = NULL; thisquery->type = &ecpg_query; thisquery->brace_level = 0; 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: NumericOnly { $$ = $1; }; opt_scale: ',' NumericOnly { $$ = $2; } | /* EMPTY */ { $$ = EMPTY; } ; 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"); } | MONTH_P TO MONTH_P { $$ = make_str("month to month"); } ; /* * variable declaration inside exec sql declare block */ ECPGDeclaration: sql_startdeclare { fputs("/* exec sql begin declare section */", yyout); } var_type_declarations sql_enddeclare { fprintf(yyout, "%s/* exec sql end declare section */", $3); free($3); output_line_number(); } ; sql_startdeclare: ecpgstart BEGIN_P DECLARE SQL_SECTION ';' {}; 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); } ; type_declaration: S_TYPEDEF { /* reset this variable so we see if there was */ /* an initializer specified */ initializer = 0; } var_type opt_pointer ECPGColLabelCommon opt_array_bounds ';' { add_typedef($5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *$4 ? 1 : 0); fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4 ? "*" : "", $5, $6.str); output_line_number(); $$ = make_str(""); }; 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(";")); } ; 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; } ; storage_clause : S_EXTERN { $$ = make_str("extern"); } | S_STATIC { $$ = make_str("static"); } | S_REGISTER { $$ = make_str("register"); } | S_AUTO { $$ = make_str("auto"); } ; storage_modifier : S_CONST { $$ = make_str("const"); } | S_VOLATILE { $$ = make_str("volatile"); } ; var_type: simple_type { $$.type_enum = $1; $$.type_str = mm_strdup(ecpg_type_name($1)); $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; } | struct_union_type { $$.type_str = $1; $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); if (strncmp($1, "struct", sizeof("struct")-1) == 0) { $$.type_enum = ECPGt_struct; $$.type_sizeof = ECPGstruct_sizeof; } else { $$.type_enum = ECPGt_union; $$.type_sizeof = NULL; } } | enum_type { $$.type_str = $1; $$.type_enum = ECPGt_int; $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; } | ECPGColLabelCommon '(' precision opt_scale ')' { if (strcmp($1, "numeric") == 0) { $$.type_enum = ECPGt_numeric; $$.type_str = make_str("numeric"); } else if (strcmp($1, "decimal") == 0) { $$.type_enum = ECPGt_decimal; $$.type_str = make_str("decimal"); } else { mmerror(PARSE_ERROR, ET_ERROR, "only data types numeric and 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; } | 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"); /* * Check for type names that the SQL grammar treats as * unreserved keywords */ if (strcmp($1, "varchar") == 0) { $$.type_enum = ECPGt_varchar; $$.type_str = EMPTY; /*make_str("varchar");*/ $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; } else if (strcmp($1, "float") == 0) { $$.type_enum = ECPGt_float; $$.type_str = make_str("float"); $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; } else if (strcmp($1, "double") == 0) { $$.type_enum = ECPGt_double; $$.type_str = make_str("double"); $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; } else if (strcmp($1, "numeric") == 0) { $$.type_enum = ECPGt_numeric; $$.type_str = make_str("numeric"); $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; } else if (strcmp($1, "decimal") == 0) { $$.type_enum = ECPGt_decimal; $$.type_str = make_str("decimal"); $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; } else if (strcmp($1, "date") == 0) { $$.type_enum = ECPGt_date; $$.type_str = make_str("date"); $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; } else if (strcmp($1, "timestamp") == 0) { $$.type_enum = ECPGt_timestamp; $$.type_str = make_str("timestamp"); $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; } else if (strcmp($1, "interval") == 0) { $$.type_enum = ECPGt_interval; $$.type_str = make_str("interval"); $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; } else if (strcmp($1, "datetime") == 0) { $$.type_enum = ECPGt_timestamp; $$.type_str = make_str("timestamp"); $$.type_dimension = make_str("-1"); $$.type_index = make_str("-1"); $$.type_sizeof = NULL; } else { /* this is for typedef'ed types */ struct typedefs *this = get_typedef($1); $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name); $$.type_enum = this->type->type_enum; $$.type_dimension = this->type->type_dimension; $$.type_index = this->type->type_index; 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); } } | s_struct_union_symbol { /* this is for named structs/unions */ char *name; struct typedefs *this; bool forward = (forward_name != NULL && strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0); name = cat2_str($1.su, $1.symbol); /* Do we have a forward definition? */ if (!forward) { /* No */ this = get_typedef(name); $$.type_str = mm_strdup(this->name); $$.type_enum = this->type->type_enum; $$.type_dimension = this->type->type_dimension; $$.type_index = this->type->type_index; $$.type_sizeof = this->type->type_sizeof; struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); free(name); } else { $$.type_str = name; $$.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: ENUM_P symbol enum_definition { $$ = cat_str(3, make_str("enum"), $2, $3); } | ENUM_P enum_definition { $$ = cat2_str(make_str("enum"), $2); } | ENUM_P symbol { $$ = cat2_str(make_str("enum"), $2); } ; enum_definition: '{' c_list '}' { $$ = cat_str(3, make_str("{"), $2, make_str("}")); }; 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"); 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--; if (strncmp($1.su, "struct", sizeof("struct")-1) == 0) su_type.type_enum = ECPGt_struct; else su_type.type_enum = ECPGt_union; 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 */ mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" is 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->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("}")); } ; struct_union_type: struct_union_type_with_symbol { $$ = $1; } | s_struct_union { struct_member_list[struct_level++] = NULL; if (struct_level >= STRUCT_DEPTH) mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition"); } '{' variable_declarations '}' { ECPGfree_struct_member(struct_member_list[struct_level]); struct_member_list[struct_level] = NULL; struct_level--; $$ = cat_str(4, $1, make_str("{"), $4, make_str("}")); } ; 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(")")); } | UNION symbol { $$.su = make_str("union"); $$.symbol = $2; } ; s_struct_union: SQL_STRUCT { ECPGstruct_sizeof = make_str(""); /* This must not be NULL to distinguish from simple types. */ $$ = make_str("struct"); } | UNION { $$ = make_str("union"); } ; simple_type: unsigned_type { $$=$1; } | opt_signed signed_type { $$=$2; } ; unsigned_type: SQL_UNSIGNED SQL_SHORT { $$ = ECPGt_unsigned_short; } | SQL_UNSIGNED SQL_SHORT INT_P { $$ = ECPGt_unsigned_short; } | SQL_UNSIGNED { $$ = ECPGt_unsigned_int; } | SQL_UNSIGNED INT_P { $$ = ECPGt_unsigned_int; } | SQL_UNSIGNED SQL_LONG { $$ = ECPGt_unsigned_long; } | SQL_UNSIGNED SQL_LONG INT_P { $$ = ECPGt_unsigned_long; } | SQL_UNSIGNED SQL_LONG SQL_LONG { #ifdef HAVE_LONG_LONG_INT_64 $$ = ECPGt_unsigned_long_long; #else $$ = ECPGt_unsigned_long; #endif } | SQL_UNSIGNED SQL_LONG SQL_LONG INT_P { #ifdef HAVE_LONG_LONG_INT_64 $$ = ECPGt_unsigned_long_long; #else $$ = ECPGt_unsigned_long; #endif } | SQL_UNSIGNED CHAR_P { $$ = ECPGt_unsigned_char; } ; signed_type: SQL_SHORT { $$ = ECPGt_short; } | SQL_SHORT INT_P { $$ = ECPGt_short; } | INT_P { $$ = ECPGt_int; } | SQL_LONG { $$ = ECPGt_long; } | SQL_LONG INT_P { $$ = ECPGt_long; } | SQL_LONG SQL_LONG { #ifdef HAVE_LONG_LONG_INT_64 $$ = ECPGt_long_long; #else $$ = ECPGt_long; #endif } | SQL_LONG SQL_LONG INT_P { #ifdef HAVE_LONG_LONG_INT_64 $$ = ECPGt_long_long; #else $$ = ECPGt_long; #endif } | SQL_BOOL { $$ = ECPGt_bool; } | CHAR_P { $$ = ECPGt_char; } | DOUBLE_P { $$ = ECPGt_double; } ; opt_signed: SQL_SIGNED | /* EMPTY */ ; variable_list: variable { $$ = $1; } | variable_list ',' variable { $$ = cat_str(3, $1, make_str(","), $3); } ; 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); switch (actual_type[struct_level].type_enum) { case ECPGt_struct: case ECPGt_union: if (atoi(dimension) < 0) type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof); 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(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, yylineno); else 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 sprintf(dim, "[%s]", dimension); /* 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, "pointers 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(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(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) { 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, 0), dimension); $$ = 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"), 0); else type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"), 0), dimension); $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5); break; } if (struct_level == 0) new_variable($2, type, braces_open); else ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1])); free($2); } ; opt_initializer: /*EMPTY*/ { $$ = EMPTY; } | '=' c_term { initializer = 1; $$ = cat2_str(make_str("="), $2); } ; opt_pointer: /*EMPTY*/ { $$ = EMPTY; } | '*' { $$ = make_str("*"); } | '*' '*' { $$ = make_str("**"); } ; /* * We try to simulate the correct DECLARE syntax here so we get dynamic SQL */ ECPGDeclare: DECLARE STATEMENT ecpg_ident { /* this is only supported for compatibility */ $$ = cat_str(3, make_str("/* declare statement"), $3, make_str("*/")); } ; /* * the exec sql disconnect statement: disconnect from the given database */ ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; } ; dis_name: connection_object { $$ = $1; } | CURRENT_P { $$ = make_str("\"CURRENT\""); } | ALL { $$ = make_str("\"ALL\""); } | /* EMPTY */ { $$ = make_str("\"CURRENT\""); } ; connection_object: database_name { $$ = make3_str(make_str("\""), $1, make_str("\"")); } | DEFAULT { $$ = make_str("\"DEFAULT\""); } | char_variable { $$ = $1; } ; execstring: char_variable { $$ = $1; } | CSTRING { $$ = make3_str(make_str("\""), $1, make_str("\"")); } ; /* * the exec sql free command to deallocate a previously * prepared statement */ 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; } | 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(&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,1), &no_indicator); $$ = EMPTY; } ; opt_sql: /*EMPTY*/ | SQL_SQL; using_list: UsingValue | UsingValue ',' using_list; UsingValue: UsingConst { 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), 0), &no_indicator); } | civar { $$ = EMPTY; } | civarind { $$ = EMPTY; } ; UsingConst: Iconst { $$ = $1; } | '+' Iconst { $$ = cat_str(2, make_str("+"), $2); } | '-' Iconst { $$ = cat_str(2, make_str("-"), $2); } | ecpg_fconst { $$ = $1; } | '+' ecpg_fconst { $$ = cat_str(2, make_str("+"), $2); } | '-' ecpg_fconst { $$ = cat_str(2, make_str("-"), $2); } | ecpg_sconst { $$ = $1; } | ecpg_bconst { $$ = $1; } | ecpg_xconst { $$ = $1; } ; /* * We accept descibe but do nothing with it so far. */ ECPGDescribe: SQL_DESCRIBE INPUT_P name using_descriptor { const char *con = connection ? connection : "NULL"; mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement"); $$ = (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 { const char *con = connection ? connection : "NULL"; mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement"); $$ = (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 { const char *con = connection ? connection : "NULL"; mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement"); $$ = (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 * originall written by Christof Petig * and Peter Eisentraut */ /* * allocate a descriptor */ ECPGAllocateDescr: SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar { add_descriptor($3,connection); $$ = $3; } ; /* * deallocate a descriptor */ ECPGDeallocateDescr: DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar { drop_descriptor($3,connection); $$ = $3; } ; /* * 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); } ; ECPGSetDescriptorHeader: SET SQL_DESCRIPTOR quoted_ident_stringvar ECPGSetDescHeaderItems { $$ = $3; } ; ECPGSetDescHeaderItems: ECPGSetDescHeaderItem | ECPGSetDescHeaderItems ',' ECPGSetDescHeaderItem ; ECPGSetDescHeaderItem: desc_header_item '=' IntConstVar { push_assignment($3, $1); } ; 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; } ; 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 ; ECPGGetDescItem: cvariable '=' descriptor_item { push_assignment($1, $3); }; ECPGSetDescriptor: SET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGSetDescItems { $$.str = $5; $$.name = $3; } ; ECPGSetDescItems: ECPGSetDescItem | ECPGSetDescItems ',' ECPGSetDescItem ; ECPGSetDescItem: descriptor_item '=' AllConstVar { push_assignment($3, $1); } ; AllConstVar: ecpg_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; } | '-' ecpg_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; } | ecpg_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; } ; descriptor_item: SQL_CARDINALITY { $$ = ECPGd_cardinality; } | DATA_P { $$ = 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 */ ECPGSetAutocommit: SET SQL_AUTOCOMMIT '=' on_off { $$ = $4; } | SET SQL_AUTOCOMMIT TO on_off { $$ = $4; } ; on_off: ON { $$ = make_str("on"); } | OFF { $$ = make_str("off"); } ; /* * set the actual connection, this needs a differnet handling as the other * set commands */ ECPGSetConnection: SET CONNECTION TO connection_object { $$ = $4; } | SET CONNECTION '=' connection_object { $$ = $4; } | SET CONNECTION connection_object { $$ = $3; } ; /* * define a new type for embedded SQL */ ECPGTypedef: TYPE_P { /* reset this variable so we see if there was */ /* an initializer specified */ initializer = 0; } ECPGColLabelCommon IS var_type opt_array_bounds opt_reference { 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("*/")); else $$ = cat_str(6, make_str("typedef "), mm_strdup($5.type_str), *$7?make_str("*"):make_str(""), mm_strdup($6.str), mm_strdup($3), make_str(";")); } ; opt_reference: SQL_REFERENCE { $$ = make_str("reference"); } | /*EMPTY*/ { $$ = EMPTY; } ; /* * define the type of one variable for embedded SQL */ ECPGVar: SQL_VAR { /* reset this variable so we see if there was */ /* an initializer specified */ initializer = 0; } ColLabel IS var_type opt_array_bounds opt_reference { struct variable *p = find_variable($3); char *dimension = $6.index1; char *length = $6.index2; struct ECPGtype * type; 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"); else { adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false); switch ($5.type_enum) { case ECPGt_struct: case ECPGt_union: if (atoi(dimension) < 0) type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_sizeof); else type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum,$5.type_sizeof), dimension); break; case ECPGt_varchar: if (atoi(dimension) == -1) type = ECPGmake_simple_type($5.type_enum, length, 0); else 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, 0); else type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension); break; default: if (atoi(length) >= 0) mmerror(PARSE_ERROR, ET_ERROR, "multidimensional arrays for simple data types are not supported"); if (atoi(dimension) < 0) 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"), 0), dimension); break; } ECPGfree_type(p->type); p->type = type; } $$ = cat_str(7, make_str("/* exec sql var"), mm_strdup($3), make_str("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, make_str("*/")); } ; /* * whenever statement: decide what to do in case of error/no data found * according to SQL standards we lack: SQLSTATE, CONSTRAINT and SQLEXCEPTION */ 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("; */")); } | 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("; */")); } | 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("; */")); } ; action : CONTINUE_P { $$.code = W_NOTHING; $$.command = NULL; $$.str = make_str("continue"); } | SQL_SQLPRINT { $$.code = W_SQLPRINT; $$.command = NULL; $$.str = make_str("sqlprint"); } | SQL_STOP { $$.code = W_STOP; $$.command = NULL; $$.str = make_str("stop"); } | SQL_GOTO name { $$.code = W_GOTO; $$.command = strdup($2); $$.str = cat2_str(make_str("goto "), $2); } | SQL_GO TO name { $$.code = W_GOTO; $$.command = strdup($3); $$.str = cat2_str(make_str("goto "), $3); } | DO name '(' c_args ')' { $$.code = W_DO; $$.command = cat_str(4, $2, make_str("("), $4, make_str(")")); $$.str = cat2_str(make_str("do"), mm_strdup($$.command)); } | DO SQL_BREAK { $$.code = W_BREAK; $$.command = NULL; $$.str = make_str("break"); } | SQL_CALL name '(' c_args ')' { $$.code = W_DO; $$.command = cat_str(4, $2, make_str("("), $4, make_str(")")); $$.str = cat2_str(make_str("call"), mm_strdup($$.command)); } | SQL_CALL name { $$.code = W_DO; $$.command = cat2_str($2, make_str("()")); $$.str = cat2_str(make_str("call"), mm_strdup($$.command)); } ; /* some other stuff for ecpg */ /* additional unreserved keywords */ ECPGKeywords: ECPGKeywords_vanames { $$ = $1; } | ECPGKeywords_rest { $$ = $1; } ; ECPGKeywords_vanames: SQL_BREAK { $$ = make_str("break"); } | SQL_CALL { $$ = make_str("call"); } | SQL_CARDINALITY { $$ = make_str("cardinality"); } | SQL_COUNT { $$ = make_str("count"); } | 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_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_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"); } ; /* 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"); } ; symbol: ColLabel { $$ = $1; } ; ECPGColId: ecpg_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 label --- allowed labels in "AS" clauses. * This presently includes *all* Postgres keywords. */ ColLabel: ECPGColLabel { $$ = $1; } | ECPGTypeName { $$ = $1; } | CHAR_P { $$ = make_str("char"); } | INPUT_P { $$ = make_str("input"); } | INT_P { $$ = make_str("int"); } | UNION { $$ = make_str("union"); } | TO { $$ = make_str("to"); } | ECPGCKeywords { $$ = $1; } | ECPGunreserved_interval { $$ = $1; } ; ECPGColLabelCommon: ecpg_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"); } ; /* * Keyword classification lists. Generally, every keyword present in * the Postgres grammar should appear in exactly one of these lists. * * Put a new keyword into the first list that it can go into without causing * shift or reduce conflicts. The earlier lists define "less reserved" * categories of keywords. */ /* "Unreserved" keywords --- available for use as any kind of name. */ /* The following symbols must be excluded from ECPGColLabel and directly included into ColLabel to enable C variables to get names from ECPGColLabel: DAY_P, HOUR_P, MINUTE_P, MONTH_P, SECOND_P, YEAR_P */ unreserved_keyword: ECPGunreserved_interval | ECPGunreserved; 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"); } ; /* 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_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"); } | AT { $$ = make_str("at"); } | BACKWARD { $$ = make_str("backward"); } | BEFORE { $$ = make_str("before"); } | BEGIN_P { $$ = make_str("begin"); } | BY { $$ = make_str("by"); } | CACHE { $$ = make_str("cache"); } | CASCADE { $$ = make_str("cascade"); } | CASCADED { $$ = make_str("cascaded"); } | CHAIN { $$ = make_str("chain"); } | 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"); } | 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"); } | CREATEROLE { $$ = make_str("createrole"); } | CREATEUSER { $$ = make_str("createuser"); } | CSV { $$ = make_str("csv"); } | CURSOR { $$ = make_str("cursor"); } | CYCLE { $$ = make_str("cycle"); } | DATA_P { $$ = make_str("data"); } | DATABASE { $$ = make_str("database"); } /* | DAY_P { $$ = make_str("day"); }*/ | 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"); } | 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"); } | 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"); } | INSERT { $$ = make_str("insert"); } | INSTEAD { $$ = make_str("instead"); } | ISOLATION { $$ = make_str("isolation"); } | KEY { $$ = make_str("key"); } | LANCOMPILER { $$ = make_str("lancompiler"); } | LANGUAGE { $$ = make_str("language"); } | LARGE_P { $$ = make_str("large"); } | LAST_P { $$ = make_str("last"); } | LC_COLLATE_P { $$ = make_str("lc_collate"); } | LC_CTYPE_P { $$ = make_str("lc_ctype"); } | LEVEL { $$ = make_str("level"); } | LISTEN { $$ = make_str("listen"); } | LOAD { $$ = make_str("load"); } | LOCAL { $$ = make_str("local"); } | LOCATION { $$ = make_str("location"); } | LOCK_P { $$ = make_str("lock"); } | LOGIN_P { $$ = make_str("login"); } | MAPPING { $$ = make_str("mapping"); } | MATCH { $$ = make_str("match"); } | MAXVALUE { $$ = make_str("maxvalue"); } /* | MINUTE_P { $$ = make_str("minute"); }*/ | MINVALUE { $$ = make_str("minvalue"); } | 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"); } | 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"); } | 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"); } | PROCEDURE { $$ = make_str("procedure"); } | QUOTE { $$ = make_str("quote"); } | READ { $$ = make_str("read"); } | REASSIGN { $$ = make_str("reassign"); } | RECHECK { $$ = make_str("recheck"); } | RECURSIVE { $$ = make_str("recursive"); } | REINDEX { $$ = make_str("reindex"); } | RELATIVE_P { $$ = make_str("relative"); } | RELEASE { $$ = make_str("release"); } | RENAME { $$ = make_str("rename"); } | 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"); } | 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"); } | 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"); } | 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"); } | UNKNOWN { $$ = make_str("unknown"); } | UNLISTEN { $$ = make_str("unlisten"); } | UNTIL { $$ = make_str("until"); } | UPDATE { $$ = make_str("update"); } | VACUUM { $$ = make_str("vacuum"); } | VALID { $$ = make_str("valid"); } | VALIDATOR { $$ = make_str("validator"); } | VALUE_P { $$ = make_str("value"); } | VARYING { $$ = make_str("varying"); } | VERSION_P { $$ = make_str("version"); } | VIEW { $$ = make_str("view"); } | VOLATILE { $$ = make_str("volatile"); } | WHITESPACE_P { $$ = make_str("whitespace"); } | 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"); } ; into_list : coutputvariable | into_list ',' coutputvariable ; ecpgstart: SQL_START { reset_variables(); pacounter = 1; } ; c_args: /*EMPTY*/ { $$ = EMPTY; } | c_list { $$ = $1; } ; coutputvariable: cvariable indicator { add_variable_to_head(&argsresult, find_variable($1), find_variable($2)); } | cvariable { add_variable_to_head(&argsresult, find_variable($1), &no_indicator); } ; civarind: cvariable indicator { if (find_variable($2)->type->type == ECPGt_array) mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input"); add_variable_to_head(&argsinsert, find_variable($1), find_variable($2)); $$ = create_questionmarks($1, false); } ; civar: cvariable { add_variable_to_head(&argsinsert, find_variable($1), &no_indicator); $$ = create_questionmarks($1, false); } ; indicator: cvariable { check_indicator((find_variable($1))->type); $$ = $1; } | SQL_INDICATOR cvariable { check_indicator((find_variable($2))->type); $$ = $2; } | SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; } ; 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, "multidimensional arrays for simple data types are not supported"); brace_open++; break; case ']': brace_open--; if (brace_open == 0) brace = true; break; case '\t': case ' ': break; default: if (brace_open == 0) brace = false; break; } } $$ = $1; } ; ecpg_param: PARAM { $$ = make_name(); } ; ecpg_bconst: BCONST { $$ = make_name(); } ; ecpg_fconst: FCONST { $$ = make_name(); } ; ecpg_sconst: SCONST { /* could have been input as '' or $$ */ $$ = (char *)mm_alloc(strlen($1) + 3); $$[0]='\''; strcpy($$+1, $1); $$[strlen($1)+1]='\''; $$[strlen($1)+2]='\0'; free($1); } | ECONST { $$ = (char *)mm_alloc(strlen($1) + 4); $$[0]='E'; $$[1]='\''; strcpy($$+2, $1); $$[strlen($1)+2]='\''; $$[strlen($1)+3]='\0'; free($1); } | NCONST { $$ = (char *)mm_alloc(strlen($1) + 4); $$[0]='N'; $$[1]='\''; strcpy($$+2, $1); $$[strlen($1)+2]='\''; $$[strlen($1)+3]='\0'; free($1); } | UCONST { $$ = $1; } | DOLCONST { $$ = $1; } ; ecpg_xconst: XCONST { $$ = make_name(); } ; ecpg_ident: IDENT { $$ = make_name(); } | CSTRING { $$ = make3_str(make_str("\""), $1, make_str("\"")); } | UIDENT { $$ = $1; } ; quoted_ident_stringvar: name { $$ = make3_str(make_str("\""), $1, make_str("\"")); } | char_variable { $$ = make3_str(make_str("("), $1, make_str(")")); } ; /* * C stuff */ c_stuff_item: c_anything { $$ = $1; } | '(' ')' { $$ = make_str("()"); } | '(' c_stuff ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); } ; c_stuff: c_stuff_item { $$ = $1; } | c_stuff c_stuff_item { $$ = cat2_str($1, $2); } ; c_list: c_term { $$ = $1; } | c_list ',' c_term { $$ = cat_str(3, $1, make_str(","), $3); } ; 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_anything: ecpg_ident { $$ = $1; } | Iconst { $$ = $1; } | ecpg_fconst { $$ = $1; } | ecpg_sconst { $$ = $1; } | '*' { $$ = make_str("*"); } | '+' { $$ = make_str("+"); } | '-' { $$ = make_str("-"); } | '/' { $$ = make_str("/"); } | '%' { $$ = make_str("%"); } | NULL_P { $$ = make_str("NULL"); } | S_ADD { $$ = make_str("+="); } | S_AND { $$ = make_str("&&"); } | S_ANYTHING { $$ = make_name(); } | S_AUTO { $$ = make_str("auto"); } | S_CONST { $$ = make_str("const"); } | S_DEC { $$ = make_str("--"); } | S_DIV { $$ = make_str("/="); } | S_DOTPOINT { $$ = make_str(".*"); } | S_EQUAL { $$ = make_str("=="); } | S_EXTERN { $$ = make_str("extern"); } | S_INC { $$ = make_str("++"); } | S_LSHIFT { $$ = make_str("<<"); } | S_MEMBER { $$ = make_str("->"); } | S_MEMPOINT { $$ = make_str("->*"); } | S_MOD { $$ = make_str("%="); } | S_MUL { $$ = make_str("*="); } | S_NEQUAL { $$ = make_str("!="); } | S_OR { $$ = make_str("||"); } | S_REGISTER { $$ = make_str("register"); } | S_RSHIFT { $$ = make_str(">>"); } | S_STATIC { $$ = make_str("static"); } | S_SUB { $$ = make_str("-="); } | S_TYPEDEF { $$ = make_str("typedef"); } | S_VOLATILE { $$ = make_str("volatile"); } | SQL_BOOL { $$ = make_str("bool"); } | ENUM_P { $$ = make_str("enum"); } | HOUR_P { $$ = make_str("hour"); } | INT_P { $$ = make_str("int"); } | SQL_LONG { $$ = make_str("long"); } | MINUTE_P { $$ = make_str("minute"); } | MONTH_P { $$ = make_str("month"); } | SECOND_P { $$ = make_str("second"); } | SQL_SHORT { $$ = make_str("short"); } | SQL_SIGNED { $$ = make_str("signed"); } | SQL_STRUCT { $$ = make_str("struct"); } | SQL_UNSIGNED { $$ = make_str("unsigned"); } | YEAR_P { $$ = make_str("year"); } | CHAR_P { $$ = make_str("char"); } | FLOAT_P { $$ = make_str("float"); } | TO { $$ = make_str("to"); } | UNION { $$ = make_str("union"); } | VARCHAR { $$ = make_str("varchar"); } | '[' { $$ = make_str("["); } | ']' { $$ = make_str("]"); } | '=' { $$ = make_str("="); } | ':' { $$ = make_str(":"); } ; DeallocateStmt: DEALLOCATE prepared_name { $$ = $2; } | DEALLOCATE PREPARE prepared_name { $$ = $3; } | DEALLOCATE ALL { $$ = make_str("all"); } | DEALLOCATE PREPARE ALL { $$ = make_str("all"); } ; Iresult: Iconst { $$ = $1; } | '(' Iresult ')' { $$ = cat_str(3, make_str("("), $2, make_str(")")); } | Iresult '+' Iresult { $$ = cat_str(3, $1, make_str("+"), $3); } | Iresult '-' Iresult { $$ = cat_str(3, $1, make_str("-"), $3); } | Iresult '*' Iresult { $$ = cat_str(3, $1, make_str("*"), $3); } | Iresult '/' Iresult { $$ = cat_str(3, $1, make_str("/"), $3); } | Iresult '%' Iresult { $$ = cat_str(3, $1, make_str("%"), $3); } | ecpg_sconst { $$ = $1; } | ColId { $$ = $1; } ; execute_rest: /* EMPTY */ { $$ = EMPTY; } | ecpg_using ecpg_into { $$ = EMPTY; } | ecpg_into ecpg_using { $$ = EMPTY; } | ecpg_using { $$ = EMPTY; } | ecpg_into { $$ = EMPTY; } ; ecpg_into: INTO into_list { $$ = EMPTY; } | into_descriptor { $$ = $1; } ; %% void base_yyerror(const char *error) { /* translator: %s is typically the translation of "syntax error" */ mmerror(PARSE_ERROR, ET_ERROR, "%s at or near \"%s\"", _(error), token_start ? token_start : yytext); } 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"