From b53955f38aa3832b84970c806e1afdd7d3053d9e Mon Sep 17 00:00:00 2001 From: Michael Meskes Date: Thu, 27 Jan 2000 19:01:35 +0000 Subject: [PATCH] *** empty log message *** --- src/interfaces/ecpg/ChangeLog | 16 + src/interfaces/ecpg/lib/ecpglib.c | 7 +- src/interfaces/ecpg/preproc/c_keywords.c | 29 +- src/interfaces/ecpg/preproc/ecpg.c | 2 +- src/interfaces/ecpg/preproc/extern.h | 1 + src/interfaces/ecpg/preproc/pgc.l | 29 +- src/interfaces/ecpg/preproc/preproc.y | 416 +++++++---------------- src/interfaces/ecpg/preproc/type.h | 2 + src/interfaces/ecpg/test/Makefile | 12 +- src/interfaces/ecpg/test/stp.pgc | 16 + src/interfaces/ecpg/test/test1.pgc | 9 + src/interfaces/ecpg/test/test2.pgc | 2 +- src/interfaces/ecpg/test/test3.pgc | 6 +- src/interfaces/ecpg/test/test5.pgc | 61 ++++ 14 files changed, 281 insertions(+), 327 deletions(-) create mode 100644 src/interfaces/ecpg/test/stp.pgc create mode 100644 src/interfaces/ecpg/test/test5.pgc diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index bb8517a4b0..aaa63f616a 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -775,5 +775,21 @@ Mon Jan 17 21:55:40 CET 2000 - Synced preproc.y with gram.y. - Changed FETCH syntax using Rene's final patch. Made it more standard compliant. + +Thu Jan 20 10:00:50 CET 2000 + + - Synced preproc.y with gram.y. + +Fri Jan 21 14:52:27 CET 2000 + + - Added more log output to ecpglib. + +Thu Jan 27 08:12:05 CET 2000 + + - Added another patch by Rene Hogendoorn. + - Fixed error messages in pgc.l. + - Improved variable parsing. + - Synced preproc.y with gram.y. - Set library version to 3.0.10. - Set ecpg version to 2.7.0. + diff --git a/src/interfaces/ecpg/lib/ecpglib.c b/src/interfaces/ecpg/lib/ecpglib.c index 5190dd0635..7e75578271 100644 --- a/src/interfaces/ecpg/lib/ecpglib.c +++ b/src/interfaces/ecpg/lib/ecpglib.c @@ -9,7 +9,7 @@ slightly modified) */ -/* Taken over as part of PostgreSQL by Michael Meskes +/* Taken over as part of PostgreSQL by Michael Meskes on Feb. 5th, 1998 */ #include @@ -724,6 +724,9 @@ ECPGexecute(struct statement * stmt) *((void **) var->pointer) = var->value; add_mem(var->value, stmt->lineno); } + + + ECPGlog("ECPGexecute line %d: TYPE db: %d c: %d\n", stmt->lineno, PQftype(results, act_field), var->type); for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++) { @@ -764,7 +767,7 @@ ECPGexecute(struct statement * stmt) status = false; break; } - + switch (var->type) { long res; diff --git a/src/interfaces/ecpg/preproc/c_keywords.c b/src/interfaces/ecpg/preproc/c_keywords.c index 4d04c00dd9..15e1494eea 100644 --- a/src/interfaces/ecpg/preproc/c_keywords.c +++ b/src/interfaces/ecpg/preproc/c_keywords.c @@ -19,25 +19,26 @@ */ static ScanKeyword ScanKeywords[] = { /* name value */ - {"VARCHAR", S_VARCHAR}, + {"VARCHAR", VARCHAR}, {"auto", S_AUTO}, - {"bool", S_BOOL}, - {"char", S_CHAR}, + {"bool", SQL_BOOL}, + {"char", CHAR}, {"const", S_CONST}, - {"double", S_DOUBLE}, - {"enum", S_ENUM}, + {"double", DOUBLE}, + {"enum", SQL_ENUM}, {"extern", S_EXTERN}, - {"float", S_FLOAT}, - {"int", S_INT}, - {"long", S_LONG}, + {"float", FLOAT}, + {"int", SQL_INT}, + {"long", SQL_LONG}, {"register", S_REGISTER}, - {"short", S_SHORT}, - {"signed", S_SIGNED}, + {"short", SQL_SHORT}, + {"signed", SQL_SIGNED}, {"static", S_STATIC}, - {"struct", S_STRUCT}, - {"union", S_UNION}, - {"unsigned", S_UNSIGNED}, - {"varchar", S_VARCHAR}, + {"struct", SQL_STRUCT}, + {"union", UNION}, + {"unsigned", SQL_UNSIGNED}, + {"varchar", VARCHAR}, + {"volatile", S_VOLATILE}, }; ScanKeyword * diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c index 46c29ba2a2..2da1761c6d 100644 --- a/src/interfaces/ecpg/preproc/ecpg.c +++ b/src/interfaces/ecpg/preproc/ecpg.c @@ -1,5 +1,5 @@ /* New main for ecpg, the PostgreSQL embedded SQL precompiler. */ -/* (C) Michael Meskes Feb 5th, 1998 */ +/* (C) Michael Meskes Feb 5th, 1998 */ /* Placed under the same copyright as PostgresSQL */ #include diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h index e921cf664f..682ead43ec 100644 --- a/src/interfaces/ecpg/preproc/extern.h +++ b/src/interfaces/ecpg/preproc/extern.h @@ -40,6 +40,7 @@ extern int yylex(void); extern void yyerror(char *); extern void *mm_alloc(size_t), *mm_realloc(void *, size_t); extern char *mm_strdup(const char *); +extern void mmerror(enum errortype, char * ); ScanKeyword *ScanECPGKeywordLookup(char *); ScanKeyword *ScanCKeywordLookup(char *); diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index 7477676d2f..f69f21b94d 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.49 2000/01/26 05:58:41 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.50 2000/01/27 19:00:39 meskes Exp $ * *------------------------------------------------------------------------- */ @@ -246,7 +246,7 @@ cppline {space}*#(.*\\{line_end})*.* errno = 0; yylval.ival = strtol(literalbuf, &endptr, 2); if (*endptr != '\0' || errno == ERANGE) - yyerror("ERROR: Bad binary integer input!"); + mmerror(ET_ERROR, "Bad binary integer input!"); return ICONST; } {xhinside} | @@ -268,7 +268,7 @@ cppline {space}*#(.*\\{line_end})*.* errno = 0; yylval.ival = strtol(literalbuf, &endptr, 16); if (*endptr != '\0' || errno == ERANGE) - yyerror("ERROR: Bad hexadecimal integer input"); + mmerror(ET_ERROR, "Bad hexadecimal integer input"); return ICONST; } @@ -355,7 +355,7 @@ cppline {space}*#(.*\\{line_end})*.* errno = 0; yylval.dval = strtod((char *)yytext,&endptr); if (*endptr != '\0' || errno == ERANGE) - yyerror("ERROR: Bad float8 input"); + mmerror(ET_ERROR, "Bad float8 input"); return FCONST; } yylval.str = mm_strdup((char*)yytext); @@ -367,7 +367,7 @@ cppline {space}*#(.*\\{line_end})*.* errno = 0; yylval.dval = strtod((char *)yytext,&endptr); if (*endptr != '\0' || errno == ERANGE) - yyerror("ERROR: Bad float input"); + mmerror(ET_ERROR, "Bad float input"); return FCONST; } :{identifier}(("->"|\.){identifier})* { @@ -385,6 +385,13 @@ cppline {space}*#(.*\\{line_end})*.* if (isascii((unsigned char)lower_text[i]) && isupper(lower_text[i])) lower_text[i] = tolower(lower_text[i]); + if (i >= NAMEDATALEN) + { + sprintf(errortext, "Identifier \"%s\" will be truncated to \"%.*s\"", yytext, NAMEDATALEN-1, yytext); + mmerror (ET_WARN, errortext); + yytext[NAMEDATALEN-1] = '\0'; + } + keyword = ScanKeywordLookup((char*)lower_text); if (keyword != NULL) { return keyword->value; @@ -509,10 +516,10 @@ cppline {space}*#(.*\\{line_end})*.* {exec_sql}{elif}{space_or_nl}* { /* pop stack */ if ( preproc_tos == 0 ) { - yyerror("ERROR: missing matching 'EXEC SQL IFDEF / EXEC SQL IFNDEF'"); + mmerror(ET_FATAL, "Missing matching 'EXEC SQL IFDEF / EXEC SQL IFNDEF'"); } else if ( stacked_if_value[preproc_tos].else_branch ) { - yyerror("ERROR: missing 'EXEC SQL ENDIF;'"); + mmerror(ET_FATAL, "Missing 'EXEC SQL ENDIF;'"); } else { preproc_tos--; @@ -523,7 +530,7 @@ cppline {space}*#(.*\\{line_end})*.* {exec_sql}{else}{space_or_nl}*";" { /* only exec sql endif pops the stack, so take care of duplicated 'else' */ if ( stacked_if_value[preproc_tos].else_branch ) { - yyerror("ERROR: duplicated 'EXEC SQL ELSE;'"); + mmerror(ET_FATAL, "Duplicated 'EXEC SQL ELSE;'"); } else { stacked_if_value[preproc_tos].else_branch = TRUE; @@ -541,7 +548,7 @@ cppline {space}*#(.*\\{line_end})*.* } {exec_sql}{endif}{space_or_nl}*";" { if ( preproc_tos == 0 ) { - yyerror("ERROR: unmatched 'EXEC SQL ENDIF;'"); + mmerror(ET_FATAL, "Unmatched 'EXEC SQL ENDIF;'"); } else { preproc_tos--; @@ -559,7 +566,7 @@ cppline {space}*#(.*\\{line_end})*.* {identifier}{space_or_nl}*";" { if ( preproc_tos >= MAX_NESTED_IF-1 ) { - yyerror("ERROR: too many nested 'EXEC SQL IFDEF' conditions"); + mmerror(ET_FATAL, "Too many nested 'EXEC SQL IFDEF' conditions"); } else { struct _defines *defptr; @@ -680,7 +687,7 @@ cppline {space}*#(.*\\{line_end})*.* if ( preproc_tos > 0 ) { preproc_tos = 0; - yyerror("ERROR: missing 'EXEC SQL ENDIF;'"); + mmerror(ET_FATAL, "Missing 'EXEC SQL ENDIF;'"); } if (yy_buffer == NULL) diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index c43ffcfa57..7b8d16f31a 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -24,6 +24,7 @@ int struct_level = 0; char errortext[128]; static char *connection = NULL; static int QueryIsRule = 0, ForUpdateNotAllowed = 0, FoundInto = 0; +static int initializer = 0; static struct this_type actual_type[STRUCT_DEPTH]; static char *actual_storage[STRUCT_DEPTH]; static char *actual_startline[STRUCT_DEPTH]; @@ -36,12 +37,10 @@ struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL}; struct ECPGtype ecpg_query = {ECPGt_char_variable, 0L, {NULL}}; -enum errortype {ET_WARN, ET_ERROR, ET_FATAL}; - /* * Handle parsing errors and warnings */ -static void +void mmerror(enum errortype type, char * error) { @@ -643,10 +642,8 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim %token SQL_VAR SQL_WHENEVER /* C token */ -%token S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_ENUM S_EXTERN -%token S_FLOAT S_INT S -%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT -%token S_UNION S_UNSIGNED S_VARCHAR +%token S_ANYTHING S_AUTO S_CONST S_EXTERN +%token S_REGISTER S_STATIC S_VOLATILE /* I need this and don't know where it is defined inside the backend */ %token TYPECAST @@ -814,21 +811,20 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim %type indicator ECPGExecute ECPGPrepare ecpg_using %type storage_clause opt_initializer c_anything blockstart %type blockend variable_list variable c_thing c_term -%type opt_pointer cvariable ECPGDisconnect dis_name +%type opt_pointer cvariable ECPGDisconnect dis_name storage_modifier %type stmt symbol opt_symbol ECPGRelease execstring server_name %type connection_object opt_server opt_port c_stuff opt_reference %type user_name opt_user char_variable ora_user ident %type db_prefix server opt_options opt_connection_name c_list -%type ECPGSetConnection cpp_line s_enum ECPGTypedef c_args +%type ECPGSetConnection cpp_line ECPGTypedef c_args %type enum_type civariableonly ECPGCursorStmt ECPGDeallocate -%type ECPGFree ECPGDeclare ECPGVar sql_variable_declarations -%type sql_declaration sql_variable_list sql_variable opt_at +%type ECPGFree ECPGDeclare ECPGVar opt_at enum_definition %type struct_type s_struct declaration declarations variable_declarations %type s_struct s_union union_type ECPGSetAutocommit on_off -%type simple_type varchar_type +%type simple_type signed_type unsigned_type varchar_type -%type type ctype +%type type %type action @@ -943,7 +939,8 @@ stmt: AlterTableStmt { output_statement($1, 0); } output_statement($1, 0); } | ECPGFree { - fprintf(yyout, "{ ECPGdeallocate(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1); + fprintf(yyout, "{ ECPGdeallocate(__LINE__, \"%s\");", $1); + whenever_action(2); free($1); } @@ -1320,9 +1317,9 @@ DEFAULT} */ } /* ALTER TABLE DROP [COLUMN] {RESTRICT|CASCADE} */ | ALTER TABLE relation_name opt_inh_star DROP opt_column ColId - drop_behavior + /* drop_behavior */ { - $$ = cat_str(6, make_str("alter table"), $3, $4, make_str("drop"), $6, $7, $8); + $$ = cat_str(5, make_str("alter table"), $3, $4, make_str("drop"), $6, $7); } /* ALTER TABLE ADD CONSTRAINT ... */ | ALTER TABLE relation_name opt_inh_star ADD TableConstraint @@ -2584,21 +2581,21 @@ createdb_opt_location: LOCATION '=' Sconst { $$ = cat2_str(make_str("location = createdb_opt_encoding: ENCODING '=' Sconst { #ifndef MULTIBYTE - mmerror(ET_ERROR, "WITH ENCODING is not supported."); + mmerror(ET_ERROR, "Multi-byte support is not enabled."); #endif $$ = cat2_str(make_str("encoding ="), $3); } | ENCODING '=' Iconst { #ifndef MULTIBYTE - mmerror(ET_ERROR, "WITH ENCODING is not supported."); + mmerror(ET_ERROR, "Multi-byte support is not enabled."); #endif $$ = cat2_str(make_str("encoding ="), $3); } | ENCODING '=' DEFAULT { #ifndef MULTIBYTE - mmerror(ET_ERROR, "WITH ENCODING is not supported."); + mmerror(ET_ERROR, "Multi-byte support is not enabled."); #endif $$ = make_str("encoding = default"); } @@ -3405,17 +3402,16 @@ opt_decimal: '(' Iconst ',' Iconst ')' } ; -/* SQL92 character data types +/* + * SQL92 character data types * The following implements CHAR() and VARCHAR(). * - ay 6/95 */ Character: character '(' Iconst ')' { - if (strncasecmp($1, "char", strlen("char")) && strncasecmp($1, "varchar", strlen("varchar"))) - mmerror(ET_ERROR, "internal parsing error; unrecognized character type"); if (atol($3) < 1) { - sprintf(errortext, "length for '%s' type must be at least 1",$1); + sprintf(errortext, "length for type '%s' type must be at least 1",$1); mmerror(ET_ERROR, errortext); } else if (atol($3) > MaxAttrSize) @@ -4332,7 +4328,9 @@ ColLabel: ColId { $$ = $1; } | EXPLAIN { $$ = make_str("explain"); } | EXTEND { $$ = make_str("extend"); } | FALSE_P { $$ = make_str("false"); } + | FLOAT { $$ = make_str("float"); } | FOREIGN { $$ = make_str("foreign"); } + | GLOBAL { $$ = make_str("global"); } | GROUP { $$ = make_str("group"); } | LISTEN { $$ = make_str("listen"); } | LOAD { $$ = make_str("load"); } @@ -4620,30 +4618,40 @@ variable_declarations: /* empty */ { $$ = EMPTY; } declarations: declaration { $$ = $1; } | declarations declaration { $$ = cat2_str($1, $2); } -declaration: storage_clause +declaration: storage_clause storage_modifier { - actual_storage[struct_level] = mm_strdup($1); + actual_storage[struct_level] = cat2_str(mm_strdup($1), mm_strdup($2)); actual_startline[struct_level] = hashline_number(); } type { - actual_type[struct_level].type_enum = $3.type_enum; - actual_type[struct_level].type_dimension = $3.type_dimension; - actual_type[struct_level].type_index = $3.type_index; + actual_type[struct_level].type_enum = $4.type_enum; + actual_type[struct_level].type_dimension = $4.type_dimension; + actual_type[struct_level].type_index = $4.type_index; + + /* we do not need the string "varchar" for output */ + /* so replace it with an empty string */ + if ($4.type_enum == ECPGt_varchar) + { + free($4.type_str); + $4.type_str=EMPTY; + } } variable_list ';' { - $$ = cat_str(5, actual_startline[struct_level], $1, $3.type_str, $5, make_str(";\n")); + $$ = cat_str(6, actual_startline[struct_level], $1, $2, $4.type_str, $6, make_str(";\n")); } storage_clause : S_EXTERN { $$ = make_str("extern"); } | S_STATIC { $$ = make_str("static"); } - | S_SIGNED { $$ = make_str("signed"); } - | S_CONST { $$ = make_str("const"); } | S_REGISTER { $$ = make_str("register"); } | S_AUTO { $$ = make_str("auto"); } | /* empty */ { $$ = EMPTY; } +storage_modifier : S_CONST { $$ = make_str("const"); } + | S_VOLATILE { $$ = make_str("volatile"); } + | /* empty */ { $$ = EMPTY; } + type: simple_type { $$.type_enum = $1; @@ -4654,7 +4662,7 @@ type: simple_type | varchar_type { $$.type_enum = ECPGt_varchar; - $$.type_str = EMPTY; + $$.type_str = make_str("varchar");; $$.type_dimension = -1; $$.type_index = -1; } @@ -4691,12 +4699,16 @@ type: simple_type struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); } -enum_type: s_enum '{' c_list '}' +enum_type: SQL_ENUM opt_symbol enum_definition { - $$ = cat_str(4, $1, make_str("{"), $3, make_str("}")); + $$ = cat_str(3, make_str("enum"), $2, $3); } - -s_enum: S_ENUM opt_symbol { $$ = cat2_str(make_str("enum"), $2); } + | SQL_ENUM symbol + { + $$ = cat2_str(make_str("enum"), $2); + } + +enum_definition: '{' c_list '}' { $$ = cat_str(3, make_str("{"), $2, make_str("}")); } struct_type: s_struct '{' variable_declarations '}' { @@ -4712,38 +4724,64 @@ union_type: s_union '{' variable_declarations '}' $$ = cat_str(4, $1, make_str("{"), $3, make_str("}")); } -s_struct : S_STRUCT opt_symbol +s_struct: SQL_STRUCT opt_symbol { struct_member_list[struct_level++] = NULL; if (struct_level >= STRUCT_DEPTH) mmerror(ET_ERROR, "Too many levels in nested structure definition"); + + /* reset this variable so we see if there was */ + /* an initializer specified */ + initializer = 0; + $$ = cat2_str(make_str("struct"), $2); } -s_union : S_UNION opt_symbol +s_union: UNION opt_symbol { struct_member_list[struct_level++] = NULL; if (struct_level >= STRUCT_DEPTH) mmerror(ET_ERROR, "Too many levels in nested structure definition"); + + /* reset this variable so we see if there was */ + /* an initializer specified */ + initializer = 0; + $$ = cat2_str(make_str("union"), $2); } opt_symbol: /* empty */ { $$ = EMPTY; } | symbol { $$ = $1; } -simple_type: S_SHORT { $$ = ECPGt_short; } - | S_UNSIGNED S_SHORT { $$ = ECPGt_unsigned_short; } - | S_INT { $$ = ECPGt_int; } - | S_UNSIGNED S_INT { $$ = ECPGt_unsigned_int; } - | S_LONG { $$ = ECPGt_long; } - | S_UNSIGNED S_LONG { $$ = ECPGt_unsigned_long; } - | S_FLOAT { $$ = ECPGt_float; } - | S_DOUBLE { $$ = ECPGt_double; } - | S_BOOL { $$ = ECPGt_bool; }; - | S_CHAR { $$ = ECPGt_char; } - | S_UNSIGNED S_CHAR { $$ = ECPGt_unsigned_char; } +simple_type: unsigned_type { $$=$1; } + | opt_signed signed_type { $$=$2; } + ; -varchar_type: S_VARCHAR { $$ = ECPGt_varchar; } +unsigned_type: SQL_UNSIGNED SQL_SHORT { $$ = ECPGt_unsigned_short; } + | SQL_UNSIGNED SQL_SHORT SQL_INT { $$ = ECPGt_unsigned_short; } + | SQL_UNSIGNED { $$ = ECPGt_unsigned_int; } + | SQL_UNSIGNED SQL_INT { $$ = ECPGt_unsigned_int; } + | SQL_UNSIGNED SQL_LONG { $$ = ECPGt_unsigned_long; } + | SQL_UNSIGNED SQL_LONG SQL_INT { $$ = ECPGt_unsigned_long; } + | SQL_UNSIGNED CHAR { $$ = ECPGt_unsigned_char; } + ; + +signed_type: SQL_SHORT { $$ = ECPGt_short; } + | SQL_SHORT SQL_INT { $$ = ECPGt_short; } + | SQL_INT { $$ = ECPGt_int; } + | SQL_LONG { $$ = ECPGt_long; } + | SQL_LONG SQL_INT { $$ = ECPGt_long; } + | SQL_BOOL { $$ = ECPGt_bool; }; + | FLOAT { $$ = ECPGt_float; } + | DOUBLE { $$ = ECPGt_double; } + | CHAR { $$ = ECPGt_char; } + ; + +opt_signed: SQL_SIGNED + | /* EMPTY */ + ; + +varchar_type: VARCHAR { $$ = ECPGt_varchar; } variable_list: variable { @@ -4830,7 +4868,10 @@ variable: opt_pointer symbol opt_array_bounds opt_initializer } opt_initializer: /* empty */ { $$ = EMPTY; } - | '=' c_term { $$ = cat2_str(make_str("="), $2); } + | '=' c_term { + initializer = 1; + $$ = cat2_str(make_str("="), $2); + } opt_pointer: /* empty */ { $$ = EMPTY; } | '*' { $$ = make_str("*"); } @@ -4966,19 +5007,24 @@ ECPGSetConnection: SET SQL_CONNECTION to_equal connection_object /* * define a new type for embedded SQL */ -ECPGTypedef: TYPE_P symbol IS ctype opt_type_array_bounds opt_reference +ECPGTypedef: TYPE_P symbol IS type opt_type_array_bounds opt_reference { /* add entry to list */ struct typedefs *ptr, *this; int dimension = $5.index1; int length = $5.index2; + if (($4.type_enum == ECPGt_struct || + $4.type_enum == ECPGt_union) && + initializer == 1) + mmerror(ET_ERROR, "Initializer not allowed in EXEC SQL VAR command"); + for (ptr = types; ptr != NULL; ptr = ptr->next) { if (strcmp($2, ptr->name) == 0) { /* re-definition is a bug */ - sprintf(errortext, "type %s already defined", $2); + sprintf(errortext, "Type %s already defined", $2); mmerror(ET_ERROR, errortext); } } @@ -5050,237 +5096,21 @@ opt_type_array_bounds: '[' ']' opt_type_array_bounds opt_reference: SQL_REFERENCE { $$ = make_str("reference"); } | /* empty */ { $$ = EMPTY; } -ctype: CHAR - { - $$.type_str = make_str("char"); - $$.type_enum = ECPGt_char; - $$.type_index = -1; - $$.type_dimension = -1; - } - | VARCHAR - { - $$.type_str = make_str("varchar"); - $$.type_enum = ECPGt_varchar; - $$.type_index = -1; - $$.type_dimension = -1; - } - | FLOAT - { - $$.type_str = make_str("float"); - $$.type_enum = ECPGt_float; - $$.type_index = -1; - $$.type_dimension = -1; - } - | DOUBLE - { - $$.type_str = make_str("double"); - $$.type_enum = ECPGt_double; - $$.type_index = -1; - $$.type_dimension = -1; - } - | opt_signed SQL_INT - { - $$.type_str = make_str("int"); - $$.type_enum = ECPGt_int; - $$.type_index = -1; - $$.type_dimension = -1; - } - | SQL_ENUM - { - $$.type_str = make_str("int"); - $$.type_enum = ECPGt_int; - $$.type_index = -1; - $$.type_dimension = -1; - } - | opt_signed SQL_SHORT - { - $$.type_str = make_str("short"); - $$.type_enum = ECPGt_short; - $$.type_index = -1; - $$.type_dimension = -1; - } - | opt_signed SQL_LONG - { - $$.type_str = make_str("long"); - $$.type_enum = ECPGt_long; - $$.type_index = -1; - $$.type_dimension = -1; - } - | SQL_BOOL - { - $$.type_str = make_str("bool"); - $$.type_enum = ECPGt_bool; - $$.type_index = -1; - $$.type_dimension = -1; - } - | SQL_UNSIGNED SQL_INT - { - $$.type_str = make_str("unsigned int"); - $$.type_enum = ECPGt_unsigned_int; - $$.type_index = -1; - $$.type_dimension = -1; - } - | SQL_UNSIGNED SQL_SHORT - { - $$.type_str = make_str("unsigned short"); - $$.type_enum = ECPGt_unsigned_short; - $$.type_index = -1; - $$.type_dimension = -1; - } - | SQL_UNSIGNED SQL_LONG - { - $$.type_str = make_str("unsigned long"); - $$.type_enum = ECPGt_unsigned_long; - $$.type_index = -1; - $$.type_dimension = -1; - } - | SQL_STRUCT - { - struct_member_list[struct_level++] = NULL; - if (struct_level >= STRUCT_DEPTH) - mmerror(ET_ERROR, "Too many levels in nested structure definition"); - } '{' sql_variable_declarations '}' - { - ECPGfree_struct_member(struct_member_list[struct_level--]); - $$.type_str = cat_str(3, make_str("struct {"), $4, make_str("}")); - $$.type_enum = ECPGt_struct; - $$.type_index = -1; - $$.type_dimension = -1; - } - | UNION - { - struct_member_list[struct_level++] = NULL; - if (struct_level >= STRUCT_DEPTH) - mmerror(ET_ERROR, "Too many levels in nested structure definition"); - } '{' sql_variable_declarations '}' - { - ECPGfree_struct_member(struct_member_list[struct_level--]); - $$.type_str = cat_str(3, make_str("union {"), $4, make_str("}")); - $$.type_enum = ECPGt_union; - $$.type_index = -1; - $$.type_dimension = -1; - } - | symbol - { - struct typedefs *this = get_typedef($1); - - $$.type_str = mm_strdup($1); - $$.type_enum = this->type->type_enum; - $$.type_dimension = this->type->type_dimension; - $$.type_index = this->type->type_index; - struct_member_list[struct_level] = this->struct_member_list; - } - -opt_signed: SQL_SIGNED | /* empty */ - -sql_variable_declarations: /* empty */ - { - $$ = EMPTY; - } - | sql_declaration sql_variable_declarations - { - $$ = cat2_str($1, $2); - } - ; - -sql_declaration: ctype - { - 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; - } - sql_variable_list ';' - { - $$ = cat_str(3, $1.type_str, $3, make_str(";")); - } - -sql_variable_list: sql_variable - { - $$ = $1; - } - | sql_variable_list ',' sql_variable - { - $$ = cat_str(3, $1, make_str(","), $3); - } - -sql_variable: opt_pointer symbol opt_array_bounds - { - int dimension = $3.index1; - int length = $3.index2; - struct ECPGtype * type; - char dim[14L]; - - adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1)); - - switch (actual_type[struct_level].type_enum) - { - case ECPGt_struct: - case ECPGt_union: - if (dimension < 0) - type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum); - else - type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum), dimension); - - break; - case ECPGt_varchar: - if (dimension == -1) - type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length); - else - type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension); - - switch(dimension) - { - case 0: - strcpy(dim, "[]"); - break; - case -1: - case 1: - *dim = '\0'; - break; - default: - sprintf(dim, "[%d]", dimension); - break; - } - - break; - case ECPGt_char: - case ECPGt_unsigned_char: - if (dimension == -1) - type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length); - else - type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length), dimension); - - break; - default: - if (length >= 0) - mmerror(ET_ERROR, "No multi-dimensional array support for simple data types"); - - if (dimension < 0) - type = ECPGmake_simple_type(actual_type[struct_level].type_enum, 1); - else - type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, 1), dimension); - - break; - } - - if (struct_level == 0) - new_variable($2, type); - else - ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1])); - - $$ = cat_str(3, $1, $2, $3.str); - } - /* * define the type of one variable for embedded SQL */ -ECPGVar: SQL_VAR symbol IS ctype opt_type_array_bounds opt_reference +ECPGVar: SQL_VAR symbol IS type opt_type_array_bounds opt_reference { struct variable *p = find_variable($2); int dimension = $5.index1; int length = $5.index2; struct ECPGtype * type; + if (($4.type_enum == ECPGt_struct || + $4.type_enum == ECPGt_union) && + initializer == 1) + mmerror(ET_ERROR, "Initializer not allowed in EXEC SQL VAR command"); + adjust_array($4.type_enum, &dimension, &length, $4.type_dimension, $4.type_index, strlen($6)); switch ($4.type_enum) @@ -5561,25 +5391,25 @@ c_anything: IDENT { $$ = $1; } | '-' { $$ = make_str("-"); } | '/' { $$ = make_str("/"); } | '%' { $$ = make_str("%"); } - | S_AUTO { $$ = make_str("auto"); } - | S_BOOL { $$ = make_str("bool"); } - | S_CHAR { $$ = make_str("char"); } - | S_CONST { $$ = make_str("const"); } - | S_DOUBLE { $$ = make_str("double"); } - | S_ENUM { $$ = make_str("enum"); } - | S_EXTERN { $$ = make_str("extern"); } - | S_FLOAT { $$ = make_str("float"); } - | S_INT { $$ = make_str("int"); } - | S_LONG { $$ = make_str("long"); } - | S_REGISTER { $$ = make_str("register"); } - | S_SHORT { $$ = make_str("short"); } - | S_SIGNED { $$ = make_str("signed"); } - | S_STATIC { $$ = make_str("static"); } - | S_STRUCT { $$ = make_str("struct"); } - | S_UNION { $$ = make_str("union"); } - | S_UNSIGNED { $$ = make_str("unsigned"); } - | S_VARCHAR { $$ = make_str("varchar"); } | S_ANYTHING { $$ = make_name(); } + | 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"); } + | SQL_BOOL { $$ = make_str("bool"); } + | SQL_ENUM { $$ = make_str("enum"); } + | SQL_INT { $$ = make_str("int"); } + | SQL_LONG { $$ = make_str("long"); } + | SQL_SHORT { $$ = make_str("short"); } + | SQL_SIGNED { $$ = make_str("signed"); } + | SQL_STRUCT { $$ = make_str("struct"); } + | SQL_UNSIGNED { $$ = make_str("unsigned"); } + | CHAR { $$ = make_str("char"); } + | DOUBLE { $$ = make_str("double"); } + | FLOAT { $$ = make_str("float"); } + | UNION { $$ = make_str("union"); } + | VARCHAR { $$ = make_str("varchar"); } | '[' { $$ = make_str("["); } | ']' { $$ = make_str("]"); } /* | '(' { $$ = make_str("("); } diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h index 1af1e63344..efc8c66923 100644 --- a/src/interfaces/ecpg/preproc/type.h +++ b/src/interfaces/ecpg/preproc/type.h @@ -138,3 +138,5 @@ struct arguments struct variable *indicator; struct arguments *next; }; + +enum errortype {ET_WARN, ET_ERROR, ET_FATAL}; diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile index e183ebc4b9..0af784f8ea 100644 --- a/src/interfaces/ecpg/test/Makefile +++ b/src/interfaces/ecpg/test/Makefile @@ -1,10 +1,12 @@ -all: test1 test2 test3 test4 perftest +all: stp.so test1 test2 test3 test4 test5 perftest #LDFLAGS=-g -I /usr/local/pgsql/include -L/usr/local/pgsql/lib -lecpg -lpq -lcrypt LDFLAGS=-g -I../include -I/usr/include/postgresql -L/usr/lib/postgresql -L../lib -lecpg -lpq -lcrypt +#LDFLAGS=-g -I/usr/include/postgresql -lecpg -lpq -lcrypt #ECPG=/usr/local/pgsql/bin/ecpg ECPG=../preproc/ecpg -I../include +#ECPG=/usr/bin/ecpg -I/usr/include/postgresql .SUFFIXES: .pgc .c @@ -12,10 +14,16 @@ test1: test1.c test2: test2.c test3: test3.c test4: test4.c +test5: test5.c perftest: perftest.c .pgc.c: $(ECPG) $? +stp.so: stp.c + cc -fPIC -I../include -I/usr/include/postgresql -c -o stp.o stp.c + cc -shared -Wl,-soname,stp.so -o stp.so stp.o -lpq -lecpg + + clean: - -/bin/rm test1 test2 test3 test4 perftest *.c log + -/bin/rm test1 test2 test3 test4 test5 perftest *.c log stp.o stp.so diff --git a/src/interfaces/ecpg/test/stp.pgc b/src/interfaces/ecpg/test/stp.pgc new file mode 100644 index 0000000000..6021ae0db4 --- /dev/null +++ b/src/interfaces/ecpg/test/stp.pgc @@ -0,0 +1,16 @@ +EXEC SQL INCLUDE sqlca; + +int my_fun (void) + { + EXEC SQL BEGIN DECLARE SECTION; + int sql_index = 0; + EXEC SQL END DECLARE SECTION; + + EXEC SQL WHENEVER SQLERROR GOTO Error; + EXEC SQL SELECT MIN(index) INTO :sql_index FROM tab; + + return (sql_index); + +Error: + return (sqlca.sqlcode); + } diff --git a/src/interfaces/ecpg/test/test1.pgc b/src/interfaces/ecpg/test/test1.pgc index d8980ade54..02a631a12f 100644 --- a/src/interfaces/ecpg/test/test1.pgc +++ b/src/interfaces/ecpg/test/test1.pgc @@ -94,11 +94,20 @@ exec sql end declare section; strcpy(msg, "select"); exec sql select name, amount, letter into :name, :amount, :letter from "Test"; + printf("Database: mm\n"); for (i=0, j=sqlca.sqlerrd[2]; i= 0) printf(", born %d", personal.birth.born); diff --git a/src/interfaces/ecpg/test/test3.pgc b/src/interfaces/ecpg/test/test3.pgc index 8e0f6c30c6..8ba8995e33 100644 --- a/src/interfaces/ecpg/test/test3.pgc +++ b/src/interfaces/ecpg/test/test3.pgc @@ -19,7 +19,7 @@ exec sql begin declare section; int ind_children; str *married = NULL; char *wifesname="Petra"; - char *query="select * from meskes where name = :var1"; + char *query="select * from meskes where name = ?"; exec sql end declare section; exec sql declare cur cursor for @@ -54,7 +54,7 @@ exec sql end declare section; while (1) { strcpy(msg, "fetch"); - exec sql fetch cur into :personal:ind_personal, :married:ind_married, :children:ind_children; + exec sql fetch from cur into :personal:ind_personal, :married:ind_married, :children:ind_children; printf("%8.8s", personal.name.arr); if (ind_personal.ind_birth.born >= 0) printf(", born %d", personal.birth.born); @@ -74,7 +74,7 @@ exec sql end declare section; exec sql close cur; /* and now a query with prepare */ - exec sql prepare MM from "select name, born, age, married, children from meskes where name = ?"; + exec sql prepare MM from :query; exec sql declare prep cursor for MM; strcpy(msg, "open"); diff --git a/src/interfaces/ecpg/test/test5.pgc b/src/interfaces/ecpg/test/test5.pgc new file mode 100644 index 0000000000..1e0c60c4dd --- /dev/null +++ b/src/interfaces/ecpg/test/test5.pgc @@ -0,0 +1,61 @@ +#include +#include + +EXEC SQL INCLUDE sqlca; + +static void ErrorExit (void); + +int main (void) + { + EXEC SQL BEGIN DECLARE SECTION; + int result; + int values[2], i; + EXEC SQL END DECLARE SECTION; + FILE *dbgs; + + + if ((dbgs = fopen("log", "w")) != NULL) + ECPGdebug(1, dbgs); + + EXEC SQL WHENEVER SQLERROR DO ErrorExit(); + EXEC SQL CONNECT TO 'mm'; + EXEC SQL CREATE TABLE tab (index int); + EXEC SQL INSERT INTO tab(index) values(14); + EXEC SQL INSERT INTO tab(index) values(7); + EXEC SQL COMMIT; + + EXEC SQL CREATE FUNCTION my_fun () RETURNS int AS + '/home/postgres/pgsql/src/interfaces/ecpg.mm/test/stp.so' LANGUAGE 'C'; + EXEC SQL COMMIT; + + EXEC SQL SELECT index INTO :values FROM tab; + for (i = 0; i < 2; i++) + printf("tab[%d] = %d\n", i, values[i]); + + EXEC SQL SELECT my_fun () INTO :result; + printf ("result = %d\n", result); + + EXEC SQL DROP TABLE tab; + EXEC SQL DROP FUNCTION my_fun (); + EXEC SQL COMMIT; + EXEC SQL DISCONNECT; + + if (dbgs != NULL) + fclose(dbgs); + exit (0); + } + + +static void ErrorExit (void) + { + EXEC SQL WHENEVER SQLERROR CONTINUE; + + sqlprint(); + + EXEC SQL DROP TABLE tab; + EXEC SQL DROP FUNCTION my_fun (); + EXEC SQL COMMIT; + + EXEC SQL DISCONNECT; + exit (-1); + }