mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +03:00
*** 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.
|
- Synced preproc.y with gram.y.
|
||||||
- Much more clean ups.
|
- Much more clean ups.
|
||||||
|
|
||||||
|
Wed Feb 23 17:08:28 CET 2000
|
||||||
|
|
||||||
|
- Even more clean ups.
|
||||||
- Set library version to 3.1.0.
|
- Set library version to 3.1.0.
|
||||||
- Set ecpg version to 2.7.0.
|
- Set ecpg version to 2.7.0.
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#define ECPG_INVALID_DESCRIPTOR_INDEX -241
|
#define ECPG_INVALID_DESCRIPTOR_INDEX -241
|
||||||
#define ECPG_UNKNOWN_DESCRIPTOR_ITEM -242
|
#define ECPG_UNKNOWN_DESCRIPTOR_ITEM -242
|
||||||
#define ECPG_VAR_NOT_NUMERIC -243
|
#define ECPG_VAR_NOT_NUMERIC -243
|
||||||
|
#define ECPG_VAR_NOT_CHAR -244
|
||||||
|
|
||||||
/* finally the backend error messages, they start at 400 */
|
/* finally the backend error messages, they start at 400 */
|
||||||
#define ECPG_PGSQL -400
|
#define ECPG_PGSQL -400
|
||||||
|
@ -16,35 +16,28 @@ extern "C"
|
|||||||
bool ECPGdisconnect(int, const char *);
|
bool ECPGdisconnect(int, const char *);
|
||||||
bool ECPGprepare(int, char *, char *);
|
bool ECPGprepare(int, char *, char *);
|
||||||
bool ECPGdeallocate(int, char *);
|
bool ECPGdeallocate(int, char *);
|
||||||
|
bool ECPGdeallocate_all(int);
|
||||||
char *ECPGprepared_statement(char *);
|
char *ECPGprepared_statement(char *);
|
||||||
|
|
||||||
void ECPGlog(const char *format,...);
|
void ECPGlog(const char *format,...);
|
||||||
|
|
||||||
|
/* print an error message */
|
||||||
|
void sqlprint(void);
|
||||||
|
|
||||||
#ifdef LIBPQ_FE_H
|
#ifdef LIBPQ_FE_H
|
||||||
bool ECPGsetdb(PGconn *);
|
bool ECPGsetdb(PGconn *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Here are some methods used by the lib. */
|
/* Here are some methods used by the lib. */
|
||||||
/* Returns a pointer to a string containing a simple type name. */
|
/* Returns a pointer to a string containing a simple type name. */
|
||||||
const char *ECPGtype_name(enum ECPGttype);
|
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. */
|
/* and some vars */
|
||||||
struct ECPGgeneric_varchar
|
extern struct auto_mem *auto_allocs;
|
||||||
{
|
|
||||||
int len;
|
|
||||||
char arr[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
/* print an error message */
|
|
||||||
void sqlprint(void);
|
|
||||||
|
|
||||||
struct cursor
|
|
||||||
{
|
|
||||||
const char *name;
|
|
||||||
char *command;
|
|
||||||
struct cursor *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* define this for simplicity as well as compatibility */
|
/* define this for simplicity as well as compatibility */
|
||||||
|
|
||||||
@ -52,9 +45,6 @@ extern "C"
|
|||||||
|
|
||||||
/* dynamic SQL */
|
/* 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,
|
bool ECPGdo_descriptor(int line,const char *connection,
|
||||||
const char *descriptor,const char *query);
|
const char *descriptor,const char *query);
|
||||||
bool ECPGdeallocate_desc(int line,const char *name);
|
bool ECPGdeallocate_desc(int line,const char *name);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
# Copyright (c) 1994, Regents of the University of California
|
# Copyright (c) 1994, Regents of the University of California
|
||||||
#
|
#
|
||||||
# IDENTIFICATION
|
# 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)
|
CFLAGS+= $(KRBFLAGS)
|
||||||
endif
|
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
|
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 <ecpgtype.h>
|
||||||
#include <ecpglib.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
|
bool
|
||||||
ECPGget_desc_header(int lineno, char * desc_name, int *count)
|
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);
|
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
|
bool
|
||||||
ECPGget_desc(int lineno, char *desc_name, int index, ...)
|
ECPGget_desc(int lineno, char *desc_name, int index, ...)
|
||||||
{
|
{
|
||||||
@ -100,51 +194,76 @@ ECPGget_desc(int lineno, char *desc_name, int index, ...)
|
|||||||
case (ECPGd_indicator):
|
case (ECPGd_indicator):
|
||||||
if (!get_int_item(lineno, var, vartype, -PQgetisnull(ECPGresult, 0, index)))
|
if (!get_int_item(lineno, var, vartype, -PQgetisnull(ECPGresult, 0, index)))
|
||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
|
ECPGlog("ECPGget_desc: INDICATOR = %d\n", -PQgetisnull(ECPGresult, 0, index));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGd_name:
|
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;
|
break;
|
||||||
|
|
||||||
case ECPGd_nullable:
|
case ECPGd_nullable:
|
||||||
if (!get_int_item(lineno, var, vartype, 1))
|
if (!get_int_item(lineno, var, vartype, 1))
|
||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGd_key_member:
|
case ECPGd_key_member:
|
||||||
if (!get_int_item(lineno, var, vartype, 0))
|
if (!get_int_item(lineno, var, vartype, 0))
|
||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGd_scale:
|
case ECPGd_scale:
|
||||||
if (!get_int_item(lineno, var, vartype, (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff))
|
if (!get_int_item(lineno, var, vartype, (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff))
|
||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
|
ECPGlog("ECPGget_desc: SCALE = %d\n", (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGd_precision:
|
case ECPGd_precision:
|
||||||
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) >> 16))
|
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) >> 16))
|
||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
|
ECPGlog("ECPGget_desc: PRECISION = %d\n", PQfmod(ECPGresult, index) >> 16);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGd_ret_length:
|
case ECPGd_ret_length:
|
||||||
case ECPGd_ret_octet:
|
case ECPGd_ret_octet:
|
||||||
if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, 0, index)))
|
if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, 0, index)))
|
||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
|
ECPGlog("ECPGget_desc: RETURNED = %d\n", PQgetlength(ECPGresult, 0, index));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGd_octet:
|
case ECPGd_octet:
|
||||||
if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
|
if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
|
||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
|
ECPGlog("ECPGget_desc: OCTET_LENGTH = %d\n", PQfsize(ECPGresult, index));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGd_length:
|
case ECPGd_length:
|
||||||
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) - VARHDRSZ))
|
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) - VARHDRSZ))
|
||||||
return (false);
|
return (false);
|
||||||
|
|
||||||
|
ECPGlog("ECPGget_desc: LENGTH = %d\n", PQfmod(ECPGresult, index) - VARHDRSZ);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ECPGd_type:
|
case ECPGd_type:
|
||||||
if (!get_int_item(lineno, var, vartype, ECPGDynamicType(PQftype(ECPGresult, index))))
|
if (!get_int_item(lineno, var, vartype, ECPGDynamicType(PQftype(ECPGresult, index))))
|
||||||
return (false);
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -164,3 +283,37 @@ ECPGget_desc(int lineno, char *desc_name, int index, ...)
|
|||||||
|
|
||||||
return (true);
|
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 variable *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct statement
|
struct auto_mem *auto_allocs;
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
static int simple_debug = 0;
|
static int simple_debug = 0;
|
||||||
static FILE *debugstream = NULL;
|
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 *
|
static struct connection *
|
||||||
get_connection(const char *connection_name)
|
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));
|
memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca));
|
||||||
if (con == NULL)
|
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);
|
return (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto_allocs = NULL;
|
||||||
|
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,37 +139,6 @@ ecpg_finish(struct connection * act)
|
|||||||
ECPGlog("ecpg_finish: called an extra time.\n");
|
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
|
static void
|
||||||
add_mem(void *ptr, int lineno)
|
add_mem(void *ptr, int lineno)
|
||||||
{
|
{
|
||||||
@ -313,7 +239,7 @@ create_statement(int lineno, struct connection * connection, struct statement **
|
|||||||
if (var->pointer == NULL)
|
if (var->pointer == NULL)
|
||||||
{
|
{
|
||||||
ECPGlog("create_statement: invalid statement name\n");
|
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);
|
free(var);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -704,7 +630,7 @@ ECPGexecute(struct statement * stmt)
|
|||||||
{
|
{
|
||||||
if ((results = PQexec(stmt->connection->connection, "begin transaction")) == NULL)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
PQclear(results);
|
PQclear(results);
|
||||||
@ -719,8 +645,7 @@ ECPGexecute(struct statement * stmt)
|
|||||||
{
|
{
|
||||||
ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno,
|
ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno,
|
||||||
PQerrorMessage(stmt->connection->connection));
|
PQerrorMessage(stmt->connection->connection));
|
||||||
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
|
ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection));
|
||||||
PQerrorMessage(stmt->connection->connection), stmt->lineno);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -749,8 +674,6 @@ ECPGexecute(struct statement * stmt)
|
|||||||
|
|
||||||
for (act_field = 0; act_field < nfields && status; act_field++)
|
for (act_field = 0; act_field < nfields && status; act_field++)
|
||||||
{
|
{
|
||||||
char *pval;
|
|
||||||
char *scan_length;
|
|
||||||
char *array_query;
|
char *array_query;
|
||||||
|
|
||||||
if (var == NULL)
|
if (var == NULL)
|
||||||
@ -820,248 +743,11 @@ ECPGexecute(struct statement * stmt)
|
|||||||
|
|
||||||
for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
|
for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
|
||||||
{
|
{
|
||||||
pval = (char *)PQgetvalue(results, act_tuple, act_field);
|
if (!get_data(results, act_tuple, act_field, stmt->lineno,
|
||||||
|
var->type, var->ind_type, var->value,
|
||||||
ECPGlog("ECPGexecute line %d: RESULT: %s\n", stmt->lineno, pval ? pval : "");
|
var->ind_value, var->varcharsize, var->offset))
|
||||||
|
|
||||||
/* 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;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var = var->next;
|
var = var->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1074,7 +760,7 @@ ECPGexecute(struct statement * stmt)
|
|||||||
break;
|
break;
|
||||||
case PGRES_EMPTY_QUERY:
|
case PGRES_EMPTY_QUERY:
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
register_error(ECPG_EMPTY, "Empty query line %d.", stmt->lineno);
|
ECPGraise(stmt->lineno, ECPG_EMPTY, NULL);
|
||||||
break;
|
break;
|
||||||
case PGRES_COMMAND_OK:
|
case PGRES_COMMAND_OK:
|
||||||
status = true;
|
status = true;
|
||||||
@ -1087,8 +773,7 @@ ECPGexecute(struct statement * stmt)
|
|||||||
case PGRES_BAD_RESPONSE:
|
case PGRES_BAD_RESPONSE:
|
||||||
ECPGlog("ECPGexecute line %d: Error: %s",
|
ECPGlog("ECPGexecute line %d: Error: %s",
|
||||||
stmt->lineno, PQerrorMessage(stmt->connection->connection));
|
stmt->lineno, PQerrorMessage(stmt->connection->connection));
|
||||||
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
|
ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection));
|
||||||
PQerrorMessage(stmt->connection->connection), stmt->lineno);
|
|
||||||
status = false;
|
status = false;
|
||||||
break;
|
break;
|
||||||
case PGRES_COPY_OUT:
|
case PGRES_COPY_OUT:
|
||||||
@ -1102,8 +787,7 @@ ECPGexecute(struct statement * stmt)
|
|||||||
default:
|
default:
|
||||||
ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
|
ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
|
||||||
stmt->lineno);
|
stmt->lineno);
|
||||||
register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
|
ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection));
|
||||||
PQerrorMessage(stmt->connection->connection), stmt->lineno);
|
|
||||||
status = false;
|
status = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1154,7 +838,7 @@ ECPGdo(int lineno, const char *connection_name, char *query, ...)
|
|||||||
{
|
{
|
||||||
free_statement(stmt);
|
free_statement(stmt);
|
||||||
ECPGlog("ECPGdo: not connected to %s\n", con->name);
|
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);
|
setlocale(LC_NUMERIC, locale);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1179,7 +863,7 @@ ECPGstatus(int lineno, const char *connection_name)
|
|||||||
if (con->connection == NULL)
|
if (con->connection == NULL)
|
||||||
{
|
{
|
||||||
ECPGlog("ECPGdo: not connected to %s\n", con->name);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1202,7 +886,7 @@ ECPGtrans(int lineno, const char *connection_name, const char *transaction)
|
|||||||
{
|
{
|
||||||
if ((res = PQexec(con->connection, transaction)) == NULL)
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
@ -1213,14 +897,9 @@ ECPGtrans(int lineno, const char *connection_name, const char *transaction)
|
|||||||
con->committed = true;
|
con->committed = true;
|
||||||
|
|
||||||
/* deallocate all prepared statements */
|
/* deallocate all prepared statements */
|
||||||
while(prep_stmts != NULL)
|
if (!ECPGdeallocate_all(lineno))
|
||||||
{
|
|
||||||
bool b = ECPGdeallocate(lineno, prep_stmts->name);
|
|
||||||
|
|
||||||
if (!b)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1242,7 +921,7 @@ ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
|
|||||||
{
|
{
|
||||||
if ((results = PQexec(con->connection, "begin transaction")) == NULL)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
PQclear(results);
|
PQclear(results);
|
||||||
@ -1256,7 +935,7 @@ ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
|
|||||||
{
|
{
|
||||||
if ((results = PQexec(con->connection, "commit")) == NULL)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
PQclear(results);
|
PQclear(results);
|
||||||
@ -1315,7 +994,7 @@ ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd
|
|||||||
{
|
{
|
||||||
ecpg_finish(this);
|
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);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1384,135 +1063,179 @@ ECPGlog(const char *format,...)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* print out an error message */
|
/* dynamic SQL support routines
|
||||||
void
|
*
|
||||||
sqlprint(void)
|
* 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';
|
char *name;
|
||||||
fprintf(stderr, "sql error %s\n", sqlca.sqlerrm.sqlerrmc);
|
PGresult *result;
|
||||||
|
struct descriptor *next;
|
||||||
|
} *all_descriptors;
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
ECPGraise(lineno, ECPG_TRANS, NULL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PQclear(results);
|
||||||
|
con->committed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
ECPGlog("execute_descriptor line %d: QUERY: %s on connection %s\n", lineno, query, con->name);
|
||||||
isvarchar(unsigned char c)
|
results = PQexec(con->connection, query);
|
||||||
|
|
||||||
|
if (results == NULL)
|
||||||
{
|
{
|
||||||
if (isalnum(c))
|
ECPGlog("ECPGexecute line %d: error: %s", lineno,
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (c == '_' || c == '>' || c == '-' || c == '.')
|
/* check for asynchronous returns */
|
||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
if (c >= 128)
|
/* like ECPGdo */
|
||||||
return true;
|
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);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/* are we connected? */
|
||||||
replace_variables(char *text)
|
if (con == NULL || con->connection == NULL)
|
||||||
{
|
{
|
||||||
char *ptr = text;
|
ECPGlog("do_descriptor2: not connected to %s\n", con->name);
|
||||||
bool string = false;
|
ECPGraise(lineno, ECPG_NOT_CONN, NULL);
|
||||||
|
setlocale(LC_NUMERIC, locale);
|
||||||
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this = (struct prepared_statement *) ecpg_alloc(sizeof(struct prepared_statement), lineno);
|
status = execute_descriptor(lineno,query,con,resultptr);
|
||||||
if (!this)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno);
|
/* and reset locale value so our application is not affected */
|
||||||
if (!stmt)
|
setlocale(LC_NUMERIC, locale);
|
||||||
|
return (status);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ECPGdo_descriptor(int line,const char *connection,
|
||||||
|
const char *descriptor,const char *query)
|
||||||
{
|
{
|
||||||
free(this);
|
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;
|
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);
|
|
||||||
register_error(ECPG_INVALID_STMT, "Invalid statement name %s in line %d", name, lineno);
|
|
||||||
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
|
* 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 /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
|
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
|
test2: test2.c
|
||||||
test3: test3.c
|
test3: test3.c
|
||||||
test4: test4.c
|
test4: test4.c
|
||||||
test5: test5.c
|
|
||||||
perftest: perftest.c
|
perftest: perftest.c
|
||||||
dyntest: dyntest.c
|
dyntest: dyntest.c
|
||||||
|
|
||||||
.pgc.c:
|
.pgc.c:
|
||||||
$(ECPG) $?
|
$(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:
|
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>
|
* 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>
|
#include <stdio.h>
|
||||||
@ -11,14 +11,16 @@ exec sql include sql3types;
|
|||||||
exec sql include sqlca;
|
exec sql include sqlca;
|
||||||
|
|
||||||
void error()
|
void error()
|
||||||
{ printf("#%d:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc);
|
{
|
||||||
|
printf("\n#%d:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc,char **argv)
|
int main(int argc,char **argv)
|
||||||
{ exec sql begin declare section;
|
{
|
||||||
|
exec sql begin declare section;
|
||||||
int COUNT;
|
int COUNT;
|
||||||
int INTVAR;
|
int INTVAR, BOOLVAR;
|
||||||
int INDEX;
|
int INDEX;
|
||||||
int INDICATOR;
|
int INDICATOR;
|
||||||
int TYPE,LENGTH,OCTET_LENGTH,PRECISION,SCALE,NULLABLE,RETURNED_OCTET_LENGTH;
|
int TYPE,LENGTH,OCTET_LENGTH,PRECISION,SCALE,NULLABLE,RETURNED_OCTET_LENGTH;
|
||||||
@ -32,6 +34,8 @@ int main(int argc,char **argv)
|
|||||||
int done=0;
|
int done=0;
|
||||||
FILE *dbgs;
|
FILE *dbgs;
|
||||||
|
|
||||||
|
exec sql var BOOLVAR is bool;
|
||||||
|
|
||||||
if ((dbgs = fopen("log", "w")) != NULL)
|
if ((dbgs = fopen("log", "w")) != NULL)
|
||||||
ECPGdebug(1, dbgs);
|
ECPGdebug(1, dbgs);
|
||||||
|
|
||||||
@ -67,14 +71,16 @@ int main(int argc,char **argv)
|
|||||||
:PRECISION = precision, :SCALE=scale,
|
:PRECISION = precision, :SCALE=scale,
|
||||||
:NULLABLE=nullable, :NAME=name,
|
:NULLABLE=nullable, :NAME=name,
|
||||||
:INDICATOR=indicator;
|
: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
|
,INDEX,NAME,TYPE,LENGTH,PRECISION,SCALE
|
||||||
,OCTET_LENGTH,RETURNED_OCTET_LENGTH,NULLABLE);
|
,OCTET_LENGTH,RETURNED_OCTET_LENGTH,NULLABLE);
|
||||||
if (INDICATOR==-1) printf("NULL\n");
|
if (INDICATOR==-1) printf("NULL\n");
|
||||||
else switch (TYPE)
|
else switch (TYPE)
|
||||||
{ case SQL3_BOOLEAN:
|
{
|
||||||
exec sql get descriptor MYDESC value :INDEX :INTVAR=data;
|
case SQL3_BOOLEAN:
|
||||||
printf("%s\n",INTVAR?"true":"false");
|
exec sql get descriptor MYDESC value :INDEX :BOOLVAR=data;
|
||||||
|
printf("%s\n",BOOLVAR ? "true":"false");
|
||||||
break;
|
break;
|
||||||
case SQL3_NUMERIC:
|
case SQL3_NUMERIC:
|
||||||
case SQL3_DECIMAL:
|
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