1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-06 07:49:08 +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:
Marc G. Fournier
1998-05-06 13:03:47 +00:00
parent f9322c66d3
commit 6bccf64d7b
25 changed files with 1782 additions and 1634 deletions

View File

@@ -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)
{