*** empty log message ***

This commit is contained in:
Michael Meskes 2000-02-23 19:26:05 +00:00
parent c969e2662f
commit 9f74608f47
16 changed files with 946 additions and 1021 deletions

View File

@ -824,5 +824,9 @@ Tue Feb 22 13:48:18 CET 2000
- Synced preproc.y with gram.y.
- Much more clean ups.
Wed Feb 23 17:08:28 CET 2000
- Even more clean ups.
- Set library version to 3.1.0.
- Set ecpg version to 2.7.0.

View File

@ -34,6 +34,7 @@
#define ECPG_INVALID_DESCRIPTOR_INDEX -241
#define ECPG_UNKNOWN_DESCRIPTOR_ITEM -242
#define ECPG_VAR_NOT_NUMERIC -243
#define ECPG_VAR_NOT_CHAR -244
/* finally the backend error messages, they start at 400 */
#define ECPG_PGSQL -400

View File

@ -16,35 +16,28 @@ extern "C"
bool ECPGdisconnect(int, const char *);
bool ECPGprepare(int, char *, char *);
bool ECPGdeallocate(int, char *);
bool ECPGdeallocate_all(int);
char *ECPGprepared_statement(char *);
void ECPGlog(const char *format,...);
/* print an error message */
void sqlprint(void);
#ifdef LIBPQ_FE_H
bool ECPGsetdb(PGconn *);
#endif
/* Here are some methods used by the lib. */
/* Returns a pointer to a string containing a simple type name. */
const char *ECPGtype_name(enum ECPGttype);
bool get_data(PGresult *, int, int, int, enum ECPGttype type,
enum ECPGttype, void *, void *, long, long);
char *ecpg_alloc(long, int);
char *ecpg_strdup(const char *, int);
/* A generic varchar type. */
struct ECPGgeneric_varchar
{
int len;
char arr[1];
};
/* print an error message */
void sqlprint(void);
struct cursor
{
const char *name;
char *command;
struct cursor *next;
};
/* and some vars */
extern struct auto_mem *auto_allocs;
/* define this for simplicity as well as compatibility */
@ -52,9 +45,6 @@ extern "C"
/* dynamic SQL */
unsigned int ECPGDynamicType(Oid type);
unsigned int ECPGDynamicType_DDT(Oid type);
PGresult * ECPGresultByDescriptor(int line,const char *name);
bool ECPGdo_descriptor(int line,const char *connection,
const char *descriptor,const char *query);
bool ECPGdeallocate_desc(int line,const char *name);

View File

@ -6,7 +6,7 @@
# Copyright (c) 1994, Regents of the University of California
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.59 2000/02/22 19:57:05 meskes Exp $
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.60 2000/02/23 19:25:42 meskes Exp $
#
#-------------------------------------------------------------------------
@ -23,7 +23,7 @@ ifdef KRBVERS
CFLAGS+= $(KRBFLAGS)
endif
OBJS= ecpglib.o typename.o descriptor.o
OBJS= ecpglib.o typename.o descriptor.o data.o error.o prepare.o memory.o
SHLIB_LINK= -L../../libpq -lpq

View File

@ -0,0 +1,252 @@
#include <stdlib.h>
#include <libpq/pqcomm.h>
#include <ecpgtype.h>
#include <ecpglib.h>
#include <sqlca.h>
bool
get_data(PGresult *results, int act_tuple, int act_field, int lineno,
enum ECPGttype type, enum ECPGttype ind_type,
void *var, void *ind, long varcharsize, long offset)
{
char *pval = (char *)PQgetvalue(results, act_tuple, act_field);
ECPGlog("get_data line %d: RESULT: %s\n", lineno, pval ? pval : "");
/* 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)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
break;
case ECPGt_int:
case ECPGt_unsigned_int:
((int *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
break;
case ECPGt_long:
case ECPGt_unsigned_long:
((long *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
break;
case ECPGt_NO_INDICATOR:
if (PQgetisnull(results, act_tuple, act_field))
{
ECPGraise(lineno, ECPG_MISSING_INDICATOR, NULL);
return (false);
}
break;
default:
ECPGraise(lineno, ECPG_UNSUPPORTED, ECPGtype_name(ind_type));
return (false);
break;
}
switch (type)
{
long res;
unsigned long ures;
double dres;
char *scan_length;
case ECPGt_short:
case ECPGt_int:
case ECPGt_long:
if (pval)
{
res = strtol(pval, &scan_length, 10);
if (*scan_length != '\0') /* Garbage left */
{
ECPGraise(lineno, ECPG_INT_FORMAT, pval);
return (false);
res = 0L;
}
}
else
res = 0L;
switch (type)
{
case ECPGt_short:
((short *) var)[act_tuple] = (short) res;
break;
case ECPGt_int:
((int *) var)[act_tuple] = (int) res;
break;
case ECPGt_long:
((long *) var)[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 */
{
ECPGraise(lineno, ECPG_UINT_FORMAT, pval);
return (false);
ures = 0L;
}
}
else
ures = 0L;
switch (type)
{
case ECPGt_unsigned_short:
((unsigned short *) var)[act_tuple] = (unsigned short) ures;
break;
case ECPGt_unsigned_int:
((unsigned int *) var)[act_tuple] = (unsigned int) ures;
break;
case ECPGt_unsigned_long:
((unsigned long *) var)[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 */
{
ECPGraise(lineno, ECPG_FLOAT_FORMAT, pval);
return (false);
dres = 0.0;
}
}
else
dres = 0.0;
switch (type)
{
case ECPGt_float:
((float *) var)[act_tuple] = dres;
break;
case ECPGt_double:
((double *) var)[act_tuple] = dres;
break;
default:
/* Cannot happen */
break;
}
break;
case ECPGt_bool:
if (pval)
{
if (pval[0] == 'f' && pval[1] == '\0')
{
((char *) var)[act_tuple] = false;
break;
}
else if (pval[0] == 't' && pval[1] == '\0')
{
((char *) var)[act_tuple] = true;
break;
}
else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field))
{
// NULL is valid
break;
}
}
ECPGraise(lineno, ECPG_CONVERT_BOOL, pval);
return (false);
break;
case ECPGt_char:
case ECPGt_unsigned_char:
{
strncpy((char *) ((long) var + offset * act_tuple), pval, varcharsize);
if (varcharsize && varcharsize < strlen(pval))
{
/* truncation */
switch (ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
((short *) ind)[act_tuple] = varcharsize;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
((int *) ind)[act_tuple] = varcharsize;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
((long *) ind)[act_tuple] = varcharsize;
break;
default:
break;
}
sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
}
}
break;
case ECPGt_varchar:
{
struct ECPGgeneric_varchar *variable =
(struct ECPGgeneric_varchar *) ((long) var + offset * act_tuple);
if (varcharsize == 0)
strncpy(variable->arr, pval, strlen(pval));
else
strncpy(variable->arr, pval, varcharsize);
variable->len = strlen(pval);
if (varcharsize > 0 && variable->len > varcharsize)
{
/* truncation */
switch (ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
((short *) ind)[act_tuple] = varcharsize;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
((int *) ind)[act_tuple] = varcharsize;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
((long *) ind)[act_tuple] = varcharsize;
break;
default:
break;
}
sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
variable->len = varcharsize;
}
}
break;
default:
ECPGraise(lineno, ECPG_UNSUPPORTED, ECPGtype_name(type));
return (false);
break;
}
return (true);
}

View File

@ -1,6 +1,68 @@
#include <ecpgtype.h>
#include <ecpglib.h>
#include <sql3types.h>
struct descriptor
{
char *name;
PGresult *result;
struct descriptor *next;
} *all_descriptors = NULL;
static PGresult
*ECPGresultByDescriptor(int line,const char *name)
{
struct descriptor *i;
for (i = all_descriptors; i != NULL; i = i->next)
{
if (!strcmp(name, i->name)) return i->result;
}
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, name);
return NULL;
}
static unsigned int
ECPGDynamicType(Oid type)
{
switch(type)
{
case 16: return SQL3_BOOLEAN; /* bool */
case 21: return SQL3_SMALLINT; /* int2 */
case 23: return SQL3_INTEGER; /* int4 */
case 25: return SQL3_CHARACTER; /* text */
case 700: return SQL3_REAL; /* float4 */
case 701: return SQL3_DOUBLE_PRECISION; /* float8 */
case 1042: return SQL3_CHARACTER; /* bpchar */
case 1043: return SQL3_CHARACTER_VARYING; /* varchar */
case 1082: return SQL3_DATE_TIME_TIMESTAMP; /* date */
case 1083: return SQL3_DATE_TIME_TIMESTAMP; /* time */
case 1184: return SQL3_DATE_TIME_TIMESTAMP; /* datetime */
case 1296: return SQL3_DATE_TIME_TIMESTAMP; /* timestamp */
case 1700: return SQL3_NUMERIC; /* numeric */
default: return -type;
}
}
#if 0
static unsigned int
ECPGDynamicType_DDT(Oid type)
{
switch(type)
{
case 1082: return SQL3_DDT_DATE; /* date */
case 1083: return SQL3_DDT_TIME; /* time */
case 1184: return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE; /* datetime */
case 1296: return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE; /* timestamp */
default:
return SQL3_DDT_ILLEGAL;
}
}
#endif
bool
ECPGget_desc_header(int lineno, char * desc_name, int *count)
{
@ -51,6 +113,38 @@ get_int_item(int lineno, void *var, enum ECPGdtype vartype, int value)
return(true);
}
static bool
get_char_item(int lineno, void *var, enum ECPGdtype vartype, char *value, int varcharsize)
{
switch (vartype)
{
case ECPGt_char:
case ECPGt_unsigned_char:
strncpy((char *) var, value, varcharsize);
break;
case ECPGt_varchar:
{
struct ECPGgeneric_varchar *variable =
(struct ECPGgeneric_varchar *) var;
if (varcharsize == 0)
strncpy(variable->arr, value, strlen(value));
else
strncpy(variable->arr, value, varcharsize);
variable->len = strlen(value);
if (varcharsize > 0 && variable->len > varcharsize)
variable->len = varcharsize;
}
break;
default:
ECPGraise(lineno, ECPG_VAR_NOT_CHAR, NULL);
return (false);
}
return(true);
}
bool
ECPGget_desc(int lineno, char *desc_name, int index, ...)
{
@ -100,53 +194,78 @@ ECPGget_desc(int lineno, char *desc_name, int index, ...)
case (ECPGd_indicator):
if (!get_int_item(lineno, var, vartype, -PQgetisnull(ECPGresult, 0, index)))
return (false);
ECPGlog("ECPGget_desc: INDICATOR = %d\n", -PQgetisnull(ECPGresult, 0, index));
break;
case ECPGd_name:
strncpy((char *)var, PQfname(ECPGresult, index), varcharsize);
if (!get_char_item(lineno, var, vartype, PQfname(ECPGresult, index), varcharsize))
return(false);
ECPGlog("ECPGget_desc: NAME = %s\n", PQfname(ECPGresult, index));
break;
case ECPGd_nullable:
if (!get_int_item(lineno, var, vartype, 1))
return (false);
break;
break;
case ECPGd_key_member:
if (!get_int_item(lineno, var, vartype, 0))
return (false);
break;
case ECPGd_scale:
if (!get_int_item(lineno, var, vartype, (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff))
return (false);
ECPGlog("ECPGget_desc: SCALE = %d\n", (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff);
break;
case ECPGd_precision:
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) >> 16))
return (false);
ECPGlog("ECPGget_desc: PRECISION = %d\n", PQfmod(ECPGresult, index) >> 16);
break;
case ECPGd_ret_length:
case ECPGd_ret_octet:
if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, 0, index)))
return (false);
ECPGlog("ECPGget_desc: RETURNED = %d\n", PQgetlength(ECPGresult, 0, index));
break;
case ECPGd_octet:
if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
return (false);
ECPGlog("ECPGget_desc: OCTET_LENGTH = %d\n", PQfsize(ECPGresult, index));
break;
case ECPGd_length:
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) - VARHDRSZ))
return (false);
ECPGlog("ECPGget_desc: LENGTH = %d\n", PQfmod(ECPGresult, index) - VARHDRSZ);
break;
case ECPGd_type:
if (!get_int_item(lineno, var, vartype, ECPGDynamicType(PQftype(ECPGresult, index))))
return (false);
ECPGlog("ECPGget_desc: TYPE = %d\n", ECPGDynamicType(PQftype(ECPGresult, index)));
break;
case ECPGd_data:
if (!get_data(ECPGresult, 0, index, lineno, vartype, ECPGt_NO_INDICATOR, var, NULL, varcharsize, offset))
return (false);
break;
default:
snprintf(type_str, sizeof(type_str), "%d", type);
ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, type_str);
@ -164,3 +283,37 @@ ECPGget_desc(int lineno, char *desc_name, int index, ...)
return (true);
}
bool
ECPGdeallocate_desc(int line, const char *name)
{
struct descriptor *i;
struct descriptor **lastptr = &all_descriptors;
for (i = all_descriptors; i; lastptr = &i->next, i = i->next)
{
if (!strcmp(name, i->name))
{
*lastptr = i->next;
free(i->name);
PQclear(i->result);
free(i);
return true;
}
}
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, name);
return false;
}
bool
ECPGallocate_desc(int line,const char *name)
{
struct descriptor *new = (struct descriptor *)malloc(sizeof(struct descriptor));
new->next = all_descriptors;
new->name = malloc(strlen(name)+1);
new->result = PQmakeEmptyPGresult(NULL, 0);
strcpy(new->name, name);
all_descriptors = new;
return true;
}

View File

@ -1,333 +0,0 @@
/* dynamic SQL support routines
*
* Copyright (c) 2000, Christof Petig <christof.petig@wtal.de>
*
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/dynamic.c,v 1.5 2000/02/22 19:57:05 meskes Exp $
*/
/* I borrowed the include files from ecpglib.c, maybe we don't need all of them */
#include <sql3types.h>
static struct descriptor
{
char *name;
PGresult *result;
struct descriptor *next;
} *all_descriptors=NULL;
PGconn *ECPG_internal_get_connection(char *name);
unsigned int ECPGDynamicType(Oid type)
{
switch(type)
{ case 16: return SQL3_BOOLEAN; /* bool */
case 21: return SQL3_SMALLINT; /* int2 */
case 23: return SQL3_INTEGER; /* int4 */
case 25: return SQL3_CHARACTER; /* text */
case 700: return SQL3_REAL; /* float4 */
case 701: return SQL3_DOUBLE_PRECISION; /* float8 */
case 1042: return SQL3_CHARACTER; /* bpchar */
case 1043: return SQL3_CHARACTER_VARYING; /* varchar */
case 1082: return SQL3_DATE_TIME_TIMESTAMP; /* date */
case 1083: return SQL3_DATE_TIME_TIMESTAMP; /* time */
case 1184: return SQL3_DATE_TIME_TIMESTAMP; /* datetime */
case 1296: return SQL3_DATE_TIME_TIMESTAMP; /* timestamp */
case 1700: return SQL3_NUMERIC; /* numeric */
default:
return -type;
}
}
unsigned int ECPGDynamicType_DDT(Oid type)
{ switch(type)
{
case 1082: return SQL3_DDT_DATE; /* date */
case 1083: return SQL3_DDT_TIME; /* time */
case 1184: return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE; /* datetime */
case 1296: return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE; /* timestamp */
default:
return SQL3_DDT_ILLEGAL;
}
}
// like ECPGexecute
static bool execute_descriptor(int lineno,const char *query
,struct connection *con,PGresult **resultptr)
{
bool status = false;
PGresult *results;
PGnotify *notify;
/* Now the request is built. */
if (con->committed && !con->autocommit)
{
if ((results = PQexec(con->connection, "begin transaction")) == NULL)
{
register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
return false;
}
PQclear(results);
con->committed = false;
}
ECPGlog("execute_descriptor line %d: QUERY: %s on connection %s\n", lineno, query, con->name);
results = PQexec(con->connection, query);
if (results == NULL)
{
ECPGlog("ECPGexecute line %d: error: %s", lineno,
PQerrorMessage(con->connection));
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
PQerrorMessage(con->connection), lineno);
}
else
{ *resultptr=results;
switch (PQresultStatus(results))
{ int ntuples;
case PGRES_TUPLES_OK:
status = true;
sqlca.sqlerrd[2] = ntuples = PQntuples(results);
if (ntuples < 1)
{
ECPGlog("execute_descriptor line %d: Incorrect number of matches: %d\n",
lineno, ntuples);
register_error(ECPG_NOT_FOUND, "No data found line %d.", lineno);
status = false;
break;
}
break;
#if 1 /* strictly these are not needed (yet) */
case PGRES_EMPTY_QUERY:
/* do nothing */
register_error(ECPG_EMPTY, "Empty query line %d.", lineno);
break;
case PGRES_COMMAND_OK:
status = true;
sqlca.sqlerrd[1] = atol(PQoidStatus(results));
sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
ECPGlog("ECPGexecute line %d Ok: %s\n", lineno, PQcmdStatus(results));
break;
case PGRES_COPY_OUT:
ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno);
PQendcopy(con->connection);
break;
case PGRES_COPY_IN:
ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.\n", lineno);
PQendcopy(con->connection);
break;
#else
case PGRES_EMPTY_QUERY:
case PGRES_COMMAND_OK:
case PGRES_COPY_OUT:
case PGRES_COPY_IN:
break;
#endif
case PGRES_NONFATAL_ERROR:
case PGRES_FATAL_ERROR:
case PGRES_BAD_RESPONSE:
ECPGlog("ECPGexecute line %d: Error: %s",
lineno, PQerrorMessage(con->connection));
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
PQerrorMessage(con->connection), lineno);
status = false;
break;
default:
ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
lineno);
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
PQerrorMessage(con->connection), lineno);
status = false;
break;
}
}
/* check for asynchronous returns */
notify = PQnotifies(con->connection);
if (notify)
{
ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
lineno, notify->relname, notify->be_pid);
free(notify);
}
return status;
}
/* like ECPGdo */
static bool do_descriptor2(int lineno,const char *connection_name,
PGresult **resultptr, const char *query)
{
struct connection *con = get_connection(connection_name);
bool status=true;
char *locale = setlocale(LC_NUMERIC, NULL);
/* Make sure we do NOT honor the locale for numeric input/output */
/* since the database wants teh standard decimal point */
setlocale(LC_NUMERIC, "C");
if (!ecpg_init(con, connection_name, lineno))
{ setlocale(LC_NUMERIC, locale);
return(false);
}
/* are we connected? */
if (con == NULL || con->connection == NULL)
{
ECPGlog("ECPGdo: not connected to %s\n", con->name);
register_error(ECPG_NOT_CONN, "Not connected in line %d.", lineno);
setlocale(LC_NUMERIC, locale);
return false;
}
status = execute_descriptor(lineno,query,con,resultptr);
/* and reset locale value so our application is not affected */
setlocale(LC_NUMERIC, locale);
return (status);
}
bool ECPGdo_descriptor(int line,const char *connection,
const char *descriptor,const char *query)
{
struct descriptor *i;
for (i=all_descriptors;i!=NULL;i=i->next)
{ if (!strcmp(descriptor,i->name))
{
bool status;
/* free previous result */
if (i->result) PQclear(i->result);
i->result=NULL;
status=do_descriptor2(line,connection,&i->result,query);
if (!i->result) PQmakeEmptyPGresult(NULL, 0);
return (status);
}
}
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, descriptor);
return false;
}
PGresult *ECPGresultByDescriptor(int line,const char *name)
{
struct descriptor *i;
for (i = all_descriptors; i != NULL; i = i->next)
{
if (!strcmp(name, i->name)) return i->result;
}
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, name);
return NULL;
}
bool ECPGdeallocate_desc(int line,const char *name)
{
struct descriptor *i;
struct descriptor **lastptr=&all_descriptors;
for (i=all_descriptors;i;lastptr=&i->next,i=i->next)
{ if (!strcmp(name,i->name))
{ *lastptr=i->next;
free(i->name);
PQclear(i->result);
free(i);
return true;
}
}
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, name);
return false;
}
bool ECPGallocate_desc(int line,const char *name)
{
struct descriptor *new=(struct descriptor *)malloc(sizeof(struct descriptor));
new->next=all_descriptors;
new->name=malloc(strlen(name)+1);
new->result=PQmakeEmptyPGresult(NULL, 0);
strcpy(new->name,name);
all_descriptors=new;
return true;
}
void
ECPGraise(int line, int code, const char *str)
{
struct auto_mem *am;
sqlca.sqlcode = code;
switch (code)
{
case ECPG_NOT_FOUND:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"No data found line %d.", line);
break;
case ECPG_OUT_OF_MEMORY:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Out of memory in line %d.", line);
break;
case ECPG_UNSUPPORTED:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Unsupported type %s in line %d.", str, line);
break;
case ECPG_TOO_MANY_ARGUMENTS:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Too many arguments in line %d.", line);
break;
case ECPG_TOO_FEW_ARGUMENTS:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Too few arguments in line %d.", line);
break;
case ECPG_MISSING_INDICATOR:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"NULL value without indicator, line %d.", line);
break;
case ECPG_UNKNOWN_DESCRIPTOR:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"descriptor %s not found, line %d.", str, line);
break;
case ECPG_INVALID_DESCRIPTOR_INDEX:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"descriptor index out of range, line %d.", line);
break;
case ECPG_UNKNOWN_DESCRIPTOR_ITEM:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"unknown descriptor item %s, line %d.", str, line);
break;
case ECPG_VAR_NOT_NUMERIC:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"variable is not a numeric type, line %d.", line);
break;
default:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"SQL error #%d, line %d.",code, line);
break;
}
/* free all memory we have allocated for the user */
for (am = auto_allocs; am;)
{
struct auto_mem *act = am;
am = am->next;
free(act->pointer);
free(act);
}
auto_allocs = NULL;
}

View File

@ -75,56 +75,11 @@ struct variable
struct variable *next;
};
struct statement
{
int lineno;
char *command;
struct connection *connection;
struct variable *inlist;
struct variable *outlist;
};
static struct prepared_statement
{
char *name;
struct statement *stmt;
struct prepared_statement *next;
} *prep_stmts = NULL;
static struct auto_mem
{
void *pointer;
struct auto_mem *next;
} *auto_allocs = NULL;
struct auto_mem *auto_allocs;
static int simple_debug = 0;
static FILE *debugstream = NULL;
static void
register_error(long code, char *fmt,...)
{
va_list args;
struct auto_mem *am;
sqlca.sqlcode = code;
va_start(args, fmt);
vsnprintf(sqlca.sqlerrm.sqlerrmc, SQLERRMC_LEN, fmt, args);
va_end(args);
sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc);
/* free all memory we have allocated for the user */
for (am = auto_allocs; am;)
{
struct auto_mem *act = am;
am = am->next;
free(act->pointer);
free(act);
}
auto_allocs = NULL;
}
static struct connection *
get_connection(const char *connection_name)
{
@ -146,10 +101,12 @@ ecpg_init(const struct connection *con, const char * connection_name, const int
memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca));
if (con == NULL)
{
register_error(ECPG_NO_CONN, "No such connection %s in line %d.", connection_name ? connection_name : "NULL", lineno);
ECPGraise(lineno, ECPG_NO_CONN, connection_name ? connection_name : "NULL");
return (false);
}
auto_allocs = NULL;
return (true);
}
@ -182,37 +139,6 @@ ecpg_finish(struct connection * act)
ECPGlog("ecpg_finish: called an extra time.\n");
}
static char *
ecpg_alloc(long size, int lineno)
{
char *new = (char *) calloc(1L, size);
if (!new)
{
ECPGlog("out of memory\n");
ECPGraise(lineno, ECPG_OUT_OF_MEMORY, NULL);
return NULL;
}
memset(new, '\0', size);
return (new);
}
static char *
ecpg_strdup(const char *string, int lineno)
{
char *new = strdup(string);
if (!new)
{
ECPGlog("out of memory\n");
ECPGraise(lineno, ECPG_OUT_OF_MEMORY, NULL);
return NULL;
}
return (new);
}
static void
add_mem(void *ptr, int lineno)
{
@ -313,7 +239,7 @@ create_statement(int lineno, struct connection * connection, struct statement **
if (var->pointer == NULL)
{
ECPGlog("create_statement: invalid statement name\n");
register_error(ECPG_INVALID_STMT, "Invalid statement name in line %d.", lineno);
ECPGraise(lineno, ECPG_INVALID_STMT, NULL);
free(var);
return false;
}
@ -704,7 +630,7 @@ ECPGexecute(struct statement * stmt)
{
if ((results = PQexec(stmt->connection->connection, "begin transaction")) == NULL)
{
register_error(ECPG_TRANS, "Error in transaction processing line %d.", stmt->lineno);
ECPGraise(stmt->lineno, ECPG_TRANS, NULL);
return false;
}
PQclear(results);
@ -719,8 +645,7 @@ ECPGexecute(struct statement * stmt)
{
ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno,
PQerrorMessage(stmt->connection->connection));
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
PQerrorMessage(stmt->connection->connection), stmt->lineno);
ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection));
}
else
{
@ -749,8 +674,6 @@ ECPGexecute(struct statement * stmt)
for (act_field = 0; act_field < nfields && status; act_field++)
{
char *pval;
char *scan_length;
char *array_query;
if (var == NULL)
@ -820,247 +743,10 @@ ECPGexecute(struct statement * stmt)
for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
{
pval = (char *)PQgetvalue(results, act_tuple, act_field);
ECPGlog("ECPGexecute line %d: RESULT: %s\n", stmt->lineno, pval ? pval : "");
/* 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 (var->ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
((short *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
break;
case ECPGt_int:
case ECPGt_unsigned_int:
((int *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
break;
case ECPGt_long:
case ECPGt_unsigned_long:
((long *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
break;
case ECPGt_NO_INDICATOR:
if (PQgetisnull(results, act_tuple, act_field))
{
register_error(ECPG_MISSING_INDICATOR, "NULL value without indicator variable on line %d.", stmt->lineno);
status = false;
}
break;
default:
ECPGraise(stmt->lineno, ECPG_UNSUPPORTED, ECPGtype_name(var->ind_type));
status = false;
break;
}
switch (var->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, stmt->lineno);
status = false;
res = 0L;
}
}
else
res = 0L;
switch (var->type)
{
case ECPGt_short:
((short *) var->value)[act_tuple] = (short) res;
break;
case ECPGt_int:
((int *) var->value)[act_tuple] = (int) res;
break;
case ECPGt_long:
((long *) var->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, stmt->lineno);
status = false;
ures = 0L;
}
}
else
ures = 0L;
switch (var->type)
{
case ECPGt_unsigned_short:
((unsigned short *) var->value)[act_tuple] = (unsigned short) ures;
break;
case ECPGt_unsigned_int:
((unsigned int *) var->value)[act_tuple] = (unsigned int) ures;
break;
case ECPGt_unsigned_long:
((unsigned long *) var->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, stmt->lineno);
status = false;
dres = 0.0;
}
}
else
dres = 0.0;
switch (var->type)
{
case ECPGt_float:
((float *) var->value)[act_tuple] = dres;
break;
case ECPGt_double:
((double *) var->value)[act_tuple] = dres;
break;
default:
/* Cannot happen */
break;
}
break;
case ECPGt_bool:
if (pval)
{
if (pval[0] == 'f' && pval[1] == '\0')
{
((char *) var->value)[act_tuple] = false;
break;
}
else if (pval[0] == 't' && pval[1] == '\0')
{
((char *) var->value)[act_tuple] = true;
break;
}
else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field))
{
// NULL is valid
break;
}
}
register_error(ECPG_CONVERT_BOOL, "Unable to convert %s to bool on line %d.",
(pval ? pval : "NULL"),
stmt->lineno);
status = false;
break;
case ECPGt_char:
case ECPGt_unsigned_char:
{
strncpy((char *) ((long) var->value + var->offset * act_tuple), pval, var->varcharsize);
if (var->varcharsize && var->varcharsize < strlen(pval))
{
/* truncation */
switch (var->ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
((short *) var->ind_value)[act_tuple] = var->varcharsize;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
((int *) var->ind_value)[act_tuple] = var->varcharsize;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
((long *) var->ind_value)[act_tuple] = var->varcharsize;
break;
default:
break;
}
sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
}
}
break;
case ECPGt_varchar:
{
struct ECPGgeneric_varchar *variable =
(struct ECPGgeneric_varchar *) ((long) var->value + var->offset * act_tuple);
if (var->varcharsize == 0)
strncpy(variable->arr, pval, strlen(pval));
else
strncpy(variable->arr, pval, var->varcharsize);
variable->len = strlen(pval);
if (var->varcharsize > 0 && variable->len > var->varcharsize)
{
/* truncation */
switch (var->ind_type)
{
case ECPGt_short:
case ECPGt_unsigned_short:
((short *) var->ind_value)[act_tuple] = var->varcharsize;
break;
case ECPGt_int:
case ECPGt_unsigned_int:
((int *) var->ind_value)[act_tuple] = var->varcharsize;
break;
case ECPGt_long:
case ECPGt_unsigned_long:
((long *) var->ind_value)[act_tuple] = var->varcharsize;
break;
default:
break;
}
sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
variable->len = var->varcharsize;
}
}
break;
default:
ECPGraise(stmt->lineno, ECPG_UNSUPPORTED, ECPGtype_name(var->type));
status = false;
break;
}
if (!get_data(results, act_tuple, act_field, stmt->lineno,
var->type, var->ind_type, var->value,
var->ind_value, var->varcharsize, var->offset))
status = false;
}
var = var->next;
}
@ -1074,7 +760,7 @@ ECPGexecute(struct statement * stmt)
break;
case PGRES_EMPTY_QUERY:
/* do nothing */
register_error(ECPG_EMPTY, "Empty query line %d.", stmt->lineno);
ECPGraise(stmt->lineno, ECPG_EMPTY, NULL);
break;
case PGRES_COMMAND_OK:
status = true;
@ -1087,8 +773,7 @@ ECPGexecute(struct statement * stmt)
case PGRES_BAD_RESPONSE:
ECPGlog("ECPGexecute line %d: Error: %s",
stmt->lineno, PQerrorMessage(stmt->connection->connection));
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
PQerrorMessage(stmt->connection->connection), stmt->lineno);
ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection));
status = false;
break;
case PGRES_COPY_OUT:
@ -1102,8 +787,7 @@ ECPGexecute(struct statement * stmt)
default:
ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
stmt->lineno);
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
PQerrorMessage(stmt->connection->connection), stmt->lineno);
ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection));
status = false;
break;
}
@ -1154,7 +838,7 @@ ECPGdo(int lineno, const char *connection_name, char *query, ...)
{
free_statement(stmt);
ECPGlog("ECPGdo: not connected to %s\n", con->name);
register_error(ECPG_NOT_CONN, "Not connected in line %d.", lineno);
ECPGraise(lineno, ECPG_NOT_CONN, NULL);
setlocale(LC_NUMERIC, locale);
return false;
}
@ -1179,7 +863,7 @@ ECPGstatus(int lineno, const char *connection_name)
if (con->connection == NULL)
{
ECPGlog("ECPGdo: not connected to %s\n", con->name);
register_error(ECPG_NOT_CONN, "Not connected in line %d", lineno);
ECPGraise(lineno, ECPG_NOT_CONN, NULL);
return false;
}
@ -1202,7 +886,7 @@ ECPGtrans(int lineno, const char *connection_name, const char *transaction)
{
if ((res = PQexec(con->connection, transaction)) == NULL)
{
register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
ECPGraise(lineno, ECPG_TRANS, NULL);
return FALSE;
}
PQclear(res);
@ -1213,13 +897,8 @@ ECPGtrans(int lineno, const char *connection_name, const char *transaction)
con->committed = true;
/* deallocate all prepared statements */
while(prep_stmts != NULL)
{
bool b = ECPGdeallocate(lineno, prep_stmts->name);
if (!b)
if (!ECPGdeallocate_all(lineno))
return false;
}
}
return true;
@ -1242,7 +921,7 @@ ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
{
if ((results = PQexec(con->connection, "begin transaction")) == NULL)
{
register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
ECPGraise(lineno, ECPG_TRANS, NULL);
return false;
}
PQclear(results);
@ -1256,7 +935,7 @@ ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
{
if ((results = PQexec(con->connection, "commit")) == NULL)
{
register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
ECPGraise(lineno, ECPG_TRANS, NULL);
return false;
}
PQclear(results);
@ -1315,7 +994,7 @@ ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd
{
ecpg_finish(this);
ECPGlog("connect: could not open database %s %s%s in line %d\n", dbname ? dbname : "<DEFAULT>", user ? "for user " : "", user ? user : "", lineno);
register_error(ECPG_CONNECT, "connect: could not open database %s.", dbname ? dbname : "<DEFAULT>");
ECPGraise(lineno, ECPG_CONNECT, dbname ? dbname : "<DEFAULT>");
return false;
}
@ -1384,135 +1063,179 @@ ECPGlog(const char *format,...)
}
}
/* print out an error message */
void
sqlprint(void)
/* dynamic SQL support routines
*
* Copyright (c) 2000, Christof Petig <christof.petig@wtal.de>
*
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/ecpglib.c,v 1.60 2000/02/23 19:25:43 meskes Exp $
*/
/* I borrowed the include files from ecpglib.c, maybe we don't need all of them */
#include <sql3types.h>
PGconn *ECPG_internal_get_connection(char *name);
extern struct descriptor
{
sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
fprintf(stderr, "sql error %s\n", sqlca.sqlerrm.sqlerrmc);
}
char *name;
PGresult *result;
struct descriptor *next;
} *all_descriptors;
static bool
isvarchar(unsigned char c)
// like ECPGexecute
static bool execute_descriptor(int lineno,const char *query
,struct connection *con,PGresult **resultptr)
{
if (isalnum(c))
return true;
bool status = false;
PGresult *results;
PGnotify *notify;
/* Now the request is built. */
if (c == '_' || c == '>' || c == '-' || c == '.')
return true;
if (c >= 128)
return true;
return (false);
}
static void
replace_variables(char *text)
{
char *ptr = text;
bool string = false;
for (; *ptr != '\0'; ptr++)
if (con->committed && !con->autocommit)
{
if (*ptr == '\'')
string = string ? false : true;
if (!string && *ptr == ':')
if ((results = PQexec(con->connection, "begin transaction")) == NULL)
{
*ptr = '?';
for (++ptr; *ptr && isvarchar(*ptr); ptr++)
*ptr = ' ';
ECPGraise(lineno, ECPG_TRANS, NULL);
return false;
}
PQclear(results);
con->committed = false;
}
ECPGlog("execute_descriptor line %d: QUERY: %s on connection %s\n", lineno, query, con->name);
results = PQexec(con->connection, query);
if (results == NULL)
{
ECPGlog("ECPGexecute line %d: error: %s", lineno,
PQerrorMessage(con->connection));
ECPGraise(lineno, ECPG_PGSQL, PQerrorMessage(con->connection));
}
else
{ *resultptr=results;
switch (PQresultStatus(results))
{ int ntuples;
case PGRES_TUPLES_OK:
status = true;
sqlca.sqlerrd[2] = ntuples = PQntuples(results);
if (ntuples < 1)
{
ECPGlog("execute_descriptor line %d: Incorrect number of matches: %d\n",
lineno, ntuples);
ECPGraise(lineno, ECPG_NOT_FOUND, NULL);
status = false;
break;
}
break;
#if 1 /* strictly these are not needed (yet) */
case PGRES_EMPTY_QUERY:
/* do nothing */
ECPGraise(lineno, ECPG_EMPTY, NULL);
break;
case PGRES_COMMAND_OK:
status = true;
sqlca.sqlerrd[1] = atol(PQoidStatus(results));
sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
ECPGlog("ECPGexecute line %d Ok: %s\n", lineno, PQcmdStatus(results));
break;
case PGRES_COPY_OUT:
ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno);
PQendcopy(con->connection);
break;
case PGRES_COPY_IN:
ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.\n", lineno);
PQendcopy(con->connection);
break;
#else
case PGRES_EMPTY_QUERY:
case PGRES_COMMAND_OK:
case PGRES_COPY_OUT:
case PGRES_COPY_IN:
break;
#endif
case PGRES_NONFATAL_ERROR:
case PGRES_FATAL_ERROR:
case PGRES_BAD_RESPONSE:
ECPGlog("ECPGexecute line %d: Error: %s",
lineno, PQerrorMessage(con->connection));
ECPGraise(lineno, ECPG_PGSQL, PQerrorMessage(con->connection));
status = false;
break;
default:
ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
lineno);
ECPGraise(lineno, ECPG_PGSQL, PQerrorMessage(con->connection));
status = false;
break;
}
}
/* check for asynchronous returns */
notify = PQnotifies(con->connection);
if (notify)
{
ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
lineno, notify->relname, notify->be_pid);
free(notify);
}
return status;
}
/* handle the EXEC SQL PREPARE statement */
bool
ECPGprepare(int lineno, char *name, char *variable)
/* like ECPGdo */
static bool do_descriptor2(int lineno,const char *connection_name,
PGresult **resultptr, const char *query)
{
struct statement *stmt;
struct prepared_statement *this;
struct connection *con = get_connection(connection_name);
bool status=true;
char *locale = setlocale(LC_NUMERIC, NULL);
/* check if we already have prepared this statement */
for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);
if (this)
{
bool b = ECPGdeallocate(lineno, name);
/* Make sure we do NOT honor the locale for numeric input/output */
/* since the database wants teh standard decimal point */
setlocale(LC_NUMERIC, "C");
if (!b)
return false;
if (!ecpg_init(con, connection_name, lineno))
{ setlocale(LC_NUMERIC, locale);
return(false);
}
this = (struct prepared_statement *) ecpg_alloc(sizeof(struct prepared_statement), lineno);
if (!this)
return false;
stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno);
if (!stmt)
/* are we connected? */
if (con == NULL || con->connection == NULL)
{
free(this);
ECPGlog("do_descriptor2: not connected to %s\n", con->name);
ECPGraise(lineno, ECPG_NOT_CONN, NULL);
setlocale(LC_NUMERIC, locale);
return false;
}
/* create statement */
stmt->lineno = lineno;
stmt->connection = NULL;
stmt->command = ecpg_strdup(variable, lineno);
stmt->inlist = stmt->outlist = NULL;
status = execute_descriptor(lineno,query,con,resultptr);
/* if we have C variables in our statment replace them with '?' */
replace_variables(stmt->command);
/* add prepared statement to our list */
this->name = ecpg_strdup(name, lineno);
this->stmt = stmt;
if (prep_stmts == NULL)
this->next = NULL;
else
this->next = prep_stmts;
prep_stmts = this;
return true;
/* and reset locale value so our application is not affected */
setlocale(LC_NUMERIC, locale);
return (status);
}
/* handle the EXEC SQL DEALLOCATE PREPARE statement */
bool
ECPGdeallocate(int lineno, char *name)
bool ECPGdo_descriptor(int line,const char *connection,
const char *descriptor,const char *query)
{
struct prepared_statement *this,
*prev;
struct descriptor *i;
for (i=all_descriptors;i!=NULL;i=i->next)
{ if (!strcmp(descriptor,i->name))
{
bool status;
/* check if we really have prepared this statement */
for (this = prep_stmts, prev = NULL; this != NULL && strcmp(this->name, name) != 0; prev = this, this = this->next);
if (this)
{
/* okay, free all the resources */
free(this->name);
free(this->stmt->command);
free(this->stmt);
if (prev != NULL)
prev->next = this->next;
else
prep_stmts = this->next;
free(this);
return true;
/* free previous result */
if (i->result) PQclear(i->result);
i->result=NULL;
status=do_descriptor2(line,connection,&i->result,query);
if (!i->result) PQmakeEmptyPGresult(NULL, 0);
return (status);
}
}
ECPGlog("deallocate_prepare: invalid statement name %s\n", name);
register_error(ECPG_INVALID_STMT, "Invalid statement name %s in line %d", name, lineno);
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, descriptor);
return false;
}
/* return the prepared statement */
char *
ECPGprepared_statement(char *name)
{
struct prepared_statement *this;
for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);
return (this) ? this->stmt->command : NULL;
}
#include "dynamic.c"

View File

@ -0,0 +1,151 @@
#include <stdio.h>
#include <ecpgerrno.h>
#include <ecpgtype.h>
#include <ecpglib.h>
#include <sqlca.h>
void
ECPGraise(int line, int code, const char *str)
{
struct auto_mem *am;
sqlca.sqlcode = code;
switch (code)
{
case ECPG_NOT_FOUND:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"No data found in line %d.", line);
break;
case ECPG_OUT_OF_MEMORY:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Out of memory in line %d.", line);
break;
case ECPG_UNSUPPORTED:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Unsupported type %s in line %d.", str, line);
break;
case ECPG_TOO_MANY_ARGUMENTS:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Too many arguments in line %d.", line);
break;
case ECPG_TOO_FEW_ARGUMENTS:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Too few arguments in line %d.", line);
break;
case ECPG_INT_FORMAT:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Not correctly formatted int type: %s line %d.", str, line);
break;
case ECPG_UINT_FORMAT:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Not correctly formatted unsigned type: %s in line %d.", str, line);
break;
case ECPG_FLOAT_FORMAT:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Not correctly formatted floating point type: %s in line %d.", str, line);
break;
case ECPG_CONVERT_BOOL:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Unable to convert %s to bool on line %d.", str, line);
break;
case ECPG_EMPTY:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Empty query in line %d.", line);
break;
case ECPG_MISSING_INDICATOR:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"NULL value without indicator in line %d.", line);
break;
case ECPG_NO_CONN:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"No such connection %s in line %d.", str, line);
break;
case ECPG_NOT_CONN:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Not connected in line %d.", line);
break;
case ECPG_INVALID_STMT:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Invalid statement name in line %d.", line);
break;
case ECPG_UNKNOWN_DESCRIPTOR:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Sescriptor %s not found in line %d.", str, line);
break;
case ECPG_INVALID_DESCRIPTOR_INDEX:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Sescriptor index out of range in line %d.", line);
break;
case ECPG_UNKNOWN_DESCRIPTOR_ITEM:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Unknown descriptor item %s in line %d.", str, line);
break;
case ECPG_VAR_NOT_NUMERIC:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Variable is not a numeric type in line %d.", line);
break;
case ECPG_VAR_NOT_CHAR:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Variable is not a character type in line %d.", line);
break;
case ECPG_PGSQL:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Postgres error '%s' in line %d.", str, line);
break;
case ECPG_TRANS:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Error in transaction processing in line %d.", line);
break;
case ECPG_CONNECT:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"Could not connect to database %s in line %d.", str, line);
break;
default:
snprintf(sqlca.sqlerrm.sqlerrmc,sizeof(sqlca.sqlerrm.sqlerrmc),
"SQL error #%d in line %d.",code, line);
break;
}
sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc);
/* free all memory we have allocated for the user */
for (am = auto_allocs; am;)
{
struct auto_mem *act = am;
am = am->next;
free(act->pointer);
free(act);
}
}
/* print out an error message */
void
sqlprint(void)
{
sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
fprintf(stderr, "sql error %s\n", sqlca.sqlerrm.sqlerrmc);
}

View File

@ -0,0 +1,33 @@
#include <ecpgtype.h>
#include <ecpglib.h>
char *
ecpg_alloc(long size, int lineno)
{
char *new = (char *) calloc(1L, size);
if (!new)
{
ECPGlog("out of memory\n");
ECPGraise(lineno, ECPG_OUT_OF_MEMORY, NULL);
return NULL;
}
memset(new, '\0', size);
return (new);
}
char *
ecpg_strdup(const char *string, int lineno)
{
char *new = strdup(string);
if (!new)
{
ECPGlog("out of memory\n");
ECPGraise(lineno, ECPG_OUT_OF_MEMORY, NULL);
return NULL;
}
return (new);
}

View File

@ -0,0 +1,149 @@
#include <ctype.h>
#include <ecpgtype.h>
#include <ecpglib.h>
#include <sqlca.h>
static struct prepared_statement
{
char *name;
struct statement *stmt;
struct prepared_statement *next;
} *prep_stmts = NULL;
static bool
isvarchar(unsigned char c)
{
if (isalnum(c))
return true;
if (c == '_' || c == '>' || c == '-' || c == '.')
return true;
if (c >= 128)
return true;
return (false);
}
static void
replace_variables(char *text)
{
char *ptr = text;
bool string = false;
for (; *ptr != '\0'; ptr++)
{
if (*ptr == '\'')
string = string ? false : true;
if (!string && *ptr == ':')
{
*ptr = '?';
for (++ptr; *ptr && isvarchar(*ptr); ptr++)
*ptr = ' ';
}
}
}
/* handle the EXEC SQL PREPARE statement */
bool
ECPGprepare(int lineno, char *name, char *variable)
{
struct statement *stmt;
struct prepared_statement *this;
/* check if we already have prepared this statement */
for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);
if (this)
{
bool b = ECPGdeallocate(lineno, name);
if (!b)
return false;
}
this = (struct prepared_statement *) ecpg_alloc(sizeof(struct prepared_statement), lineno);
if (!this)
return false;
stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno);
if (!stmt)
{
free(this);
return false;
}
/* create statement */
stmt->lineno = lineno;
stmt->connection = NULL;
stmt->command = ecpg_strdup(variable, lineno);
stmt->inlist = stmt->outlist = NULL;
/* if we have C variables in our statment replace them with '?' */
replace_variables(stmt->command);
/* add prepared statement to our list */
this->name = ecpg_strdup(name, lineno);
this->stmt = stmt;
if (prep_stmts == NULL)
this->next = NULL;
else
this->next = prep_stmts;
prep_stmts = this;
return true;
}
/* handle the EXEC SQL DEALLOCATE PREPARE statement */
bool
ECPGdeallocate(int lineno, char *name)
{
struct prepared_statement *this,
*prev;
/* check if we really have prepared this statement */
for (this = prep_stmts, prev = NULL; this != NULL && strcmp(this->name, name) != 0; prev = this, this = this->next);
if (this)
{
/* okay, free all the resources */
free(this->name);
free(this->stmt->command);
free(this->stmt);
if (prev != NULL)
prev->next = this->next;
else
prep_stmts = this->next;
free(this);
return true;
}
ECPGlog("deallocate_prepare: invalid statement name %s\n", name);
ECPGraise(lineno, ECPG_INVALID_STMT, name);
return false;
}
bool
ECPGdeallocate_all(int lineno)
{
/* deallocate all prepared statements */
while(prep_stmts != NULL)
{
bool b = ECPGdeallocate(lineno, prep_stmts->name);
if (!b)
return false;
}
}
/* return the prepared statement */
char *
ECPGprepared_statement(char *name)
{
struct prepared_statement *this;
for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);
return (this) ? this->stmt->command : NULL;
}

View File

@ -57,116 +57,6 @@ static void ECPGnumeric_lvalue(FILE *f,char *name)
}
}
static void ECPGstring_buffer(FILE *f, char *name)
{
const struct variable *v = find_variable(name);
switch(v->type->typ)
{
case ECPGt_varchar:
fprintf(yyout,"%s.arr",name);
break;
case ECPGt_char:
case ECPGt_unsigned_char:
fputs(name,yyout);
break;
default:
snprintf(errortext,sizeof errortext,"variable %s: character type needed"
,name);
mmerror(ET_ERROR,errortext);
break;
}
}
static void ECPGstring_length(FILE *f,char *name)
{
const struct variable *v=find_variable(name);
switch(v->type->typ)
{ case ECPGt_varchar:
case ECPGt_char:
case ECPGt_unsigned_char:
if (!v->type->size)
{ snprintf(errortext,sizeof errortext,"zero length char variable %s for assignment",
v->name);
mmerror(ET_ERROR,errortext);
}
fprintf(yyout,"%ld",v->type->size);
break;
default:
snprintf(errortext,sizeof errortext,"variable %s: character type needed"
,name);
mmerror(ET_ERROR,errortext);
break;
}
}
static void ECPGdata_assignment(char *variable,char *index_plus_1)
{
const struct variable *v=find_variable(variable);
fprintf(yyout,"\t\t\tif (!PQgetisnull(ECPGresult,0,(%s)-1))\n",index_plus_1);
switch(v->type->typ)
{
case ECPGt_short:
case ECPGt_int: /* use the same conversion as ecpglib does */
case ECPGt_long:
fprintf(yyout,"\t\t\t\t%s=strtol(PQgetvalue(ECPGresult,0,(%s)-1),NULL,10);\n"
,variable,index_plus_1);
break;
case ECPGt_unsigned_short:
case ECPGt_unsigned_int:
case ECPGt_unsigned_long:
fprintf(yyout,"\t\t\t\t%s=strtoul(PQgetvalue(ECPGresult,0,(%s)-1),NULL,10);\n"
,variable,index_plus_1);
break;
case ECPGt_float:
case ECPGt_double:
fprintf(yyout,"\t\t\t\t%s=strtod(PQgetvalue(ECPGresult,0,(%s)-1),NULL);\n"
,variable,index_plus_1);
break;
case ECPGt_bool:
fprintf(yyout,"\t\t\t\t%s=PQgetvalue(ECPGresult,0,(%s)-1)[0]=='t';\n"
,variable,index_plus_1);
break;
case ECPGt_varchar:
fprintf(yyout,"\t\t\t{\tstrncpy(%s.arr,PQgetvalue(ECPGresult,0,(%s)-1),%ld);\n"
,variable,index_plus_1,v->type->size);
fprintf(yyout,"\t\t\t\t%s.len=strlen(PQgetvalue(ECPGresult,0,(%s)-1)\n"
,variable,index_plus_1);
fprintf(yyout,"\t\t\t\tif (%s.len>%ld) { %s.len=%ld; sqlca.sqlwarn[0]=sqlca.sqlwarn[1]='W'; }\n"
,variable,v->type->size,variable,v->type->size);
fputs("\t\t\t}\n",yyout);
break;
case ECPGt_char:
case ECPGt_unsigned_char:
if (!v->type->size)
{
snprintf(errortext,sizeof errortext,"zero length char variable %s for DATA assignment",
v->name);
mmerror(ET_ERROR,errortext);
}
fprintf(yyout,"\t\t\t{\tstrncpy(%s,PQgetvalue(ECPGresult,0,(%s)-1),%ld);\n"
,variable,index_plus_1,v->type->size);
fprintf(yyout,"\t\t\t\tif (strlen(PQgetvalue(ECPGresult,0,(%s)-1))>=%ld)\n"
"\t\t\t\t{ %s[%ld]=0; sqlca.sqlwarn[0]=sqlca.sqlwarn[1]='W'; }\n"
,index_plus_1,v->type->size,variable,v->type->size-1);
fputs("\t\t\t}\n",yyout);
break;
default:
snprintf(errortext,sizeof errortext,"unknown variable type %d for DATA assignment"
,v->type->typ);
mmerror(ET_ERROR,errortext);
break;
}
}
/*
* descriptor name lookup
*/

View File

@ -1,4 +1,4 @@
all: stp.so test1 test2 test3 test4 test5 perftest dyntest
all: test1 test2 test3 test4 perftest dyntest
#LDFLAGS=-g -I /usr/local/pgsql/include -L/usr/local/pgsql/lib -lecpg -lpq -lcrypt
LDFLAGS=-g -I../include -I/usr/include/postgresql -L/usr/lib/postgresql -L../lib -lecpg -lpq -lcrypt
@ -14,17 +14,11 @@ test1: test1.c
test2: test2.c
test3: test3.c
test4: test4.c
test5: test5.c
perftest: perftest.c
dyntest: dyntest.c
.pgc.c:
$(ECPG) $?
stp.so: stp.c
cc -fPIC -I../include -I/usr/include/postgresql -c -o stp.o stp.c
ld -Bdynamic -shared -soname stp.so -o stp.so stp.o -lpq -lecpg -lc
clean:
-/bin/rm test1 test2 test3 test4 test5 perftest *.c log stp.o stp.so dyntest
-/bin/rm test1 test2 test3 test4 perftest *.c log dyntest

View File

@ -2,7 +2,7 @@
*
* Copyright (c) 2000, Christof Petig <christof.petig@wtal.de>
*
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Attic/dyntest.pgc,v 1.3 2000/02/22 19:57:12 meskes Exp $
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Attic/dyntest.pgc,v 1.4 2000/02/23 19:26:04 meskes Exp $
*/
#include <stdio.h>
@ -11,14 +11,16 @@ exec sql include sql3types;
exec sql include sqlca;
void error()
{ printf("#%d:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc);
{
printf("\n#%d:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc);
exit(1);
}
int main(int argc,char **argv)
{ exec sql begin declare section;
{
exec sql begin declare section;
int COUNT;
int INTVAR;
int INTVAR, BOOLVAR;
int INDEX;
int INDICATOR;
int TYPE,LENGTH,OCTET_LENGTH,PRECISION,SCALE,NULLABLE,RETURNED_OCTET_LENGTH;
@ -28,10 +30,12 @@ int main(int argc,char **argv)
float FLOATVAR;
double DOUBLEVAR;
char QUERY[1024];
exec sql end declare section;
exec sql end declare section;
int done=0;
FILE *dbgs;
exec sql var BOOLVAR is bool;
if ((dbgs = fopen("log", "w")) != NULL)
ECPGdebug(1, dbgs);
@ -67,14 +71,16 @@ int main(int argc,char **argv)
:PRECISION = precision, :SCALE=scale,
:NULLABLE=nullable, :NAME=name,
:INDICATOR=indicator;
printf("%2d %s %d(%d)(%d,%d) %d,%d %d = "
printf("%2d\t%s (type: %d length: %d precision: %d scale: %d
\toctet_length: %d returned_octet_length: %d nullable: %d)\n\t= "
,INDEX,NAME,TYPE,LENGTH,PRECISION,SCALE
,OCTET_LENGTH,RETURNED_OCTET_LENGTH,NULLABLE);
if (INDICATOR==-1) printf("NULL\n");
else switch (TYPE)
{ case SQL3_BOOLEAN:
exec sql get descriptor MYDESC value :INDEX :INTVAR=data;
printf("%s\n",INTVAR?"true":"false");
{
case SQL3_BOOLEAN:
exec sql get descriptor MYDESC value :INDEX :BOOLVAR=data;
printf("%s\n",BOOLVAR ? "true":"false");
break;
case SQL3_NUMERIC:
case SQL3_DECIMAL:

View File

@ -1,26 +0,0 @@
EXEC SQL INCLUDE sqlca;
int my_fun (void)
{
EXEC SQL BEGIN DECLARE SECTION;
int sql_index = 0;
EXEC SQL END DECLARE SECTION;
FILE *dbgs;
if ((dbgs = fopen("log", "w")) != NULL)
ECPGdebug(1, dbgs);
EXEC SQL WHENEVER SQLERROR GOTO Error;
EXEC SQL CONNECT TO 'mm';
EXEC SQL SELECT MIN(index) INTO :sql_index FROM tab;
EXEC SQL DISCONNECT;
if (dbgs != NULL)
fclose(dbgs);
return (sql_index);
Error:
return (sqlca.sqlcode);
}

View File

@ -1,62 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
EXEC SQL INCLUDE sqlca;
static void ErrorExit (void);
int main (void)
{
EXEC SQL BEGIN DECLARE SECTION;
int result;
int values[2], i;
EXEC SQL END DECLARE SECTION;
FILE *dbgs;
if ((dbgs = fopen("log", "w")) != NULL)
ECPGdebug(1, dbgs);
EXEC SQL WHENEVER SQLERROR DO ErrorExit();
EXEC SQL CONNECT TO 'mm';
EXEC SQL CREATE TABLE tab (index int);
EXEC SQL INSERT INTO tab(index) values(14);
EXEC SQL INSERT INTO tab(index) values(7);
EXEC SQL COMMIT;
EXEC SQL CREATE FUNCTION my_fun () RETURNS int AS
'/home/postgres/pgsql/src/interfaces/ecpg.mm/test/stp.so' LANGUAGE 'C';
EXEC SQL COMMIT;
EXEC SQL SELECT index INTO :values FROM tab;
for (i = 0; i < 2; i++)
printf("tab[%d] = %d\n", i, values[i]);
EXEC SQL SELECT my_fun () INTO :result;
printf ("result = %d\n", result);
EXEC SQL DROP TABLE tab;
EXEC SQL DROP FUNCTION my_fun ();
EXEC SQL COMMIT;
EXEC SQL DISCONNECT;
if (dbgs != NULL)
fclose(dbgs);
exit (0);
}
static void ErrorExit (void)
{
EXEC SQL WHENEVER SQLERROR CONTINUE;
sqlprint();
EXEC SQL ROLLBACK;
EXEC SQL DROP TABLE tab;
EXEC SQL DROP FUNCTION my_fun ();
EXEC SQL COMMIT;
EXEC SQL DISCONNECT;
exit (-1);
}