*** empty log message ***
This commit is contained in:
parent
c969e2662f
commit
9f74608f47
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
252
src/interfaces/ecpg/lib/data.c
Normal file
252
src/interfaces/ecpg/lib/data.c
Normal 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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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"
|
||||
|
151
src/interfaces/ecpg/lib/error.c
Normal file
151
src/interfaces/ecpg/lib/error.c
Normal 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);
|
||||
}
|
33
src/interfaces/ecpg/lib/memory.c
Normal file
33
src/interfaces/ecpg/lib/memory.c
Normal 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);
|
||||
}
|
149
src/interfaces/ecpg/lib/prepare.c
Normal file
149
src/interfaces/ecpg/lib/prepare.c
Normal 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;
|
||||
}
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user