aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Meskes <meskes@postgresql.org>2001-11-14 11:11:49 +0000
committerMichael Meskes <meskes@postgresql.org>2001-11-14 11:11:49 +0000
commit32a4c3008f65deed3f2cb56f8df6fac85b3969f3 (patch)
treef94ae47a8c183b174c6e8da6dc6fc26fa9664e3d /src
parentebb93323bbf7c62aeff283cd5991071ee8c575fa (diff)
downloadpostgresql-32a4c3008f65deed3f2cb56f8df6fac85b3969f3.tar.gz
postgresql-32a4c3008f65deed3f2cb56f8df6fac85b3969f3.zip
Added Christof's patches.
Diffstat (limited to 'src')
-rw-r--r--src/interfaces/ecpg/ChangeLog4
-rw-r--r--src/interfaces/ecpg/README.dynSQL14
-rw-r--r--src/interfaces/ecpg/include/ecpglib.h2
-rw-r--r--src/interfaces/ecpg/lib/connect.c26
-rw-r--r--src/interfaces/ecpg/lib/data.c6
-rw-r--r--src/interfaces/ecpg/lib/descriptor.c178
-rw-r--r--src/interfaces/ecpg/lib/error.c4
-rw-r--r--src/interfaces/ecpg/lib/execute.c170
-rw-r--r--src/interfaces/ecpg/lib/extern.h32
-rw-r--r--src/interfaces/ecpg/lib/memory.c6
-rw-r--r--src/interfaces/ecpg/lib/misc.c16
-rw-r--r--src/interfaces/ecpg/lib/pg_type.h5
-rw-r--r--src/interfaces/ecpg/lib/prepare.c10
-rw-r--r--src/interfaces/ecpg/test/Makefile4
-rw-r--r--src/interfaces/ecpg/test/dyntest.pgc2
-rw-r--r--src/interfaces/ecpg/test/dyntest2.pgc2
16 files changed, 281 insertions, 200 deletions
diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog
index 1e6c960064a..ffe622ef924 100644
--- a/src/interfaces/ecpg/ChangeLog
+++ b/src/interfaces/ecpg/ChangeLog
@@ -1146,5 +1146,9 @@ Sun Oct 21 14:19:42 CEST 2001
Fri Nov 2 16:16:25 CET 2001
- Synced preproc.y with gram.y.
+
+Wed Nov 14 11:50:27 CET 2001
+
+ - Added several patches by Christof Petig <christof.petig@wtal.de>.
- Set ecpg version to 2.9.0.
- Set library version to 3.3.0.
diff --git a/src/interfaces/ecpg/README.dynSQL b/src/interfaces/ecpg/README.dynSQL
index fedcf80402d..4c606ca3985 100644
--- a/src/interfaces/ecpg/README.dynSQL
+++ b/src/interfaces/ecpg/README.dynSQL
@@ -1,20 +1,10 @@
descriptor statements have the following shortcomings
-- up to now the only reasonable statement is
- FETCH ... INTO SQL DESCRIPTOR <name>
- no input variables allowed!
+- input descriptors (USING DESCRIPTOR <name>) are not supported
Reason: to fully support dynamic SQL the frontend/backend communication
should change to recognize input parameters.
Since this is not likely to happen in the near future and you
can cover the same functionality with the existing infrastructure
- I'll leave the work to someone else.
-
-- string buffer overflow does not always generate warnings
- (beware: terminating 0 may be missing because strncpy is used)
- :var=data sets sqlwarn accordingly (but not indicator)
-
-- char variables pointing to NULL are not allocated on demand
-
-- string truncation does not show up in indicator
+ (using s[n]printf), I'll leave the work to someone else.
diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h
index 8c455ec58b0..5c295d87280 100644
--- a/src/interfaces/ecpg/include/ecpglib.h
+++ b/src/interfaces/ecpg/include/ecpglib.h
@@ -67,6 +67,8 @@ void ECPGraise(int line, int code, const char *str);
bool ECPGget_desc_header(int, char *, int *);
bool ECPGget_desc(int, char *, int,...);
+/* dynamic result allocation */
+ void ECPGfree_auto_mem(void);
#ifdef __cplusplus
}
diff --git a/src/interfaces/ecpg/lib/connect.c b/src/interfaces/ecpg/lib/connect.c
index da4b8a3d7e0..2f02e92da37 100644
--- a/src/interfaces/ecpg/lib/connect.c
+++ b/src/interfaces/ecpg/lib/connect.c
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/connect.c,v 1.14 2001/10/31 04:49:44 momjian Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/connect.c,v 1.15 2001/11/14 11:11:49 meskes Exp $ */
#include "postgres_fe.h"
@@ -12,7 +12,7 @@ static struct connection *all_connections = NULL,
*actual_connection = NULL;
struct connection *
-get_connection(const char *connection_name)
+ECPGget_connection(const char *connection_name)
{
struct connection *con = all_connections;
@@ -63,10 +63,10 @@ ecpg_finish(struct connection * act)
bool
ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
{
- struct connection *con = get_connection(connection_name);
+ struct connection *con = ECPGget_connection(connection_name);
PGresult *results;
- if (!ecpg_init(con, connection_name, lineno))
+ if (!ECPGinit(con, connection_name, lineno))
return (false);
ECPGlog("ECPGsetcommit line %d action = %s connection = %s\n", lineno, mode, con->name);
@@ -106,9 +106,9 @@ ECPGsetcommit(int lineno, const char *mode, const char *connection_name)
bool
ECPGsetconn(int lineno, const char *connection_name)
{
- struct connection *con = get_connection(connection_name);
+ struct connection *con = ECPGget_connection(connection_name);
- if (!ecpg_init(con, connection_name, lineno))
+ if (!ECPGinit(con, connection_name, lineno))
return (false);
actual_connection = con;
@@ -269,9 +269,9 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd,
*realname = NULL,
*options = NULL;
- init_sqlca();
+ ECPGinit_sqlca();
- if ((this = (struct connection *) ecpg_alloc(sizeof(struct connection), lineno)) == NULL)
+ if ((this = (struct connection *) ECPGalloc(sizeof(struct connection), lineno)) == NULL)
return false;
if (dbname == NULL && connection_name == NULL)
@@ -393,9 +393,9 @@ ECPGconnect(int lineno, const char *name, const char *user, const char *passwd,
/* add connection to our list */
if (connection_name != NULL)
- this->name = ecpg_strdup(connection_name, lineno);
+ this->name = ECPGstrdup(connection_name, lineno);
else
- this->name = ecpg_strdup(realname, lineno);
+ this->name = ECPGstrdup(realname, lineno);
this->cache_head = NULL;
@@ -465,7 +465,7 @@ ECPGdisconnect(int lineno, const char *connection_name)
if (strcmp(connection_name, "ALL") == 0)
{
- init_sqlca();
+ ECPGinit_sqlca();
for (con = all_connections; con;)
{
struct connection *f = con;
@@ -476,9 +476,9 @@ ECPGdisconnect(int lineno, const char *connection_name)
}
else
{
- con = get_connection(connection_name);
+ con = ECPGget_connection(connection_name);
- if (!ecpg_init(con, connection_name, lineno))
+ if (!ECPGinit(con, connection_name, lineno))
return (false);
else
ecpg_finish(con);
diff --git a/src/interfaces/ecpg/lib/data.c b/src/interfaces/ecpg/lib/data.c
index 0d4ec712b55..81bdad751bf 100644
--- a/src/interfaces/ecpg/lib/data.c
+++ b/src/interfaces/ecpg/lib/data.c
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/data.c,v 1.18 2001/11/05 17:46:37 momjian Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/data.c,v 1.19 2001/11/14 11:11:49 meskes Exp $ */
#include "postgres_fe.h"
@@ -12,14 +12,14 @@
#include "sqlca.h"
bool
-get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
+ECPGget_data(const 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,
bool isarray)
{
char *pval = (char *) PQgetvalue(results, act_tuple, act_field);
- ECPGlog("get_data line %d: RESULT: %s\n", lineno, pval ? pval : "");
+ ECPGlog("ECPGget_data line %d: RESULT: %s\n", lineno, pval ? pval : "");
/* pval is a pointer to the value */
/* let's check is it really is an array if it should be one */
diff --git a/src/interfaces/ecpg/lib/descriptor.c b/src/interfaces/ecpg/lib/descriptor.c
index 95e65d603e4..533bdcea5a4 100644
--- a/src/interfaces/ecpg/lib/descriptor.c
+++ b/src/interfaces/ecpg/lib/descriptor.c
@@ -1,9 +1,10 @@
/* dynamic SQL support routines
*
- * $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/descriptor.c,v 1.18 2001/11/05 17:46:37 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/descriptor.c,v 1.19 2001/11/14 11:11:49 meskes Exp $
*/
#include "postgres_fe.h"
+#include "pg_type.h"
#include "ecpgtype.h"
#include "ecpglib.h"
@@ -30,14 +31,16 @@ 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 */
+ 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;
}
@@ -139,11 +142,10 @@ ECPGget_desc(int lineno, char *desc_name, int index,...)
va_list args;
PGresult *ECPGresult = ECPGresultByDescriptor(lineno, desc_name);
enum ECPGdtype type;
- bool Indicator_seen = false,
- Data_seen = false;
int ntuples,
act_tuple;
-
+ struct variable data_var;
+
va_start(args, index);
if (!ECPGresult)
return (false);
@@ -165,7 +167,11 @@ ECPGget_desc(int lineno, char *desc_name, int 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];
@@ -184,26 +190,27 @@ ECPGget_desc(int lineno, char *desc_name, int index,...)
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;
- /*
- * this is like ECPGexecute missing : allocate arrays,
- * perhaps this should go into a common function !!
- */
- if (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;
- }
- Indicator_seen = true;
- for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
- {
- if (!get_int_item(lineno, var, vartype, -PQgetisnull(ECPGresult, act_tuple, index)))
- return (false);
- var = (char *) var + offset;
- ECPGlog("ECPGget_desc: INDICATOR[%d] = %d\n", act_tuple, -PQgetisnull(ECPGresult, act_tuple, index));
- }
+ 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:
@@ -239,29 +246,6 @@ ECPGget_desc(int lineno, char *desc_name, int index,...)
ECPGlog("ECPGget_desc: PRECISION = %d\n", PQfmod(ECPGresult, index) >> 16);
break;
- case ECPGd_ret_length:
- case ECPGd_ret_octet:
-
- /*
- * this is like ECPGexecute missing : allocate arrays,
- * perhaps this should go into a common function !!
- */
- if (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;
- }
- 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;
-
case ECPGd_octet:
if (!get_int_item(lineno, var, vartype, PQfsize(ECPGresult, index)))
return (false);
@@ -289,38 +273,45 @@ ECPGget_desc(int lineno, char *desc_name, int index,...)
ECPGlog("ECPGget_desc: TYPE = %d\n", ECPGDynamicType_DDT(PQftype(ECPGresult, index)));
break;
- case ECPGd_data:
+
+ 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 ECPGexecute missing : allocate arrays,
- * perhaps this should go into a common function !!
+ * this is like ECPGstore_result
*/
- if (ntuples > arrsize)
+ 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;
}
- Data_seen = true;
+ /* 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 (PQgetisnull(ECPGresult, act_tuple, index))
- continue; /* do not touch data on null value */
- if (!get_data(ECPGresult, act_tuple, index, lineno,
- vartype, ECPGt_NO_INDICATOR, var, NULL,
- varcharsize, offset, false))
+ 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;
- case ECPGd_cardinality:
- if (!get_int_item(lineno, var, vartype, PQntuples(ECPGresult)))
- return (false);
-
- ECPGlog("ECPGget_desc: CARDINALITY = %d\n", PQntuples(ECPGresult));
- break;
-
default:
snprintf(type_str, sizeof(type_str), "%d", type);
ECPGraise(lineno, ECPG_UNKNOWN_DESCRIPTOR_ITEM, type_str);
@@ -330,18 +321,45 @@ ECPGget_desc(int lineno, char *desc_name, int index,...)
type = va_arg(args, enum ECPGdtype);
}
- if (Data_seen && !Indicator_seen)
+ if (data_var.type!=ECPGt_EORT)
{
+ struct statement stmt;
+ 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);
+ }
+ 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 (PQgetisnull(ECPGresult, act_tuple, index))
- {
- ECPGraise(lineno, ECPG_MISSING_INDICATOR, NULL);
+ 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));
}
}
-
+
return (true);
}
@@ -369,10 +387,10 @@ ECPGdeallocate_desc(int line, const char *name)
bool
ECPGallocate_desc(int line, const char *name)
{
- struct descriptor *new = (struct descriptor *) ecpg_alloc(sizeof(struct descriptor), line);
+ struct descriptor *new = (struct descriptor *) ECPGalloc(sizeof(struct descriptor), line);
new->next = all_descriptors;
- new->name = ecpg_alloc(strlen(name) + 1, line);
+ new->name = ECPGalloc(strlen(name) + 1, line);
new->result = PQmakeEmptyPGresult(NULL, 0);
strcpy(new->name, name);
all_descriptors = new;
diff --git a/src/interfaces/ecpg/lib/error.c b/src/interfaces/ecpg/lib/error.c
index e39ee48c115..56dd42fbed9 100644
--- a/src/interfaces/ecpg/lib/error.c
+++ b/src/interfaces/ecpg/lib/error.c
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/error.c,v 1.12 2001/10/18 20:32:58 momjian Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/error.c,v 1.13 2001/11/14 11:11:49 meskes Exp $ */
#include "postgres_fe.h"
@@ -154,7 +154,7 @@ ECPGraise(int line, int code, const char *str)
ECPGlog("raising sqlcode %d in line %d, '%s'.\n", code, line, sqlca.sqlerrm.sqlerrmc);
/* free all memory we have allocated for the user */
- free_auto_mem();
+ ECPGfree_auto_mem();
}
/* print out an error message */
diff --git a/src/interfaces/ecpg/lib/execute.c b/src/interfaces/ecpg/lib/execute.c
index 57fd5c77676..4cd13944d2b 100644
--- a/src/interfaces/ecpg/lib/execute.c
+++ b/src/interfaces/ecpg/lib/execute.c
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/execute.c,v 1.31 2001/11/05 17:46:37 momjian Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/execute.c,v 1.32 2001/11/14 11:11:49 meskes Exp $ */
/*
* The aim is to get a simpler inteface to the database routines.
@@ -55,22 +55,6 @@ struct sqlca sqlca =
}
};
-struct variable
-{
- enum ECPGttype type;
- void *value;
- void *pointer;
- long varcharsize;
- long arrsize;
- long offset;
- enum ECPGttype ind_type;
- void *ind_value;
- long ind_varcharsize;
- long ind_arrsize;
- long ind_offset;
- struct variable *next;
-};
-
/* keep a list of memory we allocated for the user */
static struct auto_mem
{
@@ -78,17 +62,17 @@ static struct auto_mem
struct auto_mem *next;
} *auto_allocs = NULL;
-static void
-add_mem(void *ptr, int lineno)
+void
+ECPGadd_mem(void *ptr, int lineno)
{
- struct auto_mem *am = (struct auto_mem *) ecpg_alloc(sizeof(struct auto_mem), 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
-free_auto_mem(void)
+ECPGfree_auto_mem(void)
{
struct auto_mem *am;
@@ -112,7 +96,7 @@ static
char *
quote_postgres(char *arg, int lineno)
{
- char *res = (char *) ecpg_alloc(2 * strlen(arg) + 3, lineno);
+ char *res = (char *) ECPGalloc(2 * strlen(arg) + 3, lineno);
int i,
ri = 0;
@@ -168,7 +152,7 @@ create_statement(int lineno, struct connection * connection, struct statement **
struct variable **list = &((*stmt)->inlist);
enum ECPGttype type;
- if (!(*stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno)))
+ if (!(*stmt = (struct statement *) ECPGalloc(sizeof(struct statement), lineno)))
return false;
(*stmt)->command = query;
@@ -188,7 +172,7 @@ create_statement(int lineno, struct connection * connection, struct statement **
struct variable *var,
*ptr;
- if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))
+ if (!(var = (struct variable *) ECPGalloc(sizeof(struct variable), lineno)))
return false;
var->type = type;
@@ -212,12 +196,18 @@ create_statement(int lineno, struct connection * connection, struct statement **
var->value = var->pointer;
var->ind_type = va_arg(ap, enum ECPGttype);
- var->ind_value = va_arg(ap, void *);
+ var->ind_pointer = va_arg(ap, void *);
var->ind_varcharsize = va_arg(ap, long);
var->ind_arrsize = va_arg(ap, long);
var->ind_offset = va_arg(ap, long);
var->next = NULL;
+ if (var->ind_type!=ECPGt_NO_INDICATOR
+ && (var->ind_arrsize == 0 || var->ind_varcharsize == 0))
+ var->ind_value = *((void **) (var->ind_pointer));
+ else
+ var->ind_value = var->ind_pointer;
+
for (ptr = *list; ptr && ptr->next; ptr = ptr->next);
if (ptr == NULL)
@@ -285,7 +275,7 @@ static void
ECPGtypeinfocache_push(struct ECPGtype_information_cache ** cache, int oid, bool isarray, int lineno)
{
struct ECPGtype_information_cache *new_entry
- = (struct ECPGtype_information_cache *) ecpg_alloc(sizeof(struct ECPGtype_information_cache), lineno);
+ = (struct ECPGtype_information_cache *) ECPGalloc(sizeof(struct ECPGtype_information_cache), lineno);
new_entry->oid = oid;
new_entry->isarray = isarray;
@@ -347,6 +337,7 @@ ECPGis_type_an_array(int type, const struct statement * stmt, const struct varia
ECPGtypeinfocache_push(&(stmt->connection->cache_head), DATEOID, false, stmt->lineno);
ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMEOID, false, stmt->lineno);
ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMESTAMPOID, false, stmt->lineno);
+ ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMESTAMPTZOID, false, stmt->lineno);
ECPGtypeinfocache_push(&(stmt->connection->cache_head), INTERVALOID, false, stmt->lineno);
ECPGtypeinfocache_push(&(stmt->connection->cache_head), TIMETZOID, false, stmt->lineno);
ECPGtypeinfocache_push(&(stmt->connection->cache_head), ZPBITOID, false, stmt->lineno);
@@ -360,7 +351,7 @@ ECPGis_type_an_array(int type, const struct statement * stmt, const struct varia
return cache_entry->isarray;
}
- array_query = (char *) ecpg_alloc(strlen("select typelem from pg_type where oid=") + 11, stmt->lineno);
+ array_query = (char *) ECPGalloc(strlen("select typelem from pg_type where oid=") + 11, stmt->lineno);
sprintf(array_query, "select typelem from pg_type where oid=%d", type);
query = PQexec(stmt->connection->connection, array_query);
free(array_query);
@@ -430,17 +421,33 @@ ECPGstore_result(const PGresult *results, int act_field,
{
case ECPGt_char:
case ECPGt_unsigned_char:
- var->varcharsize = 0;
- /* check strlen for each tuple */
- for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
+ if (!var->varcharsize && !var->arrsize)
{
- int len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
+ /* special mode for handling char**foo=0 */
+ for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
+ {
+ len += strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
+ }
+ len *= var->offset; /* should be 1, but YMNK */
+ len += (ntuples+1) * sizeof(char *);
- if (len > var->varcharsize)
- var->varcharsize = len;
+ ECPGlog("ECPGstore_result: line %d: allocating %d bytes for %d tuples (char**=0)",
+ stmt->lineno,len, ntuples);
+ }
+ else
+ {
+ var->varcharsize = 0;
+ /* check strlen for each tuple */
+ for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
+ {
+ int len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
+
+ if (len > var->varcharsize)
+ var->varcharsize = len;
+ }
+ var->offset *= var->varcharsize;
+ len = var->offset * ntuples;
}
- var->offset *= var->varcharsize;
- len = var->offset * ntuples;
break;
case ECPGt_varchar:
len = ntuples * (var->varcharsize + sizeof(int));
@@ -449,17 +456,58 @@ ECPGstore_result(const PGresult *results, int act_field,
len = var->offset * ntuples;
break;
}
- var->value = (void *) ecpg_alloc(len, stmt->lineno);
+ var->value = (void *) ECPGalloc(len, stmt->lineno);
*((void **) var->pointer) = var->value;
- add_mem(var->value, stmt->lineno);
+ ECPGadd_mem(var->value, stmt->lineno);
+ }
+ /* allocate indicator variable if needed */
+ if ((var->ind_arrsize == 0 || var->ind_varcharsize == 0) && var->ind_value == NULL && var->ind_pointer!=NULL)
+ {
+ int len = var->ind_offset * ntuples;
+ var->ind_value = (void *) ECPGalloc(len, stmt->lineno);
+ *((void **) var->ind_pointer) = var->ind_value;
+ ECPGadd_mem(var->ind_value, stmt->lineno);
}
+
+ /* fill the variable with the tuple(s) */
- for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
+ if (!var->varcharsize && !var->arrsize &&
+ (var->type==ECPGt_char || var->type==ECPGt_unsigned_char))
+ {
+ /* special mode for handling char**foo=0 */
+
+ /* filling the array of (char*)s */
+ char **current_string = (char**) var->value;
+ /* storing the data (after the last array element) */
+ char *current_data_location = (char*) &current_string[ntuples+1];
+
+ for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
+ {
+ int len = strlen(PQgetvalue(results, act_tuple, act_field)) + 1;
+ if (!ECPGget_data(results, act_tuple, act_field, stmt->lineno,
+ var->type, var->ind_type, current_data_location,
+ var->ind_value, len, 0, isarray))
+ status = false;
+ else
+ {
+ *current_string = current_data_location;
+ current_data_location += len;
+ current_string++;
+ }
+ }
+
+ /* terminate the list */
+ *current_string = NULL;
+ }
+ else
{
- if (!get_data(results, act_tuple, act_field, stmt->lineno,
- var->type, var->ind_type, var->value,
- var->ind_value, var->varcharsize, var->offset, isarray))
- status = false;
+ for (act_tuple = 0; act_tuple < ntuples && status; act_tuple++)
+ {
+ if (!ECPGget_data(results, act_tuple, act_field, stmt->lineno,
+ var->type, var->ind_type, var->value,
+ var->ind_value, var->varcharsize, var->offset, isarray))
+ status = false;
+ }
}
return status;
}
@@ -515,7 +563,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
int element;
case ECPGt_short:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
+ if (!(mallocedval = ECPGalloc(var->arrsize * 20, stmt->lineno)))
return false;
if (var->arrsize > 1)
@@ -535,7 +583,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
break;
case ECPGt_int:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
+ if (!(mallocedval = ECPGalloc(var->arrsize * 20, stmt->lineno)))
return false;
if (var->arrsize > 1)
@@ -555,7 +603,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
break;
case ECPGt_unsigned_short:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
+ if (!(mallocedval = ECPGalloc(var->arrsize * 20, stmt->lineno)))
return false;
if (var->arrsize > 1)
@@ -575,7 +623,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
break;
case ECPGt_unsigned_int:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
+ if (!(mallocedval = ECPGalloc(var->arrsize * 20, stmt->lineno)))
return false;
if (var->arrsize > 1)
@@ -595,7 +643,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
break;
case ECPGt_long:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
+ if (!(mallocedval = ECPGalloc(var->arrsize * 20, stmt->lineno)))
return false;
if (var->arrsize > 1)
@@ -615,7 +663,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
break;
case ECPGt_unsigned_long:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
+ if (!(mallocedval = ECPGalloc(var->arrsize * 20, stmt->lineno)))
return false;
if (var->arrsize > 1)
@@ -635,7 +683,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
break;
#ifdef HAVE_LONG_LONG_INT_64
case ECPGt_long_long:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 25, stmt->lineno)))
+ if (!(mallocedval = ECPGalloc(var->arrsize * 25, stmt->lineno)))
return false;
if (var->arrsize > 1)
@@ -655,7 +703,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
break;
case ECPGt_unsigned_long_long:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 25, stmt->lineno)))
+ if (!(mallocedval = ECPGalloc(var->arrsize * 25, stmt->lineno)))
return false;
if (var->arrsize > 1)
@@ -675,7 +723,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
break;
#endif /* HAVE_LONG_LONG_INT_64 */
case ECPGt_float:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
+ if (!(mallocedval = ECPGalloc(var->arrsize * 20, stmt->lineno)))
return false;
if (var->arrsize > 1)
@@ -695,7 +743,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
break;
case ECPGt_double:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
+ if (!(mallocedval = ECPGalloc(var->arrsize * 20, stmt->lineno)))
return false;
if (var->arrsize > 1)
@@ -715,7 +763,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
break;
case ECPGt_bool:
- if (!(mallocedval = ecpg_alloc(var->arrsize * 20, stmt->lineno)))
+ if (!(mallocedval = ECPGalloc(var->arrsize * 20, stmt->lineno)))
return false;
if (var->arrsize > 1)
@@ -758,7 +806,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
/* set slen to string length if type is char * */
int slen = (var->varcharsize == 0) ? strlen((char *) var->value) : var->varcharsize;
- if (!(newcopy = ecpg_alloc(slen + 1, stmt->lineno)))
+ if (!(newcopy = ECPGalloc(slen + 1, stmt->lineno)))
return false;
strncpy(newcopy, (char *) var->value, slen);
@@ -778,7 +826,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
{
int slen = strlen((char *) var->value);
- if (!(mallocedval = ecpg_alloc(slen + 1, stmt->lineno)))
+ if (!(mallocedval = ECPGalloc(slen + 1, stmt->lineno)))
return false;
strncpy(mallocedval, (char *) var->value, slen);
@@ -793,7 +841,7 @@ ECPGstore_input(const struct statement * stmt, const struct variable * var,
struct ECPGgeneric_varchar *variable =
(struct ECPGgeneric_varchar *) (var->value);
- if (!(newcopy = (char *) ecpg_alloc(variable->len + 1, stmt->lineno)))
+ if (!(newcopy = (char *) ECPGalloc(variable->len + 1, stmt->lineno)))
return false;
strncpy(newcopy, variable->arr, variable->len);
@@ -829,7 +877,7 @@ ECPGexecute(struct statement * stmt)
PGnotify *notify;
struct variable *var;
- copiedquery = ecpg_strdup(stmt->command, stmt->lineno);
+ copiedquery = ECPGstrdup(stmt->command, stmt->lineno);
/*
* Now, if the type is one of the fill in types then we take the
@@ -853,7 +901,7 @@ ECPGexecute(struct statement * stmt)
* Now tobeinserted points to an area that is to be inserted at
* the first %s
*/
- if (!(newcopy = (char *) ecpg_alloc(strlen(copiedquery) + strlen(tobeinserted) + 1, stmt->lineno)))
+ if (!(newcopy = (char *) ECPGalloc(strlen(copiedquery) + strlen(tobeinserted) + 1, stmt->lineno)))
return false;
strcpy(newcopy, copiedquery);
@@ -1054,7 +1102,7 @@ ECPGdo(int lineno, const char *connection_name, char *query,...)
{
va_list args;
struct statement *stmt;
- struct connection *con = get_connection(connection_name);
+ struct connection *con = ECPGget_connection(connection_name);
bool status;
char *oldlocale;
@@ -1063,7 +1111,7 @@ ECPGdo(int lineno, const char *connection_name, char *query,...)
oldlocale = strdup(setlocale(LC_NUMERIC, NULL));
setlocale(LC_NUMERIC, "C");
- if (!ecpg_init(con, connection_name, lineno))
+ if (!ECPGinit(con, connection_name, lineno))
{
setlocale(LC_NUMERIC, oldlocale);
free(oldlocale);
diff --git a/src/interfaces/ecpg/lib/extern.h b/src/interfaces/ecpg/lib/extern.h
index 8e7ba566a36..3759751555b 100644
--- a/src/interfaces/ecpg/lib/extern.h
+++ b/src/interfaces/ecpg/lib/extern.h
@@ -3,14 +3,15 @@
/* Here are some methods used by the lib. */
/* Returns a pointer to a string containing a simple type name. */
-void free_auto_mem(void);
-bool get_data(const PGresult *, int, int, int, enum ECPGttype type,
+void ECPGadd_mem(void *ptr, int lineno);
+
+bool ECPGget_data(const PGresult *, int, int, int, enum ECPGttype type,
enum ECPGttype, void *, void *, long, long, bool);
-struct connection *get_connection(const char *);
-void init_sqlca(void);
-char *ecpg_alloc(long, int);
-bool ecpg_init(const struct connection *, const char *, const int);
-char *ecpg_strdup(const char *, int);
+struct connection *ECPGget_connection(const char *);
+void ECPGinit_sqlca(void);
+char *ECPGalloc(long, int);
+bool ECPGinit(const struct connection *, const char *, const int);
+char *ECPGstrdup(const char *, int);
const char *ECPGtype_name(enum ECPGttype);
unsigned int ECPGDynamicType(Oid);
@@ -62,6 +63,23 @@ struct descriptor
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);
diff --git a/src/interfaces/ecpg/lib/memory.c b/src/interfaces/ecpg/lib/memory.c
index b49289abe5c..e1bc12eef3f 100644
--- a/src/interfaces/ecpg/lib/memory.c
+++ b/src/interfaces/ecpg/lib/memory.c
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/memory.c,v 1.6 2001/10/05 17:37:07 meskes Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/memory.c,v 1.7 2001/11/14 11:11:49 meskes Exp $ */
#include "postgres_fe.h"
@@ -8,7 +8,7 @@
#include "extern.h"
char *
-ecpg_alloc(long size, int lineno)
+ECPGalloc(long size, int lineno)
{
char *new = (char *) calloc(1L, size);
@@ -23,7 +23,7 @@ ecpg_alloc(long size, int lineno)
}
char *
-ecpg_strdup(const char *string, int lineno)
+ECPGstrdup(const char *string, int lineno)
{
char *new = strdup(string);
diff --git a/src/interfaces/ecpg/lib/misc.c b/src/interfaces/ecpg/lib/misc.c
index 2d3daf7d4fd..1a74cf46d30 100644
--- a/src/interfaces/ecpg/lib/misc.c
+++ b/src/interfaces/ecpg/lib/misc.c
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/misc.c,v 1.9 2001/10/30 05:38:56 momjian Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/misc.c,v 1.10 2001/11/14 11:11:49 meskes Exp $ */
#include "postgres_fe.h"
@@ -40,15 +40,15 @@ static int simple_debug = 0;
static FILE *debugstream = NULL;
void
-init_sqlca(void)
+ECPGinit_sqlca(void)
{
memcpy((char *) &sqlca, (char *) &sqlca_init, sizeof(sqlca));
}
bool
-ecpg_init(const struct connection * con, const char *connection_name, const int lineno)
+ECPGinit(const struct connection * con, const char *connection_name, const int lineno)
{
- init_sqlca();
+ ECPGinit_sqlca();
if (con == NULL)
{
ECPGraise(lineno, ECPG_NO_CONN, connection_name ? connection_name : "NULL");
@@ -61,9 +61,9 @@ ecpg_init(const struct connection * con, const char *connection_name, const int
bool
ECPGstatus(int lineno, const char *connection_name)
{
- struct connection *con = get_connection(connection_name);
+ struct connection *con = ECPGget_connection(connection_name);
- if (!ecpg_init(con, connection_name, lineno))
+ if (!ECPGinit(con, connection_name, lineno))
return (false);
/* are we connected? */
@@ -80,9 +80,9 @@ bool
ECPGtrans(int lineno, const char *connection_name, const char *transaction)
{
PGresult *res;
- struct connection *con = get_connection(connection_name);
+ struct connection *con = ECPGget_connection(connection_name);
- if (!ecpg_init(con, connection_name, lineno))
+ if (!ECPGinit(con, connection_name, lineno))
return (false);
ECPGlog("ECPGtrans line %d action = %s connection = %s\n", lineno, transaction, con->name);
diff --git a/src/interfaces/ecpg/lib/pg_type.h b/src/interfaces/ecpg/lib/pg_type.h
index 5ebe0faed17..da8cebf7ec2 100644
--- a/src/interfaces/ecpg/lib/pg_type.h
+++ b/src/interfaces/ecpg/lib/pg_type.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_type.h,v 1.5 2001/11/05 17:46:37 momjian Exp $
+ * $Id: pg_type.h,v 1.6 2001/11/14 11:11:49 meskes Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -62,7 +62,8 @@
#define VARCHAROID 1043
#define DATEOID 1082
#define TIMEOID 1083
-#define TIMESTAMPOID 1184
+#define TIMESTAMPOID 1114
+#define TIMESTAMPTZOID 1184
#define INTERVALOID 1186
#define TIMETZOID 1266
#define ZPBITOID 1560
diff --git a/src/interfaces/ecpg/lib/prepare.c b/src/interfaces/ecpg/lib/prepare.c
index e0960768799..4117454835e 100644
--- a/src/interfaces/ecpg/lib/prepare.c
+++ b/src/interfaces/ecpg/lib/prepare.c
@@ -1,4 +1,4 @@
-/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/prepare.c,v 1.10 2001/11/05 17:46:37 momjian Exp $ */
+/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/prepare.c,v 1.11 2001/11/14 11:11:49 meskes Exp $ */
#include "postgres_fe.h"
@@ -69,11 +69,11 @@ ECPGprepare(int lineno, char *name, char *variable)
return false;
}
- this = (struct prepared_statement *) ecpg_alloc(sizeof(struct prepared_statement), lineno);
+ this = (struct prepared_statement *) ECPGalloc(sizeof(struct prepared_statement), lineno);
if (!this)
return false;
- stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno);
+ stmt = (struct statement *) ECPGalloc(sizeof(struct statement), lineno);
if (!stmt)
{
free(this);
@@ -83,14 +83,14 @@ ECPGprepare(int lineno, char *name, char *variable)
/* create statement */
stmt->lineno = lineno;
stmt->connection = NULL;
- stmt->command = ecpg_strdup(variable, lineno);
+ 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 = ecpg_strdup(name, lineno);
+ this->name = ECPGstrdup(name, lineno);
this->stmt = stmt;
if (prep_stmts == NULL)
diff --git a/src/interfaces/ecpg/test/Makefile b/src/interfaces/ecpg/test/Makefile
index 33bd758378c..5ce77ef9b7f 100644
--- a/src/interfaces/ecpg/test/Makefile
+++ b/src/interfaces/ecpg/test/Makefile
@@ -1,4 +1,4 @@
-# $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Makefile,v 1.31 2001/08/11 10:52:09 petere Exp $
+# $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Makefile,v 1.32 2001/11/14 11:11:49 meskes Exp $
subdir = src/interfaces/ecpg/test
top_builddir = ../../../..
@@ -8,7 +8,7 @@ override CPPFLAGS := -I$(srcdir)/../include $(CPPFLAGS)
ECPG = ../preproc/ecpg -I$(srcdir)/../include
-TESTS = test1 test2 test3 test4 perftest dyntest dyntest2 test_notice test_code100 test_init
+TESTS = test1 test2 test3 test4 perftest dyntest dyntest2 test_notice test_code100 test_init testdynalloc
all: $(TESTS)
diff --git a/src/interfaces/ecpg/test/dyntest.pgc b/src/interfaces/ecpg/test/dyntest.pgc
index b91bcb1d940..2a432d4723b 100644
--- a/src/interfaces/ecpg/test/dyntest.pgc
+++ b/src/interfaces/ecpg/test/dyntest.pgc
@@ -2,7 +2,7 @@
*
* Copyright (c) 2000, Christof Petig <christof.petig@wtal.de>
*
- * $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Attic/dyntest.pgc,v 1.8 2001/08/11 10:52:09 petere Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Attic/dyntest.pgc,v 1.9 2001/11/14 11:11:49 meskes Exp $
*/
#include <stdio.h>
diff --git a/src/interfaces/ecpg/test/dyntest2.pgc b/src/interfaces/ecpg/test/dyntest2.pgc
index 5f9be400733..396f6a1730f 100644
--- a/src/interfaces/ecpg/test/dyntest2.pgc
+++ b/src/interfaces/ecpg/test/dyntest2.pgc
@@ -2,7 +2,7 @@
*
* Copyright (c) 2000, Christof Petig <christof.petig@wtal.de>
*
- * $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Attic/dyntest2.pgc,v 1.2 2001/08/11 10:52:09 petere Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/test/Attic/dyntest2.pgc,v 1.3 2001/11/14 11:11:49 meskes Exp $
*/
#include <stdio.h>