Re: Split-up ECPG patches - Mailing list pgsql-hackers

From Boszormenyi Zoltan
Subject Re: Split-up ECPG patches
Date
Msg-id 4A892354.8010502@cybertec.at
Whole thread Raw
In response to Re: Split-up ECPG patches  (Michael Meskes <meskes@postgresql.org>)
List pgsql-hackers
Michael Meskes írta:
> On Sun, Aug 16, 2009 at 05:59:46PM +0200, Boszormenyi Zoltan wrote:
>
>>> What heppens if the sqlda is incompatible?
>>>
>> Returns false?
>>
>
> I wasn't talking about this one function but about the flow of the resulting
> program. How can it happen that sqlda is incompatible and what happens then?
>

Hm. The following may occur. One may pass the same
sqlda ptr to two different cursors in DECLARE or FETCH
in the same loop. In this case it's wrong to not process the
"incompatible" call. Modified patch is attached:
- fixed flow, frees up the "incompatible" sqlda and creates a new one
- added ecpg_log() calls
- no more realloc(), an "empty" sqlda is allocated for full size.
  realloc() can destroy internal pointers (like the ones pointing to
  field names and ->sqlvar.)

The previous pg85-describe-5-ctxdiff.patch still applies cleanly.

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/

diff -dcrpN pgsql/src/interfaces/ecpg/ecpglib/execute.c pgsql.sqlda/src/interfaces/ecpg/ecpglib/execute.c
*** pgsql/src/interfaces/ecpg/ecpglib/execute.c    2009-08-07 13:06:28.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/ecpglib/execute.c    2009-08-17 11:13:42.000000000 +0200
***************
*** 25,30 ****
--- 25,31 ----
  #include "ecpgerrno.h"
  #include "extern.h"
  #include "sqlca.h"
+ #include "sqlda.h"
  #include "sql3types.h"
  #include "pgtypes_numeric.h"
  #include "pgtypes_date.h"
*************** ecpg_store_input(const int lineno, const
*** 1033,1038 ****
--- 1034,1040 ----
                  break;

              case ECPGt_descriptor:
+             case ECPGt_sqlda:
                  break;

              default:
*************** ecpg_execute(struct statement * stmt)
*** 1172,1177 ****
--- 1174,1235 ----
              if (desc->count == desc_counter)
                  desc_counter = 0;
          }
+         else if (var->type == ECPGt_sqlda)
+         {
+             pg_sqlda_t      **_sqlda = (pg_sqlda_t **)var->pointer;
+             pg_sqlda_t       *sqlda = *_sqlda;
+             struct variable    desc_inlist;
+             int        i;
+
+             if (sqlda == NULL)
+                 return false;
+
+             desc_counter++;
+             for (i = 0; i < sqlda->sqld; i++)
+             {
+                 if (i + 1 == desc_counter)
+                 {
+                     desc_inlist.type = ecpg_sqlda_type(sqlda->sqlvar[i].sqltype);
+                     desc_inlist.value = sqlda->sqlvar[i].sqldata;
+                     desc_inlist.pointer = &(sqlda->sqlvar[i].sqldata);
+                     switch (desc_inlist.type)
+                     {
+                         case ECPGt_char:
+                         case ECPGt_varchar:
+                             desc_inlist.varcharsize = strlen(sqlda->sqlvar[i].sqldata);
+                             break;
+                         default:
+                             desc_inlist.varcharsize = 0;
+                             break;
+                     }
+                     desc_inlist.arrsize = 1;
+                     desc_inlist.offset = 0;
+                     if (sqlda->sqlvar[i].sqlind)
+                     {
+                         desc_inlist.ind_type = ECPGt_short;
+                         /* ECPG expects indicator value < 0 */
+                         if (*(sqlda->sqlvar[i].sqlind))
+                             *(sqlda->sqlvar[i].sqlind) = -1;
+                         desc_inlist.ind_value = sqlda->sqlvar[i].sqlind;
+                         desc_inlist.ind_pointer = &(sqlda->sqlvar[i].sqlind);
+                         desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = 1;
+                         desc_inlist.ind_offset = 0;
+                     }
+                     else
+                     {
+                         desc_inlist.ind_type = ECPGt_NO_INDICATOR;
+                         desc_inlist.ind_value = desc_inlist.ind_pointer = NULL;
+                         desc_inlist.ind_varcharsize = desc_inlist.ind_arrsize = desc_inlist.ind_offset = 0;
+                     }
+                     if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, &desc_inlist, &tobeinserted, false))
+                         return false;
+
+                     break;
+                 }
+             }
+             if (sqlda->sqld == desc_counter)
+                 desc_counter = 0;
+         }
          else
          {
              if (!ecpg_store_input(stmt->lineno, stmt->force_indicator, var, &tobeinserted, false))
*************** ecpg_execute(struct statement * stmt)
*** 1353,1358 ****
--- 1411,1453 ----
                  }
                  var = var->next;
              }
+             else if (var != NULL && var->type == ECPGt_sqlda)
+             {
+                 pg_sqlda_t      **_sqlda = (pg_sqlda_t **)var->pointer;
+                 pg_sqlda_t       *sqlda = *_sqlda;
+
+                 /* If we are passed in a non-compatible sqlda then free it. */
+                 if (sqlda)
+                 {
+                     int    compat_sqlda;
+                     compat_sqlda = ecpg_compare_sqlda_with_PGresult(sqlda, results);
+                     ecpg_log("ecpg_execute on line %d: called ecpg_compare_sqlda_with_PGresult, status %d\n",
+                             stmt->lineno, compat_sqlda);
+                     if (!compat_sqlda)
+                     {
+                         free(sqlda);
+                         sqlda = NULL;
+                     }
+                 }
+                 /* Build a new sqlda structure */
+                 if (!sqlda)
+                 {
+                     sqlda = ecpg_build_sqlda_for_PGresult(stmt->lineno, results);
+                     ecpg_log("ecpg_execute on line %d: new sqlda was built\n", stmt->lineno);
+                     if (!sqlda)
+                         status = false;
+                     *_sqlda = sqlda;
+                 }
+                 /* If the sqlda was allocated then fill it. */
+                 if (status == true)
+                 {
+                     ecpg_set_sqlda_from_PGresult(stmt->lineno, _sqlda, results);
+                     ecpg_log("ecpg_execute on line %d: putting result (1 tuple %d fields) into sqlda descriptor\n",
+                             stmt->lineno, PQnfields(results));
+                 }
+
+                 var = var->next;
+             }
              else
                  for (act_field = 0; act_field < nfields && status; act_field++)
                  {
diff -dcrpN pgsql/src/interfaces/ecpg/ecpglib/extern.h pgsql.sqlda/src/interfaces/ecpg/ecpglib/extern.h
*** pgsql/src/interfaces/ecpg/ecpglib/extern.h    2009-05-25 12:08:48.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/ecpglib/extern.h    2009-08-11 10:32:34.000000000 +0200
***************
*** 6,11 ****
--- 6,12 ----
  #include "postgres_fe.h"
  #include "libpq-fe.h"
  #include "sqlca.h"
+ #include "sqlda.h"
  #include "ecpg_config.h"
  #ifndef CHAR_BIT
  #include <limits.h>
*************** bool        ecpg_init(const struct connection
*** 129,134 ****
--- 130,137 ----
  char       *ecpg_strdup(const char *, int);
  const char *ecpg_type_name(enum ECPGttype);
  int            ecpg_dynamic_type(Oid);
+ int            ecpg_sqlda_type(int);
+ int            ecpg_to_sqlda_type(Oid);
  void        ecpg_free_auto_mem(void);
  void        ecpg_clear_auto_mem(void);

*************** void        ecpg_log(const char *format,...);
*** 149,154 ****
--- 152,161 ----
  bool        ecpg_auto_prepare(int, const char *, const int, char **, const char *);
  void        ecpg_init_sqlca(struct sqlca_t * sqlca);

+ pg_sqlda_t *ecpg_build_sqlda_for_PGresult(int, PGresult *);
+ bool        ecpg_compare_sqlda_with_PGresult(pg_sqlda_t *sqlda, const PGresult *results);
+ void        ecpg_set_sqlda_from_PGresult(int, pg_sqlda_t **, const PGresult *);
+
  /* SQLSTATE values generated or processed by ecpglib (intentionally
   * not exported -- users should refer to the codes directly) */

diff -dcrpN pgsql/src/interfaces/ecpg/ecpglib/Makefile pgsql.sqlda/src/interfaces/ecpg/ecpglib/Makefile
*** pgsql/src/interfaces/ecpg/ecpglib/Makefile    2009-07-13 11:16:41.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/ecpglib/Makefile    2009-08-11 10:32:34.000000000 +0200
*************** override CFLAGS += $(PTHREAD_CFLAGS)
*** 24,30 ****
  # Need to recompile any libpgport object files
  LIBS := $(filter-out -lpgport, $(LIBS))

! OBJS= execute.o typename.o descriptor.o data.o error.o prepare.o memory.o \
      connect.o misc.o path.o pgstrcasecmp.o \
      $(filter snprintf.o strlcpy.o, $(LIBOBJS))

--- 24,30 ----
  # Need to recompile any libpgport object files
  LIBS := $(filter-out -lpgport, $(LIBS))

! OBJS= execute.o typename.o descriptor.o sqlda.o data.o error.o prepare.o memory.o \
      connect.o misc.o path.o pgstrcasecmp.o \
      $(filter snprintf.o strlcpy.o, $(LIBOBJS))

diff -dcrpN pgsql/src/interfaces/ecpg/ecpglib/sqlda.c pgsql.sqlda/src/interfaces/ecpg/ecpglib/sqlda.c
*** pgsql/src/interfaces/ecpg/ecpglib/sqlda.c    1970-01-01 01:00:00.000000000 +0100
--- pgsql.sqlda/src/interfaces/ecpg/ecpglib/sqlda.c    2009-08-17 11:10:32.000000000 +0200
***************
*** 0 ****
--- 1,329 ----
+ /*
+  * Crude SQLDA support routines
+  * Only supports fetching 1 record at a time
+  *
+  * The allocated memory area pointed by an sqlda pointer
+  * contains both the metadata and the data, so freeing up
+  * is a simple free(sqlda) as expected by the ESQL/C examples.
+  */
+
+ #define POSTGRES_ECPG_INTERNAL
+ #include "postgres_fe.h"
+ #include "pg_type.h"
+
+ #include <inttypes.h>
+ #include <dlfcn.h>
+
+ #include "ecpg-pthread-win32.h"
+ #include "decimal.h"
+ #include "ecpgtype.h"
+ #include "ecpglib.h"
+ #include "ecpgerrno.h"
+ #include "extern.h"
+ #include "sqlca.h"
+ #include "sqlda.h"
+ #include "sqltypes.h"
+
+ /*
+  * Compute the next variable's offset with
+  * the current variable's size and alignment.
+  */
+ static long
+ ecpg_sqlda_size_round_align(long offset, int alignment, int size)
+ {
+     if (offset % alignment)
+         offset += alignment - (offset % alignment);
+     offset += size;
+     return offset;
+ }
+
+ /*
+  * Compute the current variable's offset with alignment.
+  */
+ static long
+ ecpg_sqlda_size_align(long offset, int alignment)
+ {
+     if (offset % alignment)
+         offset += alignment - (offset % alignment);
+     return offset;
+ }
+
+ static long
+ ecpg_sqlda_empty_size(const PGresult *res)
+ {
+     long    size;
+     int    i;
+     int    sqld = PQnfields(res);
+
+
+     /* Initial size to store main structure and field structures */
+     size = sizeof(pg_sqlda_t) + sqld * sizeof(pg_sqlvar_t);
+
+     /* Add space for field names */
+     for (i = 0; i < sqld; i++)
+         size += strlen(PQfname(res, i)) + 1;
+
+     /* Add padding to the first field value */
+     size = ecpg_sqlda_size_align(size, sizeof(int));
+
+     return size;
+ }
+
+ static long
+ ecpg_sqlda_total_size(const PGresult *res)
+ {
+     int    i;
+     int    sqld = PQnfields(res);
+     long    size;
+
+     size = ecpg_sqlda_empty_size(res);
+
+     /* Add space for the field values */
+     for (i = 0; i < sqld; i++)
+     {
+         switch (ecpg_to_sqlda_type(PQftype(res, i)))
+         {
+             case SQLSMINT:
+                 size = ecpg_sqlda_size_round_align(size, sizeof(short), sizeof(short));
+                 break;
+             case SQLINT:
+             case SQLSERIAL:
+                 size = ecpg_sqlda_size_round_align(size, sizeof(int), sizeof(int));
+                 break;
+             case SQLFLOAT:
+                 size = ecpg_sqlda_size_round_align(size, sizeof(double), sizeof(double));
+                 break;
+             case SQLSMFLOAT:
+                 size = ecpg_sqlda_size_round_align(size, sizeof(float), sizeof(float));
+                 break;
+             case SQLDECIMAL:
+                 size = ecpg_sqlda_size_round_align(size, sizeof(int), sizeof(decimal));
+                 break;
+             case SQLINT8:
+             case SQLSERIAL8:
+                 size = ecpg_sqlda_size_round_align(size, sizeof(int64_t), sizeof(int64_t));
+                 break;
+
+             /*
+              * These types will be passed as character strings
+              * as is from the PGresult until we know what to do with them.
+              */
+             case SQLCHAR:
+             case SQLTEXT:
+             case SQLVCHAR:
+             case SQLNCHAR:
+             case SQLNVCHAR:
+             case SQLMONEY:
+             case SQLDATE:
+             case SQLDTIME:
+             case SQLINTERVAL:
+             default:
+                 break;
+         }
+     }
+     return size;
+ }
+
+ /*
+  * Build pg_sqlda_t (metadata only) from PGresult
+  */
+ pg_sqlda_t *
+ ecpg_build_sqlda_for_PGresult(int line, PGresult *res)
+ {
+     pg_sqlda_t *sqlda;
+     pg_sqlvar_t*sqlvar;
+     char       *fname;
+     long        size;
+     int        sqld;
+     int        i;
+
+     size = ecpg_sqlda_total_size(res);
+     sqlda = (pg_sqlda_t *)ecpg_alloc(size, line);
+     if (!sqlda)
+         return NULL;
+
+     memset(sqlda, 0, size);
+     sqlvar = (pg_sqlvar_t *)(sqlda + 1);
+     sqld = PQnfields(res);
+     fname = (char *)(sqlvar + sqld);
+
+     sqlda->sqld = sqld;
+     sqlda->desc_occ = size; /* cheat here, keep the full allocated size */
+     sqlda->sqlvar = sqlvar;
+
+     for (i = 0; i < sqlda->sqld; i++)
+     {
+         sqlda->sqlvar[i].sqltype = ecpg_to_sqlda_type(PQftype(res, i));
+         strcpy(fname, PQfname(res, i));
+         sqlda->sqlvar[i].sqlname = fname;
+         fname += strlen(sqlda->sqlvar[i].sqlname) + 1;
+         sqlda->sqlvar[i].sqlformat = (char *)(long)PQfformat(res, i);
+         sqlda->sqlvar[i].sqlxid = PQftype(res, i);
+         sqlda->sqlvar[i].sqltypelen = PQfsize(res, i);
+     }
+
+     return sqlda;
+ }
+
+ /*
+  * Check whether the supplied sqlda and PGresult
+  * both has the same metadata
+  */
+ bool
+ ecpg_compare_sqlda_with_PGresult(pg_sqlda_t *sqlda, const PGresult *res)
+ {
+     int    i;
+     long    size;
+
+     if (sqlda->sqld != PQnfields(res))
+     {
+         ecpg_log("ecpg_compare_sqlda_with_PGresult: sqld differ %d %d\n",
+                                                 sqlda->sqld, PQnfields(res));
+         return false;
+     }
+
+     size = ecpg_sqlda_total_size(res);
+     if (sqlda->desc_occ != size)
+     {
+         ecpg_log("ecpg_compare_sqlda_with_PGresult: structure size differ %d %d\n",
+                             sqlda->desc_occ, size);
+         return false;
+     }
+
+     for (i = 0; i < sqlda->sqld; i++)
+     {
+         if (sqlda->sqlvar[i].sqltype != ecpg_to_sqlda_type(PQftype(res, i)))
+         {
+             ecpg_log("ecpg_compare_sqlda_with_PGresult: field %d sqltype differ %d %d\n",
+                     i, sqlda->sqlvar[i].sqltype, ecpg_to_sqlda_type(PQftype(res, i)));
+             return false;
+         }
+         if (strncmp(sqlda->sqlvar[i].sqlname, PQfname(res, i), strlen(PQfname(res, i))))
+         {
+             ecpg_log("ecpg_compare_sqlda_with_PGresult: field %d sqlname differ '%s' '%s'\n",
+                     i, sqlda->sqlvar[i].sqlname, PQfname(res, i));
+             return false;
+         }
+         if (sqlda->sqlvar[i].sqlformat != (char *)(long)PQfformat(res, i))
+         {
+             ecpg_log("ecpg_compare_sqlda_with_PGresult: field %d sqlformat differ %d %d\n",
+                     i, sqlda->sqlvar[i].sqlformat, PQfformat(res, i));
+             return false;
+         }
+         if (sqlda->sqlvar[i].sqlxid != PQftype(res, i))
+         {
+             ecpg_log("ecpg_compare_sqlda_with_PGresult: field %d sqlxid differ %d %d\n",
+                     i, sqlda->sqlvar[i].sqlxid, PQftype(res, i));
+             return false;
+         }
+         if (sqlda->sqlvar[i].sqltypelen != PQfsize(res, i))
+         {
+             ecpg_log("ecpg_compare_sqlda_with_PGresult: field %d sqltypelen differ %d %d\n",
+                     i, sqlda->sqlvar[i].sqltypelen, PQfsize(res, i));
+             return false;
+         }
+     }
+
+     return true;
+ }
+
+ /*
+  * Sets values from PGresult.
+  */
+ void
+ ecpg_set_sqlda_from_PGresult(int lineno, pg_sqlda_t **_sqlda, const PGresult *res)
+ {
+     pg_sqlda_t *sqlda = (*_sqlda);
+     int        i;
+     long        size;
+     static    int2    value_is_null = -1;
+     static    int2    value_is_not_null = 0;
+
+     /* Offset for the first field value */
+     size = ecpg_sqlda_empty_size(res);
+
+     /*
+      * Set sqlvar[i]->sqldata pointers and convert values to correct format
+      */
+     for (i = 0; i < sqlda->sqld; i++)
+     {
+         int type = -1, isnull;
+         int use_getdata = true;
+
+         switch (sqlda->sqlvar[i].sqltype)
+         {
+             case SQLSMINT:
+                 size = ecpg_sqlda_size_align(size, sizeof(short));
+                 sqlda->sqlvar[i].sqldata = (char *)sqlda + size;
+                 size += sizeof(short);
+                 type = ECPGt_short;
+                 break;
+             case SQLINT:
+             case SQLSERIAL:
+                 size = ecpg_sqlda_size_align(size, sizeof(int));
+                 sqlda->sqlvar[i].sqldata = (char *)sqlda + size;
+                 size += sizeof(int);
+                 type = ECPGt_int;
+                 break;
+             case SQLFLOAT:
+                 size = ecpg_sqlda_size_align(size, sizeof(double));
+                 sqlda->sqlvar[i].sqldata = (char *)sqlda + size;
+                 size += sizeof(double);
+                 type = ECPGt_double;
+                 break;
+             case SQLSMFLOAT:
+                 size = ecpg_sqlda_size_align(size, sizeof(float));
+                 sqlda->sqlvar[i].sqldata = (char *)sqlda + size;
+                 size += sizeof(float);
+                 type = ECPGt_float;
+                 break;
+             case SQLDECIMAL:
+             {
+                 size = ecpg_sqlda_size_align(size, sizeof(int));
+                 sqlda->sqlvar[i].sqldata = (char *)sqlda + size;
+                 size += sizeof(decimal);
+                 type = ECPGt_decimal;
+                 break;
+             }
+             case SQLINT8:
+             case SQLSERIAL8:
+                 size = ecpg_sqlda_size_align(size, sizeof(int64_t));
+                 sqlda->sqlvar[i].sqldata = (char *)sqlda + size;
+                 size += sizeof(int64_t);
+                 type = ECPGt_long_long;
+                 break;
+
+             /*
+              * These types will be passed as character strings until
+              * it's known what to do with them. We use sqlvar->sqldata
+              * in all cases regardless of length, don't care about
+              * sqlvar->sqlilongdata.
+              */
+             case SQLCHAR:
+             case SQLTEXT:
+             case SQLVCHAR:
+             case SQLNCHAR:
+             case SQLNVCHAR:
+             case SQLMONEY:
+             case SQLDATE:
+             case SQLDTIME:
+             case SQLINTERVAL:
+             default:
+                 use_getdata = false;
+                 break;
+         }
+
+         isnull = PQgetisnull(res, 0, i);
+         sqlda->sqlvar[i].sqlind = isnull ? &value_is_null : &value_is_not_null;
+         if (!isnull)
+         {
+             if (use_getdata)
+                 ecpg_get_data(res, 0, i, lineno,
+                         type, ECPGt_NO_INDICATOR,
+                         sqlda->sqlvar[i].sqldata, NULL, 0, 0, 0,
+                         ECPG_ARRAY_NONE, ECPG_COMPAT_INFORMIX, false);
+             else
+                 sqlda->sqlvar[i].sqldata = PQgetvalue(res, 0, i);
+         }
+     }
+ }
diff -dcrpN pgsql/src/interfaces/ecpg/ecpglib/typename.c pgsql.sqlda/src/interfaces/ecpg/ecpglib/typename.c
*** pgsql/src/interfaces/ecpg/ecpglib/typename.c    2009-08-07 13:06:28.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/ecpglib/typename.c    2009-08-11 10:32:34.000000000 +0200
***************
*** 7,12 ****
--- 7,13 ----
  #include "ecpgtype.h"
  #include "ecpglib.h"
  #include "extern.h"
+ #include "sqltypes.h"
  #include "sql3types.h"
  #include "pg_type.h"

*************** ecpg_dynamic_type(Oid type)
*** 100,102 ****
--- 101,190 ----
              return -(int) type;
      }
  }
+
+ int
+ ecpg_sqlda_type(int type)
+ {
+     switch (type)
+     {
+         case SQLCHAR:
+         case SQLNCHAR:
+             return ECPGt_char;
+         case SQLSMINT:
+             return ECPGt_short;
+         case SQLINT:
+             return ECPGt_int;
+         case SQLFLOAT:
+             return ECPGt_double;
+         case SQLSMFLOAT:
+             return ECPGt_float;
+         case SQLDECIMAL:
+             return ECPGt_decimal;
+         case SQLSERIAL:
+             return ECPGt_int;
+         case SQLDATE:
+             return ECPGt_date;
+ #if 0
+         case SQLMONEY:
+             return ???;
+         case SQLNULL:
+             return ???;
+ #endif
+         case SQLDTIME:
+             return ECPGt_timestamp;
+ #if 0
+         case SQLBYTES:
+             return ???;
+ #endif
+         case SQLTEXT:
+             return ECPGt_char;
+         case SQLVCHAR:
+         case SQLNVCHAR:
+             return ECPGt_varchar;
+         case SQLINTERVAL:
+             return ECPGt_interval;
+         case SQLINT8:
+         case SQLSERIAL8:
+             return ECPGt_long_long;
+         default:
+             return (-type);
+     }
+ }
+
+ int
+ ecpg_to_sqlda_type(Oid type)
+ {
+     switch (type)
+     {
+         case CHAROID:
+         case BPCHAROID:
+             return SQLCHAR;
+         case INT2OID:
+             return SQLSMINT;
+         case INT4OID:
+             return SQLINT;
+         case FLOAT8OID:
+             return SQLFLOAT;
+         case FLOAT4OID:
+             return SQLSMFLOAT;
+         case NUMERICOID:
+             return SQLDECIMAL;
+         case DATEOID:
+             return SQLDATE;
+         case CASHOID:
+             return SQLMONEY;
+         case TIMESTAMPOID:
+         case TIMESTAMPTZOID:
+             return SQLDTIME;
+         case TEXTOID:
+             return SQLTEXT;
+         case VARCHAROID:
+             return SQLVCHAR;
+         case INTERVALOID:
+             return SQLINTERVAL;
+         case INT8OID:
+             return SQLINT8;
+         default:
+             return (-type);
+     }
+ }
diff -dcrpN pgsql/src/interfaces/ecpg/include/ecpgtype.h pgsql.sqlda/src/interfaces/ecpg/include/ecpgtype.h
*** pgsql/src/interfaces/ecpg/include/ecpgtype.h    2009-08-07 13:06:28.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/include/ecpgtype.h    2009-08-11 10:34:24.000000000 +0200
*************** enum ECPGttype
*** 62,68 ****
      ECPGt_EOIT,                    /* End of insert types. */
      ECPGt_EORT,                    /* End of result types. */
      ECPGt_NO_INDICATOR,            /* no indicator */
!     ECPGt_string                            /* trimmed (char *) type */
  };

   /* descriptor items */
--- 62,69 ----
      ECPGt_EOIT,                    /* End of insert types. */
      ECPGt_EORT,                    /* End of result types. */
      ECPGt_NO_INDICATOR,            /* no indicator */
!     ECPGt_string,                /* trimmed (char *) type */
!     ECPGt_sqlda                /* C struct descriptor */
  };

   /* descriptor items */
diff -dcrpN pgsql/src/interfaces/ecpg/include/sqlda.h pgsql.sqlda/src/interfaces/ecpg/include/sqlda.h
*** pgsql/src/interfaces/ecpg/include/sqlda.h    2009-06-13 18:25:05.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/include/sqlda.h    2009-08-11 10:32:34.000000000 +0200
***************
*** 1,3 ****
--- 1,74 ----
  /*
   * $PostgreSQL: pgsql/src/interfaces/ecpg/include/sqlda.h,v 1.4 2009/06/11 14:49:13 momjian Exp $
   */
+
+ #ifndef POSTGRES_SQLDA_H
+ #define POSTGRES_SQLDA_H
+
+ /* Define Informix "standard" types */
+ #ifndef C_H
+ typedef int        int4;
+ typedef    short        int2;
+ #endif
+ typedef    char        int1;
+
+ typedef    int        mint;
+ typedef    long        mlong;
+
+ typedef    short        MSHORT;
+ typedef    char        MCHAR;
+
+ typedef    unsigned int    uint4;
+ typedef    unsigned short    uint2;
+ typedef    unsigned char    uint1;
+
+ typedef    unsigned int    muint;
+ typedef    unsigned long    mulong;
+
+ typedef    unsigned short    MUSHORT;
+ typedef    unsigned char    MUCHAR;
+
+ #define MI_INT_SIZE     (sizeof(int)    * 8)
+ #define MI_LONG_SIZE    (sizeof(long)   * 8)
+ #define MI_PTR_SIZE     (sizeof(char *) * 8)
+
+ typedef struct sqlvar_struct
+ {
+     int2    sqltype;        /* variable type                */
+     int4    sqllen;            /* length in bytes              */
+     char       *sqldata;        /* pointer to data              */
+     int2       *sqlind;        /* pointer to indicator         */
+     char       *sqlname;        /* variable name                */
+     char       *sqlformat;        /* reserved for future use      */
+     int2    sqlitype;        /* ind variable type            */
+     int2    sqlilen;        /* ind length in bytes          */
+     char       *sqlidata;        /* ind data pointer             */
+     int4    sqlxid;            /* extended id type             */
+     char       *sqltypename;    /* extended type name           */
+     int2    sqltypelen;        /* length of extended type name */
+     int2    sqlownerlen;        /* length of owner name         */
+     int2    sqlsourcetype;        /* source type for distinct of built-ins */
+     char       *sqlownername;    /* owner name                   */
+     int4    sqlsourceid;        /* extended id of source type   */
+
+     /*
+      * sqlilongdata is new.  It supports data that exceeds the 32k
+      * limit.  sqlilen and sqlidata are for backward compatibility
+      * and they have maximum value of <32K.
+      */
+     char       *sqlilongdata;    /* for data field beyond 32K    */
+     int4    sqlflags;        /* for internal use only        */
+     void       *sqlreserved;    /* reserved for future use      */
+ } pg_sqlvar_t;
+
+ typedef struct sqlda
+ {
+     int2        sqld;
+     pg_sqlvar_t       *sqlvar;
+     char        desc_name[19];    /* descriptor name              */
+     int2        desc_occ;    /* size of sqlda structure      */
+     struct sqlda       *desc_next;    /* pointer to next sqlda struct */
+     void           *reserved;    /* reserved for future use */
+ } pg_sqlda_t;
+
+ #endif /* POSTGRES_SQLDA_H */
diff -dcrpN pgsql/src/interfaces/ecpg/include/sqltypes.h pgsql.sqlda/src/interfaces/ecpg/include/sqltypes.h
*** pgsql/src/interfaces/ecpg/include/sqltypes.h    2009-06-13 18:25:05.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/include/sqltypes.h    2009-08-11 10:32:34.000000000 +0200
***************
*** 30,33 ****
--- 30,55 ----
  #define CLVCHARPTRTYPE    124
  #define CTYPEMAX    25

+ /*
+  * Values used in sqlda->sqlvar[i]->sqltype
+  */
+ #define    SQLCHAR        0
+ #define    SQLSMINT    1
+ #define    SQLINT        2
+ #define    SQLFLOAT    3
+ #define    SQLSMFLOAT    4
+ #define    SQLDECIMAL    5
+ #define    SQLSERIAL    6
+ #define    SQLDATE        7
+ #define    SQLMONEY    8
+ #define    SQLDTIME    10
+ #define    SQLBYTES    11
+ #define    SQLTEXT        12
+ #define    SQLVCHAR    13
+ #define    SQLINTERVAL    14
+ #define    SQLNCHAR    15
+ #define    SQLNVCHAR    16
+ #define    SQLINT8        17
+ #define    SQLSERIAL8    18
+
  #endif   /* ndef ECPG_SQLTYPES_H */
diff -dcrpN pgsql/src/interfaces/ecpg/preproc/descriptor.c pgsql.sqlda/src/interfaces/ecpg/preproc/descriptor.c
*** pgsql/src/interfaces/ecpg/preproc/descriptor.c    2009-01-30 17:28:46.000000000 +0100
--- pgsql.sqlda/src/interfaces/ecpg/preproc/descriptor.c    2009-08-11 10:32:34.000000000 +0200
*************** descriptor_variable(const char *name, in
*** 326,328 ****
--- 326,347 ----
      strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
      return (struct variable *) & varspace[input];
  }
+
+ struct variable *
+ sqlda_variable(const char *name)
+ {
+     struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
+
+     p->name = mm_strdup(name);
+     p->type = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
+     p->type->type = ECPGt_sqlda;
+     p->type->size = NULL;
+     p->type->struct_sizeof = NULL;
+     p->type->u.element = NULL;
+     p->type->lineno = 0;
+     p->brace_level = 0;
+     p->next = NULL;
+
+     return p;
+ }
+
diff -dcrpN pgsql/src/interfaces/ecpg/preproc/ecpg.addons pgsql.sqlda/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql/src/interfaces/ecpg/preproc/ecpg.addons    2009-08-10 15:18:04.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/preproc/ecpg.addons    2009-08-11 10:42:00.000000000 +0200
*************** ECPG: FetchStmtMOVEfetch_args block
*** 405,424 ****
          current_cursor = NULL;
          $$ = cat2_str(make_str("move"), $2);
      }
!     | FETCH fetch_args ecpg_into
      {
          add_additional_variables(current_cursor, false);
          free(current_cursor);
          current_cursor = NULL;
          $$ = cat2_str(make_str("fetch"), $2);
      }
!     | FETCH FORWARD cursor_name opt_ecpg_into
      {
          char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
          add_additional_variables($3, false);
          $$ = cat_str(2, make_str("fetch forward"), cursor_marker);
      }
!     | FETCH FORWARD from_in cursor_name opt_ecpg_into
      {
          char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
          add_additional_variables($4, false);
--- 405,424 ----
          current_cursor = NULL;
          $$ = cat2_str(make_str("move"), $2);
      }
!     | FETCH fetch_args ecpg_fetch_into
      {
          add_additional_variables(current_cursor, false);
          free(current_cursor);
          current_cursor = NULL;
          $$ = cat2_str(make_str("fetch"), $2);
      }
!     | FETCH FORWARD cursor_name opt_ecpg_fetch_into
      {
          char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
          add_additional_variables($3, false);
          $$ = cat_str(2, make_str("fetch forward"), cursor_marker);
      }
!     | FETCH FORWARD from_in cursor_name opt_ecpg_fetch_into
      {
          char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
          add_additional_variables($4, false);
diff -dcrpN pgsql/src/interfaces/ecpg/preproc/ecpg.trailer pgsql.sqlda/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql/src/interfaces/ecpg/preproc/ecpg.trailer    2009-08-10 18:01:47.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/preproc/ecpg.trailer    2009-08-11 10:41:02.000000000 +0200
*************** ecpg_using:    USING using_list     { $$ = EMP
*** 1014,1032 ****

  using_descriptor: USING opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
          {
!             add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator);
              $$ = EMPTY;
          }
          ;

  into_descriptor: INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
          {
!             add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator);
              $$ = EMPTY;
          }
          ;

! opt_sql: /*EMPTY*/ | SQL_SQL;

  using_list: UsingValue | UsingValue ',' using_list;

--- 1014,1062 ----

  using_descriptor: USING opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
          {
!             if (strlen($2) || !(INFORMIX_MODE))
!                 add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator);
!             else
!             {
!                 if ($4[0] == '\"')
!                 {
!                     char *pos;
!
!                     $4[0] = ' ';
!                     for (pos = $4; *pos; pos++)
!                         if (*pos == '\"')
!                             *pos = ' ';
!                 }
!                 add_variable_to_head(&argsinsert, sqlda_variable($4), &no_indicator);
!             }
              $$ = EMPTY;
          }
          ;

  into_descriptor: INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
          {
!             if (strlen($2) || !(INFORMIX_MODE))
!                 add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator);
!             else
!             {
!                 if ($4[0] == '\"')
!                 {
!                     char *pos;
!
!                     $4[0] = ' ';
!                     for (pos = $4; *pos; pos++)
!                         if (*pos == '\"')
!                             *pos = ' ';
!                 }
!                 add_variable_to_head(&argsresult, sqlda_variable($4), &no_indicator);
!             }
              $$ = EMPTY;
          }
          ;

! opt_sql: /*EMPTY*/        { $$ = EMPTY; }
!         | SQL_SQL    { $$ = make_str("sql"); }
!         ;

  using_list: UsingValue | UsingValue ',' using_list;

*************** ecpg_into: INTO into_list    { $$ = EMPTY;
*** 2050,2057 ****
      ;


! opt_ecpg_into:    /* EMPTY */    { $$ = EMPTY; }
!     | ecpg_into        { $$ = $1; }

  %%

--- 2080,2103 ----
      ;


! ecpg_fetch_into: ecpg_into    { $$ = $1; }
!     | using_descriptor
!     {
!         struct variable *var;
!
!         if (!INFORMIX_MODE)
!             mmerror(PARSE_ERROR, ET_ERROR, "Not in Informix compatibility mode");
!
!         var = argsinsert->variable;
!         remove_variable_from_list(&argsinsert, var);
!         add_variable_to_head(&argsresult, var, &no_indicator);
!         $$ = $1;
!     }
!     ;
!
! opt_ecpg_fetch_into: /* EMPTY */    { $$ = EMPTY; }
!     | ecpg_fetch_into        { $$ = $1; }
!     ;

  %%

diff -dcrpN pgsql/src/interfaces/ecpg/preproc/ecpg.type pgsql.sqlda/src/interfaces/ecpg/preproc/ecpg.type
*** pgsql/src/interfaces/ecpg/preproc/ecpg.type    2009-08-10 18:02:24.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/preproc/ecpg.type    2009-08-11 10:44:52.000000000 +0200
***************
*** 62,67 ****
--- 62,68 ----
  %type <str> ecpg_ident
  %type <str> ecpg_interval
  %type <str> ecpg_into
+ %type <str> ecpg_fetch_into
  %type <str> ecpg_param
  %type <str> ecpg_sconst
  %type <str> ecpg_using
***************
*** 77,83 ****
  %type <str> opt_bit_field
  %type <str> opt_connection_name
  %type <str> opt_database_name
! %type <str> opt_ecpg_into
  %type <str> opt_ecpg_using
  %type <str> opt_initializer
  %type <str> opt_options
--- 78,84 ----
  %type <str> opt_bit_field
  %type <str> opt_connection_name
  %type <str> opt_database_name
! %type <str> opt_ecpg_fetch_into
  %type <str> opt_ecpg_using
  %type <str> opt_initializer
  %type <str> opt_options
***************
*** 87,92 ****
--- 88,94 ----
  %type <str> opt_reference
  %type <str> opt_scale
  %type <str> opt_server
+ %type <str> opt_sql
  %type <str> opt_user
  %type <str> opt_opt_value
  %type <str> ora_user
diff -dcrpN pgsql/src/interfaces/ecpg/preproc/extern.h pgsql.sqlda/src/interfaces/ecpg/preproc/extern.h
*** pgsql/src/interfaces/ecpg/preproc/extern.h    2009-08-09 18:13:31.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/preproc/extern.h    2009-08-11 10:32:34.000000000 +0200
*************** extern void add_descriptor(char *, char
*** 90,95 ****
--- 90,96 ----
  extern void drop_descriptor(char *, char *);
  extern struct descriptor *lookup_descriptor(char *, char *);
  extern struct variable *descriptor_variable(const char *name, int input);
+ extern struct variable *sqlda_variable(const char *name);
  extern void add_variable_to_head(struct arguments **, struct variable *, struct variable *);
  extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *);
  extern void remove_variable_from_list(struct arguments ** list, struct variable * var);
diff -dcrpN pgsql/src/interfaces/ecpg/preproc/type.c pgsql.sqlda/src/interfaces/ecpg/preproc/type.c
*** pgsql/src/interfaces/ecpg/preproc/type.c    2009-08-07 13:06:28.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/preproc/type.c    2009-08-11 11:46:04.000000000 +0200
*************** get_type(enum ECPGttype type)
*** 194,199 ****
--- 194,202 ----
          case ECPGt_descriptor:
              return ("ECPGt_descriptor");
              break;
+         case ECPGt_sqlda:
+             return ("ECPGt_sqlda");
+             break;
          case ECPGt_date:
              return ("ECPGt_date");
              break;
*************** ECPGdump_a_simple(FILE *o, const char *n
*** 328,333 ****
--- 331,338 ----
      else if (type == ECPGt_descriptor)
          /* remember that name here already contains quotes (if needed) */
          fprintf(o, "\n\tECPGt_descriptor, %s, 0L, 0L, 0L, ", name);
+     else if (type == ECPGt_sqlda)
+         fprintf(o, "\n\tECPGt_sqlda, &%s, 0L, 0L, 0L, ", name);
      else
      {
          char       *variable = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4);
diff -dcrpN pgsql/src/interfaces/ecpg/test/compat_informix/Makefile
pgsql.sqlda/src/interfaces/ecpg/test/compat_informix/Makefile
*** pgsql/src/interfaces/ecpg/test/compat_informix/Makefile    2009-08-10 18:05:33.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/test/compat_informix/Makefile    2009-08-11 10:51:42.000000000 +0200
*************** TESTS = test_informix test_informix.c \
*** 17,22 ****
--- 17,23 ----
          rfmtdate rfmtdate.c \
          rfmtlong rfmtlong.c \
          rnull rnull.c \
+         sqlda sqlda.c \
          charfuncs charfuncs.c

  all: $(TESTS)
*************** test_informix2.c: test_informix2.pgc ../
*** 30,35 ****
--- 31,39 ----
  cursor.c: cursor.pgc ../regression.h
      $(ECPG) -o $@ -I$(srcdir) $<

+ sqlda.c: sqlda.pgc ../regression.h
+     $(ECPG) -o $@ -I$(srcdir) $<
+
  dec_test.c: dec_test.pgc ../regression.h
      $(ECPG) -o $@ -I$(srcdir) $<

diff -dcrpN pgsql/src/interfaces/ecpg/test/compat_informix/sqlda.pgc
pgsql.sqlda/src/interfaces/ecpg/test/compat_informix/sqlda.pgc
*** pgsql/src/interfaces/ecpg/test/compat_informix/sqlda.pgc    1970-01-01 01:00:00.000000000 +0100
--- pgsql.sqlda/src/interfaces/ecpg/test/compat_informix/sqlda.pgc    2009-08-11 13:44:07.000000000 +0200
***************
*** 0 ****
--- 1,207 ----
+ #include <stdlib.h>
+ #include <string.h>
+ #include <inttypes.h>
+
+ exec sql include ../regression;
+
+ exec sql include sqlda.h;
+ exec sql include sqltypes.h;
+
+ exec sql whenever sqlerror stop;
+
+ /* These shouldn't be under DECLARE SECTION */
+ pg_sqlda_t    *inp_sqlda, *outp_sqlda;
+
+ static void
+ dump_sqlda(pg_sqlda_t *sqlda)
+ {
+     int    i;
+
+     for (i = 0; i < sqlda->sqld; i++)
+     {
+         if (outp_sqlda->sqlvar[i].sqlind && *(outp_sqlda->sqlvar[i].sqlind) == -1)
+             printf("name sqlda descriptor: '%s' value NULL'\n", outp_sqlda->sqlvar[i].sqlname);
+         else
+         switch (sqlda->sqlvar[i].sqltype)
+         {
+         case SQLCHAR:
+         case SQLVCHAR:
+         case SQLTEXT:
+             printf("name sqlda descriptor: '%s' value '%s'\n", sqlda->sqlvar[i].sqlname, sqlda->sqlvar[i].sqldata);
+             break;
+         case SQLSERIAL:
+         case SQLINT:
+             printf("name sqlda descriptor: '%s' value %d\n", sqlda->sqlvar[i].sqlname, *(int
*)sqlda->sqlvar[i].sqldata);
+             break;
+         case SQLSERIAL8:
+         case SQLINT8:
+             printf("name sqlda descriptor: '%s' value %" PRId64 "\n", sqlda->sqlvar[i].sqlname, *(int64_t
*)sqlda->sqlvar[i].sqldata);
+             break;
+         case SQLFLOAT:
+             printf("name sqlda descriptor: '%s' value %lf\n", sqlda->sqlvar[i].sqlname, *(double
*)sqlda->sqlvar[i].sqldata);
+             break;
+         case SQLDECIMAL:
+             {
+                 char    val[64];
+                 dectoasc((dec_t *)sqlda->sqlvar[i].sqldata, val, 64, -1);
+                 printf("name sqlda descriptor: '%s' value DECIMAL '%s'\n", sqlda->sqlvar[i].sqlname, val);
+                 break;
+             }
+         }
+     }
+ }
+
+ int
+ main (void)
+ {
+ exec sql begin declare section;
+     char    *stmt1 = "SELECT * FROM t1";
+     char    *stmt2 = "SELECT * FROM t1 WHERE id = ?";
+     int    rec;
+     int    id;
+ exec sql end declare section;
+
+     char msg[128];
+
+     ECPGdebug(1, stderr);
+
+     strcpy(msg, "connect");
+     exec sql connect to REGRESSDB1;
+
+     strcpy(msg, "set");
+     exec sql set datestyle to iso;
+
+     strcpy(msg, "create");
+     exec sql create table t1(
+         id integer,
+         t text,
+         d1 numeric,
+         d2 float8,
+         c char(10));
+
+     strcpy(msg, "insert");
+     exec sql insert into t1 values
+         (1, 'a', 1.0, 1, 'a'),
+         (2, null, null, null, null),
+         (3, '"c"', -3, 'nan'::float8, 'c'),
+         (4, 'd', 4.0, 4, 'd');
+
+     strcpy(msg, "commit");
+     exec sql commit;
+
+     /* SQLDA test for getting all records from a table */
+
+     outp_sqlda = NULL;
+
+     strcpy(msg, "prepare");
+     exec sql prepare st_id1 from :stmt1;
+
+     strcpy(msg, "declare");
+     exec sql declare mycur1 cursor for st_id1;
+
+     strcpy(msg, "open");
+     exec sql open mycur1;
+
+     exec sql whenever not found do break;
+
+     rec = 0;
+     while (1)
+     {
+         strcpy(msg, "fetch");
+         exec sql fetch 1 from mycur1 into descriptor outp_sqlda;
+
+         printf("FETCH RECORD %d\n", ++rec);
+         dump_sqlda(outp_sqlda);
+     }
+
+     exec sql whenever not found continue;
+
+     strcpy(msg, "close");
+     exec sql close mycur1;
+
+     strcpy(msg, "deallocate");
+     exec sql deallocate prepare st_id1;
+
+     free(outp_sqlda);
+
+     /* SQLDA test for getting all records from a table
+        using the Informix-specific FETCH ... USING DESCRIPTOR
+      */
+
+     outp_sqlda = NULL;
+
+     strcpy(msg, "prepare");
+     exec sql prepare st_id2 from :stmt1;
+
+     strcpy(msg, "declare");
+     exec sql declare mycur2 cursor for st_id2;
+
+     strcpy(msg, "open");
+     exec sql open mycur2;
+
+     exec sql whenever not found do break;
+
+     rec = 0;
+     while (1)
+     {
+         strcpy(msg, "fetch");
+         exec sql fetch from mycur2 using descriptor outp_sqlda;
+
+         printf("FETCH RECORD %d\n", ++rec);
+         dump_sqlda(outp_sqlda);
+     }
+
+     exec sql whenever not found continue;
+
+     strcpy(msg, "close");
+     exec sql close mycur2;
+
+     strcpy(msg, "deallocate");
+     exec sql deallocate prepare st_id2;
+
+     free(outp_sqlda);
+
+     /* SQLDA test for getting one record using an input descriptor */
+
+     /* Input sqlda has to be built manually */
+     inp_sqlda = (pg_sqlda_t *)malloc(sizeof(pg_sqlda_t));
+     memset(inp_sqlda, 0, sizeof(pg_sqlda_t));
+     inp_sqlda->sqld = 1;
+     inp_sqlda->sqlvar = malloc(sizeof(pg_sqlvar_t));
+     memset(inp_sqlda->sqlvar, 0, sizeof(pg_sqlvar_t));
+
+     inp_sqlda->sqlvar[0].sqltype = SQLINT;
+     inp_sqlda->sqlvar[0].sqldata = (char *)&id;
+
+     printf("EXECUTE RECORD 4\n");
+
+     id = 4;
+
+     outp_sqlda = NULL;
+
+     strcpy(msg, "prepare");
+     exec sql prepare st_id3 FROM :stmt2;
+
+     strcpy(msg, "execute");
+     exec sql execute st_id3 using descriptor inp_sqlda into descriptor outp_sqlda;
+
+     dump_sqlda(outp_sqlda);
+
+     strcpy(msg, "deallocate");
+     exec sql deallocate prepare st_id3;
+
+     free(outp_sqlda);
+
+     /* End test */
+
+     strcpy(msg, "drop");
+     exec sql drop table t1;
+
+     strcpy(msg, "commit");
+     exec sql commit;
+
+     strcpy(msg, "disconnect");
+     exec sql disconnect;
+
+     return (0);
+ }
diff -dcrpN pgsql/src/interfaces/ecpg/test/ecpg_schedule pgsql.sqlda/src/interfaces/ecpg/test/ecpg_schedule
*** pgsql/src/interfaces/ecpg/test/ecpg_schedule    2009-08-10 18:06:06.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/test/ecpg_schedule    2009-08-11 11:19:52.000000000 +0200
*************** test: compat_informix/rfmtdate
*** 4,9 ****
--- 4,10 ----
  test: compat_informix/rfmtlong
  test: compat_informix/rnull
  test: compat_informix/cursor
+ test: compat_informix/sqlda
  test: compat_informix/test_informix
  test: compat_informix/test_informix2
  test: connect/test2
diff -dcrpN pgsql/src/interfaces/ecpg/test/ecpg_schedule_tcp pgsql.sqlda/src/interfaces/ecpg/test/ecpg_schedule_tcp
*** pgsql/src/interfaces/ecpg/test/ecpg_schedule_tcp    2009-08-10 18:06:11.000000000 +0200
--- pgsql.sqlda/src/interfaces/ecpg/test/ecpg_schedule_tcp    2009-08-11 11:19:59.000000000 +0200
*************** test: compat_informix/rfmtdate
*** 4,9 ****
--- 4,10 ----
  test: compat_informix/rfmtlong
  test: compat_informix/rnull
  test: compat_informix/cursor
+ test: compat_informix/sqlda
  test: compat_informix/test_informix
  test: compat_informix/test_informix2
  test: connect/test2
diff -dcrpN pgsql/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
pgsql.sqlda/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c
*** pgsql/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c    1970-01-01 01:00:00.000000000 +0100
--- pgsql.sqlda/src/interfaces/ecpg/test/expected/compat_informix-sqlda.c    2009-08-11 14:24:20.000000000 +0200
***************
*** 0 ****
--- 1,506 ----
+ /* Processed by ecpg (regression mode) */
+ /* These include files are added by the preprocessor */
+ #include <ecpglib.h>
+ #include <ecpgerrno.h>
+ #include <sqlca.h>
+ /* Needed for informix compatibility */
+ #include <ecpg_informix.h>
+ /* End of automatic include section */
+ #define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))
+
+ #line 1 "sqlda.pgc"
+ #include <stdlib.h>
+ #include <string.h>
+ #include <inttypes.h>
+
+
+ #line 1 "regression.h"
+
+
+
+
+
+
+ #line 5 "sqlda.pgc"
+
+
+
+ #line 1 "sqlda.h"
+ /*
+  * $PostgreSQL: pgsql/src/interfaces/ecpg/include/sqlda.h,v 1.4 2009/06/11 14:49:13 momjian Exp $
+  */
+
+ #ifndef POSTGRES_SQLDA_H
+ #define POSTGRES_SQLDA_H
+
+ /* Define Informix "standard" types */
+ #ifndef C_H
+ typedef int        int4;
+ typedef    short        int2;
+ #endif
+ typedef    char        int1;
+
+ typedef    int        mint;
+ typedef    long        mlong;
+
+ typedef    short        MSHORT;
+ typedef    char        MCHAR;
+
+ typedef    unsigned int    uint4;
+ typedef    unsigned short    uint2;
+ typedef    unsigned char    uint1;
+
+ typedef    unsigned int    muint;
+ typedef    unsigned long    mulong;
+
+ typedef    unsigned short    MUSHORT;
+ typedef    unsigned char    MUCHAR;
+
+ #define MI_INT_SIZE     (sizeof(int)    * 8)
+ #define MI_LONG_SIZE    (sizeof(long)   * 8)
+ #define MI_PTR_SIZE     (sizeof(char *) * 8)
+
+ typedef struct sqlvar_struct
+ {
+     int2    sqltype;        /* variable type                */
+     int4    sqllen;            /* length in bytes              */
+     char       *sqldata;        /* pointer to data              */
+     int2       *sqlind;        /* pointer to indicator         */
+     char       *sqlname;        /* variable name                */
+     char       *sqlformat;        /* reserved for future use      */
+     int2    sqlitype;        /* ind variable type            */
+     int2    sqlilen;        /* ind length in bytes          */
+     char       *sqlidata;        /* ind data pointer             */
+     int4    sqlxid;            /* extended id type             */
+     char       *sqltypename;    /* extended type name           */
+     int2    sqltypelen;        /* length of extended type name */
+     int2    sqlownerlen;        /* length of owner name         */
+     int2    sqlsourcetype;        /* source type for distinct of built-ins */
+     char       *sqlownername;    /* owner name                   */
+     int4    sqlsourceid;        /* extended id of source type   */
+
+     /*
+      * sqlilongdata is new.  It supports data that exceeds the 32k
+      * limit.  sqlilen and sqlidata are for backward compatibility
+      * and they have maximum value of <32K.
+      */
+     char       *sqlilongdata;    /* for data field beyond 32K    */
+     int4    sqlflags;        /* for internal use only        */
+     void       *sqlreserved;    /* reserved for future use      */
+ } pg_sqlvar_t;
+
+ typedef struct sqlda
+ {
+     int2        sqld;
+     pg_sqlvar_t       *sqlvar;
+     char        desc_name[19];    /* descriptor name              */
+     int2        desc_occ;    /* size of sqlda structure      */
+     struct sqlda       *desc_next;    /* pointer to next sqlda struct */
+     void           *reserved;    /* reserved for future use */
+ } pg_sqlda_t;
+
+ #endif /* POSTGRES_SQLDA_H */
+
+ #line 7 "sqlda.pgc"
+
+
+ #line 1 "sqltypes.h"
+ /*
+  * $PostgreSQL: pgsql/src/interfaces/ecpg/include/sqltypes.h,v 1.9 2009/06/11 14:49:13 momjian Exp $
+  */
+ #ifndef ECPG_SQLTYPES_H
+ #define ECPG_SQLTYPES_H
+
+ #define CCHARTYPE    ECPGt_char
+ #define CSHORTTYPE    ECPGt_short
+ #define CINTTYPE    ECPGt_int
+ #define CLONGTYPE    ECPGt_long
+ #define CFLOATTYPE    ECPGt_float
+ #define CDOUBLETYPE ECPGt_double
+ #define CDECIMALTYPE    ECPGt_decimal
+ #define CFIXCHARTYPE    108
+ #define CSTRINGTYPE ECPGt_char
+ #define CDATETYPE    ECPGt_date
+ #define CMONEYTYPE    111
+ #define CDTIMETYPE    ECPGt_timestamp
+ #define CLOCATORTYPE    113
+ #define CVCHARTYPE    ECPGt_varchar
+ #define CINVTYPE    115
+ #define CFILETYPE    116
+ #define CINT8TYPE    ECPGt_long_long
+ #define CCOLLTYPE        118
+ #define CLVCHARTYPE        119
+ #define CFIXBINTYPE        120
+ #define CVARBINTYPE        121
+ #define CBOOLTYPE        ECPGt_bool
+ #define CROWTYPE        123
+ #define CLVCHARPTRTYPE    124
+ #define CTYPEMAX    25
+
+ /*
+  * Values used in sqlda->sqlvar[i]->sqltype
+  */
+ #define    SQLCHAR        0
+ #define    SQLSMINT    1
+ #define    SQLINT        2
+ #define    SQLFLOAT    3
+ #define    SQLSMFLOAT    4
+ #define    SQLDECIMAL    5
+ #define    SQLSERIAL    6
+ #define    SQLDATE        7
+ #define    SQLMONEY    8
+ #define    SQLDTIME    10
+ #define    SQLBYTES    11
+ #define    SQLTEXT        12
+ #define    SQLVCHAR    13
+ #define    SQLINTERVAL    14
+ #define    SQLNCHAR    15
+ #define    SQLNVCHAR    16
+ #define    SQLINT8        17
+ #define    SQLSERIAL8    18
+
+ #endif   /* ndef ECPG_SQLTYPES_H */
+
+ #line 8 "sqlda.pgc"
+
+
+ /* exec sql whenever sqlerror  stop ; */
+ #line 10 "sqlda.pgc"
+
+
+ /* These shouldn't be under DECLARE SECTION */
+ pg_sqlda_t    *inp_sqlda, *outp_sqlda;
+
+ static void
+ dump_sqlda(pg_sqlda_t *sqlda)
+ {
+     int    i;
+
+     for (i = 0; i < sqlda->sqld; i++)
+     {
+         if (outp_sqlda->sqlvar[i].sqlind && *(outp_sqlda->sqlvar[i].sqlind) == -1)
+             printf("name sqlda descriptor: '%s' value NULL'\n", outp_sqlda->sqlvar[i].sqlname);
+         else
+         switch (sqlda->sqlvar[i].sqltype)
+         {
+         case SQLCHAR:
+         case SQLVCHAR:
+         case SQLTEXT:
+             printf("name sqlda descriptor: '%s' value '%s'\n", sqlda->sqlvar[i].sqlname, sqlda->sqlvar[i].sqldata);
+             break;
+         case SQLSERIAL:
+         case SQLINT:
+             printf("name sqlda descriptor: '%s' value %d\n", sqlda->sqlvar[i].sqlname, *(int
*)sqlda->sqlvar[i].sqldata);
+             break;
+         case SQLSERIAL8:
+         case SQLINT8:
+             printf("name sqlda descriptor: '%s' value %" PRId64 "\n", sqlda->sqlvar[i].sqlname, *(int64_t
*)sqlda->sqlvar[i].sqldata);
+             break;
+         case SQLFLOAT:
+             printf("name sqlda descriptor: '%s' value %lf\n", sqlda->sqlvar[i].sqlname, *(double
*)sqlda->sqlvar[i].sqldata);
+             break;
+         case SQLDECIMAL:
+             {
+                 char    val[64];
+                 dectoasc((decimal *)sqlda->sqlvar[i].sqldata, val, 64, -1);
+                 printf("name sqlda descriptor: '%s' value DECIMAL '%s'\n", sqlda->sqlvar[i].sqlname, val);
+                 break;
+             }
+         }
+     }
+ }
+
+ int
+ main (void)
+ {
+ /* exec sql begin declare section */
+
+
+
+
+
+ #line 58 "sqlda.pgc"
+  char * stmt1 = "SELECT * FROM t1" ;
+
+ #line 59 "sqlda.pgc"
+  char * stmt2 = "SELECT * FROM t1 WHERE id = ?" ;
+
+ #line 60 "sqlda.pgc"
+  int rec ;
+
+ #line 61 "sqlda.pgc"
+  int id ;
+ /* exec sql end declare section */
+ #line 62 "sqlda.pgc"
+
+
+     char msg[128];
+
+     ECPGdebug(1, stderr);
+
+     strcpy(msg, "connect");
+     { ECPGconnect(__LINE__, 1, "regress1" , NULL, NULL , NULL, 0);
+ #line 69 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 69 "sqlda.pgc"
+
+
+     strcpy(msg, "set");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "set datestyle to iso", ECPGt_EOIT, ECPGt_EORT);
+ #line 72 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 72 "sqlda.pgc"
+
+
+     strcpy(msg, "create");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "create table t1 ( id integer , t text , d1 numeric , d2 float8
,c char ( 10 ) )", ECPGt_EOIT, ECPGt_EORT); 
+ #line 80 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 80 "sqlda.pgc"
+
+
+     strcpy(msg, "insert");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "insert into t1 values ( 1 , 'a' , 1.0 , 1 , 'a' ) , ( 2 , null
,null , null , null ) , ( 3 , '\"c\"' , - 3 , 'nan' :: float8 , 'c' ) , ( 4 , 'd' , 4.0 , 4 , 'd' )", ECPGt_EOIT,
ECPGt_EORT);
+ #line 87 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 87 "sqlda.pgc"
+
+
+     strcpy(msg, "commit");
+     { ECPGtrans(__LINE__, NULL, "commit");
+ #line 90 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 90 "sqlda.pgc"
+
+
+     /* SQLDA test for getting all records from a table */
+
+     outp_sqlda = NULL;
+
+     strcpy(msg, "prepare");
+     { ECPGprepare(__LINE__, NULL, 0, "st_id1", stmt1);
+ #line 97 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 97 "sqlda.pgc"
+
+
+     strcpy(msg, "declare");
+     /* declare mycur1 cursor for $1 */
+ #line 100 "sqlda.pgc"
+
+
+     strcpy(msg, "open");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "declare mycur1 cursor for $1",
+     ECPGt_char_variable,(ECPGprepared_statement(NULL, "st_id1", __LINE__)),(long)1,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 103 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 103 "sqlda.pgc"
+
+
+     /* exec sql whenever not found  break ; */
+ #line 105 "sqlda.pgc"
+
+
+     rec = 0;
+     while (1)
+     {
+         strcpy(msg, "fetch");
+         { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch 1 from mycur1", ECPGt_EOIT,
+     ECPGt_sqlda, & outp_sqlda , 0L, 0L, 0L,
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 111 "sqlda.pgc"
+
+ if (sqlca.sqlcode == ECPG_NOT_FOUND) break;
+ #line 111 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 111 "sqlda.pgc"
+
+
+         printf("FETCH RECORD %d\n", ++rec);
+         dump_sqlda(outp_sqlda);
+     }
+
+     /* exec sql whenever not found  continue ; */
+ #line 117 "sqlda.pgc"
+
+
+     strcpy(msg, "close");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "close mycur1", ECPGt_EOIT, ECPGt_EORT);
+ #line 120 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 120 "sqlda.pgc"
+
+
+     strcpy(msg, "deallocate");
+     { ECPGdeallocate(__LINE__, 1, NULL, "st_id1");
+ #line 123 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 123 "sqlda.pgc"
+
+
+     free(outp_sqlda);
+
+     /* SQLDA test for getting all records from a table
+        using the Informix-specific FETCH ... USING DESCRIPTOR
+      */
+
+     outp_sqlda = NULL;
+
+     strcpy(msg, "prepare");
+     { ECPGprepare(__LINE__, NULL, 0, "st_id2", stmt1);
+ #line 134 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 134 "sqlda.pgc"
+
+
+     strcpy(msg, "declare");
+     /* declare mycur2 cursor for $1 */
+ #line 137 "sqlda.pgc"
+
+
+     strcpy(msg, "open");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "declare mycur2 cursor for $1",
+     ECPGt_char_variable,(ECPGprepared_statement(NULL, "st_id2", __LINE__)),(long)1,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 140 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 140 "sqlda.pgc"
+
+
+     /* exec sql whenever not found  break ; */
+ #line 142 "sqlda.pgc"
+
+
+     rec = 0;
+     while (1)
+     {
+         strcpy(msg, "fetch");
+         { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch from mycur2", ECPGt_EOIT,
+     ECPGt_sqlda, & outp_sqlda , 0L, 0L, 0L,
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 148 "sqlda.pgc"
+
+ if (sqlca.sqlcode == ECPG_NOT_FOUND) break;
+ #line 148 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 148 "sqlda.pgc"
+
+
+         printf("FETCH RECORD %d\n", ++rec);
+         dump_sqlda(outp_sqlda);
+     }
+
+     /* exec sql whenever not found  continue ; */
+ #line 154 "sqlda.pgc"
+
+
+     strcpy(msg, "close");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "close mycur2", ECPGt_EOIT, ECPGt_EORT);
+ #line 157 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 157 "sqlda.pgc"
+
+
+     strcpy(msg, "deallocate");
+     { ECPGdeallocate(__LINE__, 1, NULL, "st_id2");
+ #line 160 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 160 "sqlda.pgc"
+
+
+     free(outp_sqlda);
+
+     /* SQLDA test for getting one record using an input descriptor */
+
+     /* Input sqlda has to be built manually */
+     inp_sqlda = (pg_sqlda_t *)malloc(sizeof(pg_sqlda_t));
+     memset(inp_sqlda, 0, sizeof(pg_sqlda_t));
+     inp_sqlda->sqld = 1;
+     inp_sqlda->sqlvar = malloc(sizeof(pg_sqlvar_t));
+     memset(inp_sqlda->sqlvar, 0, sizeof(pg_sqlvar_t));
+
+     inp_sqlda->sqlvar[0].sqltype = SQLINT;
+     inp_sqlda->sqlvar[0].sqldata = (char *)&id;
+
+     printf("EXECUTE RECORD 4\n");
+
+     id = 4;
+
+     outp_sqlda = NULL;
+
+     strcpy(msg, "prepare");
+     { ECPGprepare(__LINE__, NULL, 0, "st_id3", stmt2);
+ #line 183 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 183 "sqlda.pgc"
+
+
+     strcpy(msg, "execute");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, 1, "st_id3",
+     ECPGt_sqlda, & inp_sqlda , 0L, 0L, 0L,
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_sqlda, & outp_sqlda , 0L, 0L, 0L,
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 186 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 186 "sqlda.pgc"
+
+
+     dump_sqlda(outp_sqlda);
+
+     strcpy(msg, "deallocate");
+     { ECPGdeallocate(__LINE__, 1, NULL, "st_id3");
+ #line 191 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 191 "sqlda.pgc"
+
+
+     free(outp_sqlda);
+
+     /* End test */
+
+     strcpy(msg, "drop");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "drop table t1", ECPGt_EOIT, ECPGt_EORT);
+ #line 198 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 198 "sqlda.pgc"
+
+
+     strcpy(msg, "commit");
+     { ECPGtrans(__LINE__, NULL, "commit");
+ #line 201 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 201 "sqlda.pgc"
+
+
+     strcpy(msg, "disconnect");
+     { ECPGdisconnect(__LINE__, "CURRENT");
+ #line 204 "sqlda.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 204 "sqlda.pgc"
+
+
+     return (0);
+ }
diff -dcrpN pgsql/src/interfaces/ecpg/test/expected/compat_informix-sqlda.stderr
pgsql.sqlda/src/interfaces/ecpg/test/expected/compat_informix-sqlda.stderr
*** pgsql/src/interfaces/ecpg/test/expected/compat_informix-sqlda.stderr    1970-01-01 01:00:00.000000000 +0100
--- pgsql.sqlda/src/interfaces/ecpg/test/expected/compat_informix-sqlda.stderr    2009-08-17 11:22:46.000000000 +0200
***************
*** 0 ****
--- 1,224 ----
+ [NO_PID]: ECPGdebug: set to 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGconnect: opening database regress1 on <DEFAULT> port <DEFAULT>
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 72: query: set datestyle to iso; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 72: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 72: OK: SET
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 75: query: create table t1 ( id integer , t text , d1 numeric , d2 float8 , c char (
10) ); with 0 parameter(s) on connection regress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 75: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 75: OK: CREATE TABLE
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 83: query: insert into t1 values ( 1 , 'a' , 1.0 , 1 , 'a' ) , ( 2 , null , null ,
null, null ) , ( 3 , '"c"' , - 3 , 'nan' :: float8 , 'c' ) , ( 4 , 'd' , 4.0 , 4 , 'd' ); with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 83: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 83: OK: INSERT 0 4
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGtrans on line 90: action "commit"; connection "regress1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGprepare on line 97: name st_id1; query: "SELECT * FROM t1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 103: query: declare mycur1 cursor for SELECT * FROM t1; with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 103: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 103: OK: DECLARE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: correctly got 1 tuples with 5 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: new sqlda was built
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 111: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 111: RESULT: 1.0 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 111: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: putting result (1 tuple 5 fields) into sqlda descriptor
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: correctly got 1 tuples with 5 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: called ecpg_compare_sqlda_with_PGresult, status 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 111: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: putting result (1 tuple 5 fields) into sqlda descriptor
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: correctly got 1 tuples with 5 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: called ecpg_compare_sqlda_with_PGresult, status 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 111: RESULT: 3 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 111: RESULT: -3 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 111: RESULT: NaN offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: putting result (1 tuple 5 fields) into sqlda descriptor
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: correctly got 1 tuples with 5 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: called ecpg_compare_sqlda_with_PGresult, status 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 111: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 111: RESULT: 4.0 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 111: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: putting result (1 tuple 5 fields) into sqlda descriptor
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: query: fetch 1 from mycur1; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 111: correctly got 0 tuples with 5 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: raising sqlcode 100 on line 111: no data found on line 111
+ [NO_PID]: sqlca: code: 100, state: 02000
+ [NO_PID]: ecpg_execute on line 120: query: close mycur1; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 120: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 120: OK: CLOSE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGdeallocate on line 123: name st_id1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGprepare on line 134: name st_id2; query: "SELECT * FROM t1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 140: query: declare mycur2 cursor for SELECT * FROM t1; with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 140: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 140: OK: DECLARE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: query: fetch from mycur2; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: correctly got 1 tuples with 5 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: new sqlda was built
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 148: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 148: RESULT: 1.0 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 148: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: putting result (1 tuple 5 fields) into sqlda descriptor
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: query: fetch from mycur2; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: correctly got 1 tuples with 5 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: called ecpg_compare_sqlda_with_PGresult, status 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 148: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: putting result (1 tuple 5 fields) into sqlda descriptor
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: query: fetch from mycur2; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: correctly got 1 tuples with 5 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: called ecpg_compare_sqlda_with_PGresult, status 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 148: RESULT: 3 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 148: RESULT: -3 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 148: RESULT: NaN offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: putting result (1 tuple 5 fields) into sqlda descriptor
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: query: fetch from mycur2; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: correctly got 1 tuples with 5 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: called ecpg_compare_sqlda_with_PGresult, status 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 148: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 148: RESULT: 4.0 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 148: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: putting result (1 tuple 5 fields) into sqlda descriptor
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: query: fetch from mycur2; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 148: correctly got 0 tuples with 5 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: raising sqlcode 100 on line 148: no data found on line 148
+ [NO_PID]: sqlca: code: 100, state: 02000
+ [NO_PID]: ecpg_execute on line 157: query: close mycur2; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 157: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 157: OK: CLOSE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGdeallocate on line 160: name st_id2
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGprepare on line 183: name st_id3; query: "SELECT * FROM t1 WHERE id = $1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 186: query: SELECT * FROM t1 WHERE id = $1; with 1 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 186: using PQexecPrepared for "SELECT * FROM t1 WHERE id = $1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: free_params on line 186: parameter 1 = 4
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 186: correctly got 1 tuples with 5 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 186: new sqlda was built
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 186: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 186: RESULT: 4.0 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 186: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 186: putting result (1 tuple 5 fields) into sqlda descriptor
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGdeallocate on line 191: name st_id3
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 198: query: drop table t1; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 198: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 198: OK: DROP TABLE
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGtrans on line 201: action "commit"; connection "regress1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_finish: connection regress1 closed
+ [NO_PID]: sqlca: code: 0, state: 00000
diff -dcrpN pgsql/src/interfaces/ecpg/test/expected/compat_informix-sqlda.stdout
pgsql.sqlda/src/interfaces/ecpg/test/expected/compat_informix-sqlda.stdout
*** pgsql/src/interfaces/ecpg/test/expected/compat_informix-sqlda.stdout    1970-01-01 01:00:00.000000000 +0100
--- pgsql.sqlda/src/interfaces/ecpg/test/expected/compat_informix-sqlda.stdout    2009-08-11 14:24:21.000000000 +0200
***************
*** 0 ****
--- 1,54 ----
+ FETCH RECORD 1
+ name sqlda descriptor: 'id' value 1
+ name sqlda descriptor: 't' value 'a'
+ name sqlda descriptor: 'd1' value DECIMAL '1.0'
+ name sqlda descriptor: 'd2' value 1.000000
+ name sqlda descriptor: 'c' value 'a         '
+ FETCH RECORD 2
+ name sqlda descriptor: 'id' value 2
+ name sqlda descriptor: 't' value NULL'
+ name sqlda descriptor: 'd1' value NULL'
+ name sqlda descriptor: 'd2' value NULL'
+ name sqlda descriptor: 'c' value NULL'
+ FETCH RECORD 3
+ name sqlda descriptor: 'id' value 3
+ name sqlda descriptor: 't' value '"c"'
+ name sqlda descriptor: 'd1' value DECIMAL '-3'
+ name sqlda descriptor: 'd2' value nan
+ name sqlda descriptor: 'c' value 'c         '
+ FETCH RECORD 4
+ name sqlda descriptor: 'id' value 4
+ name sqlda descriptor: 't' value 'd'
+ name sqlda descriptor: 'd1' value DECIMAL '4.0'
+ name sqlda descriptor: 'd2' value 4.000000
+ name sqlda descriptor: 'c' value 'd         '
+ FETCH RECORD 1
+ name sqlda descriptor: 'id' value 1
+ name sqlda descriptor: 't' value 'a'
+ name sqlda descriptor: 'd1' value DECIMAL '1.0'
+ name sqlda descriptor: 'd2' value 1.000000
+ name sqlda descriptor: 'c' value 'a         '
+ FETCH RECORD 2
+ name sqlda descriptor: 'id' value 2
+ name sqlda descriptor: 't' value NULL'
+ name sqlda descriptor: 'd1' value NULL'
+ name sqlda descriptor: 'd2' value NULL'
+ name sqlda descriptor: 'c' value NULL'
+ FETCH RECORD 3
+ name sqlda descriptor: 'id' value 3
+ name sqlda descriptor: 't' value '"c"'
+ name sqlda descriptor: 'd1' value DECIMAL '-3'
+ name sqlda descriptor: 'd2' value nan
+ name sqlda descriptor: 'c' value 'c         '
+ FETCH RECORD 4
+ name sqlda descriptor: 'id' value 4
+ name sqlda descriptor: 't' value 'd'
+ name sqlda descriptor: 'd1' value DECIMAL '4.0'
+ name sqlda descriptor: 'd2' value 4.000000
+ name sqlda descriptor: 'c' value 'd         '
+ EXECUTE RECORD 4
+ name sqlda descriptor: 'id' value 4
+ name sqlda descriptor: 't' value 'd'
+ name sqlda descriptor: 'd1' value DECIMAL '4.0'
+ name sqlda descriptor: 'd2' value 4.000000
+ name sqlda descriptor: 'c' value 'd         '

pgsql-hackers by date:

Previous
From: ning
Date:
Subject: memory free of constantly changed function
Next
From: Robert Haas
Date:
Subject: Re: hot standby - merged up to CVS HEAD