Commit 80e12829 authored by Marc G. Fournier's avatar Marc G. Fournier

+ 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>
parent 0227a4e1
......@@ -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
SUBDIRS = include lib preproc doc
all install uninstall clean:
$(MAKE) -C include $@
$(MAKE) -C lib $@
$(MAKE) -C preproc $@
......@@ -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 *
......@@ -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 =
......
......@@ -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) $<
......
......@@ -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; }
......
This diff is collapsed.
......@@ -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.
......
......@@ -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
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment