OSDN Git Service

Added Christof's patches.
authorMichael Meskes <meskes@postgresql.org>
Wed, 14 Nov 2001 11:11:49 +0000 (11:11 +0000)
committerMichael Meskes <meskes@postgresql.org>
Wed, 14 Nov 2001 11:11:49 +0000 (11:11 +0000)
16 files changed:
src/interfaces/ecpg/ChangeLog
src/interfaces/ecpg/README.dynSQL
src/interfaces/ecpg/include/ecpglib.h
src/interfaces/ecpg/lib/connect.c
src/interfaces/ecpg/lib/data.c
src/interfaces/ecpg/lib/descriptor.c
src/interfaces/ecpg/lib/error.c
src/interfaces/ecpg/lib/execute.c
src/interfaces/ecpg/lib/extern.h
src/interfaces/ecpg/lib/memory.c
src/interfaces/ecpg/lib/misc.c
src/interfaces/ecpg/lib/pg_type.h
src/interfaces/ecpg/lib/prepare.c
src/interfaces/ecpg/test/Makefile
src/interfaces/ecpg/test/dyntest.pgc
src/interfaces/ecpg/test/dyntest2.pgc

index 1e6c960..ffe622e 100644 (file)
@@ -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.
index fedcf80..4c606ca 100644 (file)
@@ -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.
 
index 8c455ec..5c295d8 100644 (file)
@@ -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
 }
index da4b8a3..2f02e92 100644 (file)
@@ -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);
index 0d4ec71..81bdad7 100644 (file)
@@ -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"
 
 #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 */
index 95e65d6..533bdce 100644 (file)
@@ -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;
index e39ee48..56dd42f 100644 (file)
@@ -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 */
index 57fd5c7..4cd1394 100644 (file)
@@ -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);
index 8e7ba56..3759751 100644 (file)
@@ -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);
 
index b49289a..e1bc12e 100644 (file)
@@ -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);
 
index 2d3daf7..1a74cf4 100644 (file)
@@ -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);
index 5ebe0fa..da8cebf 100644 (file)
@@ -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
index e096076..4117454 100644 (file)
@@ -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)
index 33bd758..5ce77ef 100644 (file)
@@ -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)
 
index b91bcb1..2a432d4 100644 (file)
@@ -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>
index 5f9be40..396f6a1 100644 (file)
@@ -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>