From: Michael Meskes <meskes@topsystem.de>

Tue Apr 28 14:48:41 CEST 1998

      - Put operator "->" back into parser. Note that :foo->bar means the
        C term, but :foo ->bar means the operator "->".

Tue Apr 28 15:49:07 CEST 1998

      - Added exec sql disconnect command.
      - Allow varchar in C to be written in uppercase too.
      - Added whenever option "do break;"

Wed Apr 29 09:17:53 CEST 1998

      - Corrected parsing of C comments.
      - Also allow C++ style comments.
      - Make sure not found is only checked after commands that could
          return it.
      - Added error codes, see ecpgerror.h for details.
      - Added "exec sql <TransactionStmt> release" as disconnect statement
        for compatibility issues.

Thu Apr 30 10:42:10 CEST 1998

      - Added a -t option to disable automatic transaction start.
      - Added sqlerrd[] to sqlca struct.
      - Give back number of tuples affect in sqlca.sqlerrd[2].

Thu Apr 30 13:36:02 CEST 1998

      - Make the return code different in case of different errors.

Wed May  6 11:42:48 CEST 1998

      - Free memory if possible
      - Some bugfixes for bugs I found while changing the memory
          allocation code
      - Now able to fill complete array with one call (see test1.pgc for
          an example)
      - Set version to 2.3.0
      - Set library version to 2.1
This commit is contained in:
Marc G. Fournier 1998-05-06 13:03:47 +00:00
parent f9322c66d3
commit 6bccf64d7b
25 changed files with 1782 additions and 1634 deletions

View File

@ -149,3 +149,43 @@ Mon Apr 27 14:26:55 CEST 1998
and :foo.bar as variables.
- Set version to 2.2.0
Tue Apr 28 14:48:41 CEST 1998
- Put operator "->" back into parser. Note that :foo->bar means the
C term, but :foo ->bar means the operator "->".
Tue Apr 28 15:49:07 CEST 1998
- Added exec sql disconnect command.
- Allow varchar in C to be written in uppercase too.
- Added whenever option "do break;"
Wed Apr 29 09:17:53 CEST 1998
- Corrected parsing of C comments.
- Also allow C++ style comments.
- Make sure not found is only checked after commands that could
return it.
- Added error codes, see ecpgerror.h for details.
- Added "exec sql <TransactionStmt> release" as disconnect statement
for compatibility issues.
Thu Apr 30 10:42:10 CEST 1998
- Added a -t option to disable automatic transaction start.
- Added sqlerrd[] to sqlca struct.
- Give back number of tuples affect in sqlca.sqlerrd[2].
Thu Apr 30 13:36:02 CEST 1998
- Make the return code different in case of different errors.
Wed May 6 11:42:48 CEST 1998
- Free memory if possible
- Some bugfixes for bugs I found while changing the memory
allocation code
- Now able to fill complete array with one call (see test1.pgc for
an example)
- Set version to 2.3.0
- Set library version to 2.1

View File

@ -1,55 +1,14 @@
This list is still from Linus. MM
The variables should be static.
There should be different error numbers for the different errors instead of
just -1 for them all.
Missing library functions to_date et al.
Oracle has array operations that enhances speed. When implementing it in
ecpg it is done for compatibility reasons only. For them to improve speed
would require a lot more insight in the postgres internal mechanisms than I
possess.
As well as complex types like records and arrays, typedefs would be a good
thing to take care of.
To set up a database you need a few scripts with table definitions and other
configuration parameters. If you have these scripts for an old database you
would like to just apply them to get a postgres database that works in the
same way. The functionality could be accomplished with some conversion
scripts. Speed will never be accomplished in this way. To do this you need a
bigger insight in the database construction and the use of the database than
could be realised in a script.
Now comes my list (MM):
The return code is alway -1 in case of an error. You cannot see which error
occured by examining the return code.
ecpg does not understand enum datatypes.
There 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.
section of the structure variable for ecpg to be able to understand it.
There is no way yet to fill a complete array with one call except arrays of
[unsigned] char which are considered strings.
Variable type bool has to be checked. I never used it so far.
ecpg cannot use pointer variables except [unsigned] char *
give back the number of tuples affected via sqlca
There is no exec sql type statement which is the SQL version of a typedef.
exec sql disconnect {current|default|all|connectionname|connection_hostvar};
oder <disconnect statement> ::=
DISCONNECT <disconnect object>
There is no exec sql prepare statement.
<disconnect object> ::=
<connection object>
| ALL
| CURRENT
commit release|commit work release auch disconnect
It is not neccessary to check for "not found" after all commands.
There is no SQLSTATE

View File

@ -6,11 +6,13 @@ all clean::
@echo Nothing to be done.
install::
$(INSTALL) $(INSTLOPTS) ecpgerrno.h $(DESTDIR)$(HEADERDIR)
$(INSTALL) $(INSTLOPTS) ecpglib.h $(DESTDIR)$(HEADERDIR)
$(INSTALL) $(INSTLOPTS) ecpgtype.h $(DESTDIR)$(HEADERDIR)
$(INSTALL) $(INSTLOPTS) sqlca.h $(DESTDIR)$(HEADERDIR)
uninstall::
rm -f $(DESTDIR)$(HEADERDIR)/ecpgerrno.h
rm -f $(DESTDIR)$(HEADERDIR)/ecpglib.h
rm -f $(DESTDIR)$(HEADERDIR)/ecpgtype.h
rm -f $(DESTDIR)$(HEADERDIR)/sqlca.h

View File

@ -0,0 +1,22 @@
#ifndef _ECPG_ERROR_H
#define _ECPG_ERROR_H
/* This is a list of all error codes the embedded SQL program can return */
#define ECPG_NO_ERROR 0
#define ECPG_NOT_FOUND 100
#define ECPG_PGSQL -1
#define ECPG_UNSUPPORTED -2
#define ECPG_TOO_MANY_ARGUMENTS -3
#define ECPG_TOO_FEW_ARGUMENTS -4
#define ECPG_TRANS -5
#define ECPG_TOO_MANY_MATCHES -6
#define ECPG_INT_FORMAT -7
#define ECPG_UINT_FORMAT -8
#define ECPG_FLOAT_FORMAT -9
#define ECPG_CONVERT_BOOL -10
#define ECPG_EMPTY -11
#define ECPG_CONNECT -12
#define ECPG_DISCONNECT -13
#endif /* !_ECPG_ERROR_H */

View File

@ -5,11 +5,11 @@ extern "C" {
#endif
void ECPGdebug(int, FILE *);
bool ECPGconnect(const char *dbname);
bool ECPGconnect(const char *);
bool ECPGdo(int, char *,...);
bool ECPGtrans(int, const char *);
bool ECPGfinish(void);
bool ECPGstatus(void);
bool ECPGdisconnect(const char *);
void ECPGlog(const char *format,...);
@ -39,3 +39,5 @@ void sqlprint(void);
#ifdef __cplusplus
}
#endif
#include <ecpgerrno.h>

View File

@ -10,10 +10,11 @@ struct sqlca
int sqlcode;
struct
{
int sqlerrml;
int sqlerrml;
char sqlerrmc[1000];
} sqlerrm;
} sqlca;
long sqlerrd[6];
} sqlca;
#endif

View File

@ -4,7 +4,7 @@ include $(SRCDIR)/Makefile.global
PQ_INCLUDE=-I$(SRCDIR)/interfaces/libpq
SO_MAJOR_VERSION=2
SO_MINOR_VERSION=0
SO_MINOR_VERSION=1
PORTNAME=@PORTNAME@

View File

@ -24,6 +24,8 @@
#include <ecpglib.h>
#include <sqlca.h>
extern int no_auto_trans;
static PGconn *simple_connection = NULL;
static int simple_debug = 0;
static FILE *debugstream = NULL;
@ -80,6 +82,11 @@ ECPGdo(int lineno, char *query,...)
PGresult *results;
PGnotify *notify;
enum ECPGttype type;
void *value = NULL, *ind_value;
long varcharsize, ind_varcharsize;
long arrsize, ind_arrsize;
long offset, ind_offset;
enum ECPGttype ind_type;
va_start(ap, query);
@ -96,12 +103,6 @@ ECPGdo(int lineno, char *query,...)
*/
while (type != ECPGt_EOIT)
{
void *value = NULL, *ind_value;
long varcharsize, ind_varcharsize;
long size, ind_size;
long arrsize, ind_arrsize;
enum ECPGttype ind_type;
char *newcopy;
char *mallocedval = NULL;
char *tobeinserted = NULL;
@ -116,13 +117,13 @@ ECPGdo(int lineno, char *query,...)
value = va_arg(ap, void *);
varcharsize = va_arg(ap, long);
size = va_arg(ap, long);
arrsize = va_arg(ap, long);
offset = va_arg(ap, long);
ind_type = va_arg(ap, enum ECPGttype);
ind_value = va_arg(ap, void *);
ind_varcharsize = va_arg(ap, long);
ind_size = va_arg(ap, long);
ind_arrsize = va_arg(ap, long);
ind_offset = va_arg(ap, long);
buff[0] = '\0';
@ -211,7 +212,6 @@ ECPGdo(int lineno, char *query,...)
break;
case ECPGt_varchar:
case ECPGt_varchar2:
{
struct ECPGgeneric_varchar *var =
(struct ECPGgeneric_varchar *) value;
@ -233,7 +233,7 @@ ECPGdo(int lineno, char *query,...)
default:
/* Not implemented yet */
register_error(-1, "Unsupported type %s on line %d.",
register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
ECPGtype_name(type), lineno);
return false;
break;
@ -257,7 +257,7 @@ ECPGdo(int lineno, char *query,...)
* We have an argument but we dont have the matched up string
* in the string
*/
register_error(-1, "Too many arguments line %d.", lineno);
register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", lineno);
return false;
}
else
@ -293,17 +293,17 @@ ECPGdo(int lineno, char *query,...)
/* Check if there are unmatched things left. */
if (strstr(copiedquery, ";;") != NULL)
{
register_error(-1, "Too few arguments line %d.", lineno);
register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", lineno);
return false;
}
/* Now the request is built. */
if (committed)
if (committed && !no_auto_trans)
{
if ((results = PQexec(simple_connection, "begin transaction")) == NULL)
{
register_error(-1, "Error starting transaction line %d.", lineno);
register_error(ECPG_TRANS, "Error starting transaction line %d.", lineno);
return false;
}
PQclear(results);
@ -318,15 +318,15 @@ ECPGdo(int lineno, char *query,...)
{
ECPGlog("ECPGdo line %d: error: %s", lineno,
PQerrorMessage(simple_connection));
register_error(-1, "Postgres error: %s line %d.",
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
PQerrorMessage(simple_connection), lineno);
}
else
{
sqlca.sqlerrd[2] = 0;
switch (PQresultStatus(results))
{
int m,
n,
x;
int nfields, ntuples, act_tuple, act_field;
case PGRES_TUPLES_OK:
@ -336,306 +336,308 @@ ECPGdo(int lineno, char *query,...)
* !!
*/
m = PQnfields(results);
n = PQntuples(results);
if (n < 1)
{
ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n",
lineno, n);
register_error(1, "Data not found line %d.", lineno);
break;
}
if (n > 1)
{
ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n",
lineno, n);
register_error(-1, "To many matches line %d.", lineno);
break;
}
nfields = PQnfields(results);
sqlca.sqlerrd[2] = ntuples = PQntuples(results);
status = true;
for (x = 0; x < m && status; x++)
if (ntuples < 1)
{
void *value = NULL, *ind_value;
long varcharsize, ind_varcharsize;
long size, ind_size;
long arrsize, ind_arrsize;
enum ECPGttype ind_type;
ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n",
lineno, ntuples);
register_error(ECPG_NOT_FOUND, "Data not found line %d.", lineno);
status = false;
break;
}
char *pval = PQgetvalue(results, 0, x);
for (act_field = 0; act_field < nfields && status; act_field++)
{
char *pval;
char *scan_length;
type = va_arg(ap, enum ECPGttype);
value = va_arg(ap, void *);
varcharsize = va_arg(ap, long);
arrsize = va_arg(ap, long);
offset = va_arg(ap, long);
ind_type = va_arg(ap, enum ECPGttype);
ind_value = va_arg(ap, void *);
ind_varcharsize = va_arg(ap, long);
ind_arrsize = va_arg(ap, long);
ind_offset = va_arg(ap, long);
/*
* long int * res_int; char ** res_charstar; char *
* res_char; int res_len;
*/
char *scan_length;
/* if we don't have enough space, we cannot read all tuples */
if ((arrsize > 0 && ntuples > arrsize) || (ind_arrsize > 0 && ntuples > ind_arrsize))
{
ECPGlog("ECPGdo line %d: Incorrect number of matches: %d don't fit into array of %d\n",
lineno, ntuples, arrsize);
register_error(ECPG_TOO_MANY_MATCHES, "Too many matches line %d.", lineno);
status = false;
break;
}
for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
{
pval = PQgetvalue(results, act_tuple, act_field);
ECPGlog("ECPGdo line %d: RESULT: %s\n", lineno, pval ? pval : "");
ECPGlog("ECPGdo line %d: RESULT: %s\n", lineno, pval ? pval : "");
/* Now the pval is a pointer to the value. */
/* We will have to decode the value */
type = va_arg(ap, enum ECPGttype);
value = va_arg(ap, void *);
varcharsize = va_arg(ap, long);
size = va_arg(ap, long);
arrsize = va_arg(ap, long);
ind_type = va_arg(ap, enum ECPGttype);
ind_value = va_arg(ap, void *);
ind_varcharsize = va_arg(ap, long);
ind_size = va_arg(ap, long);
ind_arrsize = va_arg(ap, long);
/* check for null value and set indicator accordingly */
switch (ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
*(short *) ind_value = -PQgetisnull(results, 0, x);
break;
case ECPGt_int:
case ECPGt_unsigned_int:
*(int *) ind_value = -PQgetisnull(results, 0, x);
break;
case ECPGt_long:
case ECPGt_unsigned_long:
*(long *) ind_value = -PQgetisnull(results, 0, x);
break;
default:
break;
}
switch (type)
{
long res;
unsigned long ures;
double dres;
/* Now the pval is a pointer to the value. */
/* We will have to decode the value */
/* check for null value and set indicator accordingly */
switch (ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
((short *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
break;
case ECPGt_int:
case ECPGt_unsigned_int:
((int *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
break;
case ECPGt_long:
case ECPGt_unsigned_long:
((long *) ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
break;
default:
break;
}
switch (type)
{
long res;
unsigned long ures;
double dres;
case ECPGt_short:
case ECPGt_int:
case ECPGt_long:
if (pval)
{
res = strtol(pval, &scan_length, 10);
if (*scan_length != '\0') /* Garbage left */
{
register_error(ECPG_INT_FORMAT, "Not correctly formatted int type: %s line %d.",
pval, lineno);
status = false;
res = 0L;
}
}
else
res = 0L;
/* Again?! Yes */
switch (type)
{
case ECPGt_short:
((short *) value)[act_tuple] = (short) res;
break;
case ECPGt_int:
((int *) value)[act_tuple] = (int) res;
break;
case ECPGt_long:
((long *) value)[act_tuple] = res;
break;
default:
/* Cannot happen */
break;
}
break;
case ECPGt_unsigned_short:
case ECPGt_unsigned_int:
case ECPGt_unsigned_long:
if (pval)
{
ures = strtoul(pval, &scan_length, 10);
if (*scan_length != '\0') /* Garbage left */
{
register_error(ECPG_UINT_FORMAT, "Not correctly formatted unsigned type: %s line %d.",
pval, lineno);
status = false;
ures = 0L;
}
}
else
ures = 0L;
/* Again?! Yes */
switch (type)
{
case ECPGt_unsigned_short:
((unsigned short *) value)[act_tuple] = (unsigned short) ures;
break;
case ECPGt_unsigned_int:
((unsigned int *) value)[act_tuple] = (unsigned int) ures;
break;
case ECPGt_unsigned_long:
((unsigned long *) value)[act_tuple] = ures;
break;
default:
/* Cannot happen */
break;
}
break;
case ECPGt_float:
case ECPGt_double:
if (pval)
{
dres = strtod(pval, &scan_length);
if (*scan_length != '\0') /* Garbage left */
{
register_error(ECPG_FLOAT_FORMAT, "Not correctly formatted floating point type: %s line %d.",
pval, lineno);
status = false;
dres = 0.0;
}
}
else
dres = 0.0;
/* Again?! Yes */
switch (type)
{
case ECPGt_float:
((float *) value)[act_tuple] = dres;
break;
case ECPGt_double:
((double *) value)[act_tuple] = dres;
break;
default:
/* Cannot happen */
break;
}
break;
case ECPGt_bool:
if (pval)
{
if (pval[0] == 'f' && pval[1] == '\0')
{
((char *) value)[act_tuple] = false;
break;
}
else if (pval[0] == 't' && pval[1] == '\0')
{
((char *) value)[act_tuple] = true;
break;
}
}
register_error(ECPG_CONVERT_BOOL, "Unable to convert %s to bool on line %d.",
(pval ? pval : "NULL"),
lineno);
status = false;
break;
case ECPGt_char:
case ECPGt_unsigned_char:
{
if (varcharsize == 0)
{
/* char* */
strncpy(((char **) value)[act_tuple], pval, strlen(pval));
(((char **) value)[act_tuple])[strlen(pval)] = '\0';
}
else
{
strncpy((char *) (value + offset * act_tuple), pval, varcharsize);
if (varcharsize < strlen(pval))
{
/* truncation */
switch (ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
((short *) ind_value)[act_tuple] = varcharsize;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
((int *) ind_value)[act_tuple] = varcharsize;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
((long *) ind_value)[act_tuple] = varcharsize;
break;
default:
break;
}
}
}
}
break;
case ECPGt_varchar:
{
struct ECPGgeneric_varchar *var =
(struct ECPGgeneric_varchar *) (value + offset * act_tuple);
if (varcharsize == 0)
strncpy(var->arr, pval, strlen(pval));
else
strncpy(var->arr, pval, varcharsize);
case ECPGt_short:
case ECPGt_int:
case ECPGt_long:
if (pval)
{
res = strtol(pval, &scan_length, 10);
if (*scan_length != '\0') /* Garbage left */
{
register_error(-1, "Not correctly formatted int type: %s line %d.",
pval, lineno);
status = false;
res = 0L;
}
}
else
res = 0L;
/* Again?! Yes */
switch (type)
{
case ECPGt_short:
*(short *) value = (short) res;
break;
case ECPGt_int:
*(int *) value = (int) res;
break;
case ECPGt_long:
*(long *) value = res;
break;
default:
/* Cannot happen */
break;
}
break;
case ECPGt_unsigned_short:
case ECPGt_unsigned_int:
case ECPGt_unsigned_long:
if (pval)
{
ures = strtoul(pval, &scan_length, 10);
if (*scan_length != '\0') /* Garbage left */
{
register_error(-1, "Not correctly formatted unsigned type: %s line %d.",
pval, lineno);
status = false;
ures = 0L;
}
}
else
ures = 0L;
/* Again?! Yes */
switch (type)
{
case ECPGt_unsigned_short:
*(unsigned short *) value = (unsigned short) ures;
break;
case ECPGt_unsigned_int:
*(unsigned int *) value = (unsigned int) ures;
break;
case ECPGt_unsigned_long:
*(unsigned long *) value = ures;
break;
default:
/* Cannot happen */
break;
}
break;
case ECPGt_float:
case ECPGt_double:
if (pval)
{
dres = strtod(pval, &scan_length);
if (*scan_length != '\0') /* Garbage left */
{
register_error(-1, "Not correctly formatted floating point type: %s line %d.",
pval, lineno);
status = false;
dres = 0.0;
}
}
else
dres = 0.0;
/* Again?! Yes */
switch (type)
{
case ECPGt_float:
*(float *) value = dres;
break;
case ECPGt_double:
*(double *) value = dres;
break;
default:
/* Cannot happen */
break;
}
break;
case ECPGt_bool:
if (pval)
{
if (pval[0] == 'f' && pval[1] == '\0')
{
*(char *) value = false;
break;
}
else if (pval[0] == 't' && pval[1] == '\0')
{
*(char *) value = true;
break;
}
}
register_error(-1, "Unable to convert %s to bool on line %d.",
(pval ? pval : "NULL"),
lineno);
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);
if (varcharsize < strlen(pval))
{
/* truncation */
switch (ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
*(short *) ind_value = varcharsize;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
*(int *) ind_value = varcharsize;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
*(long *) ind_value = varcharsize;
break;
default:
break;
}
}
}
}
break;
case ECPGt_varchar:
{
struct ECPGgeneric_varchar *var =
(struct ECPGgeneric_varchar *) value;
strncpy(var->arr, pval, varcharsize);
var->len = strlen(pval);
if (var->len > varcharsize)
{
/* truncation */
switch (ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
*(short *) ind_value = varcharsize;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
*(int *) ind_value = varcharsize;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
*(long *) ind_value = varcharsize;
break;
default:
break;
}
var->len = varcharsize;
}
}
break;
case ECPGt_EORT:
ECPGlog("ECPGdo line %d: Too few arguments.\n", lineno);
register_error(-1, "Too few arguments line %d.", lineno);
status = false;
break;
default:
register_error(-1, "Unsupported type %s on line %d.",
ECPGtype_name(type), lineno);
return false;
break;
}
var->len = strlen(pval);
if (varcharsize > 0 && var->len > varcharsize)
{
/* truncation */
switch (ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
((short *) ind_value)[act_tuple] = varcharsize;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
((int *) ind_value)[act_tuple] = varcharsize;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
((long *) ind_value)[act_tuple] = varcharsize;
break;
default:
break;
}
var->len = varcharsize;
}
}
break;
case ECPGt_EORT:
ECPGlog("ECPGdo line %d: Too few arguments.\n", lineno);
register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", lineno);
status = false;
break;
default:
register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
ECPGtype_name(type), lineno);
status = false;
break;
}
}
}
type = va_arg(ap, enum ECPGttype);
if (status && type != ECPGt_EORT)
{
register_error(-1, "Too many arguments line %d.", lineno);
return false;
register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", lineno);
status = false;
}
PQclear(results);
break;
case PGRES_EMPTY_QUERY:
/* do nothing */
register_error(-1, "Empty query line %d.", lineno);
register_error(ECPG_EMPTY, "Empty query line %d.", lineno);
break;
case PGRES_COMMAND_OK:
status = true;
sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
ECPGlog("TEST: %s\n", PQcmdTuples(results));
ECPGlog("ECPGdo line %d Ok: %s\n", lineno, PQcmdStatus(results));
break;
case PGRES_NONFATAL_ERROR:
@ -643,8 +645,9 @@ ECPGdo(int lineno, char *query,...)
case PGRES_BAD_RESPONSE:
ECPGlog("ECPGdo line %d: Error: %s",
lineno, PQerrorMessage(simple_connection));
register_error(-1, "Error: %s line %d.",
register_error(ECPG_PGSQL, "Error: %s line %d.",
PQerrorMessage(simple_connection), lineno);
status = false;
break;
case PGRES_COPY_OUT:
ECPGlog("ECPGdo line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno);
@ -657,9 +660,11 @@ ECPGdo(int lineno, char *query,...)
default:
ECPGlog("ECPGdo line %d: Got something else, postgres error.\n",
lineno);
register_error(-1, "Postgres error line %d.", lineno);
register_error(ECPG_PGSQL, "Postgres error line %d.", lineno);
status = false;
break;
}
}
/* check for asynchronous returns */
notify = PQnotifies(simple_connection);
@ -683,11 +688,12 @@ ECPGtrans(int lineno, const char * transaction)
ECPGlog("ECPGtrans line %d action = %s\n", lineno, transaction);
if ((res = PQexec(simple_connection, transaction)) == NULL)
{
register_error(-1, "Error in transaction processing line %d.", lineno);
register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
return (FALSE);
}
PQclear(res);
committed = 1;
if (strcmp(transaction, "commit") == 0 || strcmp(transaction, "rollback") == 0)
committed = 1;
return (TRUE);
}
@ -716,21 +722,25 @@ ECPGconnect(const char *dbname)
if (PQstatus(simple_connection) == CONNECTION_BAD)
{
ECPGfinish();
ECPGlog("ECPGconnect: could not open database %s\n", dbname);
register_error(-1, "ECPGconnect: could not open database %s.", dbname);
ECPGlog("connect: could not open database %s\n", dbname);
register_error(ECPG_CONNECT, "connect: could not open database %s.", dbname);
return false;
}
return true;
}
bool
ECPGstatus(void)
ECPGdisconnect(const char *dbname)
{
return PQstatus(simple_connection) != CONNECTION_BAD;
if (strlen(dbname) > 0 && strcmp(PQdb(simple_connection), dbname) != 0)
{
ECPGlog("disconnect: not connected to database %s\n", dbname);
register_error(ECPG_DISCONNECT, "disconnect: not connected to database %s.", dbname);
return false;
}
return ECPGfinish();
}
bool
ECPGfinish(void)
{

View File

@ -2,7 +2,7 @@ SRCDIR= ../../..
include $(SRCDIR)/Makefile.global
MAJOR_VERSION=2
MINOR_VERSION=2
MINOR_VERSION=3
PATCHLEVEL=0
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \

View File

@ -21,6 +21,7 @@
*/
static ScanKeyword ScanKeywords[] = {
/* name value */
{"VARCHAR", S_VARCHAR},
{"auto", S_AUTO},
{"bool", S_BOOL},
{"char", S_CHAR},

View File

@ -22,12 +22,13 @@ extern char *optarg;
#include "extern.h"
struct _include_path *include_paths;
static int no_auto_trans = 0;
static void
usage(char *progname)
{
fprintf(stderr, "ecpg - the postgresql preprocessor, version: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
fprintf(stderr, "Usage: %s: [-v] [-I include path] [ -o output file name] file1 [file2] ...\n", progname);
fprintf(stderr, "Usage: %s: [-v] [-t] [-I include path] [ -o output file name] file1 [file2] ...\n", progname);
}
static void
@ -51,7 +52,7 @@ main(int argc, char *const argv[])
add_include_path("/usr/local/include");
add_include_path(".");
while ((c = getopt(argc, argv, "vo:I:")) != EOF)
while ((c = getopt(argc, argv, "vo:I:t")) != EOF)
{
switch (c)
{
@ -65,23 +66,26 @@ main(int argc, char *const argv[])
case 'I':
add_include_path(optarg);
break;
case 't':
no_auto_trans = 1;
break;
case 'v':
fprintf(stderr, "ecpg - the postgresql preprocessor, version: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
fprintf(stderr, "exec sql include ... search starts here:\n");
for (ip = include_paths; ip != NULL; ip = ip->next)
fprintf(stderr, " %s\n", ip->path);
fprintf(stderr, "End of search list.\n");
return (0);
return (OK);
default:
usage(argv[0]);
return (1);
return (ILLEGAL_OPTION);
}
}
if (optind >= argc) /* no files specified */
{
usage(argv[0]);
return(1);
return(ILLEGAL_OPTION);
}
else
{
@ -151,8 +155,8 @@ main(int argc, char *const argv[])
cur = NULL;
/* we need two includes */
fprintf(yyout, "/* Processed by ecpg (%d.%d.%d) */\n/*These two include files are added by the preprocessor */\n#include <ecpgtype.h>\n#include <ecpglib.h>\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
/* we need two includes and a constant */
fprintf(yyout, "/* Processed by ecpg (%d.%d.%d) */\n/*These two include files are added by the preprocessor */\n#include <ecpgtype.h>\n#include <ecpglib.h>\n\nconst int no_auto_trans = %d;\n\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL, no_auto_trans);
/* and parse the source */
yyparse();
@ -169,5 +173,5 @@ main(int argc, char *const argv[])
free(input_filename);
}
}
return (0);
return (OK);
}

View File

@ -21,15 +21,18 @@
*/
static ScanKeyword ScanKeywords[] = {
/* name value */
{"break", SQL_BREAK},
{"call", SQL_CALL},
{"connect", SQL_CONNECT},
{"continue", SQL_CONTINUE},
{"disconnect", SQL_DISCONNECT},
{"found", SQL_FOUND},
{"go", SQL_GO},
{"goto", SQL_GOTO},
{"immediate", SQL_IMMEDIATE},
{"indicator", SQL_INDICATOR},
{"open", SQL_OPEN},
{"release", SQL_RELEASE},
{"section", SQL_SECTION},
{"sqlerror", SQL_SQLERROR},
{"sqlprint", SQL_SQLPRINT},

View File

@ -43,3 +43,11 @@ extern void *mm_alloc(size_t), *mm_realloc(void *, size_t);
ScanKeyword * ScanECPGKeywordLookup(char *);
ScanKeyword * ScanCKeywordLookup(char *);
extern void yyerror(char *);
/* return codes */
#define OK 0
#define NO_INCLUDE_FILE 1
#define PARSE_ERROR 2
#define OUT_OF_MEMORY 3
#define ILLEGAL_OPTION 4

View File

@ -39,6 +39,7 @@ int debugging = 0;
extern YYSTYPE yylval;
int llen;
char literal[MAX_PARSE_BUFFER];
int before_comment;
struct _yy_buffer { YY_BUFFER_STATE buffer;
long lineno;
@ -153,7 +154,7 @@ space [ \t\n\f]
other .
/* some stuff needed for ecpg */
ccomment \/\*([^*]|\*[^/]|\*\*[^/])*\*\/
ccomment "//".*\n
exec [eE][xX][eE][cC]
include [iI][nN][cC][lL][uU][dD][eE]
sql [sS][qQ][lL]
@ -174,12 +175,18 @@ sql [sS][qQ][lL]
%%
<SQL>{comment} { /* ignore */ }
<SQL>{xcline} { /* ignore */ }
{xcline} { /* ignore */ }
<xc>{xcstar} |
<SQL>{xcstart} { BEGIN(xc); }
<xc>{xcstar} { /* ignore */ }
{xcstart} {
fprintf(stderr,"ys = %d %d\n", YYSTATE, before_comment);
before_comment = YYSTATE;
BEGIN(xc);
fprintf(stderr,"ys = %d %d\n", YYSTATE,
before_comment);
}
<xc>{xcstop} { BEGIN(SQL); }
<xc>{xcstop} { fprintf(stderr,"ys = %d %d\n", YYSTATE, before_comment);BEGIN(before_comment); }
<xc>{xcinside} { /* ignore */ }
@ -306,7 +313,6 @@ sql [sS][qQ][lL]
return (yytext[0]);
}
<SQL>{self} { return (yytext[0]); }
<SQL>"->" { return S_STRUCTPOINTER; }
<SQL>{operator}/-[\.0-9] {
yylval.str = strdup((char*)yytext);
return (Op);
@ -402,7 +408,7 @@ sql [sS][qQ][lL]
return (FCONST);
}
<SQL>:{identifier} {
<SQL>:{identifier}(("->"|\.){identifier})* {
yylval.str = strdup((char*)yytext+1);
return(CVARIABLE);
}
@ -436,6 +442,7 @@ sql [sS][qQ][lL]
<SQL>{other} { return (yytext[0]); }
<C>{exec}{space}{sql} { BEGIN SQL; return SQL_START; }
<C>{ccomment} { /* ignore */ }
<C>{identifier} {
ScanKeyword *keyword;
@ -501,7 +508,7 @@ sql [sS][qQ][lL]
if (!yyin)
{
fprintf(stderr, "Error: Cannot open include file %s in line %d\n", yytext, yylineno);
exit(1);
exit(NO_INCLUDE_FILE);
}
input_filename = strdup(inc_file);

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@ mm_alloc(size_t size)
if (ptr == NULL)
{
fprintf(stderr, "Out of memory\n");
exit(1);
exit(OUT_OF_MEMORY);
}
return (ptr);
@ -29,15 +29,27 @@ mm_realloc(void *ptr, size_t size)
if (ptr == NULL)
{
fprintf(stderr, "Out of memory\n");
exit(1);
exit(OUT_OF_MEMORY);
}
return (ptr);
}
/* Constructors
Yes, I mostly write c++-code
*/
/* duplicate memberlist */
static struct ECPGstruct_member *
struct_member_dup(struct ECPGstruct_member * rm)
{
struct ECPGstruct_member *new = NULL;
while (rm)
{
ECPGmake_struct_member(rm->name, rm->typ, &new);
rm = rm->next;
}
return(new);
}
/* The NAME argument is copied. The type argument is preserved as a pointer. */
struct ECPGstruct_member *
@ -72,22 +84,11 @@ ECPGmake_simple_type(enum ECPGttype typ, long siz)
return ne;
}
struct ECPGtype *
ECPGmake_varchar_type(enum ECPGttype typ, long siz)
{
struct ECPGtype *ne = ECPGmake_simple_type(typ, 1);
ne->size = siz;
return ne;
}
struct ECPGtype *
ECPGmake_array_type(struct ECPGtype * typ, long siz)
{
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, siz);
ne->size = siz;
ne->u.element = typ;
return ne;
@ -98,11 +99,57 @@ ECPGmake_struct_type(struct ECPGstruct_member * rm)
{
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_struct, 1);
ne->u.members = rm;
ne->u.members = struct_member_dup(rm);
return ne;
}
static const char *get_type(enum ECPGttype typ)
{
switch (typ)
{
case ECPGt_char:
return("ECPGt_char");
break;
case ECPGt_unsigned_char:
return("ECPGt_unsigned_char");
break;
case ECPGt_short:
return("ECPGt_short");
break;
case ECPGt_unsigned_short:
return("ECPGt_unsigned_short");
break;
case ECPGt_int:
return("ECPGt_int");
break;
case ECPGt_unsigned_int:
return("ECPGt_unsigned_int");
break;
case ECPGt_long:
return("ECPGt_long");
break;
case ECPGt_unsigned_long:
return("ECPGt_unsigned_int");
break;
case ECPGt_float:
return("ECPGt_float");
break;
case ECPGt_double:
return("ECPGt_double");
break;
case ECPGt_bool:
return("ECPGt_bool");
break;
case ECPGt_varchar:
return("ECPGt_varchar");
case ECPGt_NO_INDICATOR: /* no indicator */
return("ECPGt_NO_INDICATOR");
break;
default:
abort();
}
}
/* Dump a type.
The type is dumped as:
@ -136,41 +183,40 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in
ind_name = "no_indicator";
}
if (IS_SIMPLE_TYPE(typ->typ))
{
ECPGdump_a_simple(o, name, typ->typ, typ->size, 0, 0, prefix);
ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, 0, 0, ind_prefix);
}
else if (typ->typ == ECPGt_array)
{
if (IS_SIMPLE_TYPE(typ->u.element->typ))
{
ECPGdump_a_simple(o, name, typ->u.element->typ,
typ->u.element->size, typ->size, 0, prefix);
ECPGdump_a_simple(o, ind_name, ind_typ->u.element->typ,
ind_typ->u.element->size, ind_typ->size, 0, prefix);
}
else if (typ->u.element->typ == ECPGt_array)
{
abort(); /* Array of array, */
}
else if (typ->u.element->typ == ECPGt_struct)
{
/* Array of structs. */
ECPGdump_a_struct(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, 0, prefix, ind_prefix);
}
else
{
abort();
}
}
else if (typ->typ == ECPGt_struct)
{
ECPGdump_a_struct(o, name, ind_name, 0, typ, ind_typ, 0, prefix, ind_prefix);
}
else
{
abort();
switch(typ->typ)
{
case ECPGt_array:
if (IS_SIMPLE_TYPE(typ->u.element->typ))
{
ECPGdump_a_simple(o, name, typ->u.element->typ,
typ->u.element->size, typ->size, NULL, prefix);
if (ind_typ == &ecpg_no_indicator)
ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix);
else
ECPGdump_a_simple(o, ind_name, ind_typ->u.element->typ,
ind_typ->u.element->size, ind_typ->size, NULL, prefix);
}
else if (typ->u.element->typ == ECPGt_array)
{
yyerror("No nested arrays allowed (except strings)"); /* Array of array, */
}
else if (typ->u.element->typ == ECPGt_struct)
{
/* Array of structs. */
ECPGdump_a_struct(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, NULL, prefix, ind_prefix);
}
else
{
yyerror("Internal error: unknown datatype, pleqase inform pgsql-bugs@postgresql.org");
}
break;
case ECPGt_struct:
ECPGdump_a_struct(o, name, ind_name, 1, typ, ind_typ, NULL, prefix, ind_prefix);
break;
default:
ECPGdump_a_simple(o, name, typ->typ, typ->size, -1, NULL, prefix);
ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix);
break;
}
}
@ -180,86 +226,48 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in
void
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
long varcharsize,
long arrsiz,
long arrsize,
const char *siz,
const char *prefix
)
{
switch (typ)
{
case ECPGt_char:
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:
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),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),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(unsigned short)" : siz);
break;
case ECPGt_int:
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),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(unsigned int)" : siz);
break;
case ECPGt_long:
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),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(unsigned int)" : siz);
break;
case ECPGt_float:
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),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(double)" : siz);
break;
case ECPGt_bool:
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),%ldL,%ldL,sizeof(struct varchar_%s), ",
prefix ? prefix : "", name,
varcharsize,
arrsiz, name);
else
fprintf(o, "\n\tECPGt_varchar,&(%s%s),%ldL,%ldL,%s, ",
prefix ? prefix : "", name,
varcharsize,
arrsiz, siz);
break;
case ECPGt_NO_INDICATOR: /* no indicator */
fprintf(o, "\n\tECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ");
break;
default:
abort();
if (typ == ECPGt_NO_INDICATOR)
fprintf(o, "\n\tECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ");
else
{
char *variable = (char *)mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4);
char *offset = (char *)mm_alloc(strlen(name) + strlen("sizeof(struct varchar_)") + 1);
if (varcharsize == 0 || arrsize >= 0)
sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
else
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
switch (typ)
{
case ECPGt_varchar:
sprintf(offset, "sizeof(struct varchar_%s)", name);
break;
case ECPGt_char:
case ECPGt_unsigned_char:
sprintf(offset, "%ld*sizeof(char)", varcharsize);
break;
default:
sprintf(offset, "sizeof(%s)", ECPGtype_name(typ));
break;
}
if (arrsize < 0)
arrsize = 1;
if (siz == NULL)
fprintf(o, "\n\t%s,%s,%ldL,%ldL,%s, ", get_type(typ), variable, varcharsize, arrsize, offset);
else
fprintf(o, "\n\t%s,%s,%ldL,%ldL,%s, ", get_type(typ), variable, varcharsize, arrsize, siz);
free(variable);
free(offset);
}
}
@ -302,23 +310,18 @@ ECPGdump_a_struct(FILE *o, const char *name, const char * ind_name, long arrsiz,
}
}
/* Freeing is not really that important. Since we throw away the process
anyway. Lets implement that last! */
/* won't work anymore because a list of members may appear in several locations */
/*void
void
ECPGfree_struct_member(struct ECPGstruct_member * rm)
{
while (rm)
{
struct ECPGstruct_member *p = rm;
rm = rm->next;
free(p->name);
free(p);
}
}*/
while (rm)
{
struct ECPGstruct_member *p = rm;
rm = rm->next;
free(p->name);
free(p);
}
}
void
ECPGfree_type(struct ECPGtype * typ)
@ -332,16 +335,18 @@ ECPGfree_type(struct ECPGtype * typ)
else if (typ->u.element->typ == ECPGt_array)
abort(); /* Array of array, */
else if (typ->u.element->typ == ECPGt_struct)
{
/* Array of structs. */
ECPGfree_struct_member(typ->u.members);
free(typ->u.members);
/* ECPGfree_struct_member(typ->u.members);*/
}
else
abort();
}
else if (typ->typ == ECPGt_struct)
{
ECPGfree_struct_member(typ->u.members);
free(typ->u.members);
/* ECPGfree_struct_member(typ->u.members);*/
}
else
{

View File

@ -77,6 +77,7 @@ struct when
struct index
{
int ival;
char *str;
int index1;
int index2;
char *str;
};

View File

@ -1,14 +1,18 @@
all: test2 perftest
all: test1 test2 perftest
LDFLAGS=-g -I ../include -I ../../libpq -L../lib -lecpg -L../../libpq -lpq -lcrypt --static
test1: test1.c
test1.c: test1.pgc
../preproc/ecpg $?
test2: test2.c
gcc -g -I ../include -I ../../libpq -o test2 test2.c -L../lib -lecpg -L../../libpq -lpq -lcrypt --static
test2.c: test2.pgc
../preproc/ecpg test2.pgc
../preproc/ecpg $?
perftest: perftest.c
gcc -g -I ../include -I ../../libpq -o perftest perftest.c -L../lib -lecpg -L../../libpq -lpq -lcrypt --static
perftest.c: perftest.pgc
../preproc/ecpg perftest.pgc
perftest.c:perftest.pgc
../preproc/ecpg $?
clean:
/bin/rm test2 test2.c perftest perftest.c log
/bin/rm test1 test2 perftest *.c log

View File

@ -1,77 +0,0 @@
/* These two include files are added by the preprocessor */
#include <ecpgtype.h>
#include <ecpglib.h>
/* exec sql begin declare section */
/* VARSIZE */ struct varchar_uid
{
int len;
char arr[200];
} uid;
struct varchar_name
{
int len;
char arr[200];
} name;
short value;
/* exec sql end declare section */
#include "sqlca.h"
#define DBCP(x,y) strcpy(x.arr,y);x.len = strlen(x.arr)
#define LENFIX(x) x.len=strlen(x.arr)
#define STRFIX(x) x.arr[x.len]='\0'
#define SQLCODE sqlca.sqlcode
void
db_error(char *msg)
{
sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
printf("%s: db error %s\n", msg, sqlca.sqlerrm.sqlerrmc);
exit(1);
}
int
main()
{
strcpy(uid.arr, "test/test");
LENFIX(uid);
ECPGconnect("kom");
if (SQLCODE)
db_error("connect");
strcpy(name.arr, "opt1");
LENFIX(name);
ECPGdo(__LINE__, "declare cur cursor for select name , value from pace_test ", ECPGt_EOIT, ECPGt_EORT);
if (SQLCODE)
db_error("declare");
if (SQLCODE)
db_error("open");
while (1)
{
ECPGdo(__LINE__, "fetch in cur ", ECPGt_EOIT, ECPGt_varchar, &name, 200, 0, sizeof(struct varchar_name), ECPGt_short, &value, 0, 0, sizeof(short), ECPGt_EORT);
if (SQLCODE)
break;
STRFIX(name);
printf("%s\t%d\n", name.arr, value);
}
if (SQLCODE < 0)
db_error("fetch");
ECPGdo(__LINE__, "close cur ", ECPGt_EOIT, ECPGt_EORT);
if (SQLCODE)
db_error("close");
ECPGcommit(__LINE__);
if (SQLCODE)
db_error("commit");
return (0);
}

View File

@ -1,4 +1,4 @@
exec sql include sqlca;
exec sql whenever not found do set_not_found();
exec sql whenever not found do break;
exec sql whenever sqlerror sqlprint;

View File

@ -121,5 +121,7 @@ exec sql end declare section;
exec sql commit;
exec sql disconnect;
return (0);
}

View File

@ -1,72 +0,0 @@
exec sql begin declare section;
VARCHAR uid[200 /* VARSIZE */ ];
varchar name[200];
short value;
exec sql end declare section;
exec sql include sqlca;
#define DBCP(x,y) strcpy(x.arr,y);x.len = strlen(x.arr)
#define LENFIX(x) x.len=strlen(x.arr)
#define STRFIX(x) x.arr[x.len]='\0'
#define SQLCODE sqlca.sqlcode
void
db_error(char *msg)
{
sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
printf("%s: db error %s\n", msg, sqlca.sqlerrm.sqlerrmc);
exit(1);
}
int
main()
{
strcpy(uid.arr, "test/test");
LENFIX(uid);
exec sql connect 'kom';
if (SQLCODE)
db_error("connect");
strcpy(name.arr, "opt1");
LENFIX(name);
exec sql declare cur cursor for
select name,
value from pace_test;
if (SQLCODE)
db_error("declare");
exec sql open cur;
if (SQLCODE)
db_error("open");
while (1)
{
exec sql fetch in cur into:name,
: value;
if (SQLCODE)
break;
STRFIX(name);
printf("%s\t%d\n", name.arr, value);
}
if (SQLCODE < 0)
db_error("fetch");
exec sql close cur;
if (SQLCODE)
db_error("close");
exec sql commit;
if (SQLCODE)
db_error("commit");
return (0);
}

View File

@ -0,0 +1,63 @@
#include <stdio.h>
exec sql whenever sqlerror sqlprint;
exec sql include sqlca;
int
main ()
{
exec sql begin declare section;
int amount[5];
char name[5][8];
exec sql end declare section;
char msg[128], command[128];
FILE *dbgs;
int i,j;
if ((dbgs = fopen("log", "w")) != NULL)
ECPGdebug(1, dbgs);
strcpy(msg, "connect");
exec sql connect mm;
strcpy(msg, "create");
exec sql create table test(name char(8), amount int);
strcpy(msg, "execute insert 1");
sprintf(command, "insert into test(name, amount) values ('foobar', 1)");
exec sql execute immediate :command;
strcpy(msg, "excute insert 2");
sprintf(command, "insert into test(name, amount) select name, amount+1 from test");
exec sql execute immediate :command;
strcpy(msg, "excute insert 3");
sprintf(command, "insert into test(name, amount) select name, amount+10 from test");
exec sql execute immediate :command;
printf("Inserted %d tuples via execute immediate\n", sqlca.sqlerrd[2]);
strcpy(msg, "commit");
exec sql commit;
strcpy(msg, "select");
exec sql select name, amount into :name, :amount from test;
for (i=0, j=sqlca.sqlerrd[2]; i<j; i++)
printf("name[%d]=%8.8s, amount[%d]=%d\n", i, name[i], i, amount[i]);
strcpy(msg, "drop");
exec sql drop table test;
strcpy(msg, "commit");
exec sql commit;
strcpy(msg, "disconnect");
exec sql disconnect;
if (dbgs != NULL)
fclose(dbgs);
return (0);
}

View File

@ -2,13 +2,6 @@
exec sql include header_test;
static int not_found = 0;
static void
set_not_found(void)
{
not_found = 1;
}
int
main ()
{
@ -43,10 +36,7 @@ exec sql end declare section;
exec sql insert into meskes(name, born, age, married) values ('Michael', 19660117, 32, '19900404');
exec sql insert into meskes(name, born, age) values ('Carsten', 19910103, 7);
exec sql insert into meskes(name, born, age) values ('Marc', 19930907, 4);
sprintf(command, "insert into meskes(name, born, age) values ('Chris', 19970923, 0)");
strcpy(msg, "execute");
exec sql execute immediate :command;
exec sql insert into meskes(name, born, age) values ('Chris', 19970923, 0);
strcpy(msg, "commit");
exec sql commit;
@ -58,11 +48,10 @@ exec sql end declare section;
strcpy(msg, "open");
exec sql open cur;
while (not_found == 0) {
while (1) {
strcpy(msg, "fetch");
exec sql fetch cur into :personal:ind_personal, :married:ind_married;
if (not_found == 0)
printf ("%8.8s was born %d (age = %d) %s%s\n", personal.name.arr, personal.birth.born, personal.birth.age, ind_married ? "" : "and married ", ind_married ? "" : married);
printf ("%8.8s was born %d (age = %d) %s%s\n", personal.name.arr, personal.birth.born, personal.birth.age, ind_married ? "" : "and married ", ind_married ? "" : married);
}
strcpy(msg, "close");
@ -74,6 +63,9 @@ exec sql end declare section;
strcpy(msg, "commit");
exec sql commit;
strcpy(msg, "disconnect");
exec sql disconnect;
if (dbgs != NULL)
fclose(dbgs);