| /* $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 OptDistributedBy OptTabPartitionBy |
| { |
| 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: <tcp|unix>: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 <var>[] = "string" */ |
| { |
| /* if we have an initializer but no string size set, let's use the initializer's length */ |
| free(length); |
| length = mm_alloc(i+sizeof("sizeof()")); |
| 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 { $$ = 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 <christof.petig@wtal.de> |
| * and Peter Eisentraut <peter.eisentraut@credativ.de> |
| */ |
| |
| /* |
| * 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 = $<action>3.code; |
| when_error.command = $<action>3.command; |
| $$ = cat_str(3, make_str("/* exec sql whenever sqlerror "), $3.str, make_str("; */")); |
| } |
| | SQL_WHENEVER NOT SQL_FOUND action |
| { |
| when_nf.code = $<action>4.code; |
| when_nf.command = $<action>4.command; |
| $$ = cat_str(3, make_str("/* exec sql whenever not found "), $4.str, make_str("; */")); |
| } |
| | SQL_WHENEVER SQL_SQLWARNING action |
| { |
| when_warn.code = $<action>3.code; |
| when_warn.command = $<action>3.command; |
| $$ = cat_str(3, make_str("/* exec sql whenever sql_warning "), $3.str, make_str("; */")); |
| } |
| ; |
| |
| action : CONTINUE_P |
| { |
| $<action>$.code = W_NOTHING; |
| $<action>$.command = NULL; |
| $<action>$.str = make_str("continue"); |
| } |
| | SQL_SQLPRINT |
| { |
| $<action>$.code = W_SQLPRINT; |
| $<action>$.command = NULL; |
| $<action>$.str = make_str("sqlprint"); |
| } |
| | SQL_STOP |
| { |
| $<action>$.code = W_STOP; |
| $<action>$.command = NULL; |
| $<action>$.str = make_str("stop"); |
| } |
| | SQL_GOTO name |
| { |
| $<action>$.code = W_GOTO; |
| $<action>$.command = strdup($2); |
| $<action>$.str = cat2_str(make_str("goto "), $2); |
| } |
| | SQL_GO TO name |
| { |
| $<action>$.code = W_GOTO; |
| $<action>$.command = strdup($3); |
| $<action>$.str = cat2_str(make_str("goto "), $3); |
| } |
| | DO name '(' c_args ')' |
| { |
| $<action>$.code = W_DO; |
| $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")")); |
| $<action>$.str = cat2_str(make_str("do"), mm_strdup($<action>$.command)); |
| } |
| | DO SQL_BREAK |
| { |
| $<action>$.code = W_BREAK; |
| $<action>$.command = NULL; |
| $<action>$.str = make_str("break"); |
| } |
| | SQL_CALL name '(' c_args ')' |
| { |
| $<action>$.code = W_DO; |
| $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")")); |
| $<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command)); |
| } |
| | SQL_CALL name |
| { |
| $<action>$.code = W_DO; |
| $<action>$.command = cat2_str($2, make_str("()")); |
| $<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.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; } |
| | 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" |