Added Christof's patches.
authorMichael Meskes
Wed, 14 Nov 2001 11:11:49 +0000 (11:11 +0000)
committerMichael Meskes
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 1e6c960064a71398b13f5a1be6e79cde468a4ce6..ffe622ef924413c5e96dca4375e8be2d05482430 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 .
    - Set ecpg version to 2.9.0.
         - Set library version to 3.3.0.
index fedcf80402dbbc863d94356443769a2a17f12789..4c606ca3985a9162c8d9482bcf5686413c67fc09 100644 (file)
@@ -1,20 +1,10 @@
 descriptor statements have the following shortcomings
 
-- up to now the only reasonable statement is
-   FETCH ... INTO SQL DESCRIPTOR 
-  no input variables allowed!
+- input descriptors (USING DESCRIPTOR ) 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 8c455ec58b0d9d50ff1cd1d881c70513ec5c6a29..5c295d872802cb028c354935100d68c18feb7b33 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 da4b8a3d7e07b429b6c0ef8db360d765fe218352..2f02e92da377f5f0e7463d0836808add4830d406 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 0d4ec712b55d2a8e86386ce17aca3d23b9a8f6a9..81bdad751bf112d6aeb3d636b36094c2a59d177b 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 95e65d603e4545d7a41eadb6104733fa68ec8af7..533bdcea5a45640a158111e6bbf76371326b5113 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 e39ee48c11529fcf4a1f31a68daaf96818b96007..56dd42fbed9c942e3d7937814a884e8fe737330c 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 57fd5c7767640f0ae2483992d88b71695bc8cb0f..4cd13944d2b74ff762bbea4cb8f5775a1c6dec34 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*) ¤t_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 8e7ba566a36f99dca2e564ed802b56795829d935..3759751555bb27ec6f2cae5dafda1f85849fc0a0 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 b49289abe5c27c1cad5c37404edf22b93a57a459..e1bc12eef3f8cb493e4b084743e5a28fb09a116e 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 2d3daf7d4fdf06f206a15cceca3fc53a6175a113..1a74cf46d309a88649cba34451b1cc5300188540 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 5ebe0faed178309fe3d7efd4aad71654d97c2cbe..da8cebf7ec2c2079472c9999c655cf1749dda6fc 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 e0960768799ad53bac6c8d206db7d66bac642322..4117454835e533cdfaea5856fbff5ad375029019 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 33bd758378cd10532b2f433e0904b6429ec6f1df..5ce77ef9b7fa97d70df332b888fe46bf19ba21ef 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 b91bcb1d940aad57b0c8a1ad1f5091c260eb6547..2a432d4723b1e58b68258ac57b168bf616c2fe50 100644 (file)
@@ -2,7 +2,7 @@
  *
  * Copyright (c) 2000, Christof Petig 
  *
- * $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 
index 5f9be4007339ed403ec7c9d04f03d0eaa4bafc02..396f6a1730f59ae9456fe69a3f52e2266a20ba42 100644 (file)
@@ -2,7 +2,7 @@
  *
  * Copyright (c) 2000, Christof Petig 
  *
- * $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