aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc G. Fournier <scrappy@hub.org>1998-02-24 15:52:13 +0000
committerMarc G. Fournier <scrappy@hub.org>1998-02-24 15:52:13 +0000
commit80e12829cf79337fb71a19244a171daace974d7a (patch)
tree8c723779b20baff520c080127be3e3be4a14ca1a
parent0227a4e1141ae83ac3ae145fa283ede13e86e23e (diff)
downloadpostgresql-80e12829cf79337fb71a19244a171daace974d7a.tar.gz
postgresql-80e12829cf79337fb71a19244a171daace974d7a.zip
+ 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 From: Michael Meskes <meskes@topsystem.de>
-rw-r--r--src/interfaces/ecpg/ChangeLog18
-rw-r--r--src/interfaces/ecpg/Makefile3
-rw-r--r--src/interfaces/ecpg/TODO18
-rw-r--r--src/interfaces/ecpg/lib/ecpglib.c71
-rw-r--r--src/interfaces/ecpg/preproc/Makefile8
-rw-r--r--src/interfaces/ecpg/preproc/pgc.l5
-rw-r--r--src/interfaces/ecpg/preproc/preproc.y133
-rw-r--r--src/interfaces/ecpg/preproc/type.c66
-rw-r--r--src/interfaces/ecpg/preproc/type.h11
-rw-r--r--src/interfaces/ecpg/test/test2.pgc19
10 files changed, 247 insertions, 105 deletions
diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog
index ff721fa5013..bb39d213947 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 ee99aaeab50..f4768822a65 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 3de01c497af..dab3e0b4deb 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 19ec7f3b69a..823a335c764 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 5dddd9042c2..c6438be2326 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 f3def3d2e98..5523d0fce71 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]
<SQL>{continue} { dbg(SQL_CONTINUE); return SQL_CONTINUE; }
<SQL>{into} { dbg(SQL_INTO); return SQL_INTO; }
<SQL>{goto} { dbg(SQL_GOTO); return SQL_GOTO; }
+<SQL>{go}{ws}{to} { dbg(SQL_GOTO); return SQL_GOTO; }
+<SQL>{stop} { dbg(SQL_STOP); return SQL_STOP; }
<SQL>{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 52b814ac194..2a77c441a6e 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 <tagname> SQL_CONNECT SQL_OPEN SQL_EXECUTE SQL_IMMEDIATE
%token <tagname> SQL_COMMIT SQL_ROLLBACK SQL_RELEASE SQL_WORK SQL_WHENEVER
%token <tagname> SQL_SQLERROR SQL_NOT_FOUND SQL_BREAK SQL_CONTINUE
-%token <tagname> SQL_DO SQL_GOTO SQL_SQLPRINT
+%token <tagname> SQL_DO SQL_GOTO SQL_SQLPRINT SQL_STOP
%token <tagname> S_SYMBOL S_LENGTH S_ANYTHING S_LABEL
%token <tagname> S_VARCHAR S_VARCHAR2
-%token <tagname> S_EXTERN S_STATIC S_AUTO S_CONST S_REGISTER S_STRUCT S_SIGNED
+%token <tagname> S_EXTERN S_STATIC S_AUTO S_CONST S_REGISTER S_STRUCT
%token <tagname> S_UNSIGNED S_SIGNED
%token <tagname> S_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE S_BOOL
%token <tagname> '[' ']' ';' ',' '{' '}' '=' '*' '(' ')'
-%type <type> type type_detailed varchar_type simple_type array_type struct_type
+%type <type> type type_detailed varchar_type simple_type struct_type string_type
+/* % type <type> array_type pointer_type */
%type <symbolname> symbol label
%type <tagname> maybe_storage_clause varchar_tag db_name
-%type <type_enum> simple_tag
+%type <type_enum> simple_tag char_tag
%type <indexsize> index length
%type <action> action
%type <tagname> canything sqlanything both_anything vartext commit_release
@@ -286,7 +289,7 @@ variable_declaration : type initializer ';' {
if (struct_level == 0)
{
new_variable($<type>1.name, $<type>1.typ);
- free($<type>1.name);
+ free((void *)$<type>1.name);
}
fprintf(yyout, ";");
}
@@ -319,15 +322,16 @@ symbol : S_SYMBOL {
type : maybe_storage_clause type_detailed { $<type>$ = $<type>2; };
type_detailed : varchar_type { $<type>$ = $<type>1; }
| simple_type { $<type>$ = $<type>1; }
- | array_type {$<type>$ = $<type>1; }
- | pointer_type {$<type>$ = $<type>1; }
+ | string_type { $<type>$ = $<type>1; }
+/* | array_type {$<type>$ = $<type>1; }
+ | pointer_type {$<type>$ = $<type>1; }*/
| struct_type {$<type>$ = $<type>1; };
varchar_type : varchar_tag symbol index {
- if ($<indexsize>3 > 0)
- fprintf(yyout, "struct varchar_%s { int len; char arr[%d]; } %s", $<symbolname>2, $<indexsize>3, $<symbolname>2);
+ if ($<indexsize>3 > 0L)
+ fprintf(yyout, "struct varchar_%s { int len; char arr[%ld]; } %s", $<symbolname>2, $<indexsize>3, $<symbolname>2);
else
- fprintf(yyout, "struct varchar_%s { int len; char arr[%d]; } %s", $<symbolname>2, $<indexsize>3, $<symbolname>2);
+ fprintf(yyout, "struct varchar_%s { int len; char arr[]; } %s", $<symbolname>2, $<symbolname>2);
if (struct_level == 0)
{
$<type>$.name = $<symbolname>2;
@@ -345,15 +349,53 @@ simple_type : simple_tag symbol {
if (struct_level == 0)
{
$<type>$.name = $<symbolname>2;
- $<type>$.typ = ECPGmake_simple_type($<type_enum>1);
+ $<type>$.typ = ECPGmake_simple_type($<type_enum>1, 1);
}
else
- ECPGmake_record_member($<symbolname>2, ECPGmake_simple_type($<type_enum>1), &(record_member_list[struct_level-1]));
+ ECPGmake_record_member($<symbolname>2, ECPGmake_simple_type($<type_enum>1, 1), &(record_member_list[struct_level-1]));
}
+string_type : char_tag symbol index {
+ if ($<indexsize>3 > 0L)
+ fprintf(yyout, "%s %s [%ld]", ECPGtype_name($<type_enum>1), $<symbolname>2, $<indexsize>3);
+ else
+ fprintf(yyout, "%s %s []", ECPGtype_name($<type_enum>1), $<symbolname>2);
+ if (struct_level == 0)
+ {
+ $<type>$.name = $<symbolname>2;
+ $<type>$.typ = ECPGmake_simple_type($<type_enum>1, $<indexsize>3);
+ }
+ else
+ ECPGmake_record_member($<symbolname>2, ECPGmake_simple_type($<type_enum>1, $<indexsize>3), &(record_member_list[struct_level-1]));
+}
+ | char_tag '*' symbol {
+ fprintf(yyout, "%s *%s", ECPGtype_name($<type_enum>1), $<symbolname>3);
+ if (struct_level == 0)
+ {
+ $<type>$.name = $<symbolname>3;
+ $<type>$.typ = ECPGmake_simple_type($<type_enum>1, 0);
+ }
+ else
+ ECPGmake_record_member($<symbolname>3, ECPGmake_simple_type($<type_enum>1, 0), &(record_member_list[struct_level-1]));
+}
+ | char_tag symbol {
+ fprintf(yyout, "%s %s", ECPGtype_name($<type_enum>1), $<symbolname>2);
+ if (struct_level == 0)
+ {
+ $<type>$.name = $<symbolname>2;
+ $<type>$.typ = ECPGmake_simple_type($<type_enum>1, 1);
+ }
+ else
+ ECPGmake_record_member($<symbolname>2, ECPGmake_simple_type($<type_enum>1, 1), &(record_member_list[struct_level-1]));
+}
+
+char_tag : S_CHAR { $<type_enum>$ = ECPGt_char; }
+ | S_UNSIGNED S_CHAR { $<type_enum>$ = ECPGt_unsigned_char; }
+
+/*
array_type : simple_tag symbol index {
if ($<indexsize>3 > 0)
- fprintf(yyout, "%s %s [%d]", ECPGtype_name($<type_enum>1), $<symbolname>2, $<indexsize>3);
+ fprintf(yyout, "%s %s [%ld]", ECPGtype_name($<type_enum>1), $<symbolname>2, $<indexsize>3);
else
fprintf(yyout, "%s %s []", ECPGtype_name($<type_enum>1), $<symbolname>2);
if (struct_level == 0)
@@ -375,6 +417,7 @@ pointer_type : simple_tag '*' symbol {
else
ECPGmake_record_member($<symbolname>3, ECPGmake_array_type(ECPGmake_simple_type($<type_enum>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 { $<type_enum>$ = ECPGt_char; }
- | S_UNSIGNED S_CHAR { $<type_enum>$ = ECPGt_unsigned_char; }
- | S_SHORT { $<type_enum>$ = ECPGt_short; }
+simple_tag : S_SHORT { $<type_enum>$ = ECPGt_short; }
| S_UNSIGNED S_SHORT { $<type_enum>$ = ECPGt_unsigned_short; }
| S_INT { $<type_enum>$ = ECPGt_int; }
| S_UNSIGNED S_INT { $<type_enum>$ = ECPGt_unsigned_int; }
@@ -415,9 +456,9 @@ maybe_storage_clause : S_EXTERN { fwrite(yytext, yyleng, 1, yyout); }
| /* empty */ { };
index : '[' length ']' { $<indexsize>$ = $<indexsize>2; }
- | '[' ']' { $<indexsize>$ = 0; }
+ | '[' ']' { $<indexsize>$ = 0L; }
-length : S_LENGTH { $<indexsize>$ = atoi(yytext); }
+length : S_LENGTH { $<indexsize>$ = 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($<symbolname>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 = $<action>4;
+sqlwhenever : SQL_START SQL_WHENEVER SQL_SQLERROR {
+ fprintf(yyout, "/* exec sql whenever sqlerror ");
+} action SQL_SEMI{
+ when_error.code = $<action>5.code;
+ when_error.str = $<action>5.str;
+ fprintf(yyout, "; */\n");
}
- | SQL_START SQL_WHENEVER SQL_NOT_FOUND action SQL_SEMI{
- when_nf = $<action>4;
+ | SQL_START SQL_WHENEVER SQL_NOT_FOUND {
+ fprintf(yyout, "/* exec sql whenever not found ");
+} action SQL_SEMI{
+ when_nf.code = $<action>5.code;
+ when_nf.str=$<action>5.str;
+ fprintf(yyout, "; */\n");
}
action : SQL_BREAK {
$<action>$.code = W_BREAK;
$<action>$.str = NULL;
+ fprintf(yyout, "break");
}
| SQL_CONTINUE {
$<action>$.code = W_CONTINUE;
$<action>$.str = NULL;
+ fprintf(yyout, "continue");
}
| SQL_SQLPRINT {
$<action>$.code = W_SQLPRINT;
$<action>$.str = NULL;
+ fprintf(yyout, "sqlprint");
+}
+ | SQL_STOP {
+ $<action>$.code = W_STOP;
+ $<action>$.str = NULL;
+ fprintf(yyout, "stop");
}
| SQL_GOTO label {
$<action>$.code = W_GOTO;
$<action>$.str = $<symbolname>2;
+ fprintf(yyout, "goto %s", $<symbolname>2);
}
- | SQL_GOTO symbol {
+ | SQL_GOTO symbol {
$<action>$.code = W_GOTO;
$<action>$.str = $<symbolname>2;
+ fprintf(yyout, "goto %s", $<symbolname>2);
}
| SQL_DO symbol '(' {
do_str = (char *) mm_alloc(do_length = strlen($<symbolname>2) + 4);
@@ -513,6 +564,7 @@ action : SQL_BREAK {
do_str[strlen(do_str)]=')';
$<action>$.code = W_DO;
$<action>$.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 bac44a72ed3..a436997aaa2 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 <comma> - enum ECPGttype
reference-to-variable <comma> - void *
- size <comma> - short size of this field (if varchar)
- arrsize <comma> - short number of elements in the arr
- offset <comma> - short offset to the next element
+ size <comma> - long size of this field (if varchar)
+ arrsize <comma> - long number of elements in the arr
+ offset <comma> - 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 80a7266f9c7..8ff6ed1b9c2 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 a6f90979438..ed11be6c2a2 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;