diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index ff721fa501..bb39d21394 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -38,3 +38,21 @@ Thu Feb 19 12:48:14 CET 1998 - added do option to whenever statement +Sat Feb 21 19:10:55 CET 1998 + + - use char[] as string not as array of bytes that is integers + +Sun Feb 22 16:37:36 CET 1998 + + - use long for all size variables + - added execute immediate statement + +Sun Feb 22 20:41:32 CET 1998 + + - use varcharsize = 1 for all simple types, 0 means pointer, > 1 + means array if type is char resp. unsigned char + +Thu Feb 24 12:26:12 CET 1998 + + - allow 'go to' in whenever statement as well as 'goto' + - new argument 'stop' for whenever statement diff --git a/src/interfaces/ecpg/Makefile b/src/interfaces/ecpg/Makefile index ee99aaeab5..f4768822a6 100644 --- a/src/interfaces/ecpg/Makefile +++ b/src/interfaces/ecpg/Makefile @@ -1,5 +1,4 @@ -SUBDIRS = include lib preproc doc - all install uninstall clean: + $(MAKE) -C include $@ $(MAKE) -C lib $@ $(MAKE) -C preproc $@ diff --git a/src/interfaces/ecpg/TODO b/src/interfaces/ecpg/TODO index 3de01c497a..dab3e0b4de 100644 --- a/src/interfaces/ecpg/TODO +++ b/src/interfaces/ecpg/TODO @@ -40,8 +40,22 @@ could be realised in a script. Now comes my list (MM): -What do we do with enum data types? +The return code is alway -1 in case of an error. You cannot see which error +occured by examining the return code. -The cursor is opened when the declare statement is issued. +The cursor is opened when the declare statement is issued. + +ecpg does not understand enum datatypes. The is no exec sql prepare statement. + +The complete structure definition has to be listed inside the declare +section for ecpg to be able to understand it. + +Each variable has to be defined on a line on its own. + +There is no way yet to fill a complete array with one call except arrays of +[unsigned] char which are considered strings. + +ecpg cannot use pointer variables except [unsigned] char * + diff --git a/src/interfaces/ecpg/lib/ecpglib.c b/src/interfaces/ecpg/lib/ecpglib.c index 19ec7f3b69..823a335c76 100644 --- a/src/interfaces/ecpg/lib/ecpglib.c +++ b/src/interfaces/ecpg/lib/ecpglib.c @@ -96,9 +96,9 @@ ECPGdo(int lineno, char *query,...) while (type != ECPGt_EOIT) { void *value = NULL; - short varcharsize; - short size; - short arrsize; + long varcharsize; + long size; + long arrsize; char *newcopy; char *mallocedval = NULL; @@ -110,20 +110,18 @@ ECPGdo(int lineno, char *query,...) contents to arrive in a comma-separated list on insert (I think). */ value = va_arg(ap, void *); - varcharsize = va_arg(ap, short); - size = va_arg(ap, short); - arrsize = va_arg(ap, short); + varcharsize = va_arg(ap, long); + size = va_arg(ap, long); + arrsize = va_arg(ap, long); switch (type) { - case ECPGt_char: case ECPGt_short: case ECPGt_int: sprintf(buff, "%d", *(int *) value); tobeinserted = buff; break; - case ECPGt_unsigned_char: case ECPGt_unsigned_short: case ECPGt_unsigned_int: sprintf(buff, "%d", *(unsigned int *) value); @@ -155,6 +153,27 @@ ECPGdo(int lineno, char *query,...) tobeinserted = buff; break; + case ECPGt_char: + case ECPGt_unsigned_char: + { + /* set slen to string length if type is char * */ + int slen = (varcharsize == 0) ? strlen((char *) value) : varcharsize; + + newcopy = (char *) malloc(slen + 1); + strncpy(newcopy, (char *) value, slen); + newcopy[slen] = '\0'; + + mallocedval = (char *) malloc(2 * strlen(newcopy) + 3); + strcpy(mallocedval, "'"); + strcat(mallocedval, quote_postgres(newcopy)); + strcat(mallocedval, "'"); + + free(newcopy); + + tobeinserted = mallocedval; + } + break; + case ECPGt_varchar: case ECPGt_varchar2: { @@ -274,7 +293,7 @@ ECPGdo(int lineno, char *query,...) if (n < 1) { - ECPGlog("ECPGdo lineno %d: Incorrect number of matches: %d\n", + ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n", lineno, n); register_error(1, "Data not found line %d.", lineno); break; @@ -293,9 +312,9 @@ ECPGdo(int lineno, char *query,...) for (x = 0; x < m && status; x++) { void *value = NULL; - short varcharsize; - short size; - short arrsize; + long varcharsize; + long size; + long arrsize; char *pval = PQgetvalue(results, 0, x); @@ -311,9 +330,9 @@ ECPGdo(int lineno, char *query,...) /* We will have to decode the value */ type = va_arg(ap, enum ECPGttype); value = va_arg(ap, void *); - varcharsize = va_arg(ap, short); - size = va_arg(ap, short); - arrsize = va_arg(ap, short); + varcharsize = va_arg(ap, long); + size = va_arg(ap, long); + arrsize = va_arg(ap, long); switch (type) { @@ -321,7 +340,6 @@ ECPGdo(int lineno, char *query,...) unsigned long ures; double dres; - case ECPGt_char: case ECPGt_short: case ECPGt_int: case ECPGt_long: @@ -342,9 +360,6 @@ ECPGdo(int lineno, char *query,...) /* Again?! Yes */ switch (type) { - case ECPGt_char: - *(char *) value = (char) res; - break; case ECPGt_short: *(short *) value = (short) res; break; @@ -360,7 +375,6 @@ ECPGdo(int lineno, char *query,...) } break; - case ECPGt_unsigned_char: case ECPGt_unsigned_short: case ECPGt_unsigned_int: case ECPGt_unsigned_long: @@ -381,9 +395,6 @@ ECPGdo(int lineno, char *query,...) /* Again?! Yes */ switch (type) { - case ECPGt_unsigned_char: - *(unsigned char *) value = (unsigned char) ures; - break; case ECPGt_unsigned_short: *(unsigned short *) value = (unsigned short) ures; break; @@ -452,6 +463,20 @@ ECPGdo(int lineno, char *query,...) return false; break; + case ECPGt_char: + case ECPGt_unsigned_char: + { + if (varcharsize == 0) + { + /* char* */ + strncpy((char *) value, pval, strlen(pval)); + ((char *) value)[strlen(pval)] = '\0'; + } + else + strncpy((char *) value, pval, varcharsize); + } + break; + case ECPGt_varchar: { struct ECPGgeneric_varchar *var = diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile index 5dddd9042c..c6438be232 100644 --- a/src/interfaces/ecpg/preproc/Makefile +++ b/src/interfaces/ecpg/preproc/Makefile @@ -5,22 +5,22 @@ MAJOR_VERSION=1 MINOR_VERSION=0 PATCHLEVEL=0 -CFLAGS=-I$(SRCDIR)/include -I../include -Wall -DMAJOR_VERSION=$(MAJOR_VERSION) -DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) +CFLAGS+=-I$(SRCDIR)/include -I../include -Wall -DMAJOR_VERSION=$(MAJOR_VERSION) -DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) all:: ecpg clean: - rm -f *.o core a.out ecpg y.tab.h y.tab.c *~ + rm -f *.o core a.out ecpg y.tab.h y.tab.c pgc.c *~ install: all - $(INSTALL) $(INSTLOPTS) ecpg $(DESTDIR)$(BINDIR) + $(INSTALL) $(INSTL_EXE_OPTS) ecpg $(DESTDIR)$(BINDIR) uninstall: rm -f $(DESTDIR)$(BINDIR)/ecpg # Rule that really do something. ecpg: y.tab.o pgc.o type.o ecpg.o ../lib/typename.o - $(CC) -Wall -o ecpg y.tab.o pgc.o type.o ecpg.o ../lib/typename.o $(LEXLIB) + $(CC) -o ecpg y.tab.o pgc.o type.o ecpg.o ../lib/typename.o $(LEXLIB) y.tab.h y.tab.c: preproc.y $(YACC) $(YFLAGS) $< diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index f3def3d2e9..5523d0fce7 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -29,6 +29,7 @@ end [eE][nN][dD] exec [eE][xX][eE][cC] execute [eE][xX][eE][cC][uU][tT][eE] found [fF][oO][uU][nN][dD] +go [gG][oO] goto [gG][oO][tT][oO] immediate [iI][mM][mM][eE][dD][iI][aA][tT][eE] include [iI][nN][cC][lL][uU][dD][eE] @@ -41,6 +42,8 @@ section [sS][eE][cC][tT][iI][oO][nN] sql [sS][qQ][lL] sqlerror [sS][qQ][lL][eE][rR][rR][oO][rR] sqlprint [sS][qQ][lL][pP][rR][iI][nN][tT] +stop [sS][tT][oO][pP] +to [tT][oO] varchar [vV][aA][rR][cC][hH][aA][rR] varchar2 [vV][aA][rR][cC][hH][aA][rR]2 whenever [wW][hH][eE][nN][eE][vV][eE][rR] @@ -69,6 +72,8 @@ work [wW][oO][rR][kK] {continue} { dbg(SQL_CONTINUE); return SQL_CONTINUE; } {into} { dbg(SQL_INTO); return SQL_INTO; } {goto} { dbg(SQL_GOTO); return SQL_GOTO; } +{go}{ws}{to} { dbg(SQL_GOTO); return SQL_GOTO; } +{stop} { dbg(SQL_STOP); return SQL_STOP; } {do} { dbg(SQL_DO); return SQL_DO; } {length} { dbg(S_LENGTH); return S_LENGTH; } diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 52b814ac19..2a77c441a6 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -52,7 +52,9 @@ print_action(struct when *w) break; case W_DO: fprintf(yyout, "%s;", w->str); break; - default: fprintf(yyout, "{/* not implemented yet */}"); + case W_STOP: fprintf(yyout, "exit (1);"); + break; + default: fprintf(yyout, "{/* %d not implemented yet */}", w->code); break; } } @@ -168,8 +170,8 @@ struct arguments { static struct arguments * argsinsert = NULL; static struct arguments * argsresult = NULL; -void -reset_variables() +static void +reset_variables(void) { argsinsert = NULL; argsresult = NULL; @@ -177,7 +179,7 @@ reset_variables() /* Add a variable to a request. */ -void +static void add_variable(struct arguments ** list, struct variable * var) { struct arguments * p = (struct arguments *)malloc(sizeof(struct arguments)); @@ -191,7 +193,7 @@ add_variable(struct arguments ** list, struct variable * var) This is a recursive function that works from the end of the list and deletes the list as we go on. */ -void +static void dump_variables(struct arguments * list) { if (list == NULL) @@ -217,7 +219,7 @@ dump_variables(struct arguments * list) int tagname; struct ECPGtemp_type type; char * symbolname; - int indexsize; + long indexsize; enum ECPGttype type_enum; struct when action; } @@ -227,19 +229,20 @@ dump_variables(struct arguments * list) %token SQL_CONNECT SQL_OPEN SQL_EXECUTE SQL_IMMEDIATE %token SQL_COMMIT SQL_ROLLBACK SQL_RELEASE SQL_WORK SQL_WHENEVER %token SQL_SQLERROR SQL_NOT_FOUND SQL_BREAK SQL_CONTINUE -%token SQL_DO SQL_GOTO SQL_SQLPRINT +%token SQL_DO SQL_GOTO SQL_SQLPRINT SQL_STOP %token S_SYMBOL S_LENGTH S_ANYTHING S_LABEL %token S_VARCHAR S_VARCHAR2 -%token S_EXTERN S_STATIC S_AUTO S_CONST S_REGISTER S_STRUCT S_SIGNED +%token S_EXTERN S_STATIC S_AUTO S_CONST S_REGISTER S_STRUCT %token S_UNSIGNED S_SIGNED %token S_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE S_BOOL %token '[' ']' ';' ',' '{' '}' '=' '*' '(' ')' -%type type type_detailed varchar_type simple_type array_type struct_type +%type type type_detailed varchar_type simple_type struct_type string_type +/* % type array_type pointer_type */ %type symbol label %type maybe_storage_clause varchar_tag db_name -%type simple_tag +%type simple_tag char_tag %type index length %type action %type canything sqlanything both_anything vartext commit_release @@ -286,7 +289,7 @@ variable_declaration : type initializer ';' { if (struct_level == 0) { new_variable($1.name, $1.typ); - free($1.name); + free((void *)$1.name); } fprintf(yyout, ";"); } @@ -319,15 +322,16 @@ symbol : S_SYMBOL { type : maybe_storage_clause type_detailed { $$ = $2; }; type_detailed : varchar_type { $$ = $1; } | simple_type { $$ = $1; } - | array_type {$$ = $1; } - | pointer_type {$$ = $1; } + | string_type { $$ = $1; } +/* | array_type {$$ = $1; } + | pointer_type {$$ = $1; }*/ | struct_type {$$ = $1; }; varchar_type : varchar_tag symbol index { - if ($3 > 0) - fprintf(yyout, "struct varchar_%s { int len; char arr[%d]; } %s", $2, $3, $2); + if ($3 > 0L) + fprintf(yyout, "struct varchar_%s { int len; char arr[%ld]; } %s", $2, $3, $2); else - fprintf(yyout, "struct varchar_%s { int len; char arr[%d]; } %s", $2, $3, $2); + fprintf(yyout, "struct varchar_%s { int len; char arr[]; } %s", $2, $2); if (struct_level == 0) { $$.name = $2; @@ -345,15 +349,53 @@ simple_type : simple_tag symbol { if (struct_level == 0) { $$.name = $2; - $$.typ = ECPGmake_simple_type($1); + $$.typ = ECPGmake_simple_type($1, 1); } else - ECPGmake_record_member($2, ECPGmake_simple_type($1), &(record_member_list[struct_level-1])); + ECPGmake_record_member($2, ECPGmake_simple_type($1, 1), &(record_member_list[struct_level-1])); } +string_type : char_tag symbol index { + if ($3 > 0L) + fprintf(yyout, "%s %s [%ld]", ECPGtype_name($1), $2, $3); + else + fprintf(yyout, "%s %s []", ECPGtype_name($1), $2); + if (struct_level == 0) + { + $$.name = $2; + $$.typ = ECPGmake_simple_type($1, $3); + } + else + ECPGmake_record_member($2, ECPGmake_simple_type($1, $3), &(record_member_list[struct_level-1])); +} + | char_tag '*' symbol { + fprintf(yyout, "%s *%s", ECPGtype_name($1), $3); + if (struct_level == 0) + { + $$.name = $3; + $$.typ = ECPGmake_simple_type($1, 0); + } + else + ECPGmake_record_member($3, ECPGmake_simple_type($1, 0), &(record_member_list[struct_level-1])); +} + | char_tag symbol { + fprintf(yyout, "%s %s", ECPGtype_name($1), $2); + if (struct_level == 0) + { + $$.name = $2; + $$.typ = ECPGmake_simple_type($1, 1); + } + else + ECPGmake_record_member($2, ECPGmake_simple_type($1, 1), &(record_member_list[struct_level-1])); +} + +char_tag : S_CHAR { $$ = ECPGt_char; } + | S_UNSIGNED S_CHAR { $$ = ECPGt_unsigned_char; } + +/* array_type : simple_tag symbol index { if ($3 > 0) - fprintf(yyout, "%s %s [%d]", ECPGtype_name($1), $2, $3); + fprintf(yyout, "%s %s [%ld]", ECPGtype_name($1), $2, $3); else fprintf(yyout, "%s %s []", ECPGtype_name($1), $2); if (struct_level == 0) @@ -375,6 +417,7 @@ pointer_type : simple_tag '*' symbol { else ECPGmake_record_member($3, ECPGmake_array_type(ECPGmake_simple_type($1), 0), &(record_member_list[struct_level-1])); } +*/ s_struct : S_STRUCT symbol { struct_level++; @@ -394,9 +437,7 @@ struct_type : s_struct '{' variable_declarations '}' symbol { record_member_list[struct_level] = NULL; } -simple_tag : S_CHAR { $$ = ECPGt_char; } - | S_UNSIGNED S_CHAR { $$ = ECPGt_unsigned_char; } - | S_SHORT { $$ = ECPGt_short; } +simple_tag : S_SHORT { $$ = ECPGt_short; } | S_UNSIGNED S_SHORT { $$ = ECPGt_unsigned_short; } | S_INT { $$ = ECPGt_int; } | S_UNSIGNED S_INT { $$ = ECPGt_unsigned_int; } @@ -415,9 +456,9 @@ maybe_storage_clause : S_EXTERN { fwrite(yytext, yyleng, 1, yyout); } | /* empty */ { }; index : '[' length ']' { $$ = $2; } - | '[' ']' { $$ = 0; } + | '[' ']' { $$ = 0L; } -length : S_LENGTH { $$ = atoi(yytext); } +length : S_LENGTH { $$ = atol(yytext); } sqlinclude : SQL_START SQL_INCLUDE { fprintf(yyout, "#include \""); } filename SQL_SEMI { fprintf(yyout, ".h\""); output_line_number(); }; @@ -430,7 +471,7 @@ sqlconnect : SQL_START SQL_CONNECT { fprintf(yyout, "ECPGconnect("); } SQL_SEMI { fprintf(yyout, ");"); whenever_action();} db_name : SQL_STRING { fprintf(yyout, "\""); fwrite(yytext + 1, yyleng - 2, 1, yyout); fprintf(yyout, "\""); } - | ':' symbol { /* check if we have a char variabnle */ + | ':' symbol { /* check if we have a char variable */ struct variable *p = find_variable($2); enum ECPGttype typ = p->type->typ; @@ -465,45 +506,55 @@ sqlrollback : SQL_START SQL_ROLLBACK SQL_SEMI { whenever_action(); }; -sqlexecute : SQL_START { /* Reset stack */ - reset_variables(); - fprintf(yyout, "ECPGdo(__LINE__, \""); -} SQL_EXECUTE SQL_IMMEDIATE sqlstatement_words SQL_SEMI { - /* Dump */ - fprintf(yyout, "\", "); - dump_variables(argsinsert); - fprintf(yyout, "ECPGt_EOIT, "); - /* dump_variables(argsresult); output variables must not exist here */ - fprintf(yyout, "ECPGt_EORT );"); +sqlexecute : SQL_START SQL_EXECUTE SQL_IMMEDIATE ':' symbol SQL_SEMI { + fprintf(yyout, "ECPGdo(__LINE__, %s, ECPGt_EOIT, ECPGt_EORT );", $5); whenever_action(); }; -sqlwhenever : SQL_START SQL_WHENEVER SQL_SQLERROR action SQL_SEMI{ - when_error = $4; +sqlwhenever : SQL_START SQL_WHENEVER SQL_SQLERROR { + fprintf(yyout, "/* exec sql whenever sqlerror "); +} action SQL_SEMI{ + when_error.code = $5.code; + when_error.str = $5.str; + fprintf(yyout, "; */\n"); } - | SQL_START SQL_WHENEVER SQL_NOT_FOUND action SQL_SEMI{ - when_nf = $4; + | SQL_START SQL_WHENEVER SQL_NOT_FOUND { + fprintf(yyout, "/* exec sql whenever not found "); +} action SQL_SEMI{ + when_nf.code = $5.code; + when_nf.str=$5.str; + fprintf(yyout, "; */\n"); } action : SQL_BREAK { $$.code = W_BREAK; $$.str = NULL; + fprintf(yyout, "break"); } | SQL_CONTINUE { $$.code = W_CONTINUE; $$.str = NULL; + fprintf(yyout, "continue"); } | SQL_SQLPRINT { $$.code = W_SQLPRINT; $$.str = NULL; + fprintf(yyout, "sqlprint"); +} + | SQL_STOP { + $$.code = W_STOP; + $$.str = NULL; + fprintf(yyout, "stop"); } | SQL_GOTO label { $$.code = W_GOTO; $$.str = $2; + fprintf(yyout, "goto %s", $2); } - | SQL_GOTO symbol { + | SQL_GOTO symbol { $$.code = W_GOTO; $$.str = $2; + fprintf(yyout, "goto %s", $2); } | SQL_DO symbol '(' { do_str = (char *) mm_alloc(do_length = strlen($2) + 4); @@ -513,6 +564,7 @@ action : SQL_BREAK { do_str[strlen(do_str)]=')'; $$.code = W_DO; $$.str = do_str; + fprintf(yyout, "do %s", do_str); do_str = NULL; do_length = 0; } @@ -599,6 +651,7 @@ blockend : '}' { fwrite(yytext, yyleng, 1, yyout); } %% + static void yyerror(char * error) { fprintf(stderr, "%s in line %d\n", error, yylineno); diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index bac44a72ed..a436997aaa 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -57,21 +57,21 @@ ECPGmake_record_member(char *name, struct ECPGtype *type, struct ECPGrecord_memb } struct ECPGtype * -ECPGmake_simple_type(enum ECPGttype typ) +ECPGmake_simple_type(enum ECPGttype typ, long siz) { struct ECPGtype *ne = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype)); ne->typ = typ; - ne->size = 0; + ne->size = siz; ne->u.element = 0; return ne; } struct ECPGtype * -ECPGmake_varchar_type(enum ECPGttype typ, unsigned short siz) +ECPGmake_varchar_type(enum ECPGttype typ, long siz) { - struct ECPGtype *ne = ECPGmake_simple_type(typ); + struct ECPGtype *ne = ECPGmake_simple_type(typ, 1); ne->size = siz; @@ -79,9 +79,9 @@ ECPGmake_varchar_type(enum ECPGttype typ, unsigned short siz) } struct ECPGtype * -ECPGmake_array_type(struct ECPGtype *typ, unsigned short siz) +ECPGmake_array_type(struct ECPGtype *typ, long siz) { - struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array); + struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, siz); ne->size = siz; ne->u.element = typ; @@ -92,7 +92,7 @@ ECPGmake_array_type(struct ECPGtype *typ, unsigned short siz) struct ECPGtype * ECPGmake_record_type(struct ECPGrecord_member *rm) { - struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_record); + struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_record, 1); ne->u.members = rm; @@ -104,9 +104,9 @@ ECPGmake_record_type(struct ECPGrecord_member *rm) The type is dumped as: type-tag - enum ECPGttype reference-to-variable - void * - size - short size of this field (if varchar) - arrsize - short number of elements in the arr - offset - short offset to the next element + size - long size of this field (if varchar) + arrsize - long number of elements in the arr + offset - offset to the next element Where: type-tag is one of the simple types or varchar. reference-to-variable can be a reference to a struct element. @@ -115,9 +115,9 @@ ECPGmake_record_type(struct ECPGrecord_member *rm) the variable (required to do array fetches of records). */ void ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, - short varcharsize, - unsigned short arrsiz, const char *siz, const char *prefix); -void ECPGdump_a_record(FILE *o, const char *name, unsigned short arrsiz, + long varcharsize, + long arrsiz, const char *siz, const char *prefix); +void ECPGdump_a_record(FILE *o, const char *name, long arrsiz, struct ECPGtype *typ, const char *offset, const char *prefix); @@ -162,67 +162,75 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype *typ, const char *pre string, it represents the offset needed if we are in an array of records. */ void ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, - short varcharsize, - unsigned short arrsiz, + long varcharsize, + long arrsiz, const char *siz, const char *prefix) { switch (typ) { case ECPGt_char: - fprintf(o, "\n\tECPGt_char,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz, + if (varcharsize == 0) /* pointer */ + fprintf(o, "\n\tECPGt_char,%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, + siz == NULL ? "sizeof(char)" : siz); + else + fprintf(o, "\n\tECPGt_char,&%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, siz == NULL ? "sizeof(char)" : siz); break; case ECPGt_unsigned_char: - fprintf(o, "\n\tECPGt_unsigned_char,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz, + if (varcharsize == 0) /* pointer */ + fprintf(o, "\n\tECPGt_unsigned_char,%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, + siz == NULL ? "sizeof(char)" : siz); + else + fprintf(o, "\n\tECPGt_unsigned_char,&%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, siz == NULL ? "sizeof(unsigned char)" : siz); break; case ECPGt_short: - fprintf(o, "\n\tECPGt_short,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz, + fprintf(o, "\n\tECPGt_short,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, siz == NULL ? "sizeof(short)" : siz); break; case ECPGt_unsigned_short: fprintf(o, - "\n\tECPGt_unsigned_short,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz, + "\n\tECPGt_unsigned_short,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, siz == NULL ? "sizeof(unsigned short)" : siz); break; case ECPGt_int: - fprintf(o, "\n\tECPGt_int,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz, + fprintf(o, "\n\tECPGt_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, siz == NULL ? "sizeof(int)" : siz); break; case ECPGt_unsigned_int: - fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz, + fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, siz == NULL ? "sizeof(unsigned int)" : siz); break; case ECPGt_long: - fprintf(o, "\n\tECPGt_long,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz, + fprintf(o, "\n\tECPGt_long,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, siz == NULL ? "sizeof(long)" : siz); break; case ECPGt_unsigned_long: - fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz, + fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, siz == NULL ? "sizeof(unsigned int)" : siz); break; case ECPGt_float: - fprintf(o, "\n\tECPGt_float,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz, + fprintf(o, "\n\tECPGt_float,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, siz == NULL ? "sizeof(float)" : siz); break; case ECPGt_double: - fprintf(o, "\n\tECPGt_double,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz, + fprintf(o, "\n\tECPGt_double,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, siz == NULL ? "sizeof(double)" : siz); break; case ECPGt_bool: - fprintf(o, "\n\tECPGt_bool,&%s%s,0,%d,%s, ", prefix ? prefix : "", name, arrsiz, + fprintf(o, "\n\tECPGt_bool,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, siz == NULL ? "sizeof(bool)" : siz); break; case ECPGt_varchar: case ECPGt_varchar2: if (siz == NULL) - fprintf(o, "\n\tECPGt_varchar,&%s%s,%d,%d,sizeof(struct varchar_%s), ", + fprintf(o, "\n\tECPGt_varchar,&%s%s,%ldL,%ldL,sizeof(struct varchar_%s), ", prefix ? prefix : "", name, varcharsize, arrsiz, name); else - fprintf(o, "\n\tECPGt_varchar,&%s%s,%d,%d,%s, ", + fprintf(o, "\n\tECPGt_varchar,&%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, siz); @@ -235,7 +243,7 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, /* Penetrate a record and dump the contents. */ void -ECPGdump_a_record(FILE *o, const char *name, unsigned short arrsiz, struct ECPGtype *typ, const char *offsetarg, const char *prefix) +ECPGdump_a_record(FILE *o, const char *name, long arrsiz, struct ECPGtype *typ, const char *offsetarg, const char *prefix) { /* If offset is NULL, then this is the first recursive level. If not then we are in a record in a record and the offset is used as offset. diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h index 80a7266f9c..8ff6ed1b9c 100644 --- a/src/interfaces/ecpg/preproc/type.h +++ b/src/interfaces/ecpg/preproc/type.h @@ -9,7 +9,7 @@ struct ECPGrecord_member { struct ECPGtype { enum ECPGttype typ; - unsigned short size; /* For array it is the number of elements. + long size; /* For array it is the number of elements. * For varchar it is the maxsize of the area. */ union { @@ -23,9 +23,9 @@ struct ECPGtype { /* Everything is malloced. */ struct ECPGrecord_member * ECPGmake_record_member(char *, struct ECPGtype *, struct ECPGrecord_member **); -struct ECPGtype * ECPGmake_simple_type(enum ECPGttype); -struct ECPGtype * ECPGmake_varchar_type(enum ECPGttype, unsigned short); -struct ECPGtype * ECPGmake_array_type(struct ECPGtype *, unsigned short); +struct ECPGtype * ECPGmake_simple_type(enum ECPGttype, long); +struct ECPGtype * ECPGmake_varchar_type(enum ECPGttype, long); +struct ECPGtype * ECPGmake_array_type(struct ECPGtype *, long); struct ECPGtype * ECPGmake_record_type(struct ECPGrecord_member *); /* Frees a type. */ @@ -59,7 +59,8 @@ enum WHEN { W_BREAK, W_SQLPRINT, W_GOTO, - W_DO + W_DO, + W_STOP }; struct when diff --git a/src/interfaces/ecpg/test/test2.pgc b/src/interfaces/ecpg/test/test2.pgc index a6f9097943..ed11be6c2a 100644 --- a/src/interfaces/ecpg/test/test2.pgc +++ b/src/interfaces/ecpg/test/test2.pgc @@ -34,6 +34,16 @@ exec sql end declare section; strcpy(msg, "connect"); exec sql connect 'mm'; + strcpy(msg, "create"); + exec sql create table meskes(name char8, born int4, age int2); + + strcpy(msg, "insert"); + exec sql insert into meskes(name, born, age) values ('Petra', 19661202, 31); + exec sql insert into meskes(name, born, age) values ('Michael', 19660117, 32); + exec sql insert into meskes(name, born, age) values ('Carsten', 19910103, 7); + exec sql insert into meskes(name, born, age) values ('Marc', 19930907, 4); + exec sql insert into meskes(name, born, age) values ('Chris', 19970923, 0); + strcpy(msg, "declare"); exec sql declare cur cursor for select name, born, age from meskes; @@ -41,14 +51,23 @@ exec sql end declare section; exec sql open cur; while (1) { + /* make sure we leave this loop */ + exec sql whenever not found break; + strcpy(msg, "fetch"); exec sql fetch in cur into :personal; printf ("%8.8s was born %d (age = %d)\n", personal.name.arr, personal.birth.born, personal.birth.age); } + /* back to normal behaviour */ + exec sql whenever not found sqlprint; + strcpy(msg, "close"); exec sql close cur; + strcpy(msg, "drop"); + exec sql drop table meskes; + strcpy(msg, "commit"); exec sql commit;