- Synced preproc.y with gram.y.
- Much more clean ups.
+
+Wed Feb 23 17:08:28 CET 2000
+
+ - Even more clean ups.
- Set library version to 3.1.0.
- Set ecpg version to 2.7.0.
#define ECPG_INVALID_DESCRIPTOR_INDEX -241
#define ECPG_UNKNOWN_DESCRIPTOR_ITEM -242
#define ECPG_VAR_NOT_NUMERIC -243
+#define ECPG_VAR_NOT_CHAR -244
/* finally the backend error messages, they start at 400 */
#define ECPG_PGSQL -400
bool ECPGdisconnect(int, const char *);
bool ECPGprepare(int, char *, char *);
bool ECPGdeallocate(int, char *);
+ bool ECPGdeallocate_all(int);
char *ECPGprepared_statement(char *);
void ECPGlog(const char *format,...);
-
+
+ /* print an error message */
+ void sqlprint(void);
+
#ifdef LIBPQ_FE_H
bool ECPGsetdb(PGconn *);
-
#endif
/* Here are some methods used by the lib. */
/* Returns a pointer to a string containing a simple type name. */
const char *ECPGtype_name(enum ECPGttype);
+ bool get_data(PGresult *, int, int, int, enum ECPGttype type,
+ enum ECPGttype, void *, void *, long, long);
+ char *ecpg_alloc(long, int);
+ char *ecpg_strdup(const char *, int);
-/* A generic varchar type. */
- struct ECPGgeneric_varchar
- {
- int len;
- char arr[1];
- };
-
-/* print an error message */
- void sqlprint(void);
-
- struct cursor
- {
- const char *name;
- char *command;
- struct cursor *next;
- };
+/* and some vars */
+ extern struct auto_mem *auto_allocs;
/* define this for simplicity as well as compatibility */
/* dynamic SQL */
- unsigned int ECPGDynamicType(Oid type);
- unsigned int ECPGDynamicType_DDT(Oid type);
- PGresult * ECPGresultByDescriptor(int line,const char *name);
bool ECPGdo_descriptor(int line,const char *connection,
const char *descriptor,const char *query);
bool ECPGdeallocate_desc(int line,const char *name);
# Copyright (c) 1994, Regents of the University of California
#
# IDENTIFICATION
-# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.59 2000/02/22 19:57:05 meskes Exp $
+# $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/Makefile.in,v 1.60 2000/02/23 19:25:42 meskes Exp $
#
#-------------------------------------------------------------------------
CFLAGS+= $(KRBFLAGS)
endif
-OBJS= ecpglib.o typename.o descriptor.o
+OBJS= ecpglib.o typename.o descriptor.o data.o error.o prepare.o memory.o
SHLIB_LINK= -L../../libpq -lpq
--- /dev/null
+#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);
+}
#include <ecpgtype.h>
#include <ecpglib.h>
+#include <sql3types.h>
+
+struct descriptor
+{
+ char *name;
+ PGresult *result;
+ struct descriptor *next;
+} *all_descriptors = NULL;
+
+static PGresult
+*ECPGresultByDescriptor(int line,const char *name)
+{
+ struct descriptor *i;
+
+ for (i = all_descriptors; i != NULL; i = i->next)
+ {
+ if (!strcmp(name, i->name)) return i->result;
+ }
+
+ ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, name);
+
+ return NULL;
+}
+
+static unsigned int
+ECPGDynamicType(Oid type)
+{
+ switch(type)
+ {
+ case 16: return SQL3_BOOLEAN; /* bool */
+ case 21: return SQL3_SMALLINT; /* int2 */
+ case 23: return SQL3_INTEGER; /* int4 */
+ case 25: return SQL3_CHARACTER; /* text */
+ case 700: return SQL3_REAL; /* float4 */
+ case 701: return SQL3_DOUBLE_PRECISION; /* float8 */
+ case 1042: return SQL3_CHARACTER; /* bpchar */
+ case 1043: return SQL3_CHARACTER_VARYING; /* varchar */
+ case 1082: return SQL3_DATE_TIME_TIMESTAMP; /* date */
+ case 1083: return SQL3_DATE_TIME_TIMESTAMP; /* time */
+ case 1184: return SQL3_DATE_TIME_TIMESTAMP; /* datetime */
+ case 1296: return SQL3_DATE_TIME_TIMESTAMP; /* timestamp */
+ case 1700: return SQL3_NUMERIC; /* numeric */
+ default: return -type;
+ }
+}
+
+#if 0
+static unsigned int
+ECPGDynamicType_DDT(Oid type)
+{
+ switch(type)
+ {
+ case 1082: return SQL3_DDT_DATE; /* date */
+ case 1083: return SQL3_DDT_TIME; /* time */
+ case 1184: return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE; /* datetime */
+ case 1296: return SQL3_DDT_TIMESTAMP_WITH_TIME_ZONE; /* timestamp */
+ default:
+ return SQL3_DDT_ILLEGAL;
+ }
+}
+#endif
+
bool
ECPGget_desc_header(int lineno, char * desc_name, int *count)
{
return(true);
}
+static bool
+get_char_item(int lineno, void *var, enum ECPGdtype vartype, char *value, int varcharsize)
+{
+ switch (vartype)
+ {
+ case ECPGt_char:
+ case ECPGt_unsigned_char:
+ strncpy((char *) var, value, varcharsize);
+ break;
+ case ECPGt_varchar:
+ {
+ struct ECPGgeneric_varchar *variable =
+ (struct ECPGgeneric_varchar *) var;
+
+ if (varcharsize == 0)
+ strncpy(variable->arr, value, strlen(value));
+ else
+ strncpy(variable->arr, value, varcharsize);
+
+ variable->len = strlen(value);
+ if (varcharsize > 0 && variable->len > varcharsize)
+ variable->len = varcharsize;
+ }
+ break;
+ default:
+ ECPGraise(lineno, ECPG_VAR_NOT_CHAR, NULL);
+ return (false);
+ }
+
+ return(true);
+}
+
bool
ECPGget_desc(int lineno, char *desc_name, int index, ...)
{
case (ECPGd_indicator):
if (!get_int_item(lineno, var, vartype, -PQgetisnull(ECPGresult, 0, index)))
return (false);
+
+ ECPGlog("ECPGget_desc: INDICATOR = %d\n", -PQgetisnull(ECPGresult, 0, index));
break;
case ECPGd_name:
- strncpy((char *)var, PQfname(ECPGresult, index), varcharsize);
+ if (!get_char_item(lineno, var, vartype, PQfname(ECPGresult, index), varcharsize))
+ return(false);
+
+ ECPGlog("ECPGget_desc: NAME = %s\n", PQfname(ECPGresult, index));
break;
case ECPGd_nullable:
if (!get_int_item(lineno, var, vartype, 1))
return (false);
- break;
+
+ break;
case ECPGd_key_member:
if (!get_int_item(lineno, var, vartype, 0))
return (false);
+
break;
case ECPGd_scale:
if (!get_int_item(lineno, var, vartype, (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff))
return (false);
+
+ ECPGlog("ECPGget_desc: SCALE = %d\n", (PQfmod(ECPGresult, index) - VARHDRSZ) & 0xffff);
break;
case ECPGd_precision:
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) >> 16))
return (false);
+
+ ECPGlog("ECPGget_desc: PRECISION = %d\n", PQfmod(ECPGresult, index) >> 16);
break;
case ECPGd_ret_length:
case ECPGd_ret_octet:
if (!get_int_item(lineno, var, vartype, PQgetlength(ECPGresult, 0, index)))
return (false);
+
+ ECPGlog("ECPGget_desc: RETURNED = %d\n", PQgetlength(ECPGresult, 0, index));
break;
case ECPGd_octet:
if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
return (false);
+
+ ECPGlog("ECPGget_desc: OCTET_LENGTH = %d\n", PQfsize(ECPGresult, index));
break;
case ECPGd_length:
if (!get_int_item(lineno, var, vartype, PQfmod(ECPGresult, index) - VARHDRSZ))
return (false);
+
+ ECPGlog("ECPGget_desc: LENGTH = %d\n", PQfmod(ECPGresult, index) - VARHDRSZ);
break;
case ECPGd_type:
if (!get_int_item(lineno, var, vartype, ECPGDynamicType(PQftype(ECPGresult, index))))
return (false);
+
+ ECPGlog("ECPGget_desc: TYPE = %d\n", ECPGDynamicType(PQftype(ECPGresult, index)));
break;
-
+
+ case ECPGd_data:
+ if (!get_data(ECPGresult, 0, index, lineno, vartype, ECPGt_NO_INDICATOR, var, NULL, varcharsize, offset))
+ return (false);
+
+ break;
+
default:
snprintf(type_str, sizeof(type_str), "%d", type);
ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, type_str);
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;
+}
+++ /dev/null
-/* 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;
-}
struct variable *next;
};
-struct statement
-{
- int lineno;
- char *command;
- struct connection *connection;
- struct variable *inlist;
- struct variable *outlist;
-};
-
-static struct prepared_statement
-{
- char *name;
- struct statement *stmt;
- struct prepared_statement *next;
-} *prep_stmts = NULL;
-
-static struct auto_mem
-{
- void *pointer;
- struct auto_mem *next;
-} *auto_allocs = NULL;
+struct auto_mem *auto_allocs;
static int simple_debug = 0;
static FILE *debugstream = NULL;
-static void
-register_error(long code, char *fmt,...)
-{
- va_list args;
- struct auto_mem *am;
-
- sqlca.sqlcode = code;
- va_start(args, fmt);
- vsnprintf(sqlca.sqlerrm.sqlerrmc, SQLERRMC_LEN, fmt, args);
- va_end(args);
- sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc);
-
- /* free all memory we have allocated for the user */
- for (am = auto_allocs; am;)
- {
- struct auto_mem *act = am;
-
- am = am->next;
- free(act->pointer);
- free(act);
- }
-
- auto_allocs = NULL;
-}
-
static struct connection *
get_connection(const char *connection_name)
{
memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca));
if (con == NULL)
{
- register_error(ECPG_NO_CONN, "No such connection %s in line %d.", connection_name ? connection_name : "NULL", lineno);
+ ECPGraise(lineno, ECPG_NO_CONN, connection_name ? connection_name : "NULL");
return (false);
}
+ auto_allocs = NULL;
+
return (true);
}
ECPGlog("ecpg_finish: called an extra time.\n");
}
-static char *
-ecpg_alloc(long size, int lineno)
-{
- char *new = (char *) calloc(1L, size);
-
- if (!new)
- {
- ECPGlog("out of memory\n");
- ECPGraise(lineno, ECPG_OUT_OF_MEMORY, NULL);
- return NULL;
- }
-
- memset(new, '\0', size);
- return (new);
-}
-
-static char *
-ecpg_strdup(const char *string, int lineno)
-{
- char *new = strdup(string);
-
- if (!new)
- {
- ECPGlog("out of memory\n");
- ECPGraise(lineno, ECPG_OUT_OF_MEMORY, NULL);
- return NULL;
- }
-
- return (new);
-}
-
static void
add_mem(void *ptr, int lineno)
{
if (var->pointer == NULL)
{
ECPGlog("create_statement: invalid statement name\n");
- register_error(ECPG_INVALID_STMT, "Invalid statement name in line %d.", lineno);
+ ECPGraise(lineno, ECPG_INVALID_STMT, NULL);
free(var);
return false;
}
{
if ((results = PQexec(stmt->connection->connection, "begin transaction")) == NULL)
{
- register_error(ECPG_TRANS, "Error in transaction processing line %d.", stmt->lineno);
+ ECPGraise(stmt->lineno, ECPG_TRANS, NULL);
return false;
}
PQclear(results);
{
ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno,
PQerrorMessage(stmt->connection->connection));
- register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
- PQerrorMessage(stmt->connection->connection), stmt->lineno);
+ ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection));
}
else
{
for (act_field = 0; act_field < nfields && status; act_field++)
{
- char *pval;
- char *scan_length;
char *array_query;
if (var == NULL)
for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
{
- pval = (char *)PQgetvalue(results, act_tuple, act_field);
-
- ECPGlog("ECPGexecute line %d: RESULT: %s\n", stmt->lineno, pval ? pval : "");
-
- /* Now the pval is a pointer to the value. */
- /* We will have to decode the value */
-
- /*
- * check for null value and set indicator
- * accordingly
- */
- switch (var->ind_type)
- {
- case ECPGt_short:
- case ECPGt_unsigned_short:
- ((short *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
- break;
- case ECPGt_int:
- case ECPGt_unsigned_int:
- ((int *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
- break;
- case ECPGt_long:
- case ECPGt_unsigned_long:
- ((long *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
- break;
- case ECPGt_NO_INDICATOR:
- if (PQgetisnull(results, act_tuple, act_field))
- {
- register_error(ECPG_MISSING_INDICATOR, "NULL value without indicator variable on line %d.", stmt->lineno);
- status = false;
- }
- break;
- default:
- ECPGraise(stmt->lineno, ECPG_UNSUPPORTED, ECPGtype_name(var->ind_type));
- status = false;
- break;
- }
-
- switch (var->type)
- {
- long res;
- unsigned long ures;
- double dres;
-
- case ECPGt_short:
- case ECPGt_int:
- case ECPGt_long:
- if (pval)
- {
- res = strtol(pval, &scan_length, 10);
- if (*scan_length != '\0') /* Garbage left */
- {
- register_error(ECPG_INT_FORMAT, "Not correctly formatted int type: %s line %d.",
- pval, stmt->lineno);
- status = false;
- res = 0L;
- }
- }
- else
- res = 0L;
-
- switch (var->type)
- {
- case ECPGt_short:
- ((short *) var->value)[act_tuple] = (short) res;
- break;
- case ECPGt_int:
- ((int *) var->value)[act_tuple] = (int) res;
- break;
- case ECPGt_long:
- ((long *) var->value)[act_tuple] = res;
- break;
- default:
- /* Cannot happen */
- break;
- }
- break;
-
- case ECPGt_unsigned_short:
- case ECPGt_unsigned_int:
- case ECPGt_unsigned_long:
- if (pval)
- {
- ures = strtoul(pval, &scan_length, 10);
- if (*scan_length != '\0') /* Garbage left */
- {
- register_error(ECPG_UINT_FORMAT, "Not correctly formatted unsigned type: %s line %d.",
- pval, stmt->lineno);
- status = false;
- ures = 0L;
- }
- }
- else
- ures = 0L;
-
- switch (var->type)
- {
- case ECPGt_unsigned_short:
- ((unsigned short *) var->value)[act_tuple] = (unsigned short) ures;
- break;
- case ECPGt_unsigned_int:
- ((unsigned int *) var->value)[act_tuple] = (unsigned int) ures;
- break;
- case ECPGt_unsigned_long:
- ((unsigned long *) var->value)[act_tuple] = ures;
- break;
- default:
- /* Cannot happen */
- break;
- }
- break;
-
-
- case ECPGt_float:
- case ECPGt_double:
- if (pval)
- {
- dres = strtod(pval, &scan_length);
- if (*scan_length != '\0') /* Garbage left */
- {
- register_error(ECPG_FLOAT_FORMAT, "Not correctly formatted floating point type: %s line %d.",
- pval, stmt->lineno);
- status = false;
- dres = 0.0;
- }
- }
- else
- dres = 0.0;
-
- switch (var->type)
- {
- case ECPGt_float:
- ((float *) var->value)[act_tuple] = dres;
- break;
- case ECPGt_double:
- ((double *) var->value)[act_tuple] = dres;
- break;
- default:
- /* Cannot happen */
- break;
- }
- break;
-
- case ECPGt_bool:
- if (pval)
- {
- if (pval[0] == 'f' && pval[1] == '\0')
- {
- ((char *) var->value)[act_tuple] = false;
- break;
- }
- else if (pval[0] == 't' && pval[1] == '\0')
- {
- ((char *) var->value)[act_tuple] = true;
- break;
- }
- else if (pval[0] == '\0' && PQgetisnull(results, act_tuple, act_field))
- {
- // NULL is valid
- break;
- }
- }
-
- register_error(ECPG_CONVERT_BOOL, "Unable to convert %s to bool on line %d.",
- (pval ? pval : "NULL"),
- stmt->lineno);
- status = false;
- break;
-
- case ECPGt_char:
- case ECPGt_unsigned_char:
- {
- strncpy((char *) ((long) var->value + var->offset * act_tuple), pval, var->varcharsize);
- if (var->varcharsize && var->varcharsize < strlen(pval))
- {
- /* truncation */
- switch (var->ind_type)
- {
- case ECPGt_short:
- case ECPGt_unsigned_short:
- ((short *) var->ind_value)[act_tuple] = var->varcharsize;
- break;
- case ECPGt_int:
- case ECPGt_unsigned_int:
- ((int *) var->ind_value)[act_tuple] = var->varcharsize;
- break;
- case ECPGt_long:
- case ECPGt_unsigned_long:
- ((long *) var->ind_value)[act_tuple] = var->varcharsize;
- break;
- default:
- break;
- }
- sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
- }
- }
- break;
-
- case ECPGt_varchar:
- {
- struct ECPGgeneric_varchar *variable =
- (struct ECPGgeneric_varchar *) ((long) var->value + var->offset * act_tuple);
-
- if (var->varcharsize == 0)
- strncpy(variable->arr, pval, strlen(pval));
- else
- strncpy(variable->arr, pval, var->varcharsize);
-
- variable->len = strlen(pval);
- if (var->varcharsize > 0 && variable->len > var->varcharsize)
- {
- /* truncation */
- switch (var->ind_type)
- {
- case ECPGt_short:
- case ECPGt_unsigned_short:
- ((short *) var->ind_value)[act_tuple] = var->varcharsize;
- break;
- case ECPGt_int:
- case ECPGt_unsigned_int:
- ((int *) var->ind_value)[act_tuple] = var->varcharsize;
- break;
- case ECPGt_long:
- case ECPGt_unsigned_long:
- ((long *) var->ind_value)[act_tuple] = var->varcharsize;
- break;
- default:
- break;
- }
- sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
-
- variable->len = var->varcharsize;
- }
- }
- break;
-
- default:
- ECPGraise(stmt->lineno, ECPG_UNSUPPORTED, ECPGtype_name(var->type));
- status = false;
- break;
- }
+ if (!get_data(results, act_tuple, act_field, stmt->lineno,
+ var->type, var->ind_type, var->value,
+ var->ind_value, var->varcharsize, var->offset))
+ status = false;
}
var = var->next;
}
break;
case PGRES_EMPTY_QUERY:
/* do nothing */
- register_error(ECPG_EMPTY, "Empty query line %d.", stmt->lineno);
+ ECPGraise(stmt->lineno, ECPG_EMPTY, NULL);
break;
case PGRES_COMMAND_OK:
status = true;
case PGRES_BAD_RESPONSE:
ECPGlog("ECPGexecute line %d: Error: %s",
stmt->lineno, PQerrorMessage(stmt->connection->connection));
- register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
- PQerrorMessage(stmt->connection->connection), stmt->lineno);
+ ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection));
status = false;
break;
case PGRES_COPY_OUT:
default:
ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
stmt->lineno);
- register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
- PQerrorMessage(stmt->connection->connection), stmt->lineno);
+ ECPGraise(stmt->lineno, ECPG_PGSQL, PQerrorMessage(stmt->connection->connection));
status = false;
break;
}
{
free_statement(stmt);
ECPGlog("ECPGdo: not connected to %s\n", con->name);
- register_error(ECPG_NOT_CONN, "Not connected in line %d.", lineno);
+ ECPGraise(lineno, ECPG_NOT_CONN, NULL);
setlocale(LC_NUMERIC, locale);
return false;
}
if (con->connection == NULL)
{
ECPGlog("ECPGdo: not connected to %s\n", con->name);
- register_error(ECPG_NOT_CONN, "Not connected in line %d", lineno);
+ ECPGraise(lineno, ECPG_NOT_CONN, NULL);
return false;
}
{
if ((res = PQexec(con->connection, transaction)) == NULL)
{
- register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
+ ECPGraise(lineno, ECPG_TRANS, NULL);
return FALSE;
}
PQclear(res);
con->committed = true;
/* deallocate all prepared statements */
- while(prep_stmts != NULL)
- {
- bool b = ECPGdeallocate(lineno, prep_stmts->name);
-
- if (!b)
+ if (!ECPGdeallocate_all(lineno))
return false;
- }
}
return true;
{
if ((results = PQexec(con->connection, "begin transaction")) == NULL)
{
- register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
+ ECPGraise(lineno, ECPG_TRANS, NULL);
return false;
}
PQclear(results);
{
if ((results = PQexec(con->connection, "commit")) == NULL)
{
- register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
+ ECPGraise(lineno, ECPG_TRANS, NULL);
return false;
}
PQclear(results);
{
ecpg_finish(this);
ECPGlog("connect: could not open database %s %s%s in line %d\n", dbname ? dbname : "<DEFAULT>", user ? "for user " : "", user ? user : "", lineno);
- register_error(ECPG_CONNECT, "connect: could not open database %s.", dbname ? dbname : "<DEFAULT>");
+ ECPGraise(lineno, ECPG_CONNECT, dbname ? dbname : "<DEFAULT>");
return false;
}
}
}
-/* print out an error message */
-void
-sqlprint(void)
-{
- sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
- fprintf(stderr, "sql error %s\n", sqlca.sqlerrm.sqlerrmc);
-}
-
-static bool
-isvarchar(unsigned char c)
-{
- if (isalnum(c))
- return true;
+/* dynamic SQL support routines
+ *
+ * Copyright (c) 2000, Christof Petig <christof.petig@wtal.de>
+ *
+ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/ecpglib.c,v 1.60 2000/02/23 19:25:43 meskes Exp $
+ */
- if (c == '_' || c == '>' || c == '-' || c == '.')
- return true;
+/* I borrowed the include files from ecpglib.c, maybe we don't need all of them */
- if (c >= 128)
- return true;
+#include <sql3types.h>
- return (false);
-}
+PGconn *ECPG_internal_get_connection(char *name);
-static void
-replace_variables(char *text)
+extern struct descriptor
{
- char *ptr = text;
- bool string = false;
+ char *name;
+ 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. */
- for (; *ptr != '\0'; ptr++)
+ if (con->committed && !con->autocommit)
{
- if (*ptr == '\'')
- string = string ? false : true;
-
- if (!string && *ptr == ':')
+ if ((results = PQexec(con->connection, "begin transaction")) == NULL)
{
- *ptr = '?';
- for (++ptr; *ptr && isvarchar(*ptr); ptr++)
- *ptr = ' ';
+ ECPGraise(lineno, ECPG_TRANS, NULL);
+ return false;
}
+ PQclear(results);
+ con->committed = false;
}
-}
-/* handle the EXEC SQL PREPARE statement */
-bool
-ECPGprepare(int lineno, char *name, char *variable)
-{
- struct statement *stmt;
- struct prepared_statement *this;
+ ECPGlog("execute_descriptor line %d: QUERY: %s on connection %s\n", lineno, query, con->name);
+ results = PQexec(con->connection, query);
- /* check if we already have prepared this statement */
- for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);
- if (this)
+ if (results == NULL)
{
- bool b = ECPGdeallocate(lineno, name);
-
- if (!b)
- return false;
+ ECPGlog("ECPGexecute line %d: error: %s", lineno,
+ PQerrorMessage(con->connection));
+ ECPGraise(lineno, ECPG_PGSQL, PQerrorMessage(con->connection));
+ }
+ else
+ { *resultptr=results;
+ switch (PQresultStatus(results))
+ { int ntuples;
+ case PGRES_TUPLES_OK:
+ status = true;
+ sqlca.sqlerrd[2] = ntuples = PQntuples(results);
+ if (ntuples < 1)
+ {
+ ECPGlog("execute_descriptor line %d: Incorrect number of matches: %d\n",
+ lineno, ntuples);
+ ECPGraise(lineno, ECPG_NOT_FOUND, NULL);
+ status = false;
+ break;
+ }
+ break;
+#if 1 /* strictly these are not needed (yet) */
+ case PGRES_EMPTY_QUERY:
+ /* do nothing */
+ ECPGraise(lineno, ECPG_EMPTY, NULL);
+ break;
+ case PGRES_COMMAND_OK:
+ status = true;
+ sqlca.sqlerrd[1] = atol(PQoidStatus(results));
+ sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
+ ECPGlog("ECPGexecute line %d Ok: %s\n", lineno, PQcmdStatus(results));
+ break;
+ case PGRES_COPY_OUT:
+ ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT ... tossing.\n", lineno);
+ PQendcopy(con->connection);
+ break;
+ case PGRES_COPY_IN:
+ ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.\n", lineno);
+ PQendcopy(con->connection);
+ break;
+#else
+ case PGRES_EMPTY_QUERY:
+ case PGRES_COMMAND_OK:
+ case PGRES_COPY_OUT:
+ case PGRES_COPY_IN:
+ break;
+#endif
+ case PGRES_NONFATAL_ERROR:
+ case PGRES_FATAL_ERROR:
+ case PGRES_BAD_RESPONSE:
+ ECPGlog("ECPGexecute line %d: Error: %s",
+ lineno, PQerrorMessage(con->connection));
+ ECPGraise(lineno, ECPG_PGSQL, PQerrorMessage(con->connection));
+ status = false;
+ break;
+ default:
+ ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
+ lineno);
+ ECPGraise(lineno, ECPG_PGSQL, PQerrorMessage(con->connection));
+ status = false;
+ break;
+ }
}
- 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)
+ /* check for asynchronous returns */
+ notify = PQnotifies(con->connection);
+ if (notify)
{
- free(this);
- return false;
+ ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
+ lineno, notify->relname, notify->be_pid);
+ free(notify);
}
+ return status;
+}
- /* create statement */
- stmt->lineno = lineno;
- stmt->connection = NULL;
- stmt->command = ecpg_strdup(variable, lineno);
- stmt->inlist = stmt->outlist = NULL;
+/* 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 we have C variables in our statment replace them with '?' */
- replace_variables(stmt->command);
+ if (!ecpg_init(con, connection_name, lineno))
+ { setlocale(LC_NUMERIC, locale);
+ return(false);
+ }
- /* add prepared statement to our list */
- this->name = ecpg_strdup(name, lineno);
- this->stmt = stmt;
+ /* are we connected? */
+ if (con == NULL || con->connection == NULL)
+ {
+ ECPGlog("do_descriptor2: not connected to %s\n", con->name);
+ ECPGraise(lineno, ECPG_NOT_CONN, NULL);
+ setlocale(LC_NUMERIC, locale);
+ return false;
+ }
- if (prep_stmts == NULL)
- this->next = NULL;
- else
- this->next = prep_stmts;
+ status = execute_descriptor(lineno,query,con,resultptr);
- prep_stmts = this;
- return true;
+ /* and reset locale value so our application is not affected */
+ setlocale(LC_NUMERIC, locale);
+ return (status);
}
-/* handle the EXEC SQL DEALLOCATE PREPARE statement */
-bool
-ECPGdeallocate(int lineno, char *name)
+bool ECPGdo_descriptor(int line,const char *connection,
+ const char *descriptor,const char *query)
{
- struct prepared_statement *this,
- *prev;
-
- /* 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;
+ 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);
+ }
}
- ECPGlog("deallocate_prepare: invalid statement name %s\n", name);
- register_error(ECPG_INVALID_STMT, "Invalid statement name %s in line %d", name, lineno);
+
+ ECPGraise(line, ECPG_UNKNOWN_DESCRIPTOR, descriptor);
return false;
}
-
-/* return the prepared statement */
-char *
-ECPGprepared_statement(char *name)
-{
- struct prepared_statement *this;
-
- for (this = prep_stmts; this != NULL && strcmp(this->name, name) != 0; this = this->next);
- return (this) ? this->stmt->command : NULL;
-}
-
-#include "dynamic.c"
--- /dev/null
+#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);
+}
--- /dev/null
+#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);
+}
--- /dev/null
+#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;
+}
}
}
-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
*/
-all: stp.so test1 test2 test3 test4 test5 perftest dyntest
+all: test1 test2 test3 test4 perftest dyntest
#LDFLAGS=-g -I /usr/local/pgsql/include -L/usr/local/pgsql/lib -lecpg -lpq -lcrypt
LDFLAGS=-g -I../include -I/usr/include/postgresql -L/usr/lib/postgresql -L../lib -lecpg -lpq -lcrypt
test2: test2.c
test3: test3.c
test4: test4.c
-test5: test5.c
perftest: perftest.c
dyntest: dyntest.c
.pgc.c:
$(ECPG) $?
-stp.so: stp.c
- cc -fPIC -I../include -I/usr/include/postgresql -c -o stp.o stp.c
- ld -Bdynamic -shared -soname stp.so -o stp.so stp.o -lpq -lecpg -lc
-
-
clean:
- -/bin/rm test1 test2 test3 test4 test5 perftest *.c log stp.o stp.so dyntest
+ -/bin/rm test1 test2 test3 test4 perftest *.c log dyntest
*
* 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>
exec sql include sqlca;
void error()
-{ printf("#%d:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc);
+{
+ printf("\n#%d:%s\n",sqlca.sqlcode,sqlca.sqlerrm.sqlerrmc);
exit(1);
}
int main(int argc,char **argv)
-{ exec sql begin declare section;
+{
+exec sql begin declare section;
int COUNT;
- int INTVAR;
+ int INTVAR, BOOLVAR;
int INDEX;
int INDICATOR;
int TYPE,LENGTH,OCTET_LENGTH,PRECISION,SCALE,NULLABLE,RETURNED_OCTET_LENGTH;
float FLOATVAR;
double DOUBLEVAR;
char QUERY[1024];
- exec sql end declare section;
+exec sql end declare section;
int done=0;
FILE *dbgs;
+ exec sql var BOOLVAR is bool;
+
if ((dbgs = fopen("log", "w")) != NULL)
ECPGdebug(1, dbgs);
:PRECISION = precision, :SCALE=scale,
:NULLABLE=nullable, :NAME=name,
:INDICATOR=indicator;
- printf("%2d %s %d(%d)(%d,%d) %d,%d %d = "
+ printf("%2d\t%s (type: %d length: %d precision: %d scale: %d
+ \toctet_length: %d returned_octet_length: %d nullable: %d)\n\t= "
,INDEX,NAME,TYPE,LENGTH,PRECISION,SCALE
,OCTET_LENGTH,RETURNED_OCTET_LENGTH,NULLABLE);
if (INDICATOR==-1) printf("NULL\n");
else switch (TYPE)
- { case SQL3_BOOLEAN:
- exec sql get descriptor MYDESC value :INDEX :INTVAR=data;
- printf("%s\n",INTVAR?"true":"false");
+ {
+ case SQL3_BOOLEAN:
+ exec sql get descriptor MYDESC value :INDEX :BOOLVAR=data;
+ printf("%s\n",BOOLVAR ? "true":"false");
break;
case SQL3_NUMERIC:
case SQL3_DECIMAL:
+++ /dev/null
-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);
- }
+++ /dev/null
-#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);
- }