mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
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:
parent
f9322c66d3
commit
6bccf64d7b
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
22
src/interfaces/ecpg/include/ecpgerrno.h
Normal file
22
src/interfaces/ecpg/include/ecpgerrno.h
Normal 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 */
|
@ -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>
|
||||
|
@ -10,10 +10,11 @@ struct sqlca
|
||||
int sqlcode;
|
||||
struct
|
||||
{
|
||||
int sqlerrml;
|
||||
int sqlerrml;
|
||||
char sqlerrmc[1000];
|
||||
} sqlerrm;
|
||||
} sqlca;
|
||||
long sqlerrd[6];
|
||||
} sqlca;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -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@
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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) \
|
||||
|
@ -21,6 +21,7 @@
|
||||
*/
|
||||
static ScanKeyword ScanKeywords[] = {
|
||||
/* name value */
|
||||
{"VARCHAR", S_VARCHAR},
|
||||
{"auto", S_AUTO},
|
||||
{"bool", S_BOOL},
|
||||
{"char", S_CHAR},
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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},
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
{
|
||||
|
@ -77,6 +77,7 @@ struct when
|
||||
|
||||
struct index
|
||||
{
|
||||
int ival;
|
||||
char *str;
|
||||
int index1;
|
||||
int index2;
|
||||
char *str;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
||||
|
@ -121,5 +121,7 @@ exec sql end declare section;
|
||||
|
||||
exec sql commit;
|
||||
|
||||
exec sql disconnect;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
63
src/interfaces/ecpg/test/test1.pgc
Normal file
63
src/interfaces/ecpg/test/test1.pgc
Normal 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);
|
||||
}
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user