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.
|
and :foo.bar as variables.
|
||||||
- Set version to 2.2.0
|
- 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.
|
ecpg does not understand enum datatypes.
|
||||||
|
|
||||||
There is no exec sql prepare statement.
|
|
||||||
|
|
||||||
The complete structure definition has to be listed inside the declare
|
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
|
Variable type bool has to be checked. I never used it so far.
|
||||||
[unsigned] char which are considered strings.
|
|
||||||
|
|
||||||
ecpg cannot use pointer variables except [unsigned] char *
|
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};
|
There is no exec sql prepare statement.
|
||||||
oder <disconnect statement> ::=
|
|
||||||
DISCONNECT <disconnect object>
|
|
||||||
|
|
||||||
<disconnect object> ::=
|
There is no SQLSTATE
|
||||||
<connection object>
|
|
||||||
| ALL
|
|
||||||
| CURRENT
|
|
||||||
commit release|commit work release auch disconnect
|
|
||||||
|
|
||||||
It is not neccessary to check for "not found" after all commands.
|
|
||||||
|
@ -6,11 +6,13 @@ all clean::
|
|||||||
@echo Nothing to be done.
|
@echo Nothing to be done.
|
||||||
|
|
||||||
install::
|
install::
|
||||||
|
$(INSTALL) $(INSTLOPTS) ecpgerrno.h $(DESTDIR)$(HEADERDIR)
|
||||||
$(INSTALL) $(INSTLOPTS) ecpglib.h $(DESTDIR)$(HEADERDIR)
|
$(INSTALL) $(INSTLOPTS) ecpglib.h $(DESTDIR)$(HEADERDIR)
|
||||||
$(INSTALL) $(INSTLOPTS) ecpgtype.h $(DESTDIR)$(HEADERDIR)
|
$(INSTALL) $(INSTLOPTS) ecpgtype.h $(DESTDIR)$(HEADERDIR)
|
||||||
$(INSTALL) $(INSTLOPTS) sqlca.h $(DESTDIR)$(HEADERDIR)
|
$(INSTALL) $(INSTLOPTS) sqlca.h $(DESTDIR)$(HEADERDIR)
|
||||||
|
|
||||||
uninstall::
|
uninstall::
|
||||||
|
rm -f $(DESTDIR)$(HEADERDIR)/ecpgerrno.h
|
||||||
rm -f $(DESTDIR)$(HEADERDIR)/ecpglib.h
|
rm -f $(DESTDIR)$(HEADERDIR)/ecpglib.h
|
||||||
rm -f $(DESTDIR)$(HEADERDIR)/ecpgtype.h
|
rm -f $(DESTDIR)$(HEADERDIR)/ecpgtype.h
|
||||||
rm -f $(DESTDIR)$(HEADERDIR)/sqlca.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
|
#endif
|
||||||
|
|
||||||
void ECPGdebug(int, FILE *);
|
void ECPGdebug(int, FILE *);
|
||||||
bool ECPGconnect(const char *dbname);
|
bool ECPGconnect(const char *);
|
||||||
bool ECPGdo(int, char *,...);
|
bool ECPGdo(int, char *,...);
|
||||||
bool ECPGtrans(int, const char *);
|
bool ECPGtrans(int, const char *);
|
||||||
bool ECPGfinish(void);
|
bool ECPGfinish(void);
|
||||||
bool ECPGstatus(void);
|
bool ECPGdisconnect(const char *);
|
||||||
|
|
||||||
void ECPGlog(const char *format,...);
|
void ECPGlog(const char *format,...);
|
||||||
|
|
||||||
@ -39,3 +39,5 @@ void sqlprint(void);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <ecpgerrno.h>
|
||||||
|
@ -10,10 +10,11 @@ struct sqlca
|
|||||||
int sqlcode;
|
int sqlcode;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int sqlerrml;
|
int sqlerrml;
|
||||||
char sqlerrmc[1000];
|
char sqlerrmc[1000];
|
||||||
} sqlerrm;
|
} sqlerrm;
|
||||||
} sqlca;
|
long sqlerrd[6];
|
||||||
|
} sqlca;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ include $(SRCDIR)/Makefile.global
|
|||||||
PQ_INCLUDE=-I$(SRCDIR)/interfaces/libpq
|
PQ_INCLUDE=-I$(SRCDIR)/interfaces/libpq
|
||||||
|
|
||||||
SO_MAJOR_VERSION=2
|
SO_MAJOR_VERSION=2
|
||||||
SO_MINOR_VERSION=0
|
SO_MINOR_VERSION=1
|
||||||
|
|
||||||
PORTNAME=@PORTNAME@
|
PORTNAME=@PORTNAME@
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
#include <ecpglib.h>
|
#include <ecpglib.h>
|
||||||
#include <sqlca.h>
|
#include <sqlca.h>
|
||||||
|
|
||||||
|
extern int no_auto_trans;
|
||||||
|
|
||||||
static PGconn *simple_connection = NULL;
|
static PGconn *simple_connection = NULL;
|
||||||
static int simple_debug = 0;
|
static int simple_debug = 0;
|
||||||
static FILE *debugstream = NULL;
|
static FILE *debugstream = NULL;
|
||||||
@ -80,6 +82,11 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
PGresult *results;
|
PGresult *results;
|
||||||
PGnotify *notify;
|
PGnotify *notify;
|
||||||
enum ECPGttype type;
|
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);
|
va_start(ap, query);
|
||||||
|
|
||||||
@ -96,12 +103,6 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
*/
|
*/
|
||||||
while (type != ECPGt_EOIT)
|
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 *newcopy;
|
||||||
char *mallocedval = NULL;
|
char *mallocedval = NULL;
|
||||||
char *tobeinserted = NULL;
|
char *tobeinserted = NULL;
|
||||||
@ -116,13 +117,13 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
|
|
||||||
value = va_arg(ap, void *);
|
value = va_arg(ap, void *);
|
||||||
varcharsize = va_arg(ap, long);
|
varcharsize = va_arg(ap, long);
|
||||||
size = va_arg(ap, long);
|
|
||||||
arrsize = va_arg(ap, long);
|
arrsize = va_arg(ap, long);
|
||||||
|
offset = va_arg(ap, long);
|
||||||
ind_type = va_arg(ap, enum ECPGttype);
|
ind_type = va_arg(ap, enum ECPGttype);
|
||||||
ind_value = va_arg(ap, void *);
|
ind_value = va_arg(ap, void *);
|
||||||
ind_varcharsize = va_arg(ap, long);
|
ind_varcharsize = va_arg(ap, long);
|
||||||
ind_size = va_arg(ap, long);
|
|
||||||
ind_arrsize = va_arg(ap, long);
|
ind_arrsize = va_arg(ap, long);
|
||||||
|
ind_offset = va_arg(ap, long);
|
||||||
|
|
||||||
buff[0] = '\0';
|
buff[0] = '\0';
|
||||||
|
|
||||||
@ -211,7 +212,6 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGt_varchar:
|
case ECPGt_varchar:
|
||||||
case ECPGt_varchar2:
|
|
||||||
{
|
{
|
||||||
struct ECPGgeneric_varchar *var =
|
struct ECPGgeneric_varchar *var =
|
||||||
(struct ECPGgeneric_varchar *) value;
|
(struct ECPGgeneric_varchar *) value;
|
||||||
@ -233,7 +233,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
/* Not implemented yet */
|
/* 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);
|
ECPGtype_name(type), lineno);
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
@ -257,7 +257,7 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
* We have an argument but we dont have the matched up string
|
* We have an argument but we dont have the matched up string
|
||||||
* in the 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;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -293,17 +293,17 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
/* Check if there are unmatched things left. */
|
/* Check if there are unmatched things left. */
|
||||||
if (strstr(copiedquery, ";;") != NULL)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now the request is built. */
|
/* Now the request is built. */
|
||||||
|
|
||||||
if (committed)
|
if (committed && !no_auto_trans)
|
||||||
{
|
{
|
||||||
if ((results = PQexec(simple_connection, "begin transaction")) == NULL)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
PQclear(results);
|
PQclear(results);
|
||||||
@ -318,15 +318,15 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
{
|
{
|
||||||
ECPGlog("ECPGdo line %d: error: %s", lineno,
|
ECPGlog("ECPGdo line %d: error: %s", lineno,
|
||||||
PQerrorMessage(simple_connection));
|
PQerrorMessage(simple_connection));
|
||||||
register_error(-1, "Postgres error: %s line %d.",
|
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
|
||||||
PQerrorMessage(simple_connection), lineno);
|
PQerrorMessage(simple_connection), lineno);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
sqlca.sqlerrd[2] = 0;
|
||||||
switch (PQresultStatus(results))
|
switch (PQresultStatus(results))
|
||||||
{
|
{
|
||||||
int m,
|
int nfields, ntuples, act_tuple, act_field;
|
||||||
n,
|
|
||||||
x;
|
|
||||||
|
|
||||||
case PGRES_TUPLES_OK:
|
case PGRES_TUPLES_OK:
|
||||||
|
|
||||||
@ -336,306 +336,308 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
* !!
|
* !!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
m = PQnfields(results);
|
nfields = PQnfields(results);
|
||||||
n = PQntuples(results);
|
sqlca.sqlerrd[2] = ntuples = 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = true;
|
status = true;
|
||||||
|
|
||||||
for (x = 0; x < m && status; x++)
|
if (ntuples < 1)
|
||||||
{
|
{
|
||||||
void *value = NULL, *ind_value;
|
ECPGlog("ECPGdo line %d: Incorrect number of matches: %d\n",
|
||||||
long varcharsize, ind_varcharsize;
|
lineno, ntuples);
|
||||||
long size, ind_size;
|
register_error(ECPG_NOT_FOUND, "Data not found line %d.", lineno);
|
||||||
long arrsize, ind_arrsize;
|
status = false;
|
||||||
enum ECPGttype ind_type;
|
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);
|
||||||
* long int * res_int; char ** res_charstar; char *
|
value = va_arg(ap, void *);
|
||||||
* res_char; int res_len;
|
varcharsize = va_arg(ap, long);
|
||||||
*/
|
arrsize = va_arg(ap, long);
|
||||||
char *scan_length;
|
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);
|
||||||
|
|
||||||
ECPGlog("ECPGdo line %d: RESULT: %s\n", lineno, pval ? pval : "");
|
/* 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);
|
||||||
|
|
||||||
/* Now the pval is a pointer to the value. */
|
ECPGlog("ECPGdo line %d: RESULT: %s\n", lineno, pval ? pval : "");
|
||||||
/* 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 */
|
/* Now the pval is a pointer to the value. */
|
||||||
switch (ind_type)
|
/* We will have to decode the value */
|
||||||
{
|
|
||||||
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)
|
/* check for null value and set indicator accordingly */
|
||||||
{
|
switch (ind_type)
|
||||||
long res;
|
{
|
||||||
unsigned long ures;
|
case ECPGt_short:
|
||||||
double dres;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
case ECPGt_short:
|
switch (type)
|
||||||
case ECPGt_int:
|
{
|
||||||
case ECPGt_long:
|
long res;
|
||||||
if (pval)
|
unsigned long ures;
|
||||||
{
|
double dres;
|
||||||
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 */
|
case ECPGt_short:
|
||||||
switch (type)
|
case ECPGt_int:
|
||||||
{
|
case ECPGt_long:
|
||||||
case ECPGt_short:
|
if (pval)
|
||||||
*(short *) value = (short) res;
|
{
|
||||||
break;
|
res = strtol(pval, &scan_length, 10);
|
||||||
case ECPGt_int:
|
if (*scan_length != '\0') /* Garbage left */
|
||||||
*(int *) value = (int) res;
|
{
|
||||||
break;
|
register_error(ECPG_INT_FORMAT, "Not correctly formatted int type: %s line %d.",
|
||||||
case ECPGt_long:
|
pval, lineno);
|
||||||
*(long *) value = res;
|
status = false;
|
||||||
break;
|
res = 0L;
|
||||||
default:
|
}
|
||||||
/* Cannot happen */
|
}
|
||||||
break;
|
else
|
||||||
}
|
res = 0L;
|
||||||
break;
|
|
||||||
|
|
||||||
case ECPGt_unsigned_short:
|
/* Again?! Yes */
|
||||||
case ECPGt_unsigned_int:
|
switch (type)
|
||||||
case ECPGt_unsigned_long:
|
{
|
||||||
if (pval)
|
case ECPGt_short:
|
||||||
{
|
((short *) value)[act_tuple] = (short) res;
|
||||||
ures = strtoul(pval, &scan_length, 10);
|
break;
|
||||||
if (*scan_length != '\0') /* Garbage left */
|
case ECPGt_int:
|
||||||
{
|
((int *) value)[act_tuple] = (int) res;
|
||||||
register_error(-1, "Not correctly formatted unsigned type: %s line %d.",
|
break;
|
||||||
pval, lineno);
|
case ECPGt_long:
|
||||||
status = false;
|
((long *) value)[act_tuple] = res;
|
||||||
ures = 0L;
|
break;
|
||||||
}
|
default:
|
||||||
}
|
/* Cannot happen */
|
||||||
else
|
break;
|
||||||
ures = 0L;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
/* Again?! Yes */
|
case ECPGt_unsigned_short:
|
||||||
switch (type)
|
case ECPGt_unsigned_int:
|
||||||
{
|
case ECPGt_unsigned_long:
|
||||||
case ECPGt_unsigned_short:
|
if (pval)
|
||||||
*(unsigned short *) value = (unsigned short) ures;
|
{
|
||||||
break;
|
ures = strtoul(pval, &scan_length, 10);
|
||||||
case ECPGt_unsigned_int:
|
if (*scan_length != '\0') /* Garbage left */
|
||||||
*(unsigned int *) value = (unsigned int) ures;
|
{
|
||||||
break;
|
register_error(ECPG_UINT_FORMAT, "Not correctly formatted unsigned type: %s line %d.",
|
||||||
case ECPGt_unsigned_long:
|
pval, lineno);
|
||||||
*(unsigned long *) value = ures;
|
status = false;
|
||||||
break;
|
ures = 0L;
|
||||||
default:
|
}
|
||||||
/* Cannot happen */
|
}
|
||||||
break;
|
else
|
||||||
}
|
ures = 0L;
|
||||||
break;
|
|
||||||
|
/* 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_float:
|
||||||
case ECPGt_double:
|
case ECPGt_double:
|
||||||
if (pval)
|
if (pval)
|
||||||
{
|
{
|
||||||
dres = strtod(pval, &scan_length);
|
dres = strtod(pval, &scan_length);
|
||||||
if (*scan_length != '\0') /* Garbage left */
|
if (*scan_length != '\0') /* Garbage left */
|
||||||
{
|
{
|
||||||
register_error(-1, "Not correctly formatted floating point type: %s line %d.",
|
register_error(ECPG_FLOAT_FORMAT, "Not correctly formatted floating point type: %s line %d.",
|
||||||
pval, lineno);
|
pval, lineno);
|
||||||
status = false;
|
status = false;
|
||||||
dres = 0.0;
|
dres = 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dres = 0.0;
|
dres = 0.0;
|
||||||
|
|
||||||
/* Again?! Yes */
|
/* Again?! Yes */
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ECPGt_float:
|
case ECPGt_float:
|
||||||
*(float *) value = dres;
|
((float *) value)[act_tuple] = dres;
|
||||||
break;
|
break;
|
||||||
case ECPGt_double:
|
case ECPGt_double:
|
||||||
*(double *) value = dres;
|
((double *) value)[act_tuple] = dres;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Cannot happen */
|
/* Cannot happen */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGt_bool:
|
case ECPGt_bool:
|
||||||
if (pval)
|
if (pval)
|
||||||
{
|
{
|
||||||
if (pval[0] == 'f' && pval[1] == '\0')
|
if (pval[0] == 'f' && pval[1] == '\0')
|
||||||
{
|
{
|
||||||
*(char *) value = false;
|
((char *) value)[act_tuple] = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (pval[0] == 't' && pval[1] == '\0')
|
else if (pval[0] == 't' && pval[1] == '\0')
|
||||||
{
|
{
|
||||||
*(char *) value = true;
|
((char *) value)[act_tuple] = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
register_error(-1, "Unable to convert %s to bool on line %d.",
|
register_error(ECPG_CONVERT_BOOL, "Unable to convert %s to bool on line %d.",
|
||||||
(pval ? pval : "NULL"),
|
(pval ? pval : "NULL"),
|
||||||
lineno);
|
lineno);
|
||||||
return false;
|
status = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGt_char:
|
case ECPGt_char:
|
||||||
case ECPGt_unsigned_char:
|
case ECPGt_unsigned_char:
|
||||||
{
|
{
|
||||||
if (varcharsize == 0)
|
if (varcharsize == 0)
|
||||||
{
|
{
|
||||||
/* char* */
|
/* char* */
|
||||||
strncpy((char *) value, pval, strlen(pval));
|
strncpy(((char **) value)[act_tuple], pval, strlen(pval));
|
||||||
((char *) value)[strlen(pval)] = '\0';
|
(((char **) value)[act_tuple])[strlen(pval)] = '\0';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strncpy((char *) value, pval, varcharsize);
|
strncpy((char *) (value + offset * act_tuple), pval, varcharsize);
|
||||||
if (varcharsize < strlen(pval))
|
if (varcharsize < strlen(pval))
|
||||||
{
|
{
|
||||||
/* truncation */
|
/* truncation */
|
||||||
switch (ind_type)
|
switch (ind_type)
|
||||||
{
|
{
|
||||||
case ECPGt_short:
|
case ECPGt_short:
|
||||||
case ECPGt_unsigned_short:
|
case ECPGt_unsigned_short:
|
||||||
*(short *) ind_value = varcharsize;
|
((short *) ind_value)[act_tuple] = varcharsize;
|
||||||
break;
|
break;
|
||||||
case ECPGt_int:
|
case ECPGt_int:
|
||||||
case ECPGt_unsigned_int:
|
case ECPGt_unsigned_int:
|
||||||
*(int *) ind_value = varcharsize;
|
((int *) ind_value)[act_tuple] = varcharsize;
|
||||||
break;
|
break;
|
||||||
case ECPGt_long:
|
case ECPGt_long:
|
||||||
case ECPGt_unsigned_long:
|
case ECPGt_unsigned_long:
|
||||||
*(long *) ind_value = varcharsize;
|
((long *) ind_value)[act_tuple] = varcharsize;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGt_varchar:
|
case ECPGt_varchar:
|
||||||
{
|
{
|
||||||
struct ECPGgeneric_varchar *var =
|
struct ECPGgeneric_varchar *var =
|
||||||
(struct ECPGgeneric_varchar *) value;
|
(struct ECPGgeneric_varchar *) (value + offset * act_tuple);
|
||||||
|
|
||||||
strncpy(var->arr, pval, varcharsize);
|
if (varcharsize == 0)
|
||||||
var->len = strlen(pval);
|
strncpy(var->arr, pval, strlen(pval));
|
||||||
if (var->len > varcharsize)
|
else
|
||||||
{
|
strncpy(var->arr, pval, 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;
|
var->len = strlen(pval);
|
||||||
}
|
if (varcharsize > 0 && var->len > varcharsize)
|
||||||
}
|
{
|
||||||
break;
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
case ECPGt_EORT:
|
var->len = varcharsize;
|
||||||
ECPGlog("ECPGdo line %d: Too few arguments.\n", lineno);
|
}
|
||||||
register_error(-1, "Too few arguments line %d.", lineno);
|
}
|
||||||
status = false;
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
case ECPGt_EORT:
|
||||||
register_error(-1, "Unsupported type %s on line %d.",
|
ECPGlog("ECPGdo line %d: Too few arguments.\n", lineno);
|
||||||
ECPGtype_name(type), lineno);
|
register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", lineno);
|
||||||
return false;
|
status = false;
|
||||||
break;
|
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);
|
type = va_arg(ap, enum ECPGttype);
|
||||||
|
|
||||||
if (status && type != ECPGt_EORT)
|
if (status && type != ECPGt_EORT)
|
||||||
{
|
{
|
||||||
register_error(-1, "Too many arguments line %d.", lineno);
|
register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", lineno);
|
||||||
return false;
|
status = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PQclear(results);
|
PQclear(results);
|
||||||
break;
|
break;
|
||||||
case PGRES_EMPTY_QUERY:
|
case PGRES_EMPTY_QUERY:
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
register_error(-1, "Empty query line %d.", lineno);
|
register_error(ECPG_EMPTY, "Empty query line %d.", lineno);
|
||||||
break;
|
break;
|
||||||
case PGRES_COMMAND_OK:
|
case PGRES_COMMAND_OK:
|
||||||
status = true;
|
status = true;
|
||||||
|
sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
|
||||||
|
ECPGlog("TEST: %s\n", PQcmdTuples(results));
|
||||||
ECPGlog("ECPGdo line %d Ok: %s\n", lineno, PQcmdStatus(results));
|
ECPGlog("ECPGdo line %d Ok: %s\n", lineno, PQcmdStatus(results));
|
||||||
break;
|
break;
|
||||||
case PGRES_NONFATAL_ERROR:
|
case PGRES_NONFATAL_ERROR:
|
||||||
@ -643,8 +645,9 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
case PGRES_BAD_RESPONSE:
|
case PGRES_BAD_RESPONSE:
|
||||||
ECPGlog("ECPGdo line %d: Error: %s",
|
ECPGlog("ECPGdo line %d: Error: %s",
|
||||||
lineno, PQerrorMessage(simple_connection));
|
lineno, PQerrorMessage(simple_connection));
|
||||||
register_error(-1, "Error: %s line %d.",
|
register_error(ECPG_PGSQL, "Error: %s line %d.",
|
||||||
PQerrorMessage(simple_connection), lineno);
|
PQerrorMessage(simple_connection), lineno);
|
||||||
|
status = false;
|
||||||
break;
|
break;
|
||||||
case PGRES_COPY_OUT:
|
case PGRES_COPY_OUT:
|
||||||
ECPGlog("ECPGdo line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno);
|
ECPGlog("ECPGdo line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno);
|
||||||
@ -657,9 +660,11 @@ ECPGdo(int lineno, char *query,...)
|
|||||||
default:
|
default:
|
||||||
ECPGlog("ECPGdo line %d: Got something else, postgres error.\n",
|
ECPGlog("ECPGdo line %d: Got something else, postgres error.\n",
|
||||||
lineno);
|
lineno);
|
||||||
register_error(-1, "Postgres error line %d.", lineno);
|
register_error(ECPG_PGSQL, "Postgres error line %d.", lineno);
|
||||||
|
status = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* check for asynchronous returns */
|
/* check for asynchronous returns */
|
||||||
notify = PQnotifies(simple_connection);
|
notify = PQnotifies(simple_connection);
|
||||||
@ -683,11 +688,12 @@ ECPGtrans(int lineno, const char * transaction)
|
|||||||
ECPGlog("ECPGtrans line %d action = %s\n", lineno, transaction);
|
ECPGlog("ECPGtrans line %d action = %s\n", lineno, transaction);
|
||||||
if ((res = PQexec(simple_connection, transaction)) == NULL)
|
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);
|
return (FALSE);
|
||||||
}
|
}
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
committed = 1;
|
if (strcmp(transaction, "commit") == 0 || strcmp(transaction, "rollback") == 0)
|
||||||
|
committed = 1;
|
||||||
return (TRUE);
|
return (TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,21 +722,25 @@ ECPGconnect(const char *dbname)
|
|||||||
if (PQstatus(simple_connection) == CONNECTION_BAD)
|
if (PQstatus(simple_connection) == CONNECTION_BAD)
|
||||||
{
|
{
|
||||||
ECPGfinish();
|
ECPGfinish();
|
||||||
ECPGlog("ECPGconnect: could not open database %s\n", dbname);
|
ECPGlog("connect: could not open database %s\n", dbname);
|
||||||
register_error(-1, "ECPGconnect: could not open database %s.", dbname);
|
register_error(ECPG_CONNECT, "connect: could not open database %s.", dbname);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
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
|
bool
|
||||||
ECPGfinish(void)
|
ECPGfinish(void)
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@ SRCDIR= ../../..
|
|||||||
include $(SRCDIR)/Makefile.global
|
include $(SRCDIR)/Makefile.global
|
||||||
|
|
||||||
MAJOR_VERSION=2
|
MAJOR_VERSION=2
|
||||||
MINOR_VERSION=2
|
MINOR_VERSION=3
|
||||||
PATCHLEVEL=0
|
PATCHLEVEL=0
|
||||||
|
|
||||||
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
|
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
static ScanKeyword ScanKeywords[] = {
|
static ScanKeyword ScanKeywords[] = {
|
||||||
/* name value */
|
/* name value */
|
||||||
|
{"VARCHAR", S_VARCHAR},
|
||||||
{"auto", S_AUTO},
|
{"auto", S_AUTO},
|
||||||
{"bool", S_BOOL},
|
{"bool", S_BOOL},
|
||||||
{"char", S_CHAR},
|
{"char", S_CHAR},
|
||||||
|
@ -22,12 +22,13 @@ extern char *optarg;
|
|||||||
#include "extern.h"
|
#include "extern.h"
|
||||||
|
|
||||||
struct _include_path *include_paths;
|
struct _include_path *include_paths;
|
||||||
|
static int no_auto_trans = 0;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(char *progname)
|
usage(char *progname)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ecpg - the postgresql preprocessor, version: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
|
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
|
static void
|
||||||
@ -51,7 +52,7 @@ main(int argc, char *const argv[])
|
|||||||
add_include_path("/usr/local/include");
|
add_include_path("/usr/local/include");
|
||||||
add_include_path(".");
|
add_include_path(".");
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "vo:I:")) != EOF)
|
while ((c = getopt(argc, argv, "vo:I:t")) != EOF)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
@ -65,23 +66,26 @@ main(int argc, char *const argv[])
|
|||||||
case 'I':
|
case 'I':
|
||||||
add_include_path(optarg);
|
add_include_path(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 't':
|
||||||
|
no_auto_trans = 1;
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
fprintf(stderr, "ecpg - the postgresql preprocessor, version: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
|
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");
|
fprintf(stderr, "exec sql include ... search starts here:\n");
|
||||||
for (ip = include_paths; ip != NULL; ip = ip->next)
|
for (ip = include_paths; ip != NULL; ip = ip->next)
|
||||||
fprintf(stderr, " %s\n", ip->path);
|
fprintf(stderr, " %s\n", ip->path);
|
||||||
fprintf(stderr, "End of search list.\n");
|
fprintf(stderr, "End of search list.\n");
|
||||||
return (0);
|
return (OK);
|
||||||
default:
|
default:
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return (1);
|
return (ILLEGAL_OPTION);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind >= argc) /* no files specified */
|
if (optind >= argc) /* no files specified */
|
||||||
{
|
{
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return(1);
|
return(ILLEGAL_OPTION);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -151,8 +155,8 @@ main(int argc, char *const argv[])
|
|||||||
|
|
||||||
cur = NULL;
|
cur = NULL;
|
||||||
|
|
||||||
/* we need two includes */
|
/* 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", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
|
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 */
|
/* and parse the source */
|
||||||
yyparse();
|
yyparse();
|
||||||
@ -169,5 +173,5 @@ main(int argc, char *const argv[])
|
|||||||
free(input_filename);
|
free(input_filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (0);
|
return (OK);
|
||||||
}
|
}
|
||||||
|
@ -21,15 +21,18 @@
|
|||||||
*/
|
*/
|
||||||
static ScanKeyword ScanKeywords[] = {
|
static ScanKeyword ScanKeywords[] = {
|
||||||
/* name value */
|
/* name value */
|
||||||
|
{"break", SQL_BREAK},
|
||||||
{"call", SQL_CALL},
|
{"call", SQL_CALL},
|
||||||
{"connect", SQL_CONNECT},
|
{"connect", SQL_CONNECT},
|
||||||
{"continue", SQL_CONTINUE},
|
{"continue", SQL_CONTINUE},
|
||||||
|
{"disconnect", SQL_DISCONNECT},
|
||||||
{"found", SQL_FOUND},
|
{"found", SQL_FOUND},
|
||||||
{"go", SQL_GO},
|
{"go", SQL_GO},
|
||||||
{"goto", SQL_GOTO},
|
{"goto", SQL_GOTO},
|
||||||
{"immediate", SQL_IMMEDIATE},
|
{"immediate", SQL_IMMEDIATE},
|
||||||
{"indicator", SQL_INDICATOR},
|
{"indicator", SQL_INDICATOR},
|
||||||
{"open", SQL_OPEN},
|
{"open", SQL_OPEN},
|
||||||
|
{"release", SQL_RELEASE},
|
||||||
{"section", SQL_SECTION},
|
{"section", SQL_SECTION},
|
||||||
{"sqlerror", SQL_SQLERROR},
|
{"sqlerror", SQL_SQLERROR},
|
||||||
{"sqlprint", SQL_SQLPRINT},
|
{"sqlprint", SQL_SQLPRINT},
|
||||||
|
@ -43,3 +43,11 @@ extern void *mm_alloc(size_t), *mm_realloc(void *, size_t);
|
|||||||
ScanKeyword * ScanECPGKeywordLookup(char *);
|
ScanKeyword * ScanECPGKeywordLookup(char *);
|
||||||
ScanKeyword * ScanCKeywordLookup(char *);
|
ScanKeyword * ScanCKeywordLookup(char *);
|
||||||
extern void yyerror(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;
|
extern YYSTYPE yylval;
|
||||||
int llen;
|
int llen;
|
||||||
char literal[MAX_PARSE_BUFFER];
|
char literal[MAX_PARSE_BUFFER];
|
||||||
|
int before_comment;
|
||||||
|
|
||||||
struct _yy_buffer { YY_BUFFER_STATE buffer;
|
struct _yy_buffer { YY_BUFFER_STATE buffer;
|
||||||
long lineno;
|
long lineno;
|
||||||
@ -153,7 +154,7 @@ space [ \t\n\f]
|
|||||||
other .
|
other .
|
||||||
|
|
||||||
/* some stuff needed for ecpg */
|
/* some stuff needed for ecpg */
|
||||||
ccomment \/\*([^*]|\*[^/]|\*\*[^/])*\*\/
|
ccomment "//".*\n
|
||||||
exec [eE][xX][eE][cC]
|
exec [eE][xX][eE][cC]
|
||||||
include [iI][nN][cC][lL][uU][dD][eE]
|
include [iI][nN][cC][lL][uU][dD][eE]
|
||||||
sql [sS][qQ][lL]
|
sql [sS][qQ][lL]
|
||||||
@ -174,12 +175,18 @@ sql [sS][qQ][lL]
|
|||||||
%%
|
%%
|
||||||
<SQL>{comment} { /* ignore */ }
|
<SQL>{comment} { /* ignore */ }
|
||||||
|
|
||||||
<SQL>{xcline} { /* ignore */ }
|
{xcline} { /* ignore */ }
|
||||||
|
|
||||||
<xc>{xcstar} |
|
<xc>{xcstar} { /* ignore */ }
|
||||||
<SQL>{xcstart} { BEGIN(xc); }
|
{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 */ }
|
<xc>{xcinside} { /* ignore */ }
|
||||||
|
|
||||||
@ -306,7 +313,6 @@ sql [sS][qQ][lL]
|
|||||||
return (yytext[0]);
|
return (yytext[0]);
|
||||||
}
|
}
|
||||||
<SQL>{self} { return (yytext[0]); }
|
<SQL>{self} { return (yytext[0]); }
|
||||||
<SQL>"->" { return S_STRUCTPOINTER; }
|
|
||||||
<SQL>{operator}/-[\.0-9] {
|
<SQL>{operator}/-[\.0-9] {
|
||||||
yylval.str = strdup((char*)yytext);
|
yylval.str = strdup((char*)yytext);
|
||||||
return (Op);
|
return (Op);
|
||||||
@ -402,7 +408,7 @@ sql [sS][qQ][lL]
|
|||||||
return (FCONST);
|
return (FCONST);
|
||||||
}
|
}
|
||||||
|
|
||||||
<SQL>:{identifier} {
|
<SQL>:{identifier}(("->"|\.){identifier})* {
|
||||||
yylval.str = strdup((char*)yytext+1);
|
yylval.str = strdup((char*)yytext+1);
|
||||||
return(CVARIABLE);
|
return(CVARIABLE);
|
||||||
}
|
}
|
||||||
@ -436,6 +442,7 @@ sql [sS][qQ][lL]
|
|||||||
<SQL>{other} { return (yytext[0]); }
|
<SQL>{other} { return (yytext[0]); }
|
||||||
|
|
||||||
<C>{exec}{space}{sql} { BEGIN SQL; return SQL_START; }
|
<C>{exec}{space}{sql} { BEGIN SQL; return SQL_START; }
|
||||||
|
<C>{ccomment} { /* ignore */ }
|
||||||
<C>{identifier} {
|
<C>{identifier} {
|
||||||
ScanKeyword *keyword;
|
ScanKeyword *keyword;
|
||||||
|
|
||||||
@ -501,7 +508,7 @@ sql [sS][qQ][lL]
|
|||||||
if (!yyin)
|
if (!yyin)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error: Cannot open include file %s in line %d\n", yytext, yylineno);
|
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);
|
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)
|
if (ptr == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Out of memory\n");
|
fprintf(stderr, "Out of memory\n");
|
||||||
exit(1);
|
exit(OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ptr);
|
return (ptr);
|
||||||
@ -29,15 +29,27 @@ mm_realloc(void *ptr, size_t size)
|
|||||||
if (ptr == NULL)
|
if (ptr == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Out of memory\n");
|
fprintf(stderr, "Out of memory\n");
|
||||||
exit(1);
|
exit(OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ptr);
|
return (ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Constructors
|
/* duplicate memberlist */
|
||||||
Yes, I mostly write c++-code
|
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. */
|
/* The NAME argument is copied. The type argument is preserved as a pointer. */
|
||||||
struct ECPGstruct_member *
|
struct ECPGstruct_member *
|
||||||
@ -72,22 +84,11 @@ ECPGmake_simple_type(enum ECPGttype typ, long siz)
|
|||||||
return ne;
|
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 *
|
struct ECPGtype *
|
||||||
ECPGmake_array_type(struct ECPGtype * typ, long siz)
|
ECPGmake_array_type(struct ECPGtype * typ, long siz)
|
||||||
{
|
{
|
||||||
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, siz);
|
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, siz);
|
||||||
|
|
||||||
ne->size = siz;
|
|
||||||
ne->u.element = typ;
|
ne->u.element = typ;
|
||||||
|
|
||||||
return ne;
|
return ne;
|
||||||
@ -98,11 +99,57 @@ ECPGmake_struct_type(struct ECPGstruct_member * rm)
|
|||||||
{
|
{
|
||||||
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_struct, 1);
|
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_struct, 1);
|
||||||
|
|
||||||
ne->u.members = rm;
|
ne->u.members = struct_member_dup(rm);
|
||||||
|
|
||||||
return ne;
|
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.
|
/* Dump a type.
|
||||||
The type is dumped as:
|
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";
|
ind_name = "no_indicator";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_SIMPLE_TYPE(typ->typ))
|
switch(typ->typ)
|
||||||
{
|
{
|
||||||
ECPGdump_a_simple(o, name, typ->typ, typ->size, 0, 0, prefix);
|
case ECPGt_array:
|
||||||
ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, 0, 0, ind_prefix);
|
if (IS_SIMPLE_TYPE(typ->u.element->typ))
|
||||||
}
|
{
|
||||||
else if (typ->typ == ECPGt_array)
|
ECPGdump_a_simple(o, name, typ->u.element->typ,
|
||||||
{
|
typ->u.element->size, typ->size, NULL, prefix);
|
||||||
if (IS_SIMPLE_TYPE(typ->u.element->typ))
|
if (ind_typ == &ecpg_no_indicator)
|
||||||
{
|
ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix);
|
||||||
ECPGdump_a_simple(o, name, typ->u.element->typ,
|
else
|
||||||
typ->u.element->size, typ->size, 0, prefix);
|
ECPGdump_a_simple(o, ind_name, ind_typ->u.element->typ,
|
||||||
ECPGdump_a_simple(o, ind_name, ind_typ->u.element->typ,
|
ind_typ->u.element->size, ind_typ->size, NULL, prefix);
|
||||||
ind_typ->u.element->size, ind_typ->size, 0, prefix);
|
}
|
||||||
}
|
else if (typ->u.element->typ == ECPGt_array)
|
||||||
else if (typ->u.element->typ == ECPGt_array)
|
{
|
||||||
{
|
yyerror("No nested arrays allowed (except strings)"); /* Array of array, */
|
||||||
abort(); /* Array of array, */
|
}
|
||||||
}
|
else if (typ->u.element->typ == ECPGt_struct)
|
||||||
else if (typ->u.element->typ == ECPGt_struct)
|
{
|
||||||
{
|
/* Array of structs. */
|
||||||
/* Array of structs. */
|
ECPGdump_a_struct(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, NULL, prefix, ind_prefix);
|
||||||
ECPGdump_a_struct(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, 0, prefix, ind_prefix);
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
yyerror("Internal error: unknown datatype, pleqase inform pgsql-bugs@postgresql.org");
|
||||||
abort();
|
}
|
||||||
}
|
break;
|
||||||
}
|
case ECPGt_struct:
|
||||||
else if (typ->typ == ECPGt_struct)
|
ECPGdump_a_struct(o, name, ind_name, 1, typ, ind_typ, NULL, prefix, ind_prefix);
|
||||||
{
|
break;
|
||||||
ECPGdump_a_struct(o, name, ind_name, 0, typ, ind_typ, 0, prefix, ind_prefix);
|
default:
|
||||||
}
|
ECPGdump_a_simple(o, name, typ->typ, typ->size, -1, NULL, prefix);
|
||||||
else
|
ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix);
|
||||||
{
|
break;
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,86 +226,48 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in
|
|||||||
void
|
void
|
||||||
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
|
||||||
long varcharsize,
|
long varcharsize,
|
||||||
long arrsiz,
|
long arrsize,
|
||||||
const char *siz,
|
const char *siz,
|
||||||
const char *prefix
|
const char *prefix
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
switch (typ)
|
if (typ == ECPGt_NO_INDICATOR)
|
||||||
{
|
fprintf(o, "\n\tECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ");
|
||||||
case ECPGt_char:
|
else
|
||||||
if (varcharsize == 0) /* pointer */
|
{
|
||||||
fprintf(o, "\n\tECPGt_char,(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
|
char *variable = (char *)mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4);
|
||||||
siz == NULL ? "sizeof(char)" : siz);
|
char *offset = (char *)mm_alloc(strlen(name) + strlen("sizeof(struct varchar_)") + 1);
|
||||||
else
|
|
||||||
fprintf(o, "\n\tECPGt_char,&(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
|
if (varcharsize == 0 || arrsize >= 0)
|
||||||
siz == NULL ? "sizeof(char)" : siz);
|
sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
|
||||||
break;
|
else
|
||||||
case ECPGt_unsigned_char:
|
sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
|
||||||
if (varcharsize == 0) /* pointer */
|
|
||||||
fprintf(o, "\n\tECPGt_unsigned_char,(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
|
switch (typ)
|
||||||
siz == NULL ? "sizeof(char)" : siz);
|
{
|
||||||
else
|
case ECPGt_varchar:
|
||||||
fprintf(o, "\n\tECPGt_unsigned_char,&(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
|
sprintf(offset, "sizeof(struct varchar_%s)", name);
|
||||||
siz == NULL ? "sizeof(unsigned char)" : siz);
|
break;
|
||||||
break;
|
case ECPGt_char:
|
||||||
case ECPGt_short:
|
case ECPGt_unsigned_char:
|
||||||
fprintf(o, "\n\tECPGt_short,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
|
sprintf(offset, "%ld*sizeof(char)", varcharsize);
|
||||||
siz == NULL ? "sizeof(short)" : siz);
|
break;
|
||||||
break;
|
default:
|
||||||
case ECPGt_unsigned_short:
|
sprintf(offset, "sizeof(%s)", ECPGtype_name(typ));
|
||||||
fprintf(o,
|
break;
|
||||||
"\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 (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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
/* 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
|
|
||||||
ECPGfree_struct_member(struct ECPGstruct_member * rm)
|
ECPGfree_struct_member(struct ECPGstruct_member * rm)
|
||||||
{
|
{
|
||||||
while (rm)
|
while (rm)
|
||||||
{
|
{
|
||||||
struct ECPGstruct_member *p = rm;
|
struct ECPGstruct_member *p = rm;
|
||||||
|
|
||||||
rm = rm->next;
|
rm = rm->next;
|
||||||
free(p->name);
|
free(p->name);
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ECPGfree_type(struct ECPGtype * typ)
|
ECPGfree_type(struct ECPGtype * typ)
|
||||||
@ -332,16 +335,18 @@ ECPGfree_type(struct ECPGtype * typ)
|
|||||||
else if (typ->u.element->typ == ECPGt_array)
|
else if (typ->u.element->typ == ECPGt_array)
|
||||||
abort(); /* Array of array, */
|
abort(); /* Array of array, */
|
||||||
else if (typ->u.element->typ == ECPGt_struct)
|
else if (typ->u.element->typ == ECPGt_struct)
|
||||||
|
{
|
||||||
/* Array of structs. */
|
/* Array of structs. */
|
||||||
|
ECPGfree_struct_member(typ->u.members);
|
||||||
free(typ->u.members);
|
free(typ->u.members);
|
||||||
/* ECPGfree_struct_member(typ->u.members);*/
|
}
|
||||||
else
|
else
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
else if (typ->typ == ECPGt_struct)
|
else if (typ->typ == ECPGt_struct)
|
||||||
{
|
{
|
||||||
|
ECPGfree_struct_member(typ->u.members);
|
||||||
free(typ->u.members);
|
free(typ->u.members);
|
||||||
/* ECPGfree_struct_member(typ->u.members);*/
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -77,6 +77,7 @@ struct when
|
|||||||
|
|
||||||
struct index
|
struct index
|
||||||
{
|
{
|
||||||
int ival;
|
int index1;
|
||||||
char *str;
|
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
|
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
|
test2.c: test2.pgc
|
||||||
../preproc/ecpg test2.pgc
|
../preproc/ecpg $?
|
||||||
|
|
||||||
perftest: perftest.c
|
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
|
||||||
perftest.c: perftest.pgc
|
../preproc/ecpg $?
|
||||||
../preproc/ecpg perftest.pgc
|
|
||||||
|
|
||||||
clean:
|
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 include sqlca;
|
||||||
|
|
||||||
exec sql whenever not found do set_not_found();
|
exec sql whenever not found do break;
|
||||||
exec sql whenever sqlerror sqlprint;
|
exec sql whenever sqlerror sqlprint;
|
||||||
|
@ -121,5 +121,7 @@ exec sql end declare section;
|
|||||||
|
|
||||||
exec sql commit;
|
exec sql commit;
|
||||||
|
|
||||||
|
exec sql disconnect;
|
||||||
|
|
||||||
return (0);
|
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;
|
exec sql include header_test;
|
||||||
|
|
||||||
static int not_found = 0;
|
|
||||||
static void
|
|
||||||
set_not_found(void)
|
|
||||||
{
|
|
||||||
not_found = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main ()
|
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, 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 ('Carsten', 19910103, 7);
|
||||||
exec sql insert into meskes(name, born, age) values ('Marc', 19930907, 4);
|
exec sql insert into meskes(name, born, age) values ('Marc', 19930907, 4);
|
||||||
|
exec sql insert into meskes(name, born, age) values ('Chris', 19970923, 0);
|
||||||
sprintf(command, "insert into meskes(name, born, age) values ('Chris', 19970923, 0)");
|
|
||||||
strcpy(msg, "execute");
|
|
||||||
exec sql execute immediate :command;
|
|
||||||
|
|
||||||
strcpy(msg, "commit");
|
strcpy(msg, "commit");
|
||||||
exec sql commit;
|
exec sql commit;
|
||||||
@ -58,11 +48,10 @@ exec sql end declare section;
|
|||||||
strcpy(msg, "open");
|
strcpy(msg, "open");
|
||||||
exec sql open cur;
|
exec sql open cur;
|
||||||
|
|
||||||
while (not_found == 0) {
|
while (1) {
|
||||||
strcpy(msg, "fetch");
|
strcpy(msg, "fetch");
|
||||||
exec sql fetch cur into :personal:ind_personal, :married:ind_married;
|
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");
|
strcpy(msg, "close");
|
||||||
@ -74,6 +63,9 @@ exec sql end declare section;
|
|||||||
strcpy(msg, "commit");
|
strcpy(msg, "commit");
|
||||||
exec sql commit;
|
exec sql commit;
|
||||||
|
|
||||||
|
strcpy(msg, "disconnect");
|
||||||
|
|
||||||
|
exec sql disconnect;
|
||||||
if (dbgs != NULL)
|
if (dbgs != NULL)
|
||||||
fclose(dbgs);
|
fclose(dbgs);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user