mirror of https://github.com/postgres/postgres
Started working on a seperate pgtypes library. First test work. PLEASE test compilation on iother systems.
parent
48dfa0d057
commit
a4f25b6a9c
@ -0,0 +1,46 @@ |
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile for ecpg library
|
||||
#
|
||||
# Copyright (c) 1994, Regents of the University of California
|
||||
#
|
||||
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/Makefile,v 1.1 2003/03/16 10:42:53 meskes Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
subdir = src/interfaces/ecpg/ecpglib
|
||||
top_builddir = ../../../..
|
||||
include $(top_builddir)/src/Makefile.global |
||||
|
||||
NAME= ecpg
|
||||
SO_MAJOR_VERSION= 3
|
||||
SO_MINOR_VERSION= 4.2
|
||||
|
||||
override CPPFLAGS := -g -I$(top_srcdir)/src/interfaces/ecpg/include -I$(libpq_srcdir) $(CPPFLAGS) |
||||
|
||||
OBJS= execute.o typename.o descriptor.o data.o error.o prepare.o memory.o \
|
||||
connect.o misc.o
|
||||
|
||||
SHLIB_LINK= $(libpq)
|
||||
|
||||
all: all-lib |
||||
|
||||
# Shared library stuff
|
||||
include $(top_srcdir)/src/Makefile.shlib |
||||
|
||||
install: all installdirs install-lib |
||||
|
||||
installdirs: |
||||
$(mkinstalldirs) $(DESTDIR)$(libdir)
|
||||
|
||||
uninstall: uninstall-lib |
||||
|
||||
clean distclean maintainer-clean: clean-lib |
||||
rm -f $(OBJS)
|
||||
|
||||
depend dep: |
||||
$(CC) -MM $(CFLAGS) *.c >depend
|
||||
|
||||
ifeq (depend,$(wildcard depend)) |
||||
include depend |
||||
endif |
||||
@ -0,0 +1,495 @@ |
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/connect.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */ |
||||
|
||||
#include "postgres_fe.h" |
||||
|
||||
#include "ecpgtype.h" |
||||
#include "ecpglib.h" |
||||
#include "ecpgerrno.h" |
||||
#include "extern.h" |
||||
#include "sqlca.h" |
||||
|
||||
static struct connection *all_connections = NULL, |
||||
*actual_connection = NULL; |
||||
|
||||
struct connection * |
||||
ECPGget_connection(const char *connection_name) |
||||
{ |
||||
struct connection *con = all_connections; |
||||
|
||||
if (connection_name == NULL || strcmp(connection_name, "CURRENT") == 0) |
||||
return actual_connection; |
||||
|
||||
for (; con && strcmp(connection_name, con->name) != 0; con = con->next); |
||||
if (con) |
||||
return con; |
||||
else |
||||
return NULL; |
||||
} |
||||
|
||||
static void |
||||
ecpg_finish(struct connection * act) |
||||
{ |
||||
if (act != NULL) |
||||
{ |
||||
struct ECPGtype_information_cache *cache, |
||||
*ptr; |
||||
|
||||
ECPGlog("ecpg_finish: finishing %s.\n", act->name); |
||||
PQfinish(act->connection); |
||||
|
||||
/* remove act from the list */ |
||||
if (act == all_connections) |
||||
all_connections = act->next; |
||||
else |
||||
{ |
||||
struct connection *con; |
||||
|
||||
for (con = all_connections; con->next && con->next != act; con = con->next); |
||||
if (con->next) |
||||
con->next = act->next; |
||||
} |
||||
|
||||
if (actual_connection == act) |
||||
actual_connection = all_connections; |
||||
|
||||
for (cache = act->cache_head; cache; ptr = cache, cache = cache->next, ECPGfree(ptr)); |
||||
ECPGfree(act->name); |
||||
ECPGfree(act); |
||||
} |
||||
else |
||||
ECPGlog("ecpg_finish: called an extra time.\n"); |
||||
} |
||||
|
||||
bool |
||||
ECPGsetcommit(int lineno, const char *mode, const char *connection_name) |
||||
{ |
||||
struct connection *con = ECPGget_connection(connection_name); |
||||
PGresult *results; |
||||
|
||||
if (!ECPGinit(con, connection_name, lineno)) |
||||
return (false); |
||||
|
||||
ECPGlog("ECPGsetcommit line %d action = %s connection = %s\n", lineno, mode, con->name); |
||||
|
||||
if (con->autocommit == true && strncmp(mode, "off", strlen("off")) == 0) |
||||
{ |
||||
if (con->committed) |
||||
{ |
||||
if ((results = PQexec(con->connection, "begin transaction")) == NULL) |
||||
{ |
||||
ECPGraise(lineno, ECPG_TRANS, NULL); |
||||
return false; |
||||
} |
||||
PQclear(results); |
||||
con->committed = false; |
||||
} |
||||
con->autocommit = false; |
||||
} |
||||
else if (con->autocommit == false && strncmp(mode, "on", strlen("on")) == 0) |
||||
{ |
||||
if (!con->committed) |
||||
{ |
||||
if ((results = PQexec(con->connection, "commit")) == NULL) |
||||
{ |
||||
ECPGraise(lineno, ECPG_TRANS, NULL); |
||||
return false; |
||||
} |
||||
PQclear(results); |
||||
con->committed = true; |
||||
} |
||||
con->autocommit = true; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
bool |
||||
ECPGsetconn(int lineno, const char *connection_name) |
||||
{ |
||||
struct connection *con = ECPGget_connection(connection_name); |
||||
|
||||
if (!ECPGinit(con, connection_name, lineno)) |
||||
return (false); |
||||
|
||||
actual_connection = con; |
||||
return true; |
||||
} |
||||
|
||||
static void |
||||
ECPGnoticeProcessor_raise(int code, const char *message) |
||||
{ |
||||
sqlca.sqlcode = code; |
||||
strncpy(sqlca.sqlerrm.sqlerrmc, message, sizeof(sqlca.sqlerrm.sqlerrmc)); |
||||
sqlca.sqlerrm.sqlerrmc[sizeof(sqlca.sqlerrm.sqlerrmc) - 1] = 0; |
||||
sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc); |
||||
|
||||
/* remove trailing newline */ |
||||
if (sqlca.sqlerrm.sqlerrml |
||||
&& sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml - 1] == '\n') |
||||
{ |
||||
sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml - 1] = 0; |
||||
sqlca.sqlerrm.sqlerrml--; |
||||
} |
||||
|
||||
ECPGlog("raising sqlcode %d\n", code); |
||||
} |
||||
|
||||
/*
|
||||
* I know this is a mess, but we can't redesign the backend |
||||
*/ |
||||
|
||||
static void |
||||
ECPGnoticeProcessor(void *arg, const char *message) |
||||
{ |
||||
/* these notices raise an error */ |
||||
if (strncmp(message, "WARNING: ", 9)) |
||||
{ |
||||
ECPGlog("ECPGnoticeProcessor: strange warning '%s'\n", message); |
||||
ECPGnoticeProcessor_raise(ECPG_WARNING_UNRECOGNIZED, message); |
||||
return; |
||||
} |
||||
|
||||
message += 8; |
||||
while (*message == ' ') |
||||
message++; |
||||
ECPGlog("WARNING: %s", message); |
||||
|
||||
/* WARNING: (transaction aborted): queries ignored until END */ |
||||
|
||||
/*
|
||||
* WARNING: current transaction is aborted, queries ignored until end |
||||
* of transaction block |
||||
*/ |
||||
if (strstr(message, "queries ignored") && strstr(message, "transaction") |
||||
&& strstr(message, "aborted")) |
||||
{ |
||||
ECPGnoticeProcessor_raise(ECPG_WARNING_QUERY_IGNORED, message); |
||||
return; |
||||
} |
||||
|
||||
/* WARNING: PerformPortalClose: portal "*" not found */ |
||||
if ((!strncmp(message, "PerformPortalClose: portal", 26) |
||||
|| !strncmp(message, "PerformPortalFetch: portal", 26)) |
||||
&& strstr(message + 26, "not found")) |
||||
{ |
||||
ECPGnoticeProcessor_raise(ECPG_WARNING_UNKNOWN_PORTAL, message); |
||||
return; |
||||
} |
||||
|
||||
/* WARNING: BEGIN: already a transaction in progress */ |
||||
if (!strncmp(message, "BEGIN: already a transaction in progress", 40)) |
||||
{ |
||||
ECPGnoticeProcessor_raise(ECPG_WARNING_IN_TRANSACTION, message); |
||||
return; |
||||
} |
||||
|
||||
/* WARNING: AbortTransaction and not in in-progress state */ |
||||
/* WARNING: COMMIT: no transaction in progress */ |
||||
/* WARNING: ROLLBACK: no transaction in progress */ |
||||
if (!strncmp(message, "AbortTransaction and not in in-progress state", 45) |
||||
|| !strncmp(message, "COMMIT: no transaction in progress", 34) |
||||
|| !strncmp(message, "ROLLBACK: no transaction in progress", 36)) |
||||
{ |
||||
ECPGnoticeProcessor_raise(ECPG_WARNING_NO_TRANSACTION, message); |
||||
return; |
||||
} |
||||
|
||||
/* WARNING: BlankPortalAssignName: portal * already exists */ |
||||
if (!strncmp(message, "BlankPortalAssignName: portal", 29) |
||||
&& strstr(message + 29, "already exists")) |
||||
{ |
||||
ECPGnoticeProcessor_raise(ECPG_WARNING_PORTAL_EXISTS, message); |
||||
return; |
||||
} |
||||
|
||||
/* these are harmless - do nothing */ |
||||
|
||||
/*
|
||||
* WARNING: CREATE TABLE / PRIMARY KEY will create implicit index '*' |
||||
* for table '*' |
||||
*/ |
||||
|
||||
/*
|
||||
* WARNING: ALTER TABLE ... ADD CONSTRAINT will create implicit |
||||
* trigger(s) for FOREIGN KEY check(s) |
||||
*/ |
||||
|
||||
/*
|
||||
* WARNING: CREATE TABLE will create implicit sequence '*' for SERIAL |
||||
* column '*.*' |
||||
*/ |
||||
|
||||
/*
|
||||
* WARNING: CREATE TABLE will create implicit trigger(s) for FOREIGN |
||||
* KEY check(s) |
||||
*/ |
||||
if ((!strncmp(message, "CREATE TABLE", 12) || !strncmp(message, "ALTER TABLE", 11)) |
||||
&& strstr(message + 11, "will create implicit")) |
||||
return; |
||||
|
||||
/* WARNING: QUERY PLAN: */ |
||||
if (!strncmp(message, "QUERY PLAN:", 11)) /* do we really see these? */ |
||||
return; |
||||
|
||||
/*
|
||||
* WARNING: DROP TABLE implicitly drops referential integrity trigger |
||||
* from table "*" |
||||
*/ |
||||
if (!strncmp(message, "DROP TABLE implicitly drops", 27)) |
||||
return; |
||||
|
||||
/*
|
||||
* WARNING: Caution: DROP INDEX cannot be rolled back, so don't abort |
||||
* now |
||||
*/ |
||||
if (strstr(message, "cannot be rolled back")) |
||||
return; |
||||
|
||||
/* these and other unmentioned should set sqlca.sqlwarn[2] */ |
||||
/* WARNING: The ':' operator is deprecated. Use exp(x) instead. */ |
||||
/* WARNING: Rel *: Uninitialized page 0 - fixing */ |
||||
/* WARNING: PortalHeapMemoryFree: * not in alloc set! */ |
||||
/* WARNING: Too old parent tuple found - can't continue vc_repair_frag */ |
||||
/* WARNING: identifier "*" will be truncated to "*" */ |
||||
/* WARNING: InvalidateSharedInvalid: cache state reset */ |
||||
/* WARNING: RegisterSharedInvalid: SI buffer overflow */ |
||||
sqlca.sqlwarn[2] = 'W'; |
||||
sqlca.sqlwarn[0] = 'W'; |
||||
} |
||||
|
||||
/* this contains some quick hacks, needs to be cleaned up, but it works */ |
||||
bool |
||||
ECPGconnect(int lineno, const char *name, const char *user, const char *passwd, const char *connection_name, int autocommit) |
||||
{ |
||||
struct connection *this; |
||||
char *dbname = strdup(name), |
||||
*host = NULL, |
||||
*tmp, |
||||
*port = NULL, |
||||
*realname = NULL, |
||||
*options = NULL; |
||||
|
||||
ECPGinit_sqlca(); |
||||
|
||||
if ((this = (struct connection *) ECPGalloc(sizeof(struct connection), lineno)) == NULL) |
||||
return false; |
||||
|
||||
if (dbname == NULL && connection_name == NULL) |
||||
connection_name = "DEFAULT"; |
||||
|
||||
/* get the detail information out of dbname */ |
||||
if (strchr(dbname, '@') != NULL) |
||||
{ |
||||
/* old style: dbname[@server][:port] */ |
||||
tmp = strrchr(dbname, ':'); |
||||
if (tmp != NULL) /* port number given */ |
||||
{ |
||||
port = strdup(tmp + 1); |
||||
*tmp = '\0'; |
||||
} |
||||
|
||||
tmp = strrchr(dbname, '@'); |
||||
if (tmp != NULL) /* host name given */ |
||||
{ |
||||
host = strdup(tmp + 1); |
||||
*tmp = '\0'; |
||||
} |
||||
realname = strdup(dbname); |
||||
} |
||||
else if (strncmp(dbname, "tcp:", 4) == 0 || strncmp(dbname, "unix:", 5) == 0) |
||||
{ |
||||
int offset = 0; |
||||
|
||||
/*
|
||||
* only allow protocols tcp and unix |
||||
*/ |
||||
if (strncmp(dbname, "tcp:", 4) == 0) |
||||
offset = 4; |
||||
else if (strncmp(dbname, "unix:", 5) == 0) |
||||
offset = 5; |
||||
|
||||
if (strncmp(dbname + offset, "postgresql://", strlen("postgresql://")) == 0) |
||||
{ |
||||
|
||||
/*------
|
||||
* new style: |
||||
* <tcp|unix>:postgresql://server[:port|:/unixsocket/path:]
|
||||
* [/db name][?options] |
||||
*------ |
||||
*/ |
||||
offset += strlen("postgresql://"); |
||||
|
||||
tmp = strrchr(dbname + offset, '?'); |
||||
if (tmp != NULL) /* options given */ |
||||
{ |
||||
options = strdup(tmp + 1); |
||||
*tmp = '\0'; |
||||
} |
||||
|
||||
tmp = strrchr(dbname + offset, '/'); |
||||
if (tmp != NULL) /* database name given */ |
||||
{ |
||||
realname = strdup(tmp + 1); |
||||
*tmp = '\0'; |
||||
} |
||||
|
||||
tmp = strrchr(dbname + offset, ':'); |
||||
if (tmp != NULL) /* port number or Unix socket path given */ |
||||
{ |
||||
char *tmp2; |
||||
|
||||
*tmp = '\0'; |
||||
if ((tmp2 = strchr(tmp + 1, ':')) != NULL) |
||||
{ |
||||
*tmp2 = '\0'; |
||||
host = strdup(tmp + 1); |
||||
if (strncmp(dbname, "unix:", 5) != 0) |
||||
{ |
||||
ECPGlog("connect: socketname %s given for TCP connection in line %d\n", host, lineno); |
||||
ECPGraise(lineno, ECPG_CONNECT, realname ? realname : "<DEFAULT>"); |
||||
if (host) |
||||
ECPGfree(host); |
||||
if (port) |
||||
ECPGfree(port); |
||||
if (options) |
||||
ECPGfree(options); |
||||
if (realname) |
||||
ECPGfree(realname); |
||||
if (dbname) |
||||
ECPGfree(dbname); |
||||
return false; |
||||
} |
||||
} |
||||
else |
||||
port = strdup(tmp + 1); |
||||
} |
||||
|
||||
if (strncmp(dbname, "unix:", 5) == 0) |
||||
{ |
||||
if (strcmp(dbname + offset, "localhost") != 0 && strcmp(dbname + offset, "127.0.0.1") != 0) |
||||
{ |
||||
ECPGlog("connect: non-localhost access via sockets in line %d\n", lineno); |
||||
ECPGraise(lineno, ECPG_CONNECT, realname ? realname : "<DEFAULT>"); |
||||
if (host) |
||||
ECPGfree(host); |
||||
if (port) |
||||
ECPGfree(port); |
||||
if (options) |
||||
ECPGfree(options); |
||||
if (realname) |
||||
ECPGfree(realname); |
||||
if (dbname) |
||||
ECPGfree(dbname); |
||||
return false; |
||||
} |
||||
} |
||||
else |
||||
host = strdup(dbname + offset); |
||||
|
||||
} |
||||
else |
||||
realname = strdup(dbname); |
||||
} |
||||
else |
||||
realname = strdup(dbname); |
||||
|
||||
/* add connection to our list */ |
||||
if (connection_name != NULL) |
||||
this->name = ECPGstrdup(connection_name, lineno); |
||||
else |
||||
this->name = ECPGstrdup(realname, lineno); |
||||
|
||||
this->cache_head = NULL; |
||||
|
||||
if (all_connections == NULL) |
||||
this->next = NULL; |
||||
else |
||||
this->next = all_connections; |
||||
|
||||
actual_connection = all_connections = this; |
||||
|
||||
ECPGlog("ECPGconnect: opening database %s on %s port %s %s%s%s%s\n", |
||||
realname ? realname : "<DEFAULT>", |
||||
host ? host : "<DEFAULT>", |
||||
port ? port : "<DEFAULT>", |
||||
options ? "with options " : "", options ? options : "", |
||||
user ? "for user " : "", user ? user : ""); |
||||
|
||||
this->connection = PQsetdbLogin(host, port, options, NULL, realname, user, passwd); |
||||
|
||||
if (PQstatus(this->connection) == CONNECTION_BAD) |
||||
{ |
||||
const char *errmsg = PQerrorMessage(this->connection); |
||||
char *db = realname ? realname : "<DEFAULT>"; |
||||
|
||||
set_backend_err(errmsg, lineno); |
||||
ecpg_finish(this); |
||||
ECPGlog("connect: could not open database %s on %s port %s %s%s%s%s in line %d\n\t%s\n", |
||||
db, |
||||
host ? host : "<DEFAULT>", |
||||
port ? port : "<DEFAULT>", |
||||
options ? "with options " : "", options ? options : "", |
||||
user ? "for user " : "", user ? user : "", |
||||
lineno, errmsg); |
||||
|
||||
ECPGraise(lineno, ECPG_CONNECT, db); |
||||
if (host) |
||||
ECPGfree(host); |
||||
if (port) |
||||
ECPGfree(port); |
||||
if (options) |
||||
ECPGfree(options); |
||||
if (realname) |
||||
ECPGfree(realname); |
||||
if (dbname) |
||||
ECPGfree(dbname); |
||||
return false; |
||||
} |
||||
|
||||
if (host) |
||||
ECPGfree(host); |
||||
if (port) |
||||
ECPGfree(port); |
||||
if (options) |
||||
ECPGfree(options); |
||||
if (realname) |
||||
ECPGfree(realname); |
||||
if (dbname) |
||||
ECPGfree(dbname); |
||||
|
||||
this->committed = true; |
||||
this->autocommit = autocommit; |
||||
|
||||
PQsetNoticeProcessor(this->connection, &ECPGnoticeProcessor, (void *) this); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
bool |
||||
ECPGdisconnect(int lineno, const char *connection_name) |
||||
{ |
||||
struct connection *con; |
||||
|
||||
if (strcmp(connection_name, "ALL") == 0) |
||||
{ |
||||
ECPGinit_sqlca(); |
||||
for (con = all_connections; con;) |
||||
{ |
||||
struct connection *f = con; |
||||
|
||||
con = con->next; |
||||
ecpg_finish(f); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
con = ECPGget_connection(connection_name); |
||||
|
||||
if (!ECPGinit(con, connection_name, lineno)) |
||||
return (false); |
||||
else |
||||
ecpg_finish(con); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
@ -0,0 +1,424 @@ |
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/data.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */ |
||||
|
||||
#include "postgres_fe.h" |
||||
|
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "ecpgtype.h" |
||||
#include "ecpglib.h" |
||||
#include "ecpgerrno.h" |
||||
#include "extern.h" |
||||
#include "sqlca.h" |
||||
#include "pgtypes_numeric.h" |
||||
|
||||
bool |
||||
ECPGget_data(const PGresult *results, int act_tuple, int act_field, int lineno, |
||||
enum ECPGttype type, enum ECPGttype ind_type, |
||||
char *var, char *ind, long varcharsize, long offset, |
||||
long ind_offset, bool isarray) |
||||
{ |
||||
char *pval = (char *) PQgetvalue(results, act_tuple, act_field); |
||||
|
||||
ECPGlog("ECPGget_data line %d: RESULT: %s offset: %ld\n", lineno, pval ? pval : "", offset); |
||||
|
||||
/* pval is a pointer to the value */ |
||||
/* let's check is it really is an array if it should be one */ |
||||
if (isarray) |
||||
{ |
||||
if (*pval != '{') |
||||
{ |
||||
ECPGraise(lineno, ECPG_DATA_NOT_ARRAY, NULL); |
||||
return (false); |
||||
} |
||||
|
||||
switch (type) |
||||
{ |
||||
case ECPGt_char: |
||||
case ECPGt_unsigned_char: |
||||
case ECPGt_varchar: |
||||
break; |
||||
|
||||
default: |
||||
pval++; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
/* 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);*/ |
||||
*((short *) (ind + ind_offset * 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);*/ |
||||
*((int *) (ind + ind_offset * 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);*/ |
||||
*((long *) (ind + ind_offset * act_tuple)) = -PQgetisnull(results, act_tuple, act_field); |
||||
break; |
||||
#ifdef HAVE_LONG_LONG_INT_64 |
||||
case ECPGt_long_long: |
||||
case ECPGt_unsigned_long_long: |
||||
/* ((long long int *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);*/ |
||||
*((long long int *) (ind + ind_offset * act_tuple)) = -PQgetisnull(results, act_tuple, act_field); |
||||
break; |
||||
/* case ECPGt_unsigned_long_long:
|
||||
((unsigned long long int *) ind)[act_tuple] = -PQgetisnull(results, act_tuple, act_field); |
||||
break;*/ |
||||
#endif /* HAVE_LONG_LONG_INT_64 */ |
||||
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; |
||||
} |
||||
|
||||
do |
||||
{ |
||||
switch (type) |
||||
{ |
||||
long res; |
||||
unsigned long ures; |
||||
double dres; |
||||
char *scan_length; |
||||
NumericVar *nres; |
||||
|
||||
case ECPGt_short: |
||||
case ECPGt_int: |
||||
case ECPGt_long: |
||||
if (pval) |
||||
{ |
||||
res = strtol(pval, &scan_length, 10); |
||||
if ((isarray && *scan_length != ',' && *scan_length != '}') |
||||
|| (!isarray && *scan_length != '\0')) /* Garbage left */ |
||||
{ |
||||
ECPGraise(lineno, ECPG_INT_FORMAT, pval); |
||||
return (false); |
||||
} |
||||
} |
||||
else |
||||
res = 0L; |
||||
|
||||
switch (type) |
||||
{ |
||||
case ECPGt_short: |
||||
/* ((short *) var)[act_tuple] = (short) res;*/ |
||||
*((short *) (var + offset * act_tuple)) = (short) res; |
||||
break; |
||||
case ECPGt_int: |
||||
/* ((int *) var)[act_tuple] = (int) res;*/ |
||||
*((int *) (var + offset * act_tuple)) = (int) res; |
||||
break; |
||||
case ECPGt_long: |
||||
/* ((long *) var)[act_tuple] = res;*/ |
||||
*((long *) (var + offset * act_tuple)) = (long) 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 ((isarray && *scan_length != ',' && *scan_length != '}') |
||||
|| (!isarray && *scan_length != '\0')) /* Garbage left */ |
||||
{ |
||||
ECPGraise(lineno, ECPG_UINT_FORMAT, pval); |
||||
return (false); |
||||
} |
||||
} |
||||
else |
||||
ures = 0L; |
||||
|
||||
switch (type) |
||||
{ |
||||
case ECPGt_unsigned_short: |
||||
/* ((unsigned short *) var)[act_tuple] = (unsigned short) ures;*/ |
||||
*((unsigned short *) (var + offset * act_tuple)) = (unsigned short) ures; |
||||
break; |
||||
case ECPGt_unsigned_int: |
||||
/* ((unsigned int *) var)[act_tuple] = (unsigned int) ures;*/ |
||||
*((unsigned int *) (var + offset * act_tuple)) = (unsigned int) ures; |
||||
break; |
||||
case ECPGt_unsigned_long: |
||||
/* ((unsigned long *) var)[act_tuple] = ures;*/ |
||||
*((unsigned long *) (var + offset * act_tuple)) = (unsigned long) ures; |
||||
break; |
||||
default: |
||||
/* Cannot happen */ |
||||
break; |
||||
} |
||||
break; |
||||
|
||||
#ifdef HAVE_LONG_LONG_INT_64 |
||||
#ifdef HAVE_STRTOLL |
||||
case ECPGt_long_long: |
||||
if (pval) |
||||
{ |
||||
/* ((long long int *) var)[act_tuple] = strtoll(pval, &scan_length, 10);*/ |
||||
*((long long int *) (var + offset * act_tuple)) = strtoll(pval, &scan_length, 10); |
||||
if ((isarray && *scan_length != ',' && *scan_length != '}') |
||||
|| (!isarray && *scan_length != '\0')) /* Garbage left */ |
||||
{ |
||||
ECPGraise(lineno, ECPG_INT_FORMAT, pval); |
||||
return (false); |
||||
} |
||||
} |
||||
else |
||||
/* ((long long int *) var)[act_tuple] = (long long) 0;*/ |
||||
*((long long int *) (var + offset * act_tuple)) = (long long) 0; |
||||
|
||||
break; |
||||
#endif /* HAVE_STRTOLL */ |
||||
#ifdef HAVE_STRTOULL |
||||
case ECPGt_unsigned_long_long: |
||||
if (pval) |
||||
{ |
||||
/* ((unsigned long long int *) var)[act_tuple] = strtoull(pval, &scan_length, 10);*/ |
||||
*((unsigned long long int *) (var + offset * act_tuple)) = strtoull(pval, &scan_length, 10); |
||||
if ((isarray && *scan_length != ',' && *scan_length != '}') |
||||
|| (!isarray && *scan_length != '\0')) /* Garbage left */ |
||||
{ |
||||
ECPGraise(lineno, ECPG_UINT_FORMAT, pval); |
||||
return (false); |
||||
} |
||||
} |
||||
else |
||||
/* ((unsigned long long int *) var)[act_tuple] = (long long) 0;*/ |
||||
*((unsigned long long int *) (var + offset * act_tuple)) = (long long) 0; |
||||
|
||||
break; |
||||
#endif /* HAVE_STRTOULL */ |
||||
#endif /* HAVE_LONG_LONG_INT_64 */ |
||||
|
||||
case ECPGt_float: |
||||
case ECPGt_double: |
||||
if (pval) |
||||
{ |
||||
if (isarray && *pval == '"') |
||||
dres = strtod(pval + 1, &scan_length); |
||||
else |
||||
dres = strtod(pval, &scan_length); |
||||
|
||||
if (isarray && *scan_length == '"') |
||||
scan_length++; |
||||
|
||||
if ((isarray && *scan_length != ',' && *scan_length != '}') |
||||
|| (!isarray && *scan_length != '\0')) /* Garbage left */ |
||||
{ |
||||
ECPGraise(lineno, ECPG_FLOAT_FORMAT, pval); |
||||
return (false); |
||||
} |
||||
} |
||||
else |
||||
dres = 0.0; |
||||
|
||||
switch (type) |
||||
{ |
||||
case ECPGt_float: |
||||
/* ((float *) var)[act_tuple] = dres;*/ |
||||
*((float *) (var + offset * act_tuple)) = dres; |
||||
break; |
||||
case ECPGt_double: |
||||
/* ((double *) var)[act_tuple] = dres;*/ |
||||
*((double *) (var + offset * act_tuple)) = dres; |
||||
break; |
||||
default: |
||||
/* Cannot happen */ |
||||
break; |
||||
} |
||||
break; |
||||
|
||||
case ECPGt_bool: |
||||
if (pval) |
||||
{ |
||||
if (pval[0] == 'f' && pval[1] == '\0') |
||||
{ |
||||
if (offset == sizeof(char)) |
||||
/* ((char *) var)[act_tuple] = false;*/ |
||||
*((char *) (var + offset * act_tuple)) = false; |
||||
else if (offset == sizeof(int)) |
||||
/* ((int *) var)[act_tuple] = false;*/ |
||||
*((int *) (var + offset * act_tuple)) = false; |
||||
else |
||||
ECPGraise(lineno, ECPG_CONVERT_BOOL, "different size"); |
||||
break; |
||||
} |
||||
else if (pval[0] == 't' && pval[1] == '\0') |
||||
{ |
||||
if (offset == sizeof(char)) |
||||
/* ((char *) var)[act_tuple] = true;*/ |
||||
*((char *) (var + offset * act_tuple)) = true; |
||||
else if (offset == sizeof(int)) |
||||
/* ((int *) var)[act_tuple] = true;*/ |
||||
*((int *) (var + offset * act_tuple)) = true; |
||||
else |
||||
ECPGraise(lineno, ECPG_CONVERT_BOOL, "different size"); |
||||
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] = strlen(pval);*/ |
||||
*((short *) (ind + ind_offset * act_tuple)) = strlen(pval); |
||||
break; |
||||
case ECPGt_int: |
||||
case ECPGt_unsigned_int: |
||||
/* ((int *) ind)[act_tuple] = strlen(pval);*/ |
||||
*((int *) (ind + ind_offset * act_tuple)) = strlen(pval); |
||||
break; |
||||
case ECPGt_long: |
||||
case ECPGt_unsigned_long: |
||||
/* ((long *) ind)[act_tuple] = strlen(pval);*/ |
||||
*((long *) (ind + ind_offset * act_tuple)) = strlen(pval); |
||||
break; |
||||
#ifdef HAVE_LONG_LONG_INT_64 |
||||
case ECPGt_long_long: |
||||
case ECPGt_unsigned_long_long: |
||||
*((long long int *) (ind + ind_offset * act_tuple)) = strlen(pval); |
||||
break; |
||||
#endif /* HAVE_LONG_LONG_INT_64 */ |
||||
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); |
||||
|
||||
variable->len = strlen(pval); |
||||
if (varcharsize == 0) |
||||
strncpy(variable->arr, pval, variable->len); |
||||
else |
||||
strncpy(variable->arr, pval, varcharsize); |
||||
|
||||
if (varcharsize > 0 && variable->len > varcharsize) |
||||
{ |
||||
/* truncation */ |
||||
switch (ind_type) |
||||
{ |
||||
case ECPGt_short: |
||||
case ECPGt_unsigned_short: |
||||
/* ((short *) ind)[act_tuple] = variable->len;*/ |
||||
*((short *) (ind + offset * act_tuple)) = variable->len; |
||||
break; |
||||
case ECPGt_int: |
||||
case ECPGt_unsigned_int: |
||||
/* ((int *) ind)[act_tuple] = variable->len;*/ |
||||
*((int *) (ind + offset * act_tuple)) = variable->len; |
||||
break; |
||||
case ECPGt_long: |
||||
case ECPGt_unsigned_long: |
||||
/* ((long *) ind)[act_tuple] = variable->len;*/ |
||||
*((long *) (ind + offset * act_tuple)) = variable->len; |
||||
break; |
||||
#ifdef HAVE_LONG_LONG_INT_64 |
||||
case ECPGt_long_long: |
||||
case ECPGt_unsigned_long_long: |
||||
*((long long int *) (ind + ind_offset * act_tuple)) = variable->len; |
||||
break; |
||||
#endif /* HAVE_LONG_LONG_INT_64 */ |
||||
default: |
||||
break; |
||||
} |
||||
sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W'; |
||||
|
||||
variable->len = varcharsize; |
||||
} |
||||
} |
||||
break; |
||||
|
||||
case ECPGt_numeric: |
||||
if (pval) |
||||
{ |
||||
if (isarray && *pval == '"') |
||||
nres = PGTYPESnumeric_aton(pval + 1, &scan_length); |
||||
else |
||||
nres = PGTYPESnumeric_aton(pval, &scan_length); |
||||
|
||||
if (isarray && *scan_length == '"') |
||||
scan_length++; |
||||
|
||||
if ((isarray && *scan_length != ',' && *scan_length != '}') |
||||
|| (!isarray && *scan_length != '\0')) /* Garbage left */ |
||||
{ |
||||
ECPGraise(lineno, ECPG_FLOAT_FORMAT, pval); |
||||
return (false); |
||||
} |
||||
} |
||||
else |
||||
nres = PGTYPESnumeric_aton("0.0", &scan_length); |
||||
|
||||
PGTYPESnumeric_copy(nres, (NumericVar *)(var + offset * act_tuple)); |
||||
break; |
||||
|
||||
default: |
||||
ECPGraise(lineno, ECPG_UNSUPPORTED, ECPGtype_name(type)); |
||||
return (false); |
||||
break; |
||||
} |
||||
if (isarray) |
||||
{ |
||||
bool string = false; |
||||
|
||||
/* set array to next entry */ |
||||
++act_tuple; |
||||
|
||||
/* set pval to the next entry */ |
||||
for (; string || (*pval != ',' && *pval != '}'); ++pval) |
||||
if (*pval == '"') |
||||
string = string ? false : true; |
||||
|
||||
if (*pval == ',') |
||||
++pval; |
||||
} |
||||
} while (isarray && *pval != '}'); |
||||
|
||||
return (true); |
||||
} |
||||
@ -0,0 +1,449 @@ |
||||
/* dynamic SQL support routines
|
||||
* |
||||
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/descriptor.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ |
||||
*/ |
||||
|
||||
#include "postgres_fe.h" |
||||
#include "pg_type.h" |
||||
|
||||
#include "ecpgtype.h" |
||||
#include "ecpglib.h" |
||||
#include "ecpgerrno.h" |
||||
#include "extern.h" |
||||
#include "sqlca.h" |
||||
#include "sql3types.h" |
||||
|
||||
struct descriptor *all_descriptors = NULL; |
||||
|
||||
/* old internal convenience function that might go away later */ |
||||
static PGresult |
||||
* |
||||
ECPGresultByDescriptor(int line, const char *name) |
||||
{ |
||||
PGresult **resultpp = ECPGdescriptor_lvalue(line, name); |
||||
|
||||
if (resultpp) |
||||
return *resultpp; |
||||
return NULL; |
||||
} |
||||
|
||||
static unsigned int |
||||
ECPGDynamicType_DDT(Oid type) |
||||
{ |
||||
switch (type) |
||||
{ |
||||
case DATEOID: |
||||
return SQL3_DDT_DATE; |
||||
case TIMEOID: |
||||
return SQL3_DDT_TIME; |
||||
case TIMESTAMPOID: |
||||
return SQL3_DDT_TIMESTAMP; |
||||
case TIMESTAMPTZOID: |
||||
return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE; |
||||
case TIMETZOID: |
||||
return SQL3_DDT_TIME_WITH_TIME_ZONE; |
||||
default: |
||||
return SQL3_DDT_ILLEGAL; |
||||
} |
||||
} |
||||
|
||||
bool |
||||
ECPGget_desc_header(int lineno, char *desc_name, int *count) |
||||
{ |
||||
PGresult *ECPGresult; |
||||
|
||||
ECPGinit_sqlca(); |
||||
ECPGresult = ECPGresultByDescriptor(lineno, desc_name); |
||||
if (!ECPGresult) |
||||
return false; |
||||
|
||||
*count = PQnfields(ECPGresult); |
||||
sqlca.sqlerrd[2] = 1; |
||||
ECPGlog("ECPGget_desc_header: found %d attributes.\n", *count); |
||||
return true; |
||||
} |
||||
|
||||
static bool |
||||
get_int_item(int lineno, void *var, enum ECPGttype vartype, int value) |
||||
{ |
||||
switch (vartype) |
||||
{ |
||||
case ECPGt_short: |
||||
*(short *) var = (short) value; |
||||
break; |
||||
case ECPGt_int: |
||||
*(int *) var = (int) value; |
||||
break; |
||||
case ECPGt_long: |
||||
*(long *) var = (long) value; |
||||
break; |
||||
case ECPGt_unsigned_short: |
||||
*(unsigned short *) var = (unsigned short) value; |
||||
break; |
||||
case ECPGt_unsigned_int: |
||||
*(unsigned int *) var = (unsigned int) value; |
||||
break; |
||||
case ECPGt_unsigned_long: |
||||
*(unsigned long *) var = (unsigned long) value; |
||||
break; |
||||
#ifdef HAVE_LONG_LONG_INT_64 |
||||
case ECPGt_long_long: |
||||
*(long long int *) var = (long long int) value; |
||||
break; |
||||
case ECPGt_unsigned_long_long: |
||||
*(unsigned long long int *) var = (unsigned long long int) value; |
||||
break; |
||||
#endif /* HAVE_LONG_LONG_INT_64 */ |
||||
case ECPGt_float: |
||||
*(float *) var = (float) value; |
||||
break; |
||||
case ECPGt_double: |
||||
*(double *) var = (double) value; |
||||
break; |
||||
default: |
||||
ECPGraise(lineno, ECPG_VAR_NOT_NUMERIC, NULL); |
||||
return (false); |
||||
} |
||||
|
||||
return (true); |
||||
} |
||||
|
||||
static bool |
||||
get_char_item(int lineno, void *var, enum ECPGttype 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,...) |
||||
{ |
||||
va_list args; |
||||
PGresult *ECPGresult; |
||||
enum ECPGdtype type; |
||||
int ntuples, |
||||
act_tuple; |
||||
struct variable data_var; |
||||
|
||||
va_start(args, index); |
||||
ECPGinit_sqlca(); |
||||
ECPGresult = ECPGresultByDescriptor(lineno, desc_name); |
||||
if (!ECPGresult) |
||||
return (false); |
||||
|
||||
ntuples = PQntuples(ECPGresult); |
||||
if (ntuples < 1) |
||||
{ |
||||
ECPGraise(lineno, ECPG_NOT_FOUND, NULL); |
||||
return (false); |
||||
} |
||||
|
||||
if (index < 1 || index > PQnfields(ECPGresult)) |
||||
{ |
||||
ECPGraise(lineno, ECPG_INVALID_DESCRIPTOR_INDEX, NULL); |
||||
return (false); |
||||
} |
||||
|
||||
ECPGlog("ECPGget_desc: reading items for tuple %d\n", index); |
||||
--index; |
||||
|
||||
type = va_arg(args, enum ECPGdtype); |
||||
|
||||
memset(&data_var, 0, sizeof data_var); |
||||
data_var.type = ECPGt_EORT; |
||||
data_var.ind_type = ECPGt_NO_INDICATOR; |
||||
|
||||
while (type != ECPGd_EODT) |
||||
{ |
||||
char type_str[20]; |
||||
long varcharsize; |
||||
long offset; |
||||
long arrsize; |
||||
enum ECPGttype vartype; |
||||
void *var; |
||||
|
||||
vartype = va_arg(args, enum ECPGttype); |
||||
var = va_arg(args, void *); |
||||
varcharsize = va_arg(args, long); |
||||
arrsize = va_arg(args, long); |
||||
offset = va_arg(args, long); |
||||
|
||||
switch (type) |
||||
{ |
||||
case (ECPGd_indicator): |
||||
data_var.ind_type = vartype; |
||||
data_var.ind_pointer = var; |
||||
data_var.ind_varcharsize = varcharsize; |
||||
data_var.ind_arrsize = arrsize; |
||||
data_var.ind_offset = offset; |
||||
if (data_var.ind_arrsize == 0 || data_var.ind_varcharsize == 0) |
||||
data_var.ind_value = *((void **) (data_var.ind_pointer)); |
||||
else |
||||
data_var.ind_value = data_var.ind_pointer; |
||||
break; |
||||
|
||||
case ECPGd_data: |
||||
data_var.type = vartype; |
||||
data_var.pointer = var; |
||||
data_var.varcharsize = varcharsize; |
||||
data_var.arrsize = arrsize; |
||||
data_var.offset = offset; |
||||
if (data_var.arrsize == 0 || data_var.varcharsize == 0) |
||||
data_var.value = *((void **) (data_var.pointer)); |
||||
else |
||||
data_var.value = data_var.pointer; |
||||
break; |
||||
|
||||
case ECPGd_name: |
||||
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; |
||||
|
||||
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_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_di_code: |
||||
if (!get_int_item(lineno, var, vartype, ECPGDynamicType_DDT(PQftype(ECPGresult, index)))) |
||||
return (false); |
||||
|
||||
ECPGlog("ECPGget_desc: TYPE = %d\n", ECPGDynamicType_DDT(PQftype(ECPGresult, index))); |
||||
break; |
||||
|
||||
case ECPGd_cardinality: |
||||
if (!get_int_item(lineno, var, vartype, PQntuples(ECPGresult))) |
||||
return (false); |
||||
|
||||
ECPGlog("ECPGget_desc: CARDINALITY = %d\n", PQntuples(ECPGresult)); |
||||
break; |
||||
|
||||
case ECPGd_ret_length: |
||||
case ECPGd_ret_octet: |
||||
|
||||
/*
|
||||
* this is like ECPGstore_result |
||||
*/ |
||||
if (arrsize > 0 && ntuples > arrsize) |
||||
{ |
||||
ECPGlog("ECPGget_desc line %d: Incorrect number of matches: %d don't fit into array of %d\n", |
||||
lineno, ntuples, arrsize); |
||||
ECPGraise(lineno, ECPG_TOO_MANY_MATCHES, NULL); |
||||
return false; |
||||
} |
||||
/* allocate storage if needed */ |
||||
if (arrsize == 0 && var != NULL && *(void **) var == NULL) |
||||
{ |
||||
void *mem = (void *) ECPGalloc(offset * ntuples, lineno); |
||||
|
||||
*(void **) var = mem; |
||||
ECPGadd_mem(mem, lineno); |
||||
var = mem; |
||||
} |
||||
|
||||
for (act_tuple = 0; act_tuple < ntuples; act_tuple++) |
||||
{ |
||||
if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, act_tuple, index))) |
||||
return (false); |
||||
var = (char *) var + offset; |
||||
ECPGlog("ECPGget_desc: RETURNED[%d] = %d\n", act_tuple, PQgetlength(ECPGresult, act_tuple, index)); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
snprintf(type_str, sizeof(type_str), "%d", type); |
||||
ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, type_str); |
||||
return (false); |
||||
} |
||||
|
||||
type = va_arg(args, enum ECPGdtype); |
||||
} |
||||
|
||||
if (data_var.type != ECPGt_EORT) |
||||
{ |
||||
struct statement stmt; |
||||
char *oldlocale; |
||||
|
||||
/* Make sure we do NOT honor the locale for numeric input */ |
||||
/* since the database gives the standard decimal point */ |
||||
oldlocale = strdup(setlocale(LC_NUMERIC, NULL)); |
||||
setlocale(LC_NUMERIC, "C"); |
||||
|
||||
memset(&stmt, 0, sizeof stmt); |
||||
stmt.lineno = lineno; |
||||
|
||||
/* desparate try to guess something sensible */ |
||||
stmt.connection = ECPGget_connection(NULL); |
||||
ECPGstore_result(ECPGresult, index, &stmt, &data_var); |
||||
|
||||
setlocale(LC_NUMERIC, oldlocale); |
||||
ECPGfree(oldlocale); |
||||
} |
||||
else if (data_var.ind_type != ECPGt_NO_INDICATOR) |
||||
{ |
||||
/*
|
||||
* this is like ECPGstore_result but since we don't have a data |
||||
* variable at hand, we can't call it |
||||
*/ |
||||
if (data_var.ind_arrsize > 0 && ntuples > data_var.ind_arrsize) |
||||
{ |
||||
ECPGlog("ECPGget_desc line %d: Incorrect number of matches (indicator): %d don't fit into array of %d\n", |
||||
lineno, ntuples, data_var.ind_arrsize); |
||||
ECPGraise(lineno, ECPG_TOO_MANY_MATCHES, NULL); |
||||
return false; |
||||
} |
||||
/* allocate storage if needed */ |
||||
if (data_var.ind_arrsize == 0 && data_var.ind_pointer != NULL && data_var.ind_value == NULL) |
||||
{ |
||||
void *mem = (void *) ECPGalloc(data_var.ind_offset * ntuples, lineno); |
||||
|
||||
*(void **) data_var.ind_pointer = mem; |
||||
ECPGadd_mem(mem, lineno); |
||||
data_var.ind_value = mem; |
||||
} |
||||
for (act_tuple = 0; act_tuple < ntuples; act_tuple++) |
||||
{ |
||||
if (!get_int_item(lineno, data_var.ind_value, data_var.ind_type, -PQgetisnull(ECPGresult, act_tuple, index))) |
||||
return (false); |
||||
data_var.ind_value = (char *) data_var.ind_value + data_var.ind_offset; |
||||
ECPGlog("ECPGget_desc: INDICATOR[%d] = %d\n", act_tuple, -PQgetisnull(ECPGresult, act_tuple, index)); |
||||
} |
||||
} |
||||
sqlca.sqlerrd[2] = ntuples; |
||||
return (true); |
||||
} |
||||
|
||||
bool |
||||
ECPGdeallocate_desc(int line, const char *name) |
||||
{ |
||||
struct descriptor *i; |
||||
struct descriptor **lastptr = &all_descriptors; |
||||
|
||||
ECPGinit_sqlca(); |
||||
for (i = all_descriptors; i; lastptr = &i->next, i = i->next) |
||||
{ |
||||
if (!strcmp(name, i->name)) |
||||
{ |
||||
*lastptr = i->next; |
||||
ECPGfree(i->name); |
||||
PQclear(i->result); |
||||
ECPGfree(i); |
||||
return true; |
||||
} |
||||
} |
||||
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, name); |
||||
return false; |
||||
} |
||||
|
||||
bool |
||||
ECPGallocate_desc(int line, const char *name) |
||||
{ |
||||
struct descriptor *new; |
||||
|
||||
ECPGinit_sqlca(); |
||||
new = (struct descriptor *) ECPGalloc(sizeof(struct descriptor), line); |
||||
if (!new) |
||||
return false; |
||||
new->next = all_descriptors; |
||||
new->name = ECPGalloc(strlen(name) + 1, line); |
||||
if (!new->name) |
||||
{ |
||||
ECPGfree(new); |
||||
return false; |
||||
} |
||||
new->result = PQmakeEmptyPGresult(NULL, 0); |
||||
if (!new->result) |
||||
{ |
||||
ECPGfree(new->name); |
||||
ECPGfree(new); |
||||
ECPGraise(line, ECPG_OUT_OF_MEMORY, NULL); |
||||
return false; |
||||
} |
||||
strcpy(new->name, name); |
||||
all_descriptors = new; |
||||
return true; |
||||
} |
||||
|
||||
PGresult ** |
||||
ECPGdescriptor_lvalue(int line, const char *descriptor) |
||||
{ |
||||
struct descriptor *i; |
||||
|
||||
for (i = all_descriptors; i != NULL; i = i->next) |
||||
{ |
||||
if (!strcmp(descriptor, i->name)) |
||||
return &i->result; |
||||
} |
||||
|
||||
ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, (char *) descriptor); |
||||
return NULL; |
||||
} |
||||
@ -0,0 +1,198 @@ |
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/error.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */ |
||||
|
||||
#include "postgres_fe.h" |
||||
|
||||
#include <stdio.h> |
||||
|
||||
#include "ecpgerrno.h" |
||||
#include "ecpgtype.h" |
||||
#include "ecpglib.h" |
||||
#include "extern.h" |
||||
#include "sqlca.h" |
||||
|
||||
/* This should hold the back-end error message from
|
||||
* the last back-end operation. */ |
||||
static char *ECPGerr; |
||||
|
||||
void |
||||
ECPGraise(int line, int code, const char *str) |
||||
{ |
||||
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_ARRAY: |
||||
snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc), |
||||
"Variable is not an array in line %d.", line); |
||||
break; |
||||
|
||||
case ECPG_DATA_NOT_ARRAY: |
||||
snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc), |
||||
"Data read from backend is not an array in line %d.", line); |
||||
break; |
||||
|
||||
case ECPG_ARRAY_INSERT: |
||||
snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc), |
||||
"Trying to insert an array of variables 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 to '%s' in line %d.", str, line); |
||||
break; |
||||
|
||||
case ECPG_INVALID_STMT: |
||||
snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc), |
||||
"Invalid statement name %s in line %d.", str, line); |
||||
break; |
||||
|
||||
case ECPG_UNKNOWN_DESCRIPTOR: |
||||
snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc), |
||||
"Descriptor %s not found in line %d.", str, line); |
||||
break; |
||||
|
||||
case ECPG_INVALID_DESCRIPTOR_INDEX: |
||||
snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc), |
||||
"Descriptor 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: |
||||
{ |
||||
int slen = strlen(str); |
||||
|
||||
/* strip trailing newline */ |
||||
if (slen > 0 && str[slen - 1] == '\n') |
||||
slen--; |
||||
snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc), |
||||
"'%.*s' in line %d.", slen, 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); |
||||
ECPGlog("raising sqlcode %d in line %d, '%s'.\n", code, line, sqlca.sqlerrm.sqlerrmc); |
||||
|
||||
/* free all memory we have allocated for the user */ |
||||
ECPGfree_auto_mem(); |
||||
} |
||||
|
||||
/* Set the error message string from the backend */ |
||||
void |
||||
set_backend_err(const char *err, int lineno) |
||||
{ |
||||
if (ECPGerr) |
||||
ECPGfree(ECPGerr); |
||||
|
||||
if (!err) |
||||
{ |
||||
ECPGerr = NULL; |
||||
return; |
||||
} |
||||
|
||||
ECPGerr = ECPGstrdup(err, lineno); |
||||
} |
||||
|
||||
/* Retrieve the error message from the backend. */ |
||||
char * |
||||
ECPGerrmsg(void) |
||||
{ |
||||
return ECPGerr; |
||||
} |
||||
|
||||
/* print out an error message */ |
||||
void |
||||
sqlprint(void) |
||||
{ |
||||
sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0'; |
||||
fprintf(stderr, "sql error %s\n", sqlca.sqlerrm.sqlerrmc); |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,103 @@ |
||||
#ifndef _ECPG_LIB_EXTERN_H |
||||
#define _ECPG_LIB_EXTERN_H |
||||
|
||||
#include "postgres_fe.h" |
||||
#include "libpq-fe.h" |
||||
|
||||
/* Here are some methods used by the lib. */ |
||||
|
||||
/* Stores the backend error message for client access */ |
||||
void set_backend_err(const char *err, int lineon); |
||||
|
||||
/* Store and retrieve the backend error message for client access */ |
||||
void set_backend_err(const char *err, int lineon); |
||||
char *ECPGerrmsg(void); |
||||
|
||||
/* Returns a pointer to a string containing a simple type name. */ |
||||
void ECPGadd_mem(void *ptr, int lineno); |
||||
|
||||
bool ECPGget_data(const PGresult *, int, int, int, enum ECPGttype type, |
||||
enum ECPGttype, char *, char *, long, long, long, bool); |
||||
struct connection *ECPGget_connection(const char *); |
||||
void ECPGinit_sqlca(void); |
||||
char *ECPGalloc(long, int); |
||||
char *ECPGrealloc(void *, long, int); |
||||
void ECPGfree(void *); |
||||
bool ECPGinit(const struct connection *, const char *, const int); |
||||
char *ECPGstrdup(const char *, int); |
||||
const char *ECPGtype_name(enum ECPGttype); |
||||
unsigned int ECPGDynamicType(Oid); |
||||
void ECPGfree_auto_mem(void); |
||||
void ECPGclear_auto_mem(void); |
||||
|
||||
/* A generic varchar type. */ |
||||
struct ECPGgeneric_varchar |
||||
{ |
||||
int len; |
||||
char arr[1]; |
||||
}; |
||||
|
||||
/*
|
||||
* type information cache |
||||
*/ |
||||
|
||||
struct ECPGtype_information_cache |
||||
{ |
||||
struct ECPGtype_information_cache *next; |
||||
int oid; |
||||
bool isarray; |
||||
}; |
||||
|
||||
/* structure to store one statement */ |
||||
struct statement |
||||
{ |
||||
int lineno; |
||||
char *command; |
||||
struct connection *connection; |
||||
struct variable *inlist; |
||||
struct variable *outlist; |
||||
}; |
||||
|
||||
/* structure to store connections */ |
||||
struct connection |
||||
{ |
||||
char *name; |
||||
PGconn *connection; |
||||
bool committed; |
||||
int autocommit; |
||||
struct ECPGtype_information_cache *cache_head; |
||||
struct connection *next; |
||||
}; |
||||
|
||||
/* structure to store descriptors */ |
||||
struct descriptor |
||||
{ |
||||
char *name; |
||||
PGresult *result; |
||||
struct descriptor *next; |
||||
}; |
||||
|
||||
struct variable |
||||
{ |
||||
enum ECPGttype type; |
||||
void *value; |
||||
void *pointer; |
||||
long varcharsize; |
||||
long arrsize; |
||||
long offset; |
||||
enum ECPGttype ind_type; |
||||
void *ind_value; |
||||
void *ind_pointer; |
||||
long ind_varcharsize; |
||||
long ind_arrsize; |
||||
long ind_offset; |
||||
struct variable *next; |
||||
}; |
||||
|
||||
PGresult ** |
||||
ECPGdescriptor_lvalue(int line, const char *descriptor); |
||||
|
||||
bool ECPGstore_result(const PGresult *results, int act_field, |
||||
const struct statement * stmt, struct variable * var); |
||||
|
||||
#endif /* _ECPG_LIB_EXTERN_H */ |
||||
@ -0,0 +1,109 @@ |
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/memory.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */ |
||||
|
||||
#include "postgres_fe.h" |
||||
|
||||
#include "ecpgtype.h" |
||||
#include "ecpglib.h" |
||||
#include "ecpgerrno.h" |
||||
#include "extern.h" |
||||
|
||||
void |
||||
ECPGfree(void *ptr) |
||||
{ |
||||
free(ptr); |
||||
} |
||||
|
||||
char * |
||||
ECPGalloc(long size, int lineno) |
||||
{ |
||||
char *new = (char *) calloc(1L, size); |
||||
|
||||
if (!new) |
||||
{ |
||||
ECPGraise(lineno, ECPG_OUT_OF_MEMORY, NULL); |
||||
return NULL; |
||||
} |
||||
|
||||
memset(new, '\0', size); |
||||
return (new); |
||||
} |
||||
|
||||
char * |
||||
ECPGrealloc(void *ptr, long size, int lineno) |
||||
{ |
||||
char *new = (char *) realloc(ptr, size); |
||||
|
||||
if (!new) |
||||
{ |
||||
ECPGraise(lineno, ECPG_OUT_OF_MEMORY, NULL); |
||||
return NULL; |
||||
} |
||||
|
||||
return (new); |
||||
} |
||||
|
||||
char * |
||||
ECPGstrdup(const char *string, int lineno) |
||||
{ |
||||
char *new = strdup(string); |
||||
|
||||
if (!new) |
||||
{ |
||||
ECPGraise(lineno, ECPG_OUT_OF_MEMORY, NULL); |
||||
return NULL; |
||||
} |
||||
|
||||
return (new); |
||||
} |
||||
|
||||
/* keep a list of memory we allocated for the user */ |
||||
static struct auto_mem |
||||
{ |
||||
void *pointer; |
||||
struct auto_mem *next; |
||||
} *auto_allocs = NULL; |
||||
|
||||
void |
||||
ECPGadd_mem(void *ptr, int lineno) |
||||
{ |
||||
struct auto_mem *am = (struct auto_mem *) ECPGalloc(sizeof(struct auto_mem), lineno); |
||||
|
||||
am->pointer = ptr; |
||||
am->next = auto_allocs; |
||||
auto_allocs = am; |
||||
} |
||||
|
||||
void |
||||
ECPGfree_auto_mem(void) |
||||
{ |
||||
struct auto_mem *am; |
||||
|
||||
/* free all memory we have allocated for the user */ |
||||
for (am = auto_allocs; am;) |
||||
{ |
||||
struct auto_mem *act = am; |
||||
|
||||
am = am->next; |
||||
ECPGfree(act->pointer); |
||||
ECPGfree(act); |
||||
} |
||||
|
||||
auto_allocs = NULL; |
||||
} |
||||
|
||||
void |
||||
ECPGclear_auto_mem(void) |
||||
{ |
||||
struct auto_mem *am; |
||||
|
||||
/* free just our own structure */ |
||||
for (am = auto_allocs; am;) |
||||
{ |
||||
struct auto_mem *act = am; |
||||
|
||||
am = am->next; |
||||
ECPGfree(act); |
||||
} |
||||
|
||||
auto_allocs = NULL; |
||||
} |
||||
@ -0,0 +1,149 @@ |
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/misc.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */ |
||||
|
||||
#include "postgres_fe.h" |
||||
|
||||
#include <unistd.h> |
||||
#include "ecpgtype.h" |
||||
#include "ecpglib.h" |
||||
#include "ecpgerrno.h" |
||||
#include "extern.h" |
||||
#include "sqlca.h" |
||||
|
||||
static struct sqlca sqlca_init = |
||||
{ |
||||
{ |
||||
'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' ' |
||||
}, |
||||
sizeof(struct sqlca), |
||||
0, |
||||
{ |
||||
0, |
||||
{ |
||||
0 |
||||
} |
||||
}, |
||||
{ |
||||
'N', 'O', 'T', ' ', 'S', 'E', 'T', ' ' |
||||
}, |
||||
{ |
||||
0, 0, 0, 0, 0, 0 |
||||
}, |
||||
{ |
||||
0, 0, 0, 0, 0, 0, 0, 0 |
||||
}, |
||||
{ |
||||
0, 0, 0, 0, 0, 0, 0, 0 |
||||
} |
||||
}; |
||||
|
||||
static int simple_debug = 0; |
||||
static FILE *debugstream = NULL; |
||||
|
||||
void |
||||
ECPGinit_sqlca(void) |
||||
{ |
||||
memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca)); |
||||
} |
||||
|
||||
bool |
||||
ECPGinit(const struct connection * con, const char *connection_name, const int lineno) |
||||
{ |
||||
ECPGinit_sqlca(); |
||||
if (con == NULL) |
||||
{ |
||||
ECPGraise(lineno, ECPG_NO_CONN, connection_name ? connection_name : "NULL"); |
||||
return (false); |
||||
} |
||||
|
||||
return (true); |
||||
} |
||||
|
||||
bool |
||||
ECPGstatus(int lineno, const char *connection_name) |
||||
{ |
||||
struct connection *con = ECPGget_connection(connection_name); |
||||
|
||||
if (!ECPGinit(con, connection_name, lineno)) |
||||
return (false); |
||||
|
||||
/* are we connected? */ |
||||
if (con->connection == NULL) |
||||
{ |
||||
ECPGraise(lineno, ECPG_NOT_CONN, con->name); |
||||
return false; |
||||
} |
||||
|
||||
return (true); |
||||
} |
||||
|
||||
bool |
||||
ECPGtrans(int lineno, const char *connection_name, const char *transaction) |
||||
{ |
||||
PGresult *res; |
||||
struct connection *con = ECPGget_connection(connection_name); |
||||
|
||||
if (!ECPGinit(con, connection_name, lineno)) |
||||
return (false); |
||||
|
||||
ECPGlog("ECPGtrans line %d action = %s connection = %s\n", lineno, transaction, con->name); |
||||
|
||||
/* if we have no connection we just simulate the command */ |
||||
if (con && con->connection) |
||||
{ |
||||
/*
|
||||
* if we are not in autocommit mode, already have committed the |
||||
* transaction and get another commit, just ignore it |
||||
*/ |
||||
if (!con->committed || con->autocommit) |
||||
{ |
||||
if ((res = PQexec(con->connection, transaction)) == NULL) |
||||
{ |
||||
ECPGraise(lineno, ECPG_TRANS, NULL); |
||||
return FALSE; |
||||
} |
||||
PQclear(res); |
||||
} |
||||
} |
||||
|
||||
if (strcmp(transaction, "commit") == 0 || strcmp(transaction, "rollback") == 0) |
||||
{ |
||||
con->committed = true; |
||||
|
||||
/* deallocate all prepared statements */ |
||||
if (!ECPGdeallocate_all(lineno)) |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
|
||||
void |
||||
ECPGdebug(int n, FILE *dbgs) |
||||
{ |
||||
simple_debug = n; |
||||
debugstream = dbgs; |
||||
ECPGlog("ECPGdebug: set to %d\n", simple_debug); |
||||
} |
||||
|
||||
void |
||||
ECPGlog(const char *format,...) |
||||
{ |
||||
va_list ap; |
||||
|
||||
if (simple_debug) |
||||
{ |
||||
char *f = (char *) malloc(strlen(format) + 100); |
||||
|
||||
if (!f) |
||||
return; |
||||
|
||||
sprintf(f, "[%d]: %s", (int) getpid(), format); |
||||
|
||||
va_start(ap, format); |
||||
vfprintf(debugstream, f, ap); |
||||
va_end(ap); |
||||
|
||||
ECPGfree(f); |
||||
} |
||||
} |
||||
@ -0,0 +1,73 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* pg_type.h |
||||
* definition of the system "type" relation (pg_type) |
||||
* along with the relation's initial contents. |
||||
* |
||||
* |
||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group |
||||
* Portions Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* $Id: pg_type.h,v 1.1 2003/03/16 10:42:53 meskes Exp $ |
||||
* |
||||
* NOTES |
||||
* the genbki.sh script reads this file and generates .bki |
||||
* information from the DATA() statements. |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef PG_TYPE_H |
||||
#define PG_TYPE_H |
||||
|
||||
/* ----------------
|
||||
* initial contents of pg_type |
||||
* ---------------- |
||||
*/ |
||||
|
||||
/* keep the following ordered by OID so that later changes can be made easier*/ |
||||
|
||||
/* OIDS 1 - 99 */ |
||||
#define BOOLOID 16 |
||||
#define BYTEAOID 17 |
||||
#define CHAROID 18 |
||||
#define NAMEOID 19 |
||||
#define INT8OID 20 |
||||
#define INT2OID 21 |
||||
#define INT2VECTOROID 22 |
||||
#define INT4OID 23 |
||||
#define REGPROCOID 24 |
||||
#define TEXTOID 25 |
||||
#define OIDOID 26 |
||||
#define TIDOID 27 |
||||
#define XIDOID 28 |
||||
#define CIDOID 29 |
||||
#define OIDVECTOROID 30 |
||||
#define POINTOID 600 |
||||
#define LSEGOID 601 |
||||
#define PATHOID 602 |
||||
#define BOXOID 603 |
||||
#define POLYGONOID 604 |
||||
#define LINEOID 628 |
||||
#define FLOAT4OID 700 |
||||
#define FLOAT8OID 701 |
||||
#define ABSTIMEOID 702 |
||||
#define RELTIMEOID 703 |
||||
#define TINTERVALOID 704 |
||||
#define UNKNOWNOID 705 |
||||
#define CIRCLEOID 718 |
||||
#define CASHOID 790 |
||||
#define INETOID 869 |
||||
#define CIDROID 650 |
||||
#define BPCHAROID 1042 |
||||
#define VARCHAROID 1043 |
||||
#define DATEOID 1082 |
||||
#define TIMEOID 1083 |
||||
#define TIMESTAMPOID 1114 |
||||
#define TIMESTAMPTZOID 1184 |
||||
#define INTERVALOID 1186 |
||||
#define TIMETZOID 1266 |
||||
#define ZPBITOID 1560 |
||||
#define VARBITOID 1562 |
||||
#define NUMERICOID 1700 |
||||
|
||||
#endif /* PG_TYPE_H */ |
||||
@ -0,0 +1,155 @@ |
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */ |
||||
|
||||
#include "postgres_fe.h" |
||||
|
||||
#include <ctype.h> |
||||
|
||||
#include "ecpgtype.h" |
||||
#include "ecpglib.h" |
||||
#include "ecpgerrno.h" |
||||
#include "extern.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 *) ECPGalloc(sizeof(struct prepared_statement), lineno); |
||||
if (!this) |
||||
return false; |
||||
|
||||
stmt = (struct statement *) ECPGalloc(sizeof(struct statement), lineno); |
||||
if (!stmt) |
||||
{ |
||||
ECPGfree(this); |
||||
return false; |
||||
} |
||||
|
||||
/* create statement */ |
||||
stmt->lineno = lineno; |
||||
stmt->connection = NULL; |
||||
stmt->command = ECPGstrdup(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 = ECPGstrdup(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 */ |
||||
ECPGfree(this->name); |
||||
ECPGfree(this->stmt->command); |
||||
ECPGfree(this->stmt); |
||||
if (prev != NULL) |
||||
prev->next = this->next; |
||||
else |
||||
prep_stmts = this->next; |
||||
|
||||
ECPGfree(this); |
||||
return true; |
||||
} |
||||
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 true; |
||||
} |
||||
|
||||
/* 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; |
||||
} |
||||
@ -0,0 +1,90 @@ |
||||
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/typename.c,v 1.1 2003/03/16 10:42:53 meskes Exp $ */ |
||||
|
||||
#include "postgres_fe.h" |
||||
|
||||
#include <stdlib.h> |
||||
#include "ecpgtype.h" |
||||
#include "ecpglib.h" |
||||
#include "extern.h" |
||||
#include "sql3types.h" |
||||
#include "pg_type.h" |
||||
|
||||
/*
|
||||
* This function is used to generate the correct type names. |
||||
*/ |
||||
const char * |
||||
ECPGtype_name(enum ECPGttype typ) |
||||
{ |
||||
switch (typ) |
||||
{ |
||||
case ECPGt_char: |
||||
return "char"; |
||||
case ECPGt_unsigned_char: |
||||
return "unsigned char"; |
||||
case ECPGt_short: |
||||
return "short"; |
||||
case ECPGt_unsigned_short: |
||||
return "unsigned short"; |
||||
case ECPGt_int: |
||||
return "int"; |
||||
case ECPGt_unsigned_int: |
||||
return "unsigned int"; |
||||
case ECPGt_long: |
||||
return "long"; |
||||
case ECPGt_unsigned_long: |
||||
return "unsigned long"; |
||||
case ECPGt_long_long: |
||||
return "long long"; |
||||
case ECPGt_unsigned_long_long: |
||||
return "unsigned long long"; |
||||
case ECPGt_float: |
||||
return "float"; |
||||
case ECPGt_double: |
||||
return "double"; |
||||
case ECPGt_bool: |
||||
return "bool"; |
||||
case ECPGt_varchar: |
||||
return "varchar"; |
||||
case ECPGt_char_variable: |
||||
return "char"; |
||||
case ECPGt_numeric: |
||||
return "numeric"; |
||||
default: |
||||
abort(); |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
unsigned int |
||||
ECPGDynamicType(Oid type) |
||||
{ |
||||
switch (type) |
||||
{ |
||||
case BOOLOID: |
||||
return SQL3_BOOLEAN; /* bool */ |
||||
case INT2OID: |
||||
return SQL3_SMALLINT; /* int2 */ |
||||
case INT4OID: |
||||
return SQL3_INTEGER; /* int4 */ |
||||
case TEXTOID: |
||||
return SQL3_CHARACTER; /* text */ |
||||
case FLOAT4OID: |
||||
return SQL3_REAL; /* float4 */ |
||||
case FLOAT8OID: |
||||
return SQL3_DOUBLE_PRECISION; /* float8 */ |
||||
case BPCHAROID: |
||||
return SQL3_CHARACTER; /* bpchar */ |
||||
case VARCHAROID: |
||||
return SQL3_CHARACTER_VARYING; /* varchar */ |
||||
case DATEOID: |
||||
return SQL3_DATE_TIME_TIMESTAMP; /* date */ |
||||
case TIMEOID: |
||||
return SQL3_DATE_TIME_TIMESTAMP; /* time */ |
||||
case TIMESTAMPOID: |
||||
return SQL3_DATE_TIME_TIMESTAMP; /* datetime */ |
||||
case NUMERICOID: |
||||
return SQL3_NUMERIC; /* numeric */ |
||||
default: |
||||
return -type; |
||||
} |
||||
} |
||||
@ -0,0 +1,43 @@ |
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile for ecpg library
|
||||
#
|
||||
# Copyright (c) 1994, Regents of the University of California
|
||||
#
|
||||
# $Header: /cvsroot/pgsql/src/interfaces/ecpg/pgtypeslib/Makefile,v 1.1 2003/03/16 10:42:54 meskes Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
subdir = src/interfaces/ecpg/pgtypeslib
|
||||
top_builddir = ../../../..
|
||||
include $(top_builddir)/src/Makefile.global |
||||
|
||||
NAME= pgtypes
|
||||
SO_MAJOR_VERSION= 1
|
||||
SO_MINOR_VERSION= 0.0
|
||||
|
||||
override CPPFLAGS := -g -I$(top_srcdir)/src/interfaces/ecpg/include -I$(top_srcdir)/src/include/utils $(CPPFLAGS) |
||||
|
||||
OBJS= numeric.o
|
||||
|
||||
all: all-lib |
||||
|
||||
# Shared library stuff
|
||||
include $(top_srcdir)/src/Makefile.shlib |
||||
|
||||
install: all installdirs install-lib |
||||
|
||||
installdirs: |
||||
$(mkinstalldirs) $(DESTDIR)$(libdir)
|
||||
|
||||
uninstall: uninstall-lib |
||||
|
||||
clean distclean maintainer-clean: clean-lib |
||||
rm -f $(OBJS)
|
||||
|
||||
depend dep: |
||||
$(CC) -MM $(CFLAGS) *.c >depend
|
||||
|
||||
ifeq (depend,$(wildcard depend)) |
||||
include depend |
||||
endif |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,56 @@ |
||||
#include <stdio.h> |
||||
|
||||
int |
||||
main() |
||||
{ |
||||
char *text="error\n"; |
||||
NumericVar *value1, *value2, *res; |
||||
exec sql begin declare section; |
||||
decimal(14,7) des = {0, 0, 0, 0, 0, NULL, NULL} ; |
||||
exec sql end declare section; |
||||
double d; |
||||
FILE *dbgs; |
||||
|
||||
if ((dbgs = fopen("log", "w")) != NULL) |
||||
ECPGdebug(1, dbgs); |
||||
exec sql whenever sqlerror do sqlprint(); |
||||
|
||||
exec sql connect to mm; |
||||
exec sql create table test (text char(5), num decimal(14,7)); |
||||
|
||||
value1 = PGTYPESnew(); |
||||
PGTYPESnumeric_iton(1407, value1); |
||||
text = PGTYPESnumeric_ntoa(value1); |
||||
printf("long = %s\n", text); |
||||
|
||||
value1 = PGTYPESnumeric_aton("2369.7", -1); |
||||
value2 = PGTYPESnumeric_aton("10.0", -1); |
||||
res = PGTYPESnew(); |
||||
decadd(value1, value2, res); |
||||
text = PGTYPESnumeric_ntoa(res); |
||||
printf("add = %s\n", text); |
||||
|
||||
PGTYPESnumeric_sub(res, value2, res); |
||||
text = PGTYPESnumeric_ntoa(res); |
||||
printf("sub = %s\n", text); |
||||
|
||||
PGTYPESnumeric_copy(res, &des); |
||||
exec sql insert into test (text, num) values ('test', :des); |
||||
|
||||
value2 = PGTYPESnumeric_aton("2369.7", -1); |
||||
PGTYPESnumeric_mul(value1, value2, res); |
||||
|
||||
exec sql select num into :des from test where text = 'test'; |
||||
|
||||
PGTYPESnumeric_mul(res, &des, res); |
||||
text = PGTYPESnumeric_ntoa(res); |
||||
printf("mul = %s\n", text); |
||||
|
||||
value2 = PGTYPESnumeric_aton("10000", -1); |
||||
PGTYPESnumeric_div(res, value2, res); |
||||
text = PGTYPESnumeric_ntoa(res); |
||||
PGTYPESnumeric_ntod(res, &d); |
||||
printf("div = %s %e\n", text, d); |
||||
return (0); |
||||
} |
||||
|
||||
Loading…
Reference in new issue