1) Separate APD and IPD more explicitly.
authorHiroshi Inoue <inoue@tpf.co.jp>
Mon, 16 Dec 2002 15:01:34 +0000 (15:01 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Mon, 16 Dec 2002 15:01:34 +0000 (15:01 +0000)
2) Add a conversion functionality between SQL_C_CHAR
   and SQL_VARBINARY.
3) The first cut of the use of server side prepare.
4) Check if a relation is a view more precisely.
5) Fix a crash bug with no parameter binding for
  prepare statements with parameter markers(bug
  report from Han).
6) Fix a bug about SQLGetDiagField(bug report from
  Han).
7) Add a missing ENTER_STMT_CS at the start of
  SQLForeignKey().

27 files changed:
bind.c
bind.h
connection.c
connection.h
convert.c
convert.h
descriptor.h
dlg_specific.c
dlg_specific.h
environ.c
environ.h
execute.c
info.c
info30.c
multibyte.c
odbcapi.c
odbcapiw.c
pgapi30.c
pgtypes.c
pgtypes.h
psqlodbc.c
psqlodbc.h
results.c
statement.c
statement.h
tuple.c
tuple.h

diff --git a/bind.c b/bind.c
index fdee467f97347839ca5f596098b1ab97c1f0be7a..77838fd08fb4557e961e5a3a40157a62237fe784 100644 (file)
--- a/bind.c
+++ b/bind.c
@@ -42,7 +42,8 @@ PGAPI_BindParameter(
 {
    StatementClass *stmt = (StatementClass *) hstmt;
    static char *func = "PGAPI_BindParameter";
-   APDFields   *opts;
+   APDFields   *apdopts;
+   IPDFields   *ipdopts;
 
    mylog("%s: entering...\n", func);
 
@@ -53,71 +54,77 @@ PGAPI_BindParameter(
    }
    SC_clear_error(stmt);
 
-   opts = SC_get_APD(stmt);
-   if (opts->allocated < ipar)
-       extend_parameter_bindings(opts, ipar);
+   apdopts = SC_get_APD(stmt);
+   if (apdopts->allocated < ipar)
+       extend_parameter_bindings(apdopts, ipar);
+   ipdopts = SC_get_IPD(stmt);
+   if (ipdopts->allocated < ipar)
+       extend_iparameter_bindings(ipdopts, ipar);
 
    /* use zero based column numbers for the below part */
    ipar--;
 
    /* store the given info */
-   opts->parameters[ipar].buflen = cbValueMax;
-   opts->parameters[ipar].buffer = rgbValue;
-   opts->parameters[ipar].used = pcbValue;
-   opts->parameters[ipar].paramType = fParamType;
-   opts->parameters[ipar].CType = fCType;
-   opts->parameters[ipar].SQLType = fSqlType;
-   opts->parameters[ipar].column_size = cbColDef;
-   opts->parameters[ipar].decimal_digits = ibScale;
-   opts->parameters[ipar].precision = 0;
-   opts->parameters[ipar].scale = 0;
+   apdopts->parameters[ipar].buflen = cbValueMax;
+   apdopts->parameters[ipar].buffer = rgbValue;
+   apdopts->parameters[ipar].used = pcbValue;
+   apdopts->parameters[ipar].paramType = fParamType;
+   apdopts->parameters[ipar].CType = fCType;
+   ipdopts->parameters[ipar].SQLType = fSqlType;
+   ipdopts->parameters[ipar].paramType = fParamType;
+   ipdopts->parameters[ipar].column_size = cbColDef;
+   ipdopts->parameters[ipar].decimal_digits = ibScale;
+   ipdopts->parameters[ipar].precision = 0;
+   ipdopts->parameters[ipar].scale = 0;
+   ipdopts->parameters[ipar].PGType = sqltype_to_pgtype(stmt, fSqlType);
 #if (ODBCVER >= 0x0300)
    switch (fCType)
    {
        case SQL_C_NUMERIC:
            if (cbColDef > 0)
-               opts->parameters[ipar].precision = (UInt2) cbColDef;
+               ipdopts->parameters[ipar].precision = (UInt2) cbColDef;
            if (ibScale > 0)
-               opts->parameters[ipar].scale = ibScale;
+               ipdopts->parameters[ipar].scale = ibScale;
            break;
        case SQL_C_TYPE_TIMESTAMP:
            if (ibScale > 0)
-               opts->parameters[ipar].precision = ibScale;
+               ipdopts->parameters[ipar].precision = ibScale;
            break;
    }
+   apdopts->parameters[ipar].precision = ipdopts->parameters[ipar].precision;
+   apdopts->parameters[ipar].scale = ipdopts->parameters[ipar].scale;
 #endif /* ODBCVER */
 
    /*
     * If rebinding a parameter that had data-at-exec stuff in it, then
     * free that stuff
     */
-   if (opts->parameters[ipar].EXEC_used)
+   if (apdopts->parameters[ipar].EXEC_used)
    {
-       free(opts->parameters[ipar].EXEC_used);
-       opts->parameters[ipar].EXEC_used = NULL;
+       free(apdopts->parameters[ipar].EXEC_used);
+       apdopts->parameters[ipar].EXEC_used = NULL;
    }
 
-   if (opts->parameters[ipar].EXEC_buffer)
+   if (apdopts->parameters[ipar].EXEC_buffer)
    {
-       if (opts->parameters[ipar].SQLType != SQL_LONGVARBINARY)
-           free(opts->parameters[ipar].EXEC_buffer);
-       opts->parameters[ipar].EXEC_buffer = NULL;
+       free(apdopts->parameters[ipar].EXEC_buffer);
+       apdopts->parameters[ipar].EXEC_buffer = NULL;
    }
 
-   if (pcbValue && opts->param_offset_ptr)
-       pcbValue += (*opts->param_offset_ptr >> 2);
+   if (pcbValue && apdopts->param_offset_ptr)
+       pcbValue += (*apdopts->param_offset_ptr >> 2);
    /* Data at exec macro only valid for C char/binary data */
    if (pcbValue && (*pcbValue == SQL_DATA_AT_EXEC ||
                     *pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET))
-       opts->parameters[ipar].data_at_exec = TRUE;
+       apdopts->parameters[ipar].data_at_exec = TRUE;
    else
-       opts->parameters[ipar].data_at_exec = FALSE;
+       apdopts->parameters[ipar].data_at_exec = FALSE;
 
    /* Clear premature result */
    if (stmt->status == STMT_PREMATURE)
        SC_recycle_statement(stmt);
 
-   mylog("PGAPI_BindParamater: ipar=%d, paramType=%d, fCType=%d, fSqlType=%d, cbColDef=%d, ibScale=%d, rgbValue=%d, *pcbValue = %d, data_at_exec = %d\n", ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, pcbValue ? *pcbValue : -777, opts->parameters[ipar].data_at_exec);
+   mylog("PGAPI_BindParamater: ipar=%d, paramType=%d, fCType=%d, fSqlType=%d, cbColDef=%d, ibScale=%d, rgbValue=%d, *pcbValue = %d, data_at_exec = %d\n", ipar, fParamType, fCType, fSqlType, cbColDef, ibScale, rgbValue, pcbValue ? *pcbValue : -777, apdopts->parameters[ipar].data_at_exec);
 
    return SQL_SUCCESS;
 }
@@ -224,6 +231,7 @@ inolog("Column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
            free(opts->bindings[icol].ttlbuf);
        opts->bindings[icol].ttlbuf = NULL;
        opts->bindings[icol].ttlbuflen = 0;
+       opts->bindings[icol].ttlbufused = 0;
        opts->bindings[icol].precision = 0;
        opts->bindings[icol].scale = 0;
    }
@@ -268,7 +276,8 @@ PGAPI_DescribeParam(
 {
    StatementClass *stmt = (StatementClass *) hstmt;
    static char *func = "PGAPI_DescribeParam";
-   APDFields   *opts;
+   APDFields   *apdopts;
+   IPDFields   *ipdopts;
 
    mylog("%s: entering...\n", func);
 
@@ -279,13 +288,14 @@ PGAPI_DescribeParam(
    }
    SC_clear_error(stmt);
 
-   opts = SC_get_APD(stmt);
-   if ((ipar < 1) || (ipar > opts->allocated))
+   apdopts = SC_get_APD(stmt);
+   if ((ipar < 1) || (ipar > apdopts->allocated))
    {
        SC_set_error(stmt, STMT_BAD_PARAMETER_NUMBER_ERROR, "Invalid parameter number for PGAPI_DescribeParam.");
        SC_log_error(func, "", stmt);
        return SQL_ERROR;
    }
+   ipdopts = SC_get_IPD(stmt);
 
    ipar--;
 
@@ -295,16 +305,16 @@ PGAPI_DescribeParam(
     */
    /* parameter markers, not bound parameters.  */
    if (pfSqlType)
-       *pfSqlType = opts->parameters[ipar].SQLType;
+       *pfSqlType = ipdopts->parameters[ipar].SQLType;
 
    if (pcbColDef)
-       *pcbColDef = opts->parameters[ipar].column_size;
+       *pcbColDef = ipdopts->parameters[ipar].column_size;
 
    if (pibScale)
-       *pibScale = opts->parameters[ipar].decimal_digits;
+       *pibScale = ipdopts->parameters[ipar].decimal_digits;
 
    if (pfNullable)
-       *pfNullable = pgtype_nullable(stmt, opts->parameters[ipar].paramType);
+       *pfNullable = pgtype_nullable(stmt, apdopts->parameters[ipar].paramType);
 
    return SQL_SUCCESS;
 }
@@ -319,12 +329,12 @@ PGAPI_ParamOptions(
 {
    static char *func = "PGAPI_ParamOptions";
    StatementClass *stmt = (StatementClass *) hstmt;
-   APDFields   *opts;
+   APDFields   *apdopts;
 
    mylog("%s: entering... %d %x\n", func, crow, pirow);
 
-   opts = SC_get_APD(stmt);
-   opts->paramset_size = crow;
+   apdopts = SC_get_APD(stmt);
+   apdopts->paramset_size = crow;
    SC_get_IPD(stmt)->param_processed_ptr = (UInt4 *) pirow;
    return SQL_SUCCESS;
 }
@@ -356,7 +366,6 @@ PGAPI_NumParams(
        SC_log_error(func, "", NULL);
        return SQL_INVALID_HANDLE;
    }
-   SC_clear_error(stmt);
 
    if (pcpar)
        *pcpar = 0;
@@ -412,6 +421,7 @@ create_empty_bindings(int num_columns)
        new_bindings[i].data_left = -1;
        new_bindings[i].ttlbuf = NULL;
        new_bindings[i].ttlbuflen = 0;
+       new_bindings[i].ttlbufused = 0;
    }
 
    return new_bindings;
@@ -450,6 +460,39 @@ extend_parameter_bindings(APDFields *self, int num_params)
    mylog("exit extend_parameter_bindings\n");
 }
 
+void
+extend_iparameter_bindings(IPDFields *self, int num_params)
+{
+   static char *func = "extend_iparameter_bindings";
+   ParameterImplClass *new_bindings;
+
+   mylog("%s: entering ... self=%u, parameters_allocated=%d, num_params=%d\n", func, self, self->allocated, num_params);
+
+   /*
+    * if we have too few, allocate room for more, and copy the old
+    * entries into the new structure
+    */
+   if (self->allocated < num_params)
+   {
+       new_bindings = (ParameterImplClass *) realloc(self->parameters, sizeof(ParameterImplClass) * num_params);
+       if (!new_bindings)
+       {
+           mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_params, self->allocated);
+
+           self->parameters = NULL;
+           self->allocated = 0;
+           return;
+       }
+       memset(&new_bindings[self->allocated], 0,
+           sizeof(ParameterImplClass) * (num_params - self->allocated));
+
+       self->parameters = new_bindings;
+       self->allocated = num_params;
+   }
+
+   mylog("exit extend_iparameter_bindings\n");
+}
+
 void
 reset_a_parameter_binding(APDFields *self, int ipar)
 {
@@ -466,6 +509,7 @@ reset_a_parameter_binding(APDFields *self, int ipar)
    self->parameters[ipar].used = 0;
    self->parameters[ipar].paramType = 0;
    self->parameters[ipar].CType = 0;
+   self->parameters[ipar].data_at_exec = FALSE;
    if (self->parameters[ipar].EXEC_used)
    {
        free(self->parameters[ipar].EXEC_used);
@@ -474,62 +518,94 @@ reset_a_parameter_binding(APDFields *self, int ipar)
 
    if (self->parameters[ipar].EXEC_buffer)
    {
-       if (self->parameters[ipar].SQLType != SQL_LONGVARBINARY)
-           free(self->parameters[ipar].EXEC_buffer);
+       free(self->parameters[ipar].EXEC_buffer);
        self->parameters[ipar].EXEC_buffer = NULL;
    }
+   self->parameters[ipar].lobj_oid = 0;
+   self->parameters[ipar].precision = 0;
+   self->parameters[ipar].scale = 0;
+}
+
+void
+reset_a_iparameter_binding(IPDFields *self, int ipar)
+{
+   static char *func = "reset_a_iparameter_binding";
+
+   mylog("%s: entering ... self=%u, parameters_allocated=%d, ipar=%d\n", func, self, self->allocated, ipar);
+
+   if (ipar < 1 || ipar > self->allocated)
+       return;
+
+   ipar--;
+   self->parameters[ipar].paramType = 0;
    self->parameters[ipar].SQLType = 0;
    self->parameters[ipar].column_size = 0;
    self->parameters[ipar].decimal_digits = 0;
    self->parameters[ipar].precision = 0;
    self->parameters[ipar].scale = 0;
-   self->parameters[ipar].data_at_exec = FALSE;
-   self->parameters[ipar].lobj_oid = 0;
 }
 
 /*
  * Free parameters and free the memory.
  */
 void
-APD_free_params(APDFields *self, char option)
+APD_free_params(APDFields *apdopts, char option)
 {
    int         i;
 
-   mylog("APD_free_params:  ENTER, self=%d\n", self);
+   mylog("APD_free_params:  ENTER, self=%d\n", apdopts);
 
-   if (!self->parameters)
+   if (!apdopts->parameters)
        return;
 
-   for (i = 0; i < self->allocated; i++)
+   for (i = 0; i < apdopts->allocated; i++)
    {
-       if (self->parameters[i].data_at_exec)
+       if (apdopts->parameters[i].data_at_exec)
        {
-           if (self->parameters[i].EXEC_used)
+           if (apdopts->parameters[i].EXEC_used)
            {
-               free(self->parameters[i].EXEC_used);
-               self->parameters[i].EXEC_used = NULL;
+               free(apdopts->parameters[i].EXEC_used);
+               apdopts->parameters[i].EXEC_used = NULL;
            }
-
-           if (self->parameters[i].EXEC_buffer)
+           if (apdopts->parameters[i].EXEC_buffer)
            {
-               if (self->parameters[i].SQLType != SQL_LONGVARBINARY)
-                   free(self->parameters[i].EXEC_buffer);
-               self->parameters[i].EXEC_buffer = NULL;
+               free(apdopts->parameters[i].EXEC_buffer);
+               apdopts->parameters[i].EXEC_buffer = NULL;
            }
        }
    }
 
    if (option == STMT_FREE_PARAMS_ALL)
    {
-       if (self->parameters)
-           free(self->parameters);
-       self->parameters = NULL;
-       self->allocated = 0;
+       if (apdopts->parameters)
+           free(apdopts->parameters);
+       apdopts->parameters = NULL;
+       apdopts->allocated = 0;
    }
 
    mylog("APD_free_params:  EXIT\n");
 }
 
+/*
+ * Free parameters and free the memory.
+ */
+void
+IPD_free_params(IPDFields *ipdopts, char option)
+{
+   mylog("IPD_free_params:  ENTER, self=%d\n", ipdopts);
+
+   if (ipdopts->parameters &&
+       option == STMT_FREE_PARAMS_ALL)
+   {
+       if (ipdopts->parameters)
+           free(ipdopts->parameters);
+       ipdopts->parameters = NULL;
+       ipdopts->allocated = 0;
+   }
+
+   mylog("IPD_free_params:  EXIT\n");
+}
+
 void
 extend_column_bindings(ARDFields *self, int num_columns)
 {
@@ -614,6 +690,7 @@ reset_a_column_binding(ARDFields *self, int icol)
            free(self->bindings[icol].ttlbuf);
        self->bindings[icol].ttlbuf = NULL;
        self->bindings[icol].ttlbuflen = 0;
+       self->bindings[icol].ttlbufused = 0;
    }
 }
 
diff --git a/bind.h b/bind.h
index f2467c7713a9b2e3762bfda4115ac031bd838d9a..02c9b116442e05f251c83504c9da51389c3ce3b3 100644 (file)
--- a/bind.h
+++ b/bind.h
@@ -24,6 +24,7 @@ struct BindInfoClass_
                                 * not counting the '\0') */
    char       *ttlbuf;         /* to save the large result */
    Int4        ttlbuflen;      /* the buffer length */
+   Int4        ttlbufused;     /* used length of the buffer */
    Int2        returntype;     /* kind of conversion to be applied when
                                 * returning (SQL_C_DEFAULT,
                                 * SQL_C_CHAR...) */
@@ -41,22 +42,34 @@ struct ParameterInfoClass_
    Int4       *used;
    Int2        paramType;
    Int2        CType;
-   Int2        SQLType;
-   Int2        decimal_digits;
-   UInt4       column_size;
    Oid         lobj_oid;
-   Int4       *EXEC_used;      /* amount of data OR the oid of the large
-                                * object */
-   char       *EXEC_buffer;    /* the data or the FD of the large object */
+   Int4       *EXEC_used;      /* amount of data */
+   char       *EXEC_buffer;    /* the data */
    Int2        precision;  /* the precision for numeric or timestamp type */
    Int2        scale;      /* the scale for numeric type */
    char        data_at_exec;
 };
 
+/*
+ * ParameterImplClass -- stores implemntation information about a parameter
+ */
+struct ParameterImplClass_
+{
+   Int2        paramType;
+   Int2        SQLType;
+   Int4        PGType;
+   UInt4       column_size;
+   Int2        decimal_digits;
+   Int2        precision;  /* the precision for numeric or timestamp type */
+   Int2        scale;      /* the scale for numeric type */
+};
+
 BindInfoClass *create_empty_bindings(int num_columns);
 void   extend_column_bindings(ARDFields *opts, int num_columns);
 void   reset_a_column_binding(ARDFields *opts, int icol);
 void   extend_parameter_bindings(APDFields *opts, int num_columns);
+void   extend_iparameter_bindings(IPDFields *opts, int num_columns);
 void   reset_a_parameter_binding(APDFields *opts, int ipar);
+void   reset_a_iparameter_binding(IPDFields *opts, int ipar);
 
 #endif
index 1d7c265fc2631fda98849f6d7ba6269d6d650979..43e69da4c982a3dbf86bf12df3f163010c460474 100644 (file)
@@ -238,6 +238,8 @@ CC_conninfo_init(ConnInfo *conninfo)
        conninfo->lf_conversion = -1;
        conninfo->true_is_minus1 = -1;
        conninfo->int8_as = -101;
+       conninfo->bytea_as_longvarbinary = -1;
+       conninfo->use_server_side_prepare = -1;
        memcpy(&(conninfo->drivers), &globals, sizeof(globals));
 }
 /*
@@ -273,7 +275,7 @@ CC_Constructor()
 
        rv->num_stmts = STMT_INCREMENT;
 
-       rv->lobj_type = PG_TYPE_LO;
+       rv->lobj_type = PG_TYPE_LO_UNDEFINED;
 
        rv->ntables = 0;
        rv->col_info = NULL;
index c605e9c07262667d381a86aa8364e86da258b5bf..0bf20e59c95795f625f97f7ccb4bec5c65714b45 100644 (file)
@@ -87,7 +87,7 @@ typedef enum
 #define CC_set_errornumber(x, n)   (x->__error_number = n)
 
 /* For Multi-thread */
-#if defined(WIN_MULTITHREAD_SUPPORT)
+#if defined(WIN_FREETHREAD_SUPPORT)
 #define INIT_CONN_CS(x)        InitializeCriticalSection(&((x)->cs))
 #define ENTER_CONN_CS(x)   EnterCriticalSection(&((x)->cs))
 #define LEAVE_CONN_CS(x)   LeaveCriticalSection(&((x)->cs))
@@ -201,6 +201,8 @@ typedef struct
    char        lf_conversion;
    char        true_is_minus1;
    char        int8_as;
+   char        bytea_as_longvarbinary;
+   char        use_server_side_prepare;
    GLOBAL_VALUES drivers;      /* moved from driver's option */
 } ConnInfo;
 
index ffefab1709bfe3eb7ffa1f5017710dc7b320c780..c2759aa0120ace4dc86f466f5aa4880fd4a20d40 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -131,6 +131,8 @@ static const char *mapFunction(const char *func, int param_count);
 static unsigned int conv_from_octal(const unsigned char *s);
 static unsigned int conv_from_hex(const unsigned char *s);
 static char *conv_to_octal(unsigned char val, char *octal);
+static int pg_bin2hex(UCHAR *src, UCHAR *dst, int length);
+static int pg_hex2bin(UCHAR *src, UCHAR *dst, int length);
 
 /*---------
  *         A Guide for date/time/timestamp conversions
@@ -614,7 +616,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
             * This is a large object OID, which is used to store
             * LONGVARBINARY objects.
             */
-       case PG_TYPE_LO:
+       case PG_TYPE_LO_UNDEFINED:
 
            return convert_lo(stmt, value, fCType, ((char *) rgbValue + rgbValueOffset), cbValueMax, (SDWORD *) ((char *) pcbValue + pcbValueOffset));
 
@@ -695,10 +697,6 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                 */
            case PG_TYPE_BYTEA:/* convert binary data to hex strings
                                 * (i.e, 255 = "FF") */
-               len = convert_pgbinary_to_char(neut_str, rgbValueBindRow, cbValueMax);
-
-               /***** THIS IS NOT PROPERLY IMPLEMENTED *****/
-               break;
 
            default:
                if (stmt->current_col < 0)
@@ -720,8 +718,15 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                    }
                    else
 #endif /* UNICODE_SUPPORT */
-                   /* convert linefeeds to carriage-return/linefeed */
-                   len = convert_linefeeds(neut_str, NULL, 0, lf_conv, &changed);
+                   if (PG_TYPE_BYTEA == field_type)
+                   {
+                       len = convert_from_pgbinary(neut_str, NULL, 0);
+                       len *= 2;
+                       changed = TRUE;
+                   }
+                   else
+                       /* convert linefeeds to carriage-return/linefeed */
+                       len = convert_linefeeds(neut_str, NULL, 0, lf_conv, &changed);
                    if (cbValueMax == 0)        /* just returns length
                                                 * info */
                    {
@@ -744,8 +749,16 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                        }
                        else
 #endif /* UNICODE_SUPPORT */
-                       convert_linefeeds(neut_str, pbic->ttlbuf, pbic->ttlbuflen, lf_conv, &changed);
+                       if (PG_TYPE_BYTEA == field_type)
+                       {
+                           len = convert_from_pgbinary(neut_str, pbic->ttlbuf, pbic->ttlbuflen);
+                           pg_bin2hex(pbic->ttlbuf, pbic->ttlbuf, len);
+                           len *= 2; 
+                       }
+                       else
+                           convert_linefeeds(neut_str, pbic->ttlbuf, pbic->ttlbuflen, lf_conv, &changed);
                        ptr = pbic->ttlbuf;
+                       pbic->ttlbufused = len;
                    }
                    else
                    {
@@ -758,7 +771,10 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                    }
                }
                else
+               {
                    ptr = pbic->ttlbuf;
+                   len = pbic->ttlbufused;
+               }
 
                mylog("DEFAULT: len = %d, ptr = '%s'\n", len, ptr);
 
@@ -766,7 +782,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                {
                    if (pbic->data_left > 0)
                    {
-                       ptr += strlen(ptr) - pbic->data_left;
+                       ptr += len - pbic->data_left;
                        len = pbic->data_left;
                    }
                    else
@@ -1138,6 +1154,11 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
 #endif /* ODBCINT64 */
            case SQL_C_BINARY:
 
+               if (PG_TYPE_BYTEA != field_type)
+               {
+                   mylog("couldn't convert the type %d to SQL_C_BINARY\n", field_type);
+                   return COPY_UNSUPPORTED_TYPE;
+               }
                /* truncate if necessary */
                /* convert octal escapes to bytes */
 
@@ -1150,12 +1171,24 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                    pbic = &opts->bindings[stmt->current_col];
                if (!pbic->ttlbuf)
                    pbic->ttlbuflen = 0;
-               if (len = strlen(neut_str), len >= (int) pbic->ttlbuflen)
+               if (pbic->data_left < 0)
                {
-                   pbic->ttlbuf = realloc(pbic->ttlbuf, len + 1);
-                   pbic->ttlbuflen = len + 1;
+                   if (cbValueMax <= 0)
+                   {
+                       len = convert_from_pgbinary(neut_str, NULL, 0);
+                       result = COPY_RESULT_TRUNCATED;
+                       break;
+                   }
+                   if (len = strlen(neut_str), len >= (int) pbic->ttlbuflen)
+                   {
+                       pbic->ttlbuf = realloc(pbic->ttlbuf, len + 1);
+                       pbic->ttlbuflen = len + 1;
+                   }
+                   len = convert_from_pgbinary(neut_str, pbic->ttlbuf, pbic->ttlbuflen);
+                   pbic->ttlbufused = len;
                }
-               len = convert_from_pgbinary(neut_str, pbic->ttlbuf, pbic->ttlbuflen);
+               else
+                   len = pbic->ttlbufused;
                ptr = pbic->ttlbuf;
 
                if (stmt->current_col >= 0)
@@ -1194,8 +1227,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
                 */
                if (len > cbValueMax)
                    result = COPY_RESULT_TRUNCATED;
-
-               if (pbic->ttlbuf)
+               else if (pbic->ttlbuf)
                {
                    free(pbic->ttlbuf);
                    pbic->ttlbuf = NULL;
@@ -1232,6 +1264,7 @@ copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2
 #define    FLGP_CURSOR_CHECK_OK    (1L << 1)
 #define    FLGP_SELECT_INTO        (1L << 2)
 #define    FLGP_SELECT_FOR_UPDATE  (1L << 3)
+#define    FLGP_BUILDING_PREPARE_STATEMENT (1L << 4)
 typedef struct _QueryParse {
    const char  *statement;
    int     statement_type;
@@ -1252,7 +1285,7 @@ typedef struct _QueryParse {
 static int
 QP_initialize(QueryParse *q, const StatementClass *stmt)
 {
-   q->statement = stmt->statement;
+   q->statement = stmt->execute_statement ? stmt->execute_statement : stmt->statement;
    q->statement_type = stmt->statement_type;
    q->opos = 0;
    q->from_pos = -1;
@@ -1274,6 +1307,7 @@ QP_initialize(QueryParse *q, const StatementClass *stmt)
 #define    FLGB_INACCURATE_RESULT  (1L << 1)
 #define    FLGB_CREATE_KEYSET  (1L << 2)
 #define    FLGB_KEYSET_DRIVEN  (1L << 3)
+#define    FLGB_BUILDING_PREPARE_STATEMENT (1L << 4)
 typedef struct _QueryBuild {
    char    *query_statement;
    UInt4   str_size_limit;
@@ -1282,6 +1316,7 @@ typedef struct _QueryBuild {
    int current_row;
    int param_number;
    APDFields *apdopts;
+   IPDFields *ipdopts;
    UInt4   load_stmt_len;
    UInt4   flags;
    BOOL    lf_conv;
@@ -1303,11 +1338,13 @@ QB_initialize(QueryBuild *qb, UInt4 size, StatementClass *stmt, ConnectionClass
    qb->load_stmt_len = 0;
    qb->stmt = stmt;
    qb->apdopts = NULL;
+   qb->ipdopts = NULL;
    if (conn)
        qb->conn = conn;
    else if (stmt)
    {
        qb->apdopts = SC_get_APD(stmt);
+       qb->ipdopts = SC_get_IPD(stmt);
        qb->conn = SC_get_conn(stmt);
        if (stmt->pre_executing)
            qb->flags |= FLGB_PRE_EXECUTING;
@@ -1658,6 +1695,106 @@ insert_without_target(const char *stmt, int *endpos)
        || ';' == wstmt[0];
 }
 
+static int
+Prepare_and_convert(StatementClass *stmt, QueryParse *qp, QueryBuild *qb)
+{
+   const static char *func = "Prepare_and_convert";
+   char    *new_statement, *exe_statement = NULL;
+   int retval;
+
+   if (QB_initialize(qb, qp->stmt_len, stmt, NULL) < 0)
+       return SQL_ERROR;
+   if (!stmt->prepared) /*  not yet prepared */
+   {
+       int i, elen;
+       SWORD   marker_count;
+       const IPDFields *ipdopts = qb->ipdopts;
+
+       new_statement = qb->query_statement;
+       qb->flags = FLGB_BUILDING_PREPARE_STATEMENT;
+       sprintf(new_statement, "PREPARE _PLAN%0x", stmt);
+       qb->npos = strlen(new_statement);
+       if (SQL_SUCCESS != PGAPI_NumParams(stmt, &marker_count))
+       {
+           QB_Destructor(qb);
+           return SQL_ERROR;
+       }
+       if (marker_count > 0)
+       {
+           CVT_APPEND_CHAR(qb, '(');
+           for (i = 0; i < marker_count; i++)
+           {
+               if (i > 0)
+                   CVT_APPEND_STR(qb, ", ");
+               CVT_APPEND_STR(qb, pgtype_to_name(stmt, ipdopts->parameters[i].PGType));
+           }
+           CVT_APPEND_CHAR(qb, ')');
+       }
+       CVT_APPEND_STR(qb, " as ");
+       for (qp->opos = 0; qp->opos < qp->stmt_len; qp->opos++)
+       {
+           retval = inner_process_tokens(qp, qb);
+           if (SQL_ERROR == retval)
+           {
+               if (0 == SC_get_errornumber(stmt))
+               {
+                   SC_set_error(stmt, qb->errornumber, qb->errormsg);
+               }
+               SC_log_error(func, "", stmt);
+               QB_Destructor(qb);
+               return retval;
+           }
+       }
+       CVT_APPEND_CHAR(qb, ';');
+       /* build the execute statement */
+       exe_statement = malloc(30 + 2 * marker_count);
+       sprintf(exe_statement, "EXECUTE _PLAN%0x", stmt);
+       if (marker_count > 0)
+       {
+           elen = strlen(exe_statement);
+           exe_statement[elen++] = '(';
+           for (i = 0; i < marker_count; i++)
+           {
+               if (i > 0)
+                   exe_statement[elen++] = ',';
+               exe_statement[elen++]  = '?';
+           }
+           exe_statement[elen++] = ')';
+           exe_statement[elen] = '\0';
+       }
+       stmt->execute_statement = exe_statement;
+       QP_initialize(qp, stmt);
+   }
+   qb->flags = 0;
+   qb->param_number = -1;
+   for (qp->opos = 0; qp->opos < qp->stmt_len; qp->opos++)
+   {
+       retval = inner_process_tokens(qp, qb);
+       if (SQL_ERROR == retval)
+       {
+           if (0 == SC_get_errornumber(stmt))
+           {
+               SC_set_error(stmt, qb->errornumber, qb->errormsg);
+           }
+           SC_log_error(func, "", stmt);
+           if (exe_statement)
+           {
+               free(exe_statement);
+               stmt->execute_statement = NULL;
+           }
+           QB_Destructor(qb);
+           return retval;
+       }
+   }
+   /* make sure new_statement is always null-terminated */
+   CVT_TERMINATE(qb);
+
+   if (exe_statement)
+       SC_set_prepare_before_exec(stmt);
+   stmt->stmt_with_params = qb->query_statement;
+   return SQL_SUCCESS;
+}
+
 #define        my_strchr(conn, s1,c1) pg_mbschr(conn->ccsc, s1,c1)
 
 /*
@@ -1666,7 +1803,7 @@ insert_without_target(const char *stmt, int *endpos)
  * This function does a dynamic memory allocation to get rid of query size limit!
  */
 int
-copy_statement_with_parameters(StatementClass *stmt)
+copy_statement_with_parameters(StatementClass *stmt, BOOL buildPrepareStatement)
 {
    static char *func = "copy_statement_with_parameters";
    RETCODE     retval;
@@ -1690,12 +1827,6 @@ copy_statement_with_parameters(StatementClass *stmt)
    qp = &query_org;
    QP_initialize(qp, stmt);
 
-   if (ci->disallow_premature)
-       prepare_dummy_cursor = stmt->pre_executing;
-   if (prepare_dummy_cursor)
-       qp->flags |= FLGP_PREPARE_DUMMY_CURSOR;
-
-
 #ifdef DRIVER_CURSOR_IMPLEMENT
    if (stmt->statement_type != STMT_TYPE_SELECT)
    {
@@ -1731,6 +1862,7 @@ copy_statement_with_parameters(StatementClass *stmt)
        stmt->options.cursor_type = SQL_CURSOR_STATIC;
 #endif   /* DRIVER_CURSOR_IMPLEMENT */
 
+   stmt->miscinfo = 0;
    /* If the application hasn't set a cursor name, then generate one */
    if (stmt->cursor_name[0] == '\0')
        sprintf(stmt->cursor_name, "SQL_CUR%p", stmt);
@@ -1739,12 +1871,21 @@ copy_statement_with_parameters(StatementClass *stmt)
        free(stmt->stmt_with_params);
        stmt->stmt_with_params = NULL;
    }
+
    qb = &query_crt;
+   if (stmt->prepared || (buildPrepareStatement && stmt->options.scroll_concurrency == SQL_CONCUR_READ_ONLY))
+   {
+       return Prepare_and_convert(stmt, qp, qb);
+   }
+
+   if (ci->disallow_premature)
+       prepare_dummy_cursor = stmt->pre_executing;
+   if (prepare_dummy_cursor)
+       qp->flags |= FLGP_PREPARE_DUMMY_CURSOR;
    if (QB_initialize(qb, qp->stmt_len, stmt, NULL) < 0)
        return SQL_ERROR;
    new_statement = qb->query_statement;
 
-   stmt->miscinfo = 0;
    /* For selects, prepend a declare cursor to the statement */
    if (stmt->statement_type == STMT_TYPE_SELECT)
    {
@@ -2183,11 +2324,13 @@ ResolveOneParam(QueryBuild *qb)
 
    ConnectionClass *conn = qb->conn;
    ConnInfo   *ci = &(conn->connInfo);
-   APDFields *opts = qb->apdopts;
+   const APDFields *apdopts = qb->apdopts;
+   const IPDFields *ipdopts = qb->ipdopts;
 
    int     param_number;
    char        param_string[128], tmp[256],
            cbuf[PG_NUMERIC_MAX_PRECISION * 2]; /* seems big enough to handle the data in this function */
+   Int4        param_pgtype;
    Int2        param_ctype, param_sqltype;
    SIMPLE_TIME st;
    time_t      t;
@@ -2199,15 +2342,16 @@ ResolveOneParam(QueryBuild *qb)
    char        *buffer, *buf, *allocbuf;
    Oid     lobj_oid;
    int     lobj_fd, retval;
-   UInt4   offset = opts->param_offset_ptr ? *opts->param_offset_ptr : 0;
+   UInt4   offset = apdopts->param_offset_ptr ? *apdopts->param_offset_ptr : 0;
    UInt4   current_row = qb->current_row;
+   BOOL    handling_large_object = FALSE;
 
    /*
     * Its a '?' parameter alright
     */
    param_number = ++qb->param_number;
 
-   if (param_number >= opts->allocated)
+   if (param_number >= apdopts->allocated)
    {
        if (0 != (qb->flags & FLGB_PRE_EXECUTING))
        {
@@ -2217,40 +2361,59 @@ ResolveOneParam(QueryBuild *qb)
        }
        else
        {
-           CVT_APPEND_CHAR(qb, '?');
-           return SQL_SUCCESS;
+           qb->errormsg = "The # of binded parameters < the # of parameter markers";
+           qb->errornumber = STMT_COUNT_FIELD_INCORRECT;
+           CVT_TERMINATE(qb);  /* just in case */
+           return SQL_ERROR;
        }
    }
+   if (SQL_PARAM_OUTPUT == apdopts->parameters[param_number].paramType)
+   {
+       qb->errormsg = "Output parameter isn't available";
+       qb->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
+       CVT_TERMINATE(qb);  /* just in case */
+       return SQL_ERROR;
+   }
 
+   if (0 != (qb->flags & FLGB_BUILDING_PREPARE_STATEMENT))
+   {
+       char    pnum[16];
+
+       sprintf(pnum, "$%d", param_number + 1);
+       CVT_APPEND_STR(qb, pnum); 
+       return SQL_SUCCESS;
+   } 
    /* Assign correct buffers based on data at exec param or not */
-   if (opts->parameters[param_number].data_at_exec)
+   if (apdopts->parameters[param_number].data_at_exec)
    {
-       used = opts->parameters[param_number].EXEC_used ? *opts->parameters[param_number].EXEC_used : SQL_NTS;
-       buffer = opts->parameters[param_number].EXEC_buffer;
+       used = apdopts->parameters[param_number].EXEC_used ? *apdopts->parameters[param_number].EXEC_used : SQL_NTS;
+       buffer = apdopts->parameters[param_number].EXEC_buffer;
+       if (apdopts->parameters[param_number].lobj_oid)
+           handling_large_object = TRUE;
    }
    else
    {
-       UInt4   bind_size = opts->param_bind_type;
+       UInt4   bind_size = apdopts->param_bind_type;
        UInt4   ctypelen;
 
-       buffer = opts->parameters[param_number].buffer + offset;
+       buffer = apdopts->parameters[param_number].buffer + offset;
        if (current_row > 0)
        {
            if (bind_size > 0)
                buffer += (bind_size * current_row);
-           else if (ctypelen = ctype_length(opts->parameters[param_number].CType), ctypelen > 0)
+           else if (ctypelen = ctype_length(apdopts->parameters[param_number].CType), ctypelen > 0)
                buffer += current_row * ctypelen;
            else 
-               buffer += current_row * opts->parameters[param_number].buflen;
+               buffer += current_row * apdopts->parameters[param_number].buflen;
        }
-       if (opts->parameters[param_number].used)
+       if (apdopts->parameters[param_number].used)
        {
            UInt4   p_offset = offset;
            if (bind_size > 0)
                p_offset = offset + bind_size * current_row;
            else
                p_offset = offset + sizeof(SDWORD) * current_row;
-           used = *(SDWORD *)((char *)opts->parameters[param_number].used + p_offset);
+           used = *(SDWORD *)((char *)apdopts->parameters[param_number].used + p_offset);
        }
        else
            used = SQL_NTS;
@@ -2275,15 +2438,16 @@ ResolveOneParam(QueryBuild *qb)
            qb->flags |= FLGB_INACCURATE_RESULT;
            return SQL_SUCCESS;
        }
-       else
+       else if (!handling_large_object)
        {
            CVT_APPEND_CHAR(qb, '?');
            return SQL_SUCCESS;
        }
    }
 
-   param_ctype = opts->parameters[param_number].CType;
-   param_sqltype = opts->parameters[param_number].SQLType;
+   param_ctype = apdopts->parameters[param_number].CType;
+   param_sqltype = ipdopts->parameters[param_number].SQLType;
+   param_pgtype = ipdopts->parameters[param_number].PGType;
 
    mylog("%s: from(fcType)=%d, to(fSqlType)=%d\n", func,
                param_ctype, param_sqltype);
@@ -2541,22 +2705,56 @@ ResolveOneParam(QueryBuild *qb)
            break;
 
        case SQL_BINARY:
-       case SQL_VARBINARY:/* non-ascii characters should be
-                           * converted to octal */
-           CVT_APPEND_CHAR(qb, '\'');  /* Open Quote */
-
-           mylog("SQL_VARBINARY: about to call convert_to_pgbinary, used = %d\n", used);
+       case SQL_VARBINARY:
+       case SQL_LONGVARBINARY:
+           switch (param_ctype)
+           {
+               case SQL_C_BINARY:
+                   break;
+               case SQL_C_CHAR:
+                   switch (used)
+                   {
+                       case SQL_NTS:
+                           used = strlen(buf);
+                           break;
+                   }
+                   allocbuf = malloc(used / 2 + 1);
+                   if (allocbuf)
+                   {
+                       pg_hex2bin(buf, allocbuf, used);
+                       buf = allocbuf;
+                       used /= 2;
+                   }
+                   break;
+               default:
+                   qb->errormsg = "Could not convert the ctype to binary type";
+                   qb->errornumber = STMT_EXEC_ERROR;
+                   return SQL_ERROR;
+           }
+           if (param_pgtype == PG_TYPE_BYTEA)
+           {
+               /* non-ascii characters should be
+                * converted to octal
+                */
+               CVT_APPEND_CHAR(qb, '\'');  /* Open Quote */
 
-           CVT_APPEND_BINARY(qb, buf, used);
+               mylog("SQL_VARBINARY: about to call convert_to_pgbinary, used = %d\n", used);
 
-           CVT_APPEND_CHAR(qb, '\'');  /* Close Quote */
+               CVT_APPEND_BINARY(qb, buf, used);
 
-           break;
+               CVT_APPEND_CHAR(qb, '\'');  /* Close Quote */
 
-       case SQL_LONGVARBINARY:
+               break;
+           }
+           if (param_pgtype != conn->lobj_type)
+           {
+               qb->errormsg = "Could not convert binary other than LO type";
+               qb->errornumber = STMT_EXEC_ERROR;
+               return SQL_ERROR;
+           }
 
-           if (opts->parameters[param_number].data_at_exec)
-               lobj_oid = opts->parameters[param_number].lobj_oid;
+           if (apdopts->parameters[param_number].data_at_exec)
+               lobj_oid = apdopts->parameters[param_number].lobj_oid;
            else
            {
                /* begin transaction if needed */
@@ -2609,7 +2807,7 @@ ResolveOneParam(QueryBuild *qb)
             * parameter marker -- the data has already been sent to
             * the large object
             */
-           sprintf(param_string, "'%d'", lobj_oid);
+           sprintf(param_string, "'%d'::lo", lobj_oid);
            CVT_APPEND_STR(qb, param_string);
 
            break;
@@ -2671,10 +2869,8 @@ ResolveOneParam(QueryBuild *qb)
 
            break;
    }
-#ifdef UNICODE_SUPPORT
    if (allocbuf)
        free(allocbuf);
-#endif /* UNICODE_SUPPORT */
    return SQL_SUCCESS;
 }
 
@@ -3275,22 +3471,32 @@ convert_from_pgbinary(const unsigned char *value, unsigned char *rgbValue, int c
        {
            if (value[i + 1] == '\\')
            {
-               rgbValue[o] = value[i];
+               if (rgbValue)
+                   rgbValue[o] = value[i];
                i += 2;
            }
            else
            {
-               rgbValue[o] = conv_from_octal(&value[i]);
+               if (rgbValue)
+                   rgbValue[o] = conv_from_octal(&value[i]);
                i += 4;
            }
        }
        else
-           rgbValue[o] = value[i++];
-       mylog("convert_from_pgbinary: i=%d, rgbValue[%d] = %d, %c\n", i, o, rgbValue[o], rgbValue[o]);
+       {
+           if (rgbValue)
+               rgbValue[o] = value[i];
+           i++;
+       }
+       /** if (rgbValue)
+           mylog("convert_from_pgbinary: i=%d, rgbValue[%d] = %d, %c\n", i, o, rgbValue[o], rgbValue[o]); ***/
        o++;
    }
 
-   rgbValue[o] = '\0';         /* extra protection */
+   if (rgbValue)
+       rgbValue[o] = '\0';     /* extra protection */
+
+   mylog("convert_from_pgbinary: in=%d, out = %d\n", ilen, o);
 
    return o;
 }
@@ -3430,6 +3636,37 @@ pg_bin2hex(UCHAR *src, UCHAR *dst, int length)
    return length;
 }
 
+static int
+pg_hex2bin(UCHAR *src, UCHAR *dst, int length)
+{
+   UCHAR       chr,
+              *src_wk,
+              *dst_wk;
+   int     i, val;
+   BOOL        HByte = TRUE;
+
+   for (i = 0, src_wk = src, dst_wk = dst; i < length; i++, src_wk++)
+   {
+       chr = *src_wk;
+       if (chr >= 'a' && chr <= 'f')
+           val = chr - 'a' + 10;
+       else if (chr >= 'A' && chr <= 'F')
+           val = chr - 'A' + 10;
+       else
+           val = chr - '0';
+       if (HByte)
+           *dst_wk = (val << 4);
+       else
+       {
+           *dst_wk += val; 
+           dst_wk++;
+       }
+       HByte = !HByte;
+   }
+   *dst_wk = '\0';
+   return length;
+}
+
 /*-------
  * 1. get oid (from 'value')
  * 2. open the large object
@@ -3458,8 +3695,20 @@ convert_lo(StatementClass *stmt, const void *value, Int2 fCType, PTR rgbValue,
    ConnectionClass *conn = SC_get_conn(stmt);
    ConnInfo   *ci = &(conn->connInfo);
    ARDFields   *opts = SC_get_ARD(stmt);
-   int         factor = (fCType == SQL_C_CHAR ? 2 : 1);
+   int         factor;
 
+   switch (fCType)
+   {
+       case SQL_C_CHAR:
+           factor = 2;
+           break;
+       case SQL_C_BINARY:
+           factor = 1;
+           break;
+       default:
+           SC_set_error(stmt, STMT_EXEC_ERROR, "Could not convert lo to the c-type");
+           return COPY_GENERAL_ERROR;
+   }
    /* If using SQLGetData, then current_col will be set */
    if (stmt->current_col >= 0)
    {
index 8f65472e1f27d916214eee750ccf8bf08a28ac97..157fdcae1650b1eba1577e83427f6b544670e133 100644 (file)
--- a/convert.h
+++ b/convert.h
@@ -39,7 +39,7 @@ int           copy_and_convert_field_bindinfo(StatementClass *stmt, Int4 field_type, voi
 int copy_and_convert_field(StatementClass *stmt, Int4 field_type, void *value, Int2 fCType,
                       PTR rgbValue, SDWORD cbValueMax, SDWORD *pcbValue);
 
-int            copy_statement_with_parameters(StatementClass *stmt);
+int        copy_statement_with_parameters(StatementClass *stmt, BOOL);
 BOOL       convert_money(const char *s, char *sout, size_t soutmax);
 char       parse_datetime(const char *buf, SIMPLE_TIME *st);
 int            convert_linefeeds(const char *s, char *dst, size_t max, BOOL convlf, BOOL *changed);
index abae3fddc9926cf098dbce1881a1eef832645c40..ca2bfe4fb28ad0549134c6317b959b72554921a8 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Comments:       See "notice.txt" for copyright and license information.
  *
- * $Id: descriptor.h,v 1.8 2002/09/23 08:08:21 hinoue Exp $
+ * $Id: descriptor.h,v 1.9 2002/12/16 15:01:33 hinoue Exp $
  *
  */
 
@@ -85,6 +85,8 @@ struct IPDFields_
    StatementClass  *stmt;
    UInt4       *param_processed_ptr;
    UInt2       *param_status_ptr;
+   ParameterImplClass  *parameters;
+   int         allocated;
 };
 
 void   InitializeARDFields(ARDFields *self);
@@ -97,6 +99,7 @@ void  IRDFields_free(IRDFields *self);
 void   IPDFields_free(IPDFields *self);
 void   ARD_unbind_cols(ARDFields *self, BOOL freeall);
 void   APD_free_params(APDFields *self, char option);
+void   IPD_free_params(IPDFields *self, char option);
 #if (ODBCVER >= 0x0300)
 void   Desc_set_error(SQLHDESC hdesc, int errornumber, const char * errormsg);
 #endif /* ODBCVER */
index e94669d7b155641cd7603d3a1ed16f26e571c0b6..ba5bac44d2af2b175778d3d51f758236794e1f2e 100644 (file)
@@ -61,7 +61,7 @@ makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
    hlen = strlen(connect_string);
    if (!abbrev)
        sprintf(&connect_string[hlen],
-               ";%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%s;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d",
+               ";%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%s;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%s;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d;%s=%d",
                INI_READONLY,
                ci->onlyread,
                INI_PROTOCOL,
@@ -117,7 +117,11 @@ makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
                INI_TRUEISMINUS1,
                ci->true_is_minus1,
                INI_INT8AS,
-               ci->int8_as);
+               ci->int8_as,
+               INI_BYTEAASLONGVARBINARY,
+               ci->bytea_as_longvarbinary,
+               INI_USESERVERSIDEPREPARE,
+               ci->use_server_side_prepare);
    /* Abbrebiation is needed ? */
    if (abbrev || strlen(connect_string) >= len)
    {
@@ -175,6 +179,10 @@ makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len)
            flag |= BIT_FAKEOIDINDEX;
        if (ci->true_is_minus1)
            flag |= BIT_TRUEISMINUS1;
+       if (ci->bytea_as_longvarbinary)
+           flag |= BIT_BYTEAASLONGVARBINARY;
+       if (ci->use_server_side_prepare)
+           flag |= BIT_USESERVERSIDEPREPARE;
 
        sprintf(&connect_string[hlen],
                ";A6=%s;A7=%d;A8=%d;B0=%d;B1=%d;%s=%d;C2=%s;CX=%02x%lx",
@@ -244,6 +252,8 @@ unfoldCXAttribute(ConnInfo *ci, const char *value)
    sprintf(ci->show_oid_column, "%d", (char)((flag & BIT_SHOWOIDCOLUMN) != 0));
    sprintf(ci->fake_oid_index, "%d", (char)((flag & BIT_FAKEOIDINDEX) != 0));
    ci->true_is_minus1 = (char)((flag & BIT_TRUEISMINUS1) != 0);
+   ci->bytea_as_longvarbinary = (char)((flag & BIT_BYTEAASLONGVARBINARY) != 0);
+   ci->use_server_side_prepare = (char)((flag & BIT_USESERVERSIDEPREPARE) != 0);
 }
 void
 copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
@@ -302,6 +312,10 @@ copyAttributes(ConnInfo *ci, const char *attribute, const char *value)
        ci->true_is_minus1 = atoi(value);
    else if (stricmp(attribute, INI_INT8AS) == 0)
        ci->int8_as = atoi(value);
+   else if (stricmp(attribute, INI_BYTEAASLONGVARBINARY) == 0)
+       ci->bytea_as_longvarbinary = atoi(value);
+   else if (stricmp(attribute, INI_USESERVERSIDEPREPARE) == 0)
+       ci->use_server_side_prepare = atoi(value);
    else if (stricmp(attribute, "CX") == 0)
        unfoldCXAttribute(ci, value);
 
@@ -405,6 +419,10 @@ getDSNdefaults(ConnInfo *ci)
        ci->true_is_minus1 = DEFAULT_TRUEISMINUS1;
    if (ci->int8_as < -100)
        ci->int8_as = DEFAULT_INT8AS;
+   if (ci->bytea_as_longvarbinary < 0)
+       ci->bytea_as_longvarbinary = DEFAULT_BYTEAASLONGVARBINARY;
+   if (ci->use_server_side_prepare < 0)
+       ci->use_server_side_prepare = DEFAULT_USESERVERSIDEPREPARE;
 }
 
 
@@ -516,6 +534,20 @@ getDSNinfo(ConnInfo *ci, char overwrite)
            ci->int8_as = atoi(temp);
    }
 
+   if (ci->bytea_as_longvarbinary < 0 || overwrite)
+   {
+       SQLGetPrivateProfileString(DSN, INI_BYTEAASLONGVARBINARY, "", temp, sizeof(temp), ODBC_INI);
+       if (temp[0])
+           ci->bytea_as_longvarbinary = atoi(temp);
+   }
+
+   if (ci->use_server_side_prepare < 0 || overwrite)
+   {
+       SQLGetPrivateProfileString(DSN, INI_USESERVERSIDEPREPARE, "", temp, sizeof(temp), ODBC_INI);
+       if (temp[0])
+           ci->use_server_side_prepare = atoi(temp);
+   }
+
    /* Allow override of odbcinst.ini parameters here */
    getCommonDefaults(DSN, ODBC_INI, ci);
 
@@ -752,6 +784,11 @@ writeDSNinfo(const ConnInfo *ci)
                                 INI_INT8AS,
                                 temp,
                                 ODBC_INI);
+   sprintf(temp, "%d", ci->bytea_as_longvarbinary);
+   SQLWritePrivateProfileString(DSN,
+                                INI_INT8AS,
+                                temp,
+                                ODBC_INI);
 }
 
 
index 370d936fef4f0d15a9c9efdb70ba54d8575ac3bb..2066660c69c1d1778c6bfb7e40987e5b8141d9d4 100644 (file)
@@ -99,6 +99,8 @@
 #define INI_LFCONVERSION           "LFConversion"
 #define INI_TRUEISMINUS1           "TrueIsMinus1"
 #define INI_INT8AS             "BI"
+#define INI_BYTEAASLONGVARBINARY       "ByteaAsLongVarBinary"
+#define INI_USESERVERSIDEPREPARE       "UseServerSidePrepare"
 /* Bit representaion for abbreviated connection strings */
 #define BIT_LFCONVERSION           (1L)
 #define BIT_UPDATABLECURSORS           (1L<<1)
 #define BIT_SHOWOIDCOLUMN          (1L<<21)
 #define BIT_FAKEOIDINDEX           (1L<<22)
 #define BIT_TRUEISMINUS1           (1L<<23)
+#define BIT_BYTEAASLONGVARBINARY       (1L<<24)
+#define BIT_USESERVERSIDEPREPARE       (1L<<25)
 
-#define EFFECTIVE_BIT_COUNT            24
+#define EFFECTIVE_BIT_COUNT            26
 
 
 /* Connection Defaults */
 #define DEFAULT_LFCONVERSION       0
 #endif /* WIN32 */
 #define DEFAULT_INT8AS         0
+#define DEFAULT_BYTEAASLONGVARBINARY   0
+#define DEFAULT_USESERVERSIDEPREPARE   0
 
 /* prototypes */
 void       getCommonDefaults(const char *section, const char *filename, ConnInfo *ci);
index 8a898a1c35b7b26394e203a3d2d6de1c035237d6..8121cfd452b2ad23050929f04136ed837abea36a 100644 (file)
--- a/environ.c
+++ b/environ.c
@@ -301,6 +301,9 @@ PGAPI_StmtError(    HSTMT hstmt,
            case STMT_OPTION_NOT_FOR_THE_DRIVER:
                pg_sqlstate_set(env, szSqlState, "HYC00", "HYC00");
                break;
+           case STMT_COUNT_FIELD_INCORRECT:
+               pg_sqlstate_set(env, szSqlState, "07002", "07002");
+               break;
            case STMT_EXEC_ERROR:
            default:
                pg_sqlstate_set(env, szSqlState, "HY000", "S1000");
index 95debf3d5c2d5760f47ad881a42072f31d147d78..70cf54dad0bdf50d7a9ec4282c20b0f7a01f4cc0 100644 (file)
--- a/environ.h
+++ b/environ.h
@@ -55,7 +55,7 @@ void      EN_log_error(char *func, char *desc, EnvironmentClass *self);
 #define    LEAVE_CONNS_CS  LeaveCriticalSection(&conns_cs)
 #define    DELETE_CONNS_CS DeleteCriticalSection(&conns_cs)
 #define INIT_ENV_CS(x)     InitializeCriticalSection(&((x)->cs))
-#define ENTER_ENV_CS(x)        EnterCriticalSection(&((x)->cs))
+#define ENTER_ENV_CS(x)    EnterCriticalSection(&((x)->cs))
 #define LEAVE_ENV_CS(x)        LeaveCriticalSection(&((x)->cs))
 #define DELETE_ENV_CS(x)   DeleteCriticalSection(&((x)->cs))
 #elif defined(POSIX_MULTITHREAD_SUPPORT)
index b2b8bb3e062528c35d05e9261d4d926a040fd33e..ea2e089d6440d09438b027adba79521cf6ac034e 100644 (file)
--- a/execute.c
+++ b/execute.c
@@ -90,14 +90,7 @@ PGAPI_Prepare(HSTMT hstmt,
            return SQL_ERROR;
    }
 
-   if (self->statement)
-       free(self->statement);
-   if (self->stmt_with_params)
-       free(self->stmt_with_params);
-   self->stmt_with_params = NULL;
-   if (self->load_statement)
-       free(self->load_statement);
-   self->load_statement = NULL;
+   SC_initialize_stmts(self, TRUE);
 
    self->statement = make_string(szSqlStr, cbSqlStr, NULL);
    if (!self->statement)
@@ -108,6 +101,7 @@ PGAPI_Prepare(HSTMT hstmt,
    }
 
    self->prepare = TRUE;
+   self->prepared = FALSE;
    self->statement_type = statement_type(self->statement);
 
    /* Check if connection is onlyread (only selects are allowed) */
@@ -141,14 +135,7 @@ PGAPI_ExecDirect(
        return SQL_INVALID_HANDLE;
    }
 
-   if (stmt->statement)
-       free(stmt->statement);
-   if (stmt->stmt_with_params)
-       free(stmt->stmt_with_params);
-   stmt->stmt_with_params = NULL;
-   if (stmt->load_statement)
-       free(stmt->load_statement);
-   stmt->load_statement = NULL;
+   SC_initialize_stmts(stmt, TRUE);
 
    /*
     * keep a copy of the un-parametrized statement, in case they try to
@@ -165,6 +152,7 @@ PGAPI_ExecDirect(
    mylog("**** %s: hstmt=%u, statement='%s'\n", func, hstmt, stmt->statement);
 
    stmt->prepare = FALSE;
+   stmt->prepared = FALSE;
 
    /*
     * If an SQLPrepare was performed prior to this, but was left in the
@@ -192,6 +180,185 @@ PGAPI_ExecDirect(
    return result;
 }
 
+/*
+ * The execution after all parameters were resolved.
+ */
+static
+RETCODE    Exec_with_parameters_resolved(StatementClass *stmt, BOOL *exec_end)
+{
+   static const char *func = "Exec_with_parameters_resolved";
+   RETCODE     retval;
+   int     end_row, cursor_type, scroll_concurrency;
+   ConnectionClass *conn;
+   QResultClass    *res;
+   APDFields   *apdopts;
+   IPDFields   *ipdopts;
+   BOOL        prepare_before_exec = FALSE;
+
+   *exec_end = FALSE;
+   conn = SC_get_conn(stmt);
+   mylog("%s: copying statement params: trans_status=%d, len=%d, stmt='%s'\n", func, conn->transact_status, strlen(stmt->statement), stmt->statement);
+
+   /* save the cursor's info before the execution */
+   cursor_type = stmt->options.cursor_type;
+   scroll_concurrency = stmt->options.scroll_concurrency;
+   /* Prepare the statement if possible at backend side */
+   if (stmt->prepare &&
+       !stmt->prepared &&
+       !stmt->inaccurate_result &&
+       conn->connInfo.use_server_side_prepare &&
+       PG_VERSION_GE(conn, 7.3))
+       prepare_before_exec = TRUE;
+   /* Create the statement with parameters substituted. */
+   retval = copy_statement_with_parameters(stmt, prepare_before_exec);
+   stmt->current_exec_param = -1;
+   if (retval != SQL_SUCCESS)
+   {
+       stmt->exec_current_row = -1;
+       *exec_end = TRUE;
+       return retval; /* error msg is passed from the above */
+   }
+
+   mylog("   stmt_with_params = '%s'\n", stmt->stmt_with_params);
+
+   /*
+    *  Dummy exection to get the column info.
+    */ 
+   if (stmt->inaccurate_result && conn->connInfo.disallow_premature)
+   {
+       BOOL        in_trans = CC_is_in_trans(conn);
+       BOOL        issued_begin = FALSE,
+                   begin_included = FALSE;
+       QResultClass *curres;
+
+       stmt->exec_current_row = -1;
+       *exec_end = TRUE;
+       if (!SC_is_pre_executable(stmt))
+           return SQL_SUCCESS;
+       if (strnicmp(stmt->stmt_with_params, "BEGIN;", 6) == 0)
+           begin_included = TRUE;
+       else if (!in_trans)
+       {
+           if (issued_begin = CC_begin(conn), !issued_begin)
+           {
+               SC_set_error(stmt, STMT_EXEC_ERROR,  "Handle prepare error");
+               return SQL_ERROR;
+           }
+       }
+       /* we are now in a transaction */
+       res = CC_send_query(conn, stmt->stmt_with_params, NULL, CLEAR_RESULT_ON_ABORT);
+       if (!res)
+       {
+           CC_abort(conn);
+           SC_set_error(stmt, STMT_EXEC_ERROR, "Handle prepare error");
+           return SQL_ERROR;
+       }
+       SC_set_Result(stmt, res);
+       for (curres = res; !curres->num_fields; curres = curres->next)
+           ;
+       SC_set_Curres(stmt, curres);
+       if (CC_is_in_autocommit(conn))
+       {
+           if (issued_begin)
+               CC_commit(conn);
+       }
+       stmt->status = STMT_FINISHED;
+       return SQL_SUCCESS;
+   }
+   /*
+    *  The real execution.
+    */
+   retval = SC_execute(stmt);
+   if (retval == SQL_ERROR)
+   {
+       stmt->exec_current_row = -1;
+       *exec_end = TRUE;
+       return retval;
+   }
+   res = SC_get_Result(stmt);
+   /* special handling of result for keyset driven cursors */
+   if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type &&
+       SQL_CONCUR_READ_ONLY != stmt->options.scroll_concurrency)
+   {
+       QResultClass    *kres;
+
+       if (kres = res->next, kres)
+       {
+           kres->fields = res->fields;
+           res->fields = NULL;
+           kres->num_fields = res->num_fields;
+           res->next = NULL;
+           QR_Destructor(res);
+           SC_set_Result(stmt, kres);
+           res = kres;
+       }
+   }
+   else if (SC_is_prepare_before_exec(stmt))
+   {
+       if (res && QR_command_maybe_successful(res))
+       {
+           QResultClass    *kres;
+       
+           kres = res->next;
+           SC_set_Result(stmt, kres);
+           res->next = NULL;
+           QR_Destructor(res);
+           res = kres;
+           stmt->prepared = TRUE;
+       }
+       else
+       {
+           retval = SQL_ERROR;
+           if (stmt->execute_statement)
+               free(stmt->execute_statement);
+           stmt->execute_statement = NULL;
+       }
+   }
+#if (ODBCVER >= 0x0300)
+   ipdopts = SC_get_IPD(stmt);
+   if (ipdopts->param_status_ptr)
+   {
+       switch (retval)
+       {
+           case SQL_SUCCESS: 
+               ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS;
+               break;
+           case SQL_SUCCESS_WITH_INFO: 
+               ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS_WITH_INFO;
+               break;
+           default: 
+               ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
+               break;
+       }
+   }
+#endif /* ODBCVER */
+   if (end_row = stmt->exec_end_row, end_row < 0)
+   {
+       apdopts = SC_get_APD(stmt);
+       end_row = apdopts->paramset_size - 1;
+   }
+   if (stmt->inaccurate_result ||
+       stmt->exec_current_row >= end_row)
+   {
+       *exec_end = TRUE;
+       stmt->exec_current_row = -1;
+   }
+   else
+       stmt->exec_current_row++;
+   if (res)
+       stmt->diag_row_count = res->recent_processed_row_count;
+   /*
+    *  The cursor's info was changed ?
+    */
+   if (retval == SQL_SUCCESS &&
+       (stmt->options.cursor_type != cursor_type ||
+        stmt->options.scroll_concurrency != scroll_concurrency))
+   {
+       SC_set_error(stmt, STMT_OPTION_VALUE_CHANGED, "cursor updatability changed");
+       retval = SQL_SUCCESS_WITH_INFO;
+   }
+   return retval;
+}
 
 /* Execute a prepared SQL statement */
 RETCODE        SQL_API
@@ -200,13 +367,12 @@ PGAPI_Execute(
 {
    static char *func = "PGAPI_Execute";
    StatementClass *stmt = (StatementClass *) hstmt;
-   APDFields   *opts;
+   APDFields   *apdopts;
    IPDFields   *ipdopts;
    ConnectionClass *conn;
    int         i,
                retval, start_row, end_row;
-   int cursor_type, scroll_concurrency;
-   QResultClass    *res;
+   BOOL    exec_end, recycled = FALSE, recycle = TRUE;
 
    mylog("%s: entering...\n", func);
 
@@ -217,9 +383,7 @@ PGAPI_Execute(
        return SQL_INVALID_HANDLE;
    }
 
-   opts = SC_get_APD(stmt);
-   cursor_type = stmt->options.cursor_type;
-   scroll_concurrency = stmt->options.scroll_concurrency;
+   apdopts = SC_get_APD(stmt);
    /*
     * If the statement is premature, it means we already executed it from
     * an SQLPrepare/SQLDescribeCol type of scenario.  So just return
@@ -270,20 +434,44 @@ PGAPI_Execute(
        return SQL_ERROR;
    }
 
+   if (stmt->exec_current_row > 0)
+   {
+       /*
+        * executing an array of parameters.
+        * Don't recycle the statement.
+        */
+       recycle = FALSE;
+   }
+   else if (stmt->prepared)
+   {
+       QResultClass    *res;
+
+       /*
+        * re-executing an prepared statement.
+        * Don't recycle the statement but
+        * discard the old result.
+        */
+       recycle = FALSE;
+       if (res = SC_get_Result(stmt), res)
+       {
+               QR_Destructor(res);
+               SC_set_Result(stmt, NULL);
+       }
+   }
    /*
     * If SQLExecute is being called again, recycle the statement. Note
     * this should have been done by the application in a call to
     * SQLFreeStmt(SQL_CLOSE) or SQLCancel.
     */
-   if (stmt->status == STMT_FINISHED)
+   else if (stmt->status == STMT_FINISHED)
    {
        mylog("%s: recycling statement (should have been done by app)...\n", func);
 /******** Is this really NEEDED ? ******/
        SC_recycle_statement(stmt);
+       recycled = TRUE;
    }
-
    /* Check if the statement is in the correct state */
-   if ((stmt->prepare && stmt->status != STMT_READY) ||
+   else if ((stmt->prepare && stmt->status != STMT_READY) ||
        (stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY))
    {
        SC_set_error(stmt, STMT_STATUS_ERROR, "The handle does not point to a statement that is ready to be executed");
@@ -295,7 +483,7 @@ PGAPI_Execute(
    if (start_row = stmt->exec_start_row, start_row < 0)
        start_row = 0; 
    if (end_row = stmt->exec_end_row, end_row < 0)
-       end_row = opts->paramset_size - 1; 
+       end_row = apdopts->paramset_size - 1; 
    if (stmt->exec_current_row < 0)
        stmt->exec_current_row = start_row;
    ipdopts = SC_get_IPD(stmt);
@@ -313,14 +501,15 @@ PGAPI_Execute(
                ipdopts->param_status_ptr[i] = SQL_PARAM_UNUSED;
        }
 #endif /* ODBCVER */
-       SC_recycle_statement(stmt);
+       if (recycle && !recycled)
+           SC_recycle_statement(stmt);
    }
 
 next_param_row:
 #if (ODBCVER >= 0x0300)
-   if (opts->param_operation_ptr)
+   if (apdopts->param_operation_ptr)
    {
-       while (opts->param_operation_ptr[stmt->exec_current_row] == SQL_PARAM_IGNORE)
+       while (apdopts->param_operation_ptr[stmt->exec_current_row] == SQL_PARAM_IGNORE)
        {
            if (stmt->exec_current_row >= end_row)
            {
@@ -347,8 +536,8 @@ next_param_row:
         * execute of this statement?  Therefore check for params and
         * re-copy.
         */
-       UInt4   offset = opts->param_offset_ptr ? *opts->param_offset_ptr : 0;
-       Int4    bind_size = opts->param_bind_type;
+       UInt4   offset = apdopts->param_offset_ptr ? *apdopts->param_offset_ptr : 0;
+       Int4    bind_size = apdopts->param_bind_type;
        Int4    current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
 
        /*
@@ -357,11 +546,11 @@ next_param_row:
        if (ipdopts->param_processed_ptr)
            (*ipdopts->param_processed_ptr)++;
        stmt->data_at_exec = -1;
-       for (i = 0; i < opts->allocated; i++)
+       for (i = 0; i < apdopts->allocated; i++)
        {
-           Int4       *pcVal = opts->parameters[i].used;
+           Int4       *pcVal = apdopts->parameters[i].used;
 
-           opts->parameters[i].data_at_exec = FALSE;
+           apdopts->parameters[i].data_at_exec = FALSE;
            if (pcVal)
            {
                if (bind_size > 0)
@@ -369,10 +558,10 @@ next_param_row:
                else
                    pcVal = (Int4 *)((char *)pcVal + offset + sizeof(SDWORD) * current_row);
                if (*pcVal == SQL_DATA_AT_EXEC || *pcVal <= SQL_LEN_DATA_AT_EXEC_OFFSET)
-                   opts->parameters[i].data_at_exec = TRUE;
+                   apdopts->parameters[i].data_at_exec = TRUE;
            }
            /* Check for data at execution parameters */
-           if (opts->parameters[i].data_at_exec)
+           if (apdopts->parameters[i].data_at_exec)
            {
                if (stmt->data_at_exec < 0)
                    stmt->data_at_exec = 1;
@@ -395,118 +584,10 @@ next_param_row:
 
    }
 
-
-   mylog("%s: copying statement params: trans_status=%d, len=%d, stmt='%s'\n", func, conn->transact_status, strlen(stmt->statement), stmt->statement);
-
-   /* Create the statement with parameters substituted. */
-   retval = copy_statement_with_parameters(stmt);
-   if (retval != SQL_SUCCESS)
-       /* error msg passed from above */
-       return retval;
-
-   mylog("   stmt_with_params = '%s'\n", stmt->stmt_with_params);
-
-   if (!stmt->inaccurate_result || !conn->connInfo.disallow_premature)
-   {
-       retval = SC_execute(stmt);
-       if (retval != SQL_ERROR)
-       {
-           /* special handling of result for keyset driven cursors */
-           if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type &&
-               SQL_CONCUR_READ_ONLY != stmt->options.scroll_concurrency)
-           {
-               QResultClass    *kres;
-
-               res = SC_get_Result(stmt);
-               if (kres = res->next, kres)
-               {
-                   kres->fields = res->fields;
-                   res->fields = NULL;
-                   kres->num_fields = res->num_fields;
-                   res->next = NULL;
-                   QR_Destructor(res);
-                   SC_set_Result(stmt, kres);
-               }
-           }
-       }
-#if (ODBCVER >= 0x0300)
-       if (ipdopts->param_status_ptr)
-       {
-           switch (retval)
-           {
-               case SQL_SUCCESS: 
-                   ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS;
-                   break;
-               case SQL_SUCCESS_WITH_INFO: 
-                   ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS_WITH_INFO;
-                   break;
-               default: 
-                   ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
-                   break;
-           }
-       }
-#endif /* ODBCVER */
-       if (retval == SQL_ERROR ||
-           stmt->inaccurate_result ||
-           stmt->exec_current_row >= end_row)
-       {
-           stmt->exec_current_row = -1;
-           return retval;
-       }
-       stmt->exec_current_row++;
+   retval = Exec_with_parameters_resolved(stmt, &exec_end);
+   if (!exec_end)
        goto next_param_row;
-   }
-   /*
-    * Get the field info for the prepared query using dummy backward
-    * fetch.
-    */
-   if (SC_is_pre_executable(stmt))
-   {
-       BOOL        in_trans = CC_is_in_trans(conn);
-       BOOL        issued_begin = FALSE,
-                   begin_included = FALSE;
-       QResultClass *curres;
-
-       if (strnicmp(stmt->stmt_with_params, "BEGIN;", 6) == 0)
-           begin_included = TRUE;
-       else if (!in_trans)
-       {
-           if (issued_begin = CC_begin(conn), !issued_begin)
-           {
-               SC_set_error(stmt, STMT_EXEC_ERROR,  "Handle prepare error");
-               return SQL_ERROR;
-           }
-       }
-       /* we are now in a transaction */
-       res = CC_send_query(conn, stmt->stmt_with_params, NULL, CLEAR_RESULT_ON_ABORT);
-       if (!res)
-       {
-           CC_abort(conn);
-           SC_set_error(stmt, STMT_EXEC_ERROR, "Handle prepare error");
-           return SQL_ERROR;
-       }
-       SC_set_Result(stmt, res);
-       for (curres = res; !curres->num_fields; curres = curres->next)
-           ;
-       SC_set_Curres(stmt, curres);
-       if (CC_is_in_autocommit(conn))
-       {
-           if (issued_begin)
-               CC_commit(conn);
-       }
-       stmt->status = STMT_FINISHED;
-       return SQL_SUCCESS;
-   }
-   if (res = SC_get_Curres(stmt), res)
-       stmt->diag_row_count = res->recent_processed_row_count;
-   if (stmt->options.cursor_type != cursor_type ||
-       stmt->options.scroll_concurrency != scroll_concurrency)
-   {
-       SC_set_error(stmt, STMT_OPTION_VALUE_CHANGED, "cursor updatability changed");
-       return SQL_SUCCESS_WITH_INFO;
-   }
-   else 
-       return SQL_SUCCESS;
+   return retval;
 }
 
 
@@ -736,7 +817,7 @@ PGAPI_ParamData(
 {
    static char *func = "PGAPI_ParamData";
    StatementClass *stmt = (StatementClass *) hstmt;
-   APDFields   *opts;
+   APDFields   *apdopts;
    IPDFields   *ipdopts;
    int         i,
                retval;
@@ -750,9 +831,9 @@ PGAPI_ParamData(
        return SQL_INVALID_HANDLE;
    }
    ci = &(SC_get_conn(stmt)->connInfo);
-   opts = SC_get_APD(stmt);
+   apdopts = SC_get_APD(stmt);
 
-   mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, stmt->data_at_exec, opts->allocated);
+   mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, stmt->data_at_exec, apdopts->allocated);
 
    if (stmt->data_at_exec < 0)
    {
@@ -761,7 +842,7 @@ PGAPI_ParamData(
        return SQL_ERROR;
    }
 
-   if (stmt->data_at_exec > opts->allocated)
+   if (stmt->data_at_exec > apdopts->allocated)
    {
        SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Too many execution-time parameters were present");
        SC_log_error(func, "", stmt);
@@ -790,42 +871,11 @@ PGAPI_ParamData(
    ipdopts = SC_get_IPD(stmt);
    if (stmt->data_at_exec == 0)
    {
-       int end_row;
+       BOOL    exec_end;
 
-       retval = copy_statement_with_parameters(stmt);
-       if (retval != SQL_SUCCESS)
+       retval = Exec_with_parameters_resolved(stmt, &exec_end);
+       if (exec_end)
            return retval;
-
-       stmt->current_exec_param = -1;
-
-       retval = SC_execute(stmt);
-#if (ODBCVER >= 0x0300)
-       if (ipdopts->param_status_ptr)
-       {
-           switch (retval)
-           {
-               case SQL_SUCCESS: 
-                   ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS;
-                   break;
-               case SQL_SUCCESS_WITH_INFO: 
-                   ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS_WITH_INFO;
-                   break;
-               default: 
-                   ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
-                   break;
-           }
-       }
-#endif /* ODBCVER */
-       end_row = stmt->exec_end_row;
-       if (end_row < 0)
-           end_row = opts->paramset_size - 1;
-       if (retval == SQL_ERROR ||
-           stmt->exec_current_row >= end_row)
-       {
-           stmt->exec_current_row = -1;
-           return retval;
-       }
-       stmt->exec_current_row++;
        return PGAPI_Execute(stmt);
    }
 
@@ -836,14 +886,14 @@ PGAPI_ParamData(
    i = stmt->current_exec_param >= 0 ? stmt->current_exec_param + 1 : 0;
 
    /* At least 1 data at execution parameter, so Fill in the token value */
-   for (; i < opts->allocated; i++)
+   for (; i < apdopts->allocated; i++)
    {
-       if (opts->parameters[i].data_at_exec)
+       if (apdopts->parameters[i].data_at_exec)
        {
            stmt->data_at_exec--;
            stmt->current_exec_param = i;
            stmt->put_data = FALSE;
-           *prgbValue = opts->parameters[i].buffer;    /* token */
+           *prgbValue = apdopts->parameters[i].buffer; /* token */
            break;
        }
    }
@@ -864,10 +914,13 @@ PGAPI_PutData(
 {
    static char *func = "PGAPI_PutData";
    StatementClass *stmt = (StatementClass *) hstmt;
-   APDFields   *opts;
+   ConnectionClass *conn;
+   APDFields   *apdopts;
+   IPDFields   *ipdopts;
    int         old_pos,
                retval;
    ParameterInfoClass *current_param;
+   ParameterImplClass *current_iparam;
    char       *buffer;
 
    mylog("%s: entering...\n", func);
@@ -878,7 +931,7 @@ PGAPI_PutData(
        return SQL_INVALID_HANDLE;
    }
 
-   opts = SC_get_APD(stmt);
+   apdopts = SC_get_APD(stmt);
    if (stmt->current_exec_param < 0)
    {
        SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Previous call was not SQLPutData or SQLParamData");
@@ -886,8 +939,11 @@ PGAPI_PutData(
        return SQL_ERROR;
    }
 
-   current_param = &(opts->parameters[stmt->current_exec_param]);
+   current_param = &(apdopts->parameters[stmt->current_exec_param]);
+   ipdopts = SC_get_IPD(stmt);
+   current_iparam = &(ipdopts->parameters[stmt->current_exec_param]);
 
+   conn = SC_get_conn(stmt);
    if (!stmt->put_data)
    {                           /* first call */
        mylog("PGAPI_PutData: (1) cbValue = %d\n", cbValue);
@@ -908,7 +964,8 @@ PGAPI_PutData(
            return SQL_SUCCESS;
 
        /* Handle Long Var Binary with Large Objects */
-       if (current_param->SQLType == SQL_LONGVARBINARY)
+       /* if (current_iparam->SQLType == SQL_LONGVARBINARY) */
+       if (current_iparam->PGType == conn->lobj_type)
        {
            /* begin transaction if needed */
            if (!CC_is_in_trans(stmt->hdbc))
@@ -934,7 +991,7 @@ PGAPI_PutData(
             * major hack -- to allow convert to see somethings there have
             * to modify convert to handle this better
             */
-           current_param->EXEC_buffer = (char *) &current_param->lobj_oid;
+           /***current_param->EXEC_buffer = (char *) &current_param->lobj_oid;***/
 
            /* store the fd */
            stmt->lobj_fd = lo_open(stmt->hdbc, current_param->lobj_oid, INV_WRITE);
@@ -952,7 +1009,7 @@ PGAPI_PutData(
        {
            Int2        ctype = current_param->CType;
            if (ctype == SQL_C_DEFAULT)
-               ctype = sqltype_to_default_ctype(current_param->SQLType);
+               ctype = sqltype_to_default_ctype(current_iparam->SQLType);
 
 #ifdef UNICODE_SUPPORT
            if (SQL_NTS == cbValue && SQL_C_WCHAR == ctype)
@@ -1008,7 +1065,8 @@ PGAPI_PutData(
        /* calling SQLPutData more than once */
        mylog("PGAPI_PutData: (>1) cbValue = %d\n", cbValue);
 
-       if (current_param->SQLType == SQL_LONGVARBINARY)
+       /* if (current_iparam->SQLType == SQL_LONGVARBINARY) */
+       if (current_iparam->PGType == conn->lobj_type)
        {
            /* the large object fd is in EXEC_buffer */
            retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
@@ -1021,7 +1079,7 @@ PGAPI_PutData(
            Int2    ctype = current_param->CType;
 
            if (ctype == SQL_C_DEFAULT)
-               ctype = sqltype_to_default_ctype(current_param->SQLType);
+               ctype = sqltype_to_default_ctype(current_iparam->SQLType);
            buffer = current_param->EXEC_buffer;
            if (old_pos = *current_param->EXEC_used, SQL_NTS == old_pos)
            {
diff --git a/info.c b/info.c
index ea0d483634579e8858194be7f604f902ac868959..ef40cc716be4eabfea2bc25eba6527e54b02ae1d 100644 (file)
--- a/info.c
+++ b/info.c
@@ -1637,7 +1637,8 @@ PGAPI_Columns(
                ordinal;
    char        useStaticPrecision;
    char        not_null[MAX_INFO_STRING],
-               relhasrules[MAX_INFO_STRING];
+               relhasrules[MAX_INFO_STRING], relkind[8];
+   BOOL        relisaview;
    ConnInfo   *ci;
    ConnectionClass *conn;
 
@@ -1662,14 +1663,15 @@ PGAPI_Columns(
     */
    if (conn->schema_support)
        sprintf(columns_query, "select u.nspname, c.relname, a.attname, a.atttypid"
-      ", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules"
+      ", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules, c.relkind"
            " from pg_namespace u, pg_class c, pg_attribute a, pg_type t"
            " where u.oid = c.relnamespace"
-     " and c.oid= a.attrelid and a.atttypid = t.oid and (a.attnum > 0) and not(attisdropped)",
+           " and (not a.attisdropped)"
+     " and c.oid= a.attrelid and a.atttypid = t.oid and (a.attnum > 0)",
            "a.atttypmod");
    else
        sprintf(columns_query, "select u.usename, c.relname, a.attname, a.atttypid"
-      ", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules"
+      ", t.typname, a.attnum, a.attlen, %s, a.attnotnull, c.relhasrules, c.relkind"
            " from pg_user u, pg_class c, pg_attribute a, pg_type t"
            " where u.usesysid = c.relowner"
      " and c.oid= a.attrelid and a.atttypid = t.oid and (a.attnum > 0)",
@@ -1828,6 +1830,16 @@ PGAPI_Columns(
        return SQL_ERROR;
    }
 
+   result = PGAPI_BindCol(hcol_stmt, 11, SQL_C_CHAR,
+                          relkind, sizeof(relkind), NULL);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+   {
+       SC_error_copy(stmt, col_stmt);
+       SC_log_error(func, "", stmt);
+       PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
+       return SQL_ERROR;
+   }
+
    if (res = QR_Constructor(), !res)
    {
        SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Couldn't allocate memory for PGAPI_Columns result.");
@@ -1887,9 +1899,13 @@ PGAPI_Columns(
     * table
     */
 
+   if (PG_VERSION_GE(conn, 7.1))
+       relisaview = (relkind[0] == 'v');
+   else
+       relisaview = (relhasrules[0] == '1');
    if (result != SQL_ERROR && !stmt->internal)
    {
-       if (relhasrules[0] != '1' &&
+       if (!relisaview &&
            (atoi(ci->show_oid_column) ||
             strncmp(table_name, POSTGRES_SYS_PREFIX, strlen(POSTGRES_SYS_PREFIX)) == 0))
        {
@@ -2059,7 +2075,7 @@ PGAPI_Columns(
     * Put the row version column at the end so it might not be mistaken
     * for a key field.
     */
-   if (relhasrules[0] != '1' && !stmt->internal && atoi(ci->row_versioning))
+   if (!relisaview && !stmt->internal && atoi(ci->row_versioning))
    {
        /* For Row Versioning fields */
        the_type = PG_TYPE_INT4;
@@ -2138,7 +2154,8 @@ PGAPI_SpecialColumns(
    StatementClass *col_stmt;
    char        columns_query[INFO_INQUIRY_LEN];
    RETCODE     result;
-   char        relhasrules[MAX_INFO_STRING];
+   char        relhasrules[MAX_INFO_STRING], relkind[8];
+   BOOL        relisaview;
 
    mylog("%s: entering...stmt=%u scnm=%x len=%d colType=%d\n", func, stmt, szTableOwner, cbTableOwner, fColType);
 
@@ -2156,11 +2173,11 @@ PGAPI_SpecialColumns(
     * Create the query to find out if this is a view or not...
     */
    if (conn->schema_support)
-       sprintf(columns_query, "select c.relhasrules "
+       sprintf(columns_query, "select c.relhasrules, c.relkind "
            "from pg_namespace u, pg_class c where "
            "u.oid = c.relnamespace");
    else
-       sprintf(columns_query, "select c.relhasrules "
+       sprintf(columns_query, "select c.relhasrules, c.relkind "
            "from pg_user u, pg_class c where "
            "u.usesysid = c.relowner");
 
@@ -2204,7 +2221,21 @@ PGAPI_SpecialColumns(
        return SQL_ERROR;
    }
 
+   result = PGAPI_BindCol(hcol_stmt, 2, SQL_C_CHAR,
+                   relkind, sizeof(relkind), NULL);
+   if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO))
+   {
+       SC_error_copy(stmt, col_stmt);
+       SC_log_error(func, "", stmt);
+       PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
+       return SQL_ERROR;
+   }
+
    result = PGAPI_Fetch(hcol_stmt);
+   if (PG_VERSION_GE(conn, 7.1))
+       relisaview = (relkind[0] == 'v');
+   else
+       relisaview = (relhasrules[0] == '1');
    PGAPI_FreeStmt(hcol_stmt, SQL_DROP);
 
    res = QR_Constructor();
@@ -2221,7 +2252,7 @@ PGAPI_SpecialColumns(
    QR_set_field_info(res, 6, "SCALE", PG_TYPE_INT2, 2);
    QR_set_field_info(res, 7, "PSEUDO_COLUMN", PG_TYPE_INT2, 2);
 
-   if (relhasrules[0] != '1')
+   if (!relisaview)
    {
        /* use the oid value for the rowid */
        if (fColType == SQL_BEST_ROWID)
@@ -2345,7 +2376,7 @@ PGAPI_Statistics(
               *indx_stmt;
    char        column_name[MAX_INFO_STRING],
            table_qualifier[MAX_INFO_STRING],
-               relhasrules[10];
+               relhasrules[10], relkind[8];
    char      **column_names = 0;
    SQLINTEGER  column_name_len;
    int         total_columns = 0;
@@ -2599,6 +2630,8 @@ PGAPI_Statistics(
        goto SEEYA;
    }
 
+   relhasrules[0] = '0';
+   result = PGAPI_Fetch(hindx_stmt);
    /* fake index of OID */
    if (relhasrules[0] != '1' && atoi(ci->show_oid_column) && atoi(ci->fake_oid_index))
    {
@@ -2635,7 +2668,6 @@ PGAPI_Statistics(
        QR_add_tuple(res, row);
    }
 
-   result = PGAPI_Fetch(hindx_stmt);
    while ((result == SQL_SUCCESS) || (result == SQL_SUCCESS_WITH_INFO))
    {
        /* If only requesting unique indexs, then just return those. */
@@ -2898,8 +2930,8 @@ PGAPI_PrimaryKeys(
                        " AND ia.attrelid = i.indexrelid"
                        " AND ta.attrelid = i.indrelid"
                        " AND ta.attnum = i.indkey[ia.attnum-1]"
-                                                " AND NOT(ta.attisdropped)"
-                                                " AND NOT(ia.attisdropped)"
+                       " AND (NOT ta.attisdropped)"
+                       " AND (NOT ia.attisdropped)"
                        " order by ia.attnum", pktab, pkscm);
                else
                    sprintf(tables_query, "select ta.attname, ia.attnum"
@@ -2927,8 +2959,8 @@ PGAPI_PrimaryKeys(
                        " AND ia.attrelid = i.indexrelid"
                        " AND ta.attrelid = i.indrelid"
                        " AND ta.attnum = i.indkey[ia.attnum-1]"
-                                                " AND NOT(ta.attisdropped)"
-                                                " AND NOT(ia.attisdropped)"
+                       " AND (NOT ta.attisdropped)"
+                       " AND (NOT ia.attisdropped)"
                        " order by ia.attnum", pktab, pkscm);
                else
                    sprintf(tables_query, "select ta.attname, ia.attnum"
@@ -3123,7 +3155,8 @@ getClientColumnName(ConnectionClass *conn, const char * serverSchemaName, const
        if (conn->schema_support)
            sprintf(query, "select attrelid, attnum from pg_class, pg_attribute "
                "where relname = '%s' and attrelid = pg_class.oid "
-               "and attname = '%s' and pg_namespace.oid = relnamespace and pg_namespace.nspname = '%s' and not(attisdropped)", serverTableName, serverColumnName, serverSchemaName);
+               "and (not attisdropped) "
+               "and attname = '%s' and pg_namespace.oid = relnamespace and pg_namespace.nspname = '%s'", serverTableName, serverColumnName, serverSchemaName);
        else
            sprintf(query, "select attrelid, attnum from pg_class, pg_attribute "
                "where relname = '%s' and attrelid = pg_class.oid "
index 90072239435d06cc92eb3a72df8f95622ba7e60f..111da5dc7d6909a80125cfcefcb9c4de55af1a7a 100644 (file)
--- a/info30.c
+++ b/info30.c
@@ -181,11 +181,16 @@ PGAPI_GetInfo30(HDBC hdbc, UWORD fInfoType, PTR rgbInfoValue,
            break;
        case SQL_CREATE_TABLE:
            len = 4;
-           value = SQL_CT_CREATE_TABLE | SQL_CT_TABLE_CONSTRAINT
-               | SQL_CT_CONSTRAINT_NAME_DEFINITION 
-               | SQL_CT_LOCAL_TEMPORARY | SQL_CT_COLUMN_CONSTRAINT
-               | SQL_CT_COLUMN_DEFAULT | SQL_CT_CONSTRAINT_INITIALLY_DEFERRED
-               | SQL_CT_CONSTRAINT_INITIALLY_IMMEDIATE | SQL_CT_CONSTRAINT_DEFERRABLE;
+           value = SQL_CT_CREATE_TABLE | SQL_CT_COLUMN_CONSTRAINT
+               | SQL_CT_COLUMN_DEFAULT;
+           if (PG_VERSION_GE(conn, 6.5)) 
+               value |= SQL_CT_GLOBAL_TEMPORARY; 
+           if (PG_VERSION_GE(conn, 7.0)) 
+               value |= SQL_CT_TABLE_CONSTRAINT
+                   | SQL_CT_CONSTRAINT_NAME_DEFINITION 
+                   | SQL_CT_CONSTRAINT_INITIALLY_DEFERRED
+                   | SQL_CT_CONSTRAINT_INITIALLY_IMMEDIATE
+                   | SQL_CT_CONSTRAINT_DEFERRABLE;
            break;
        case SQL_CREATE_TRANSLATION:
            len = 4;
index a61163d1747f928d390e76a12b072b79553e8ee0..d880b993cd63a8bf1d75b8631944b81b6d61852a 100644 (file)
@@ -386,12 +386,12 @@ CC_lookup_characterset(ConnectionClass *self)
                wenc = "SJIS";
                break;
            case 936:
-               if (!encstr || PG_VERSION_LE(self, 7.2))
+               if (!encstr || PG_VERSION_GT(self, 7.2))
                    wenc = "GBK";
                break;
            case 949:
-               if (!encstr || PG_VERSION_LE(self, 7.2) ||
-                   stricmp(encstr, "EUC_KR"))  
+               if (!encstr ||
+                 (PG_VERSION_GT(self, 7.2) && stricmp(encstr, "EUC_KR")))  
                    wenc = "UHC";
                break;
            case 950:
index b1f64ce2eb8dad4b2dc00bff72dba6c71833fb5a..a0c746a9575cf1b6445eda32c796c3b3ca73bdcf 100644 (file)
--- a/odbcapi.c
+++ b/odbcapi.c
@@ -40,11 +40,12 @@ SQLAllocConnect(HENV EnvironmentHandle,
                HDBC FAR * ConnectionHandle)
 {
    RETCODE ret;
+   EnvironmentClass *env = (EnvironmentClass *) EnvironmentHandle;
 
    mylog("[SQLAllocConnect]");
-   ENTER_ENV_CS((EnvironmentClass *) EnvironmentHandle);
+   ENTER_ENV_CS(env);
    ret = PGAPI_AllocConnect(EnvironmentHandle, ConnectionHandle);
-   LEAVE_ENV_CS((EnvironmentClass *) EnvironmentHandle);
+   LEAVE_ENV_CS(env);
    return ret;
 }
 
@@ -63,12 +64,13 @@ SQLAllocStmt(HDBC ConnectionHandle,
             HSTMT *StatementHandle)
 {
    RETCODE ret;
+   ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
 
    mylog("[SQLAllocStmt]");
-   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
-   CC_clear_error((ConnectionClass *) ConnectionHandle);
+   ENTER_CONN_CS(conn);
+   CC_clear_error(conn);
    ret = PGAPI_AllocStmt(ConnectionHandle, StatementHandle);
-   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   LEAVE_CONN_CS(conn);
    return ret;
 }
 
@@ -79,13 +81,14 @@ SQLBindCol(HSTMT StatementHandle,
           SQLINTEGER *StrLen_or_Ind)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLBindCol]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_BindCol(StatementHandle, ColumnNumber,
                   TargetType, TargetValue, BufferLength, StrLen_or_Ind);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -105,14 +108,15 @@ SQLColumns(HSTMT StatementHandle,
           SQLCHAR *ColumnName, SQLSMALLINT NameLength4)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLColumns]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_Columns(StatementHandle, CatalogName, NameLength1,
                    SchemaName, NameLength2, TableName, NameLength3,
                    ColumnName, NameLength4, 0);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -124,13 +128,14 @@ SQLConnect(HDBC ConnectionHandle,
           SQLCHAR *Authentication, SQLSMALLINT NameLength3)
 {
    RETCODE ret;
+   ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
 
    mylog("[SQLConnect]");
-   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
-   CC_clear_error((ConnectionClass *) ConnectionHandle);
+   ENTER_CONN_CS(conn);
+   CC_clear_error(conn);
    ret = PGAPI_Connect(ConnectionHandle, ServerName, NameLength1,
                     UserName, NameLength2, Authentication, NameLength3);
-   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   LEAVE_CONN_CS(conn);
    return ret;
 }
 
@@ -145,13 +150,14 @@ SQLDriverConnect(HDBC hdbc,
                 UWORD fDriverCompletion)
 {
    RETCODE ret;
+   ConnectionClass *conn = (ConnectionClass *) hdbc;
 
    mylog("[SQLDriverConnect]");
-   ENTER_CONN_CS((ConnectionClass *) hdbc);
-   CC_clear_error((ConnectionClass *) hdbc);
+   ENTER_CONN_CS(conn);
+   CC_clear_error(conn);
    ret = PGAPI_DriverConnect(hdbc, hwnd, szConnStrIn, cbConnStrIn,
        szConnStrOut, cbConnStrOutMax, pcbConnStrOut, fDriverCompletion);
-   LEAVE_CONN_CS((ConnectionClass *) hdbc);
+   LEAVE_CONN_CS(conn);
    return ret;
 }
 RETCODE        SQL_API
@@ -164,13 +170,14 @@ SQLBrowseConnect(
                 SQLSMALLINT *pcbConnStrOut)
 {
    RETCODE ret;
+   ConnectionClass *conn = (ConnectionClass *) hdbc;
 
    mylog("[SQLBrowseConnect]");
-   ENTER_CONN_CS((ConnectionClass *) hdbc);
-   CC_clear_error((ConnectionClass *) hdbc);
+   ENTER_CONN_CS(conn);
+   CC_clear_error(conn);
    ret = PGAPI_BrowseConnect(hdbc, szConnStrIn, cbConnStrIn,
                           szConnStrOut, cbConnStrOutMax, pcbConnStrOut);
-   LEAVE_CONN_CS((ConnectionClass *) hdbc);
+   LEAVE_CONN_CS(conn);
    return ret;
 }
 
@@ -199,14 +206,15 @@ SQLDescribeCol(HSTMT StatementHandle,
               SQLSMALLINT *DecimalDigits, SQLSMALLINT *Nullable)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLDescribeCol]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_DescribeCol(StatementHandle, ColumnNumber,
                             ColumnName, BufferLength, NameLength,
                          DataType, ColumnSize, DecimalDigits, Nullable);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -214,12 +222,13 @@ RETCODE       SQL_API
 SQLDisconnect(HDBC ConnectionHandle)
 {
    RETCODE ret;
+   ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
 
    mylog("[SQLDisconnect]");
-   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
-   CC_clear_error((ConnectionClass *) ConnectionHandle);
+   ENTER_CONN_CS(conn);
+   CC_clear_error(conn);
    ret = PGAPI_Disconnect(ConnectionHandle);
-   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   LEAVE_CONN_CS(conn);
    return ret;
 }
 
@@ -248,12 +257,13 @@ SQLExecDirect(HSTMT StatementHandle,
              SQLCHAR *StatementText, SQLINTEGER TextLength)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLExecDirect]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_ExecDirect(StatementHandle, StatementText, TextLength);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -261,12 +271,13 @@ RETCODE       SQL_API
 SQLExecute(HSTMT StatementHandle)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLExecute]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_Execute(StatementHandle);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -336,12 +347,13 @@ SQLGetConnectOption(HDBC ConnectionHandle,
                    SQLUSMALLINT Option, PTR Value)
 {
    RETCODE ret;
+   ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
 
    mylog("[SQLGetConnectOption]");
-   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
-   CC_clear_error((ConnectionClass *) ConnectionHandle);
+   ENTER_CONN_CS(conn);
+   CC_clear_error(conn);
    ret = PGAPI_GetConnectOption(ConnectionHandle, Option, Value);
-   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   LEAVE_CONN_CS(conn);
    return ret;
 }
 RETCODE        SQL_API
@@ -350,13 +362,14 @@ SQLGetCursorName(HSTMT StatementHandle,
                 SQLSMALLINT *NameLength)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLGetCursorName]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_GetCursorName(StatementHandle, CursorName, BufferLength,
                               NameLength);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -367,13 +380,14 @@ SQLGetData(HSTMT StatementHandle,
           SQLINTEGER *StrLen_or_Ind)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLGetData]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_GetData(StatementHandle, ColumnNumber, TargetType,
                         TargetValue, BufferLength, StrLen_or_Ind);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -382,10 +396,11 @@ SQLGetFunctions(HDBC ConnectionHandle,
                SQLUSMALLINT FunctionId, SQLUSMALLINT *Supported)
 {
    RETCODE ret;
+   ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
 
    mylog("[SQLGetFunctions]");
-   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
-   CC_clear_error((ConnectionClass *) ConnectionHandle);
+   ENTER_CONN_CS(conn);
+   CC_clear_error(conn);
 #if (ODBCVER >= 0x0300)
    if (FunctionId == SQL_API_ODBC3_ALL_FUNCTIONS)
        ret = PGAPI_GetFunctions30(ConnectionHandle, FunctionId, Supported);
@@ -394,7 +409,7 @@ SQLGetFunctions(HDBC ConnectionHandle,
    {
        ret = PGAPI_GetFunctions(ConnectionHandle, FunctionId, Supported);
    }
-   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   LEAVE_CONN_CS(conn);
    return ret;
 }
 RETCODE        SQL_API
@@ -405,7 +420,7 @@ SQLGetInfo(HDBC ConnectionHandle,
    RETCODE     ret;
    ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
 
-   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
+   ENTER_CONN_CS(conn);
    CC_clear_error(conn);
 #if (ODBCVER >= 0x0300)
    mylog("[SQLGetInfo(30)]");
@@ -427,7 +442,7 @@ SQLGetInfo(HDBC ConnectionHandle,
            BufferLength, StringLength), SQL_ERROR == ret)
        CC_log_error("PGAPI_GetInfo", "", conn);
 #endif
-   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   LEAVE_CONN_CS(conn);
    return ret;
 }
 
@@ -436,12 +451,13 @@ SQLGetStmtOption(HSTMT StatementHandle,
                 SQLUSMALLINT Option, PTR Value)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLGetStmtOption]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_GetStmtOption(StatementHandle, Option, Value);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -450,12 +466,13 @@ SQLGetTypeInfo(HSTMT StatementHandle,
               SQLSMALLINT DataType)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLGetTypeInfo]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_GetTypeInfo(StatementHandle, DataType);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -464,12 +481,13 @@ SQLNumResultCols(HSTMT StatementHandle,
                 SQLSMALLINT *ColumnCount)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLNumResultCols]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_NumResultCols(StatementHandle, ColumnCount);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -478,12 +496,13 @@ SQLParamData(HSTMT StatementHandle,
             PTR *Value)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLParamData]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_ParamData(StatementHandle, Value);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -492,12 +511,13 @@ SQLPrepare(HSTMT StatementHandle,
           SQLCHAR *StatementText, SQLINTEGER TextLength)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLPrepare]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_Prepare(StatementHandle, StatementText, TextLength);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -506,12 +526,13 @@ SQLPutData(HSTMT StatementHandle,
           PTR Data, SQLINTEGER StrLen_or_Ind)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLPutData]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_PutData(StatementHandle, Data, StrLen_or_Ind);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -520,12 +541,13 @@ SQLRowCount(HSTMT StatementHandle,
            SQLINTEGER *RowCount)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLRowCount]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_RowCount(StatementHandle, RowCount);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -534,12 +556,13 @@ SQLSetConnectOption(HDBC ConnectionHandle,
                    SQLUSMALLINT Option, SQLUINTEGER Value)
 {
    RETCODE ret;
+   ConnectionClass *conn = (ConnectionClass *) ConnectionHandle;
 
    mylog("[SQLSetConnectionOption]");
-   ENTER_CONN_CS((ConnectionClass *) ConnectionHandle);
-   CC_clear_error((ConnectionClass *) ConnectionHandle);
+   ENTER_CONN_CS(conn);
+   CC_clear_error(conn);
    ret = PGAPI_SetConnectOption(ConnectionHandle, Option, Value);
-   LEAVE_CONN_CS((ConnectionClass *) ConnectionHandle);
+   LEAVE_CONN_CS(conn);
    return ret;
 }
 
@@ -548,12 +571,13 @@ SQLSetCursorName(HSTMT StatementHandle,
                 SQLCHAR *CursorName, SQLSMALLINT NameLength)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLSetCursorName]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_SetCursorName(StatementHandle, CursorName, NameLength);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -580,12 +604,13 @@ SQLSetStmtOption(HSTMT StatementHandle,
                 SQLUSMALLINT Option, SQLUINTEGER Value)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLSetStmtOption]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_SetStmtOption(StatementHandle, Option, Value);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -598,14 +623,15 @@ SQLSpecialColumns(HSTMT StatementHandle,
                  SQLUSMALLINT Nullable)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLSpecialColumns]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_SpecialColumns(StatementHandle, IdentifierType, CatalogName,
            NameLength1, SchemaName, NameLength2, TableName, NameLength3,
                                Scope, Nullable);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -617,14 +643,15 @@ SQLStatistics(HSTMT StatementHandle,
              SQLUSMALLINT Unique, SQLUSMALLINT Reserved)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLStatistics]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_Statistics(StatementHandle, CatalogName, NameLength1,
                 SchemaName, NameLength2, TableName, NameLength3, Unique,
                            Reserved);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -636,14 +663,15 @@ SQLTables(HSTMT StatementHandle,
          SQLCHAR *TableType, SQLSMALLINT NameLength4)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) StatementHandle;
 
    mylog("[SQLTables]");
-   ENTER_STMT_CS((StatementClass *) StatementHandle);
-   SC_clear_error((StatementClass *) StatementHandle);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_Tables(StatementHandle, CatalogName, NameLength1,
                        SchemaName, NameLength2, TableName, NameLength3,
                        TableType, NameLength4);
-   LEAVE_STMT_CS((StatementClass *) StatementHandle);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -677,13 +705,14 @@ SQLColAttributes(
                 SQLINTEGER *pfDesc)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLColAttributes]");
-   ENTER_STMT_CS((StatementClass *) hstmt);
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_ColAttributes(hstmt, icol, fDescType, rgbDesc,
                               cbDescMax, pcbDesc, pfDesc);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -700,14 +729,15 @@ SQLColumnPrivileges(
                    SQLSMALLINT cbColumnName)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLColumnPrivileges]");
-   ENTER_STMT_CS((StatementClass *) hstmt);
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_ColumnPrivileges(hstmt, szCatalogName, cbCatalogName,
                    szSchemaName, cbSchemaName, szTableName, cbTableName,
                                  szColumnName, cbColumnName);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -721,13 +751,14 @@ SQLDescribeParam(
                 SQLSMALLINT *pfNullable)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLDescribeParam]");
-   ENTER_STMT_CS((StatementClass *) hstmt);
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_DescribeParam(hstmt, ipar, pfSqlType, pcbParamDef,
                               pibScale, pfNullable);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -740,12 +771,13 @@ SQLExtendedFetch(
                 SQLUSMALLINT *rgfRowStatus)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLExtendedFetch]");
-   ENTER_STMT_CS((StatementClass *) hstmt);
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_ExtendedFetch(hstmt, fFetchType, irow, pcrow, rgfRowStatus, 0);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -766,14 +798,16 @@ SQLForeignKeys(
               SQLSMALLINT cbFkTableName)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLForeignKeys]");
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_ForeignKeys(hstmt, szPkCatalogName, cbPkCatalogName,
                           szPkSchemaName, cbPkSchemaName, szPkTableName,
                         cbPkTableName, szFkCatalogName, cbFkCatalogName,
           szFkSchemaName, cbFkSchemaName, szFkTableName, cbFkTableName);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -781,12 +815,13 @@ RETCODE       SQL_API
 SQLMoreResults(HSTMT hstmt)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLMoreResults]");
-   ENTER_STMT_CS((StatementClass *) hstmt);
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_MoreResults(hstmt);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -800,13 +835,14 @@ SQLNativeSql(
             SQLINTEGER *pcbSqlStr)
 {
    RETCODE ret;
+   ConnectionClass *conn = (ConnectionClass *) hdbc;
 
    mylog("[SQLNativeSql]");
-   ENTER_CONN_CS((ConnectionClass *) hdbc);
-   CC_clear_error((ConnectionClass *) hdbc);
+   ENTER_CONN_CS(conn);
+   CC_clear_error(conn);
    ret = PGAPI_NativeSql(hdbc, szSqlStrIn, cbSqlStrIn, szSqlStr,
                           cbSqlStrMax, pcbSqlStr);
-   LEAVE_CONN_CS((ConnectionClass *) hdbc);
+   LEAVE_CONN_CS(conn);
    return ret;
 }
 
@@ -816,12 +852,13 @@ SQLNumParams(
             SQLSMALLINT *pcpar)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLNumParams]");
-   ENTER_STMT_CS((StatementClass *) hstmt);
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_NumParams(hstmt, pcpar);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -832,12 +869,13 @@ SQLParamOptions(
                SQLUINTEGER *pirow)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLParamOptions]");
-   ENTER_STMT_CS((StatementClass *) hstmt);
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_ParamOptions(hstmt, crow, pirow);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -852,13 +890,14 @@ SQLPrimaryKeys(
               SQLSMALLINT cbTableName)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLPrimaryKeys]");
-   ENTER_STMT_CS((StatementClass *) hstmt);
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_PrimaryKeys(hstmt, szCatalogName, cbCatalogName,
                   szSchemaName, cbSchemaName, szTableName, cbTableName);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -875,14 +914,15 @@ SQLProcedureColumns(
                    SQLSMALLINT cbColumnName)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLProcedureColumns]");
-   ENTER_STMT_CS((StatementClass *) hstmt);
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_ProcedureColumns(hstmt, szCatalogName, cbCatalogName,
                      szSchemaName, cbSchemaName, szProcName, cbProcName,
                                  szColumnName, cbColumnName);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -897,13 +937,14 @@ SQLProcedures(
              SQLSMALLINT cbProcName)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLProcedures]");
-   ENTER_STMT_CS((StatementClass *) hstmt);
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_Procedures(hstmt, szCatalogName, cbCatalogName,
                     szSchemaName, cbSchemaName, szProcName, cbProcName);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -915,12 +956,13 @@ SQLSetPos(
          SQLUSMALLINT fLock)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLSetPos]");
-   ENTER_STMT_CS((StatementClass *) hstmt);
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_SetPos(hstmt, irow, fOption, fLock);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -935,13 +977,14 @@ SQLTablePrivileges(
                   SQLSMALLINT cbTableName)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLTablePrivileges]");
-   ENTER_STMT_CS((StatementClass *) hstmt);
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_TablePrivileges(hstmt, szCatalogName, cbCatalogName,
                   szSchemaName, cbSchemaName, szTableName, cbTableName, 0);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
 
@@ -959,13 +1002,14 @@ SQLBindParameter(
                 SQLINTEGER *pcbValue)
 {
    RETCODE ret;
+   StatementClass *stmt = (StatementClass *) hstmt;
 
    mylog("[SQLBindParameter]");
-   ENTER_STMT_CS((StatementClass *) hstmt);
-   SC_clear_error((StatementClass *) hstmt);
+   ENTER_STMT_CS(stmt);
+   SC_clear_error(stmt);
    ret = PGAPI_BindParameter(hstmt, ipar, fParamType, fCType,
                       fSqlType, cbColDef, ibScale, rgbValue, cbValueMax,
                               pcbValue);
-   LEAVE_STMT_CS((StatementClass *) hstmt);
+   LEAVE_STMT_CS(stmt);
    return ret;
 }
index 48cbcf08200bd2b2bd92f0165b167d093136254b..acc9e1ec8b0a9347ac9fe18cb601f47d611ba892 100644 (file)
@@ -661,6 +661,7 @@ RETCODE SQL_API SQLGetTypeInfoW(
 {
    RETCODE ret;
 
+   mylog("[SQLGetInfoW]");
    ENTER_STMT_CS((StatementClass *) StatementHandle);
    ret = PGAPI_GetTypeInfo(StatementHandle, DataType);
    LEAVE_STMT_CS((StatementClass *) StatementHandle);
index 4c0b40f89779fdf5bcdc06e02ab48bcfce005627..b616594e8ff6405708232eaa5b50034b4de1bbbf 100644 (file)
--- a/pgapi30.c
+++ b/pgapi30.c
@@ -249,18 +249,19 @@ PGAPI_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
                    *((SQLINTEGER *) DiagInfoPtr) = 0;
                    ret = SQL_NO_DATA_FOUND;
                    stmt = (StatementClass *) Handle;
-                   do
+                   rtn = PGAPI_StmtError(Handle, -1, NULL,
+                        NULL, NULL, 0, &pcbErrm, 0);
+                   switch (rtn)
                    {
-                       rtn = PGAPI_StmtError(Handle, RecNumber,
-                                       NULL, NULL, NULL,
-                           0, &pcbErrm, 0);
-                       if (SQL_SUCCESS == rtn ||
-                               SQL_SUCCESS_WITH_INFO == rtn)
-                       {
-                           *((SQLINTEGER *) DiagInfoPtr)++;
+                       case SQL_SUCCESS:
+                       case SQL_SUCCESS_WITH_INFO:
                            ret = SQL_SUCCESS;
-                       }
-                   } while (pcbErrm >= stmt->error_recsize);
+                           if (pcbErrm > 0)
+                               *((SQLINTEGER *) DiagInfoPtr) = (pcbErrm  - 1)/ stmt->error_recsize + 1;
+                           break;
+                       default:
+                           break;
+                   }
                    if (StringLengthPtr)
                        *StringLengthPtr = sizeof(SQLINTEGER);
                    break;
@@ -597,6 +598,29 @@ static  void parameter_bindings_set(APDFields *opts, int params, BOOL maxset)
    }
 }
 
+static  void parameter_ibindings_set(IPDFields *opts, int params, BOOL maxset)
+{
+   int i;
+
+   if (params == opts->allocated)
+       return;
+   if (params > opts->allocated)
+   {
+       extend_iparameter_bindings(opts, params);
+       return;
+   }
+   if (maxset) return;
+
+   for (i = opts->allocated; i > params; i--)
+       reset_a_iparameter_binding(opts, i);
+   opts->allocated = params;
+   if (0 == params)
+   {
+       free(opts->parameters);
+       opts->parameters = NULL;
+   }
+}
+
 static RETCODE SQL_API
 APDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
        SQLSMALLINT FieldIdentifier, PTR Value, SQLINTEGER BufferLength)
@@ -751,7 +775,6 @@ IPDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
 {
    RETCODE     ret = SQL_SUCCESS;
    IPDFields   *ipdopts = SC_get_IPD(stmt);
-   APDFields   *apdopts = SC_get_APD(stmt);
 
    switch (FieldIdentifier)
    {
@@ -769,12 +792,13 @@ IPDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
            }
            break;
        case SQL_DESC_TYPE:
-           parameter_bindings_set(apdopts, RecNumber, TRUE);
-           apdopts->parameters[RecNumber - 1].SQLType = (Int4) Value;
+           parameter_ibindings_set(ipdopts, RecNumber, TRUE);
+           reset_a_iparameter_binding(ipdopts, RecNumber);
+           ipdopts->parameters[RecNumber - 1].SQLType = (Int4) Value;
            break;
        case SQL_DESC_DATETIME_INTERVAL_CODE:
-           parameter_bindings_set(apdopts, RecNumber, TRUE);
-           switch (apdopts->parameters[RecNumber - 1].SQLType)
+           parameter_ibindings_set(ipdopts, RecNumber, TRUE);
+           switch (ipdopts->parameters[RecNumber - 1].SQLType)
            {
                case SQL_DATETIME:
                case SQL_TYPE_DATE:
@@ -783,30 +807,30 @@ IPDSetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                switch ((Int4) Value)
                {
                    case SQL_CODE_DATE:
-                       apdopts->parameters[RecNumber - 1].SQLType = SQL_TYPE_DATE;
+                       ipdopts->parameters[RecNumber - 1].SQLType = SQL_TYPE_DATE;
                        break;
                    case SQL_CODE_TIME:
-                       apdopts->parameters[RecNumber - 1].SQLType = SQL_TYPE_TIME;
+                       ipdopts->parameters[RecNumber - 1].SQLType = SQL_TYPE_TIME;
                        break;
                    case SQL_CODE_TIMESTAMP:
-                       apdopts->parameters[RecNumber - 1].SQLType = SQL_TYPE_TIMESTAMP;
+                       ipdopts->parameters[RecNumber - 1].SQLType = SQL_TYPE_TIMESTAMP;
                        break;
                }
                break;
            }
            break;
        case SQL_DESC_CONCISE_TYPE:
-           parameter_bindings_set(apdopts, RecNumber, TRUE);
-           apdopts->parameters[RecNumber - 1].SQLType = (Int4) Value;
+           parameter_ibindings_set(ipdopts, RecNumber, TRUE);
+           ipdopts->parameters[RecNumber - 1].SQLType = (Int4) Value;
            break;
        case SQL_DESC_COUNT:
-           parameter_bindings_set(apdopts, (SQLUINTEGER) Value, FALSE);
+           parameter_ibindings_set(ipdopts, (SQLUINTEGER) Value, FALSE);
            break; 
        case SQL_DESC_PARAMETER_TYPE:
-           apdopts->parameters[RecNumber - 1].paramType = (Int2) Value;
+           ipdopts->parameters[RecNumber - 1].paramType = (Int2) Value;
            break;
        case SQL_DESC_SCALE:
-           apdopts->parameters[RecNumber - 1].decimal_digits = (Int2) Value;
+           ipdopts->parameters[RecNumber - 1].decimal_digits = (Int2) Value;
            break;
        case SQL_DESC_ALLOC_TYPE: /* read-only */ 
        case SQL_DESC_CASE_SENSITIVE: /* read-only */
@@ -1186,7 +1210,6 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
    SQLINTEGER  ival = 0, len, rettype = 0;
    PTR     ptr = NULL;
    const IPDFields *ipdopts = SC_get_IPD(stmt);
-   const APDFields *apdopts = SC_get_APD(stmt);
 
    switch (FieldIdentifier)
    {
@@ -1202,7 +1225,7 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
            ival = SQL_UNNAMED;
            break;
        case SQL_DESC_TYPE:
-           switch (apdopts->parameters[RecNumber - 1].SQLType)
+           switch (ipdopts->parameters[RecNumber - 1].SQLType)
            {
                case SQL_TYPE_DATE:
                case SQL_TYPE_TIME:
@@ -1210,11 +1233,11 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
                    ival = SQL_DATETIME;
                    break;
                default:
-                   ival = apdopts->parameters[RecNumber - 1].SQLType;
+                   ival = ipdopts->parameters[RecNumber - 1].SQLType;
            }
            break;
        case SQL_DESC_DATETIME_INTERVAL_CODE:
-           switch (apdopts->parameters[RecNumber - 1].SQLType)
+           switch (ipdopts->parameters[RecNumber - 1].SQLType)
            {
                case SQL_TYPE_DATE:
                    ival = SQL_CODE_DATE;
@@ -1229,30 +1252,30 @@ IPDGetField(StatementClass *stmt, SQLSMALLINT RecNumber,
            }
            break;
        case SQL_DESC_CONCISE_TYPE:
-           ival = apdopts->parameters[RecNumber - 1].SQLType;
+           ival = ipdopts->parameters[RecNumber - 1].SQLType;
            break;
        case SQL_DESC_COUNT:
-           ival = apdopts->allocated;
+           ival = ipdopts->allocated;
            break; 
        case SQL_DESC_PARAMETER_TYPE:
-           ival = apdopts->parameters[RecNumber - 1].paramType;
+           ival = ipdopts->parameters[RecNumber - 1].paramType;
            break;
        case SQL_DESC_PRECISION:
-           switch (apdopts->parameters[RecNumber - 1].CType)
+           switch (ipdopts->parameters[RecNumber - 1].SQLType)
            {
-               case SQL_C_TYPE_DATE:
-               case SQL_C_TYPE_TIME:
-               case SQL_C_TYPE_TIMESTAMP:
+               case SQL_TYPE_DATE:
+               case SQL_TYPE_TIME:
+               case SQL_TYPE_TIMESTAMP:
                case SQL_DATETIME:
-                   ival = apdopts->parameters[RecNumber - 1].decimal_digits;
+                   ival = ipdopts->parameters[RecNumber - 1].decimal_digits;
                    break;
            }
            break;
        case SQL_DESC_SCALE:
-           switch (apdopts->parameters[RecNumber - 1].CType)
+           switch (ipdopts->parameters[RecNumber - 1].SQLType)
            {
-               case SQL_C_NUMERIC:
-                   ival = apdopts->parameters[RecNumber - 1].decimal_digits;
+               case SQL_NUMERIC:
+                   ival = ipdopts->parameters[RecNumber - 1].decimal_digits;
                    break;
            }
            break;
index 780867a0d491572a76fb11ed47d1569bc5270fd8..32201ab6c668d778848991e49458255da14a1af5 100644 (file)
--- a/pgtypes.c
+++ b/pgtypes.c
@@ -66,7 +66,7 @@ Int4 pgtypes_defined[]    = {
                PG_TYPE_MONEY,
                PG_TYPE_BOOL,
                PG_TYPE_BYTEA,
-               PG_TYPE_LO,
+               PG_TYPE_LO_UNDEFINED,
                0 };
 */
 
@@ -169,7 +169,18 @@ sqltype_to_pgtype(StatementClass *stmt, SWORD fSqlType)
            break;
 
        case SQL_LONGVARBINARY:
-           pgType = PG_TYPE_LO;
+           switch (conn->lobj_type)
+           {
+               case PG_TYPE_LO_UNDEFINED:
+                   if (ci->bytea_as_longvarbinary)
+                   {
+                       pgType = PG_TYPE_BYTEA;
+                       break;
+                   }
+               default:
+                   pgType = conn->lobj_type;
+                   break;
+           }
            break;
 
        case SQL_LONGVARCHAR:
@@ -282,8 +293,14 @@ pgtype_to_concise_type(StatementClass *stmt, Int4 type)
 #endif /* UNICODE_SUPPORT */
 
        case PG_TYPE_BYTEA:
+           switch (conn->lobj_type)
+           {
+               case PG_TYPE_LO_UNDEFINED:  
+                   if (ci->bytea_as_longvarbinary)
+                       return SQL_LONGVARBINARY;
+           }
            return SQL_VARBINARY;
-       case PG_TYPE_LO:
+       case PG_TYPE_LO_UNDEFINED:
            return SQL_LONGVARBINARY;
 
        case PG_TYPE_INT2:
@@ -446,7 +463,7 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
 
        case PG_TYPE_BYTEA:
            return SQL_C_BINARY;
-       case PG_TYPE_LO:
+       case PG_TYPE_LO_UNDEFINED:
            return SQL_C_BINARY;
 #ifdef UNICODE_SUPPORT
        case PG_TYPE_BPCHAR:
@@ -469,7 +486,7 @@ pgtype_to_ctype(StatementClass *stmt, Int4 type)
 }
 
 
-char *
+const char *
 pgtype_to_name(StatementClass *stmt, Int4 type)
 {
    ConnectionClass *conn = SC_get_conn(stmt);
@@ -527,7 +544,7 @@ pgtype_to_name(StatementClass *stmt, Int4 type)
        case PG_TYPE_BYTEA:
            return "bytea";
 
-       case PG_TYPE_LO:
+       case PG_TYPE_LO_UNDEFINED:
            return PG_TYPE_LO_NAME;
 
        default:
@@ -883,7 +900,7 @@ pgtype_column_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_
            return true_is_minus1 ? 2 : 1;
        }
 
-       case PG_TYPE_LO:
+       case PG_TYPE_LO_UNDEFINED:
            return SQL_NO_TOTAL;
 
        default:
index cef2362ddfe71435fbcb0f0ab03f2760ede84c8a..987f5935cc18ed9b15b18452e518ea67bde773d2 100644 (file)
--- a/pgtypes.h
+++ b/pgtypes.h
@@ -76,7 +76,7 @@ Int2      pgtype_to_concise_type(StatementClass *stmt, Int4 type);
 Int2       pgtype_to_sqldesctype(StatementClass *stmt, Int4 type);
 Int2       pgtype_to_datetime_sub(StatementClass *stmt, Int4 type);
 Int2       pgtype_to_ctype(StatementClass *stmt, Int4 type);
-char      *pgtype_to_name(StatementClass *stmt, Int4 type);
+const char *pgtype_to_name(StatementClass *stmt, Int4 type);
 
 /* These functions can use static numbers or result sets(col parameter) */
 Int4       pgtype_column_size(StatementClass *stmt, Int4 type, int col, int handle_unknown_size_as); /* corresponds to "precision" in ODBC 2.x */
index fba807cf09d249278237847fdc8bddc9ae08d1e8..59bdd4991e054894b4c3511d94e000ca87590a46 100644 (file)
@@ -70,8 +70,8 @@ DllMain(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
 
        case DLL_PROCESS_DETACH:
            DELETE_CONNS_CS;
-            DELETE_MYLOG_CS;
            DELETE_QLOG_CS;
+           DELETE_MYLOG_CS;
            WSACleanup();
            return TRUE;
 
index 2c3b7f70c5ee8eaa868d8a6c47a9266e767e6ac5..3c434b2e46835980296623f7ceb1491702b3a8ab 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Comments:       See "notice.txt" for copyright and license information.
  *
- * $Id: psqlodbc.h,v 1.72 2002/10/16 07:39:53 dpage Exp $
+ * $Id: psqlodbc.h,v 1.73 2002/12/16 15:01:34 hinoue Exp $
  *
  */
 
@@ -89,7 +89,7 @@ typedef UInt4 Oid;
 
 /* Driver stuff */
 
-#define DRIVERNAME                 "PostgreSQL ODBC"
+#define DRIVERNAME             "PostgreSQL ODBC"
 #if (ODBCVER >= 0x0300)
 #define DRIVER_ODBC_VER                "03.00"
 #ifdef UNICODE_SUPPORT
@@ -99,7 +99,7 @@ typedef UInt4 Oid;
 #endif /* UNICODE_SUPPORT */
 #else
 #define DRIVER_ODBC_VER                "02.50"
-#define DBMS_NAME                  "PostgreSQL"
+#define DBMS_NAME              "PostgreSQL"
 #endif   /* ODBCVER */
 
 #ifdef WIN32
@@ -190,6 +190,7 @@ typedef struct QResultClass_ QResultClass;
 typedef struct SocketClass_ SocketClass;
 typedef struct BindInfoClass_ BindInfoClass;
 typedef struct ParameterInfoClass_ ParameterInfoClass;
+typedef struct ParameterImplClass_ ParameterImplClass;
 typedef struct ColumnInfoClass_ ColumnInfoClass;
 typedef struct TupleListClass_ TupleListClass;
 typedef struct EnvironmentClass_ EnvironmentClass;
@@ -253,7 +254,7 @@ typedef struct QueryInfo_
 
 void       logs_on_off(int cnopen, int, int);
 
-#define PG_TYPE_LO                 (-999)      /* hack until permanent
+#define PG_TYPE_LO_UNDEFINED           (-999)      /* hack until permanent
                                                 * type available */
 #define PG_TYPE_LO_NAME                "lo"
 #define OID_ATTNUM                 (-2)        /* the attnum in pg_index
index 0d0f0347f7c05da7446d1fffe05a3973cd9e5db9..b269eb7bab98933142bb26091740b03d4e75e18e 100644 (file)
--- a/results.c
+++ b/results.c
@@ -83,6 +83,9 @@ PGAPI_RowCount(
 
    *pcrow = -1;
    return SQL_SUCCESS;
+   /* SC_set_errornumber(stmt, STMT_SEQUENCE_ERROR);
+   SC_log_error(func, "Bad return value", stmt);
+   return SQL_ERROR; */
 }
 
 
index b98fa0e28935250ba1a0508e11d9641c9d9588c5..fdb71435b898c3aee2d65dbf9aba796eedf62c5d 100644 (file)
@@ -254,6 +254,7 @@ SC_Constructor(void)
        rv->curres = NULL;
        rv->manual_result = FALSE;
        rv->prepare = FALSE;
+       rv->prepared = FALSE;
        rv->status = STMT_ALLOCATED;
        rv->internal = FALSE;
 
@@ -264,6 +265,7 @@ SC_Constructor(void)
        rv->statement = NULL;
        rv->stmt_with_params = NULL;
        rv->load_statement = NULL;
+       rv->execute_statement = NULL;
        rv->stmt_size_limit = -1;
        rv->statement_type = STMT_TYPE_UNKNOWN;
 
@@ -352,6 +354,8 @@ void IRDFields_free(IRDFields * self)
 
 void IPDFields_free(IPDFields * self)
 {
+   /* param bindings */
+   IPD_free_params(self, STMT_FREE_PARAMS_ALL);
 }
 
 char
@@ -375,15 +379,7 @@ SC_Destructor(StatementClass *self)
        QR_Destructor(res);
    }
 
-   if (self->statement)
-       free(self->statement);
-   if (self->stmt_with_params)
-   {
-       free(self->stmt_with_params);
-       self->stmt_with_params = NULL;
-   }
-   if (self->load_statement)
-       free(self->load_statement);
+   SC_initialize_stmts(self, TRUE);
 
         /* Free the parsed table information */
    if (self->ti)
@@ -423,6 +419,7 @@ void
 SC_free_params(StatementClass *self, char option)
 {
    APD_free_params(SC_get_APD(self), option);
+   IPD_free_params(SC_get_IPD(self), option);
    self->data_at_exec = -1;
    self->current_exec_param = -1;
    self->put_data = FALSE;
@@ -451,6 +448,51 @@ statement_type(char *statement)
    return STMT_TYPE_OTHER;
 }
 
+/*
+ * Initialize stmt_with_params, load_statement and execute_statement
+ *     member pointer deallocating corresponding prepared plan.
+ * Also initialize statement member pointer if specified.
+ */
+RETCODE
+SC_initialize_stmts(StatementClass *self, BOOL initializeOriginal)
+{
+   if (initializeOriginal && self->statement)
+   {
+       free(self->statement);
+       self->statement = NULL;
+   }
+   if (self->stmt_with_params)
+   {
+       free(self->stmt_with_params);
+       self->stmt_with_params = NULL;
+   }
+   if (self->load_statement)
+   {
+       free(self->load_statement);
+       self->load_statement = NULL;
+   }
+   if (self->execute_statement)
+   {
+       free(self->execute_statement);
+       self->execute_statement = NULL;
+   }
+   if (self->prepared)
+   {
+       ConnectionClass *conn = SC_get_conn(self);
+       if (CONN_CONNECTED == conn->status)
+       {
+           QResultClass    *res;
+           char dealloc_stmt[128];
+
+           sprintf(dealloc_stmt, "DEALLOCATE _PLAN%0x", self);
+           res = CC_send_query(conn, dealloc_stmt, NULL, 0);
+           if (res)
+               QR_Destructor(res); 
+       }
+       self->prepared = FALSE;
+   }
+   return 0;
+}
 
 /*
  * Called from SQLPrepare if STMT_PREMATURE, or
@@ -554,12 +596,7 @@ SC_recycle_statement(StatementClass *self)
     * SQLParamData/SQLPutData is called.
     */
    SC_free_params(self, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY);
-   if (self->stmt_with_params)
-       free(self->stmt_with_params);
-   self->stmt_with_params = NULL;
-   if (self->load_statement)
-       free(self->load_statement);
-   self->load_statement = NULL;
+   SC_initialize_stmts(self, FALSE);
    /*
     *  reset the current attr setting to the original one.
     */
@@ -1101,8 +1138,13 @@ SC_execute(StatementClass *self)
        }
        else
        {
+           QResultClass    *tres;
+
            /* see if the query did return any result columns */
-           numcols = QR_NumResultCols(res);
+           for (tres = res, numcols = 0; !numcols && tres; tres = tres->next)
+           {
+               numcols = QR_NumResultCols(tres);
+           }
            /* now allocate the array to hold the binding info */
            if (numcols > 0)
            {
index 84390a12d1cf6d1d9545a4ea9099a33b7b3f5b24..ab60beb243288476ea3f8cef415d7fa635b9aed6 100644 (file)
@@ -84,6 +84,7 @@ typedef enum
 #define STMT_INVALID_DESCRIPTOR_IDENTIFIER             31
 #define STMT_OPTION_NOT_FOR_THE_DRIVER                 32
 #define STMT_FETCH_OUT_OF_RANGE                        33
+#define STMT_COUNT_FIELD_INCORRECT                 34
 
 /* statement types */
 enum
@@ -175,9 +176,9 @@ struct StatementClass_
    char        errormsg_created;       /* has an informative error msg
                                         * been created?  */
    char        manual_result;  /* Is the statement result manually built? */
-   char        prepare;        /* is this statement a prepared statement
-                                * or direct */
-
+   char        prepare;        /* is this statement a prepared statement ? */
+   char        prepared;       /* is this statement already
+                        * prepared at the server ? */
    char        internal;       /* Is this statement being called
                                 * internally? */
 
@@ -199,6 +200,7 @@ struct StatementClass_
    SWORD       error_recsize;
    Int4        diag_row_count;
    char        *load_statement; /* to (re)load updatable individual rows */
+   char        *execute_statement; /* to execute the prepared plans */
    Int4        from_pos;   
    Int4        where_pos;
    Int4        last_fetch_count_include_ommitted;
@@ -235,9 +237,12 @@ struct StatementClass_
 #define SC_set_fetchcursor(a)  (a->miscinfo |= 2L)
 #define SC_no_fetchcursor(a)   (a->miscinfo &= ~2L)
 #define SC_is_fetchcursor(a)   ((a->miscinfo & 2L) != 0)
+#define SC_set_prepare_before_exec(a)  (a->miscinfo |= 4L)
+#define SC_no_prepare_before_exec(a)   (a->miscinfo &= ~4L)
+#define SC_is_prepare_before_exec(a)   ((a->miscinfo & 4L) != 0)
 
 /* For Multi-thread */
-#if defined(WIN_MULTITHREAD_SUPPORT)
+#if defined(WIN_FREETHREAD_SUPPORT)
 #define INIT_STMT_CS(x)        InitializeCriticalSection(&((x)->cs))
 #define ENTER_STMT_CS(x)   EnterCriticalSection(&((x)->cs))
 #define LEAVE_STMT_CS(x)   LeaveCriticalSection(&((x)->cs))
@@ -270,6 +275,7 @@ void        SC_error_copy(StatementClass *self, const StatementClass *from);
 void       SC_full_error_copy(StatementClass *self, const StatementClass *from);
 char       SC_get_error(StatementClass *self, int *number, char **message);
 char       *SC_create_errormsg(const StatementClass *self);
+RETCODE        SC_initialize_stmts(StatementClass *self, BOOL);
 RETCODE        SC_execute(StatementClass *self);
 RETCODE        SC_fetch(StatementClass *self);
 void       SC_free_params(StatementClass *self, char option);
diff --git a/tuple.c b/tuple.c
index 512f36d2b23de4fdd2b607d67bf130a0a583b56c..edbe4886f9d04faff65d15e36513833a8f38c5d9 100644 (file)
--- a/tuple.c
+++ b/tuple.c
@@ -32,7 +32,7 @@ set_tuplefield_null(TupleField *tuple_field)
 
 
 void
-set_tuplefield_string(TupleField *tuple_field, char *string)
+set_tuplefield_string(TupleField *tuple_field, const char *string)
 {
    tuple_field->len = strlen(string);
    tuple_field->value = malloc(strlen(string) + 1);
diff --git a/tuple.h b/tuple.h
index c7fe46def45f028079105d2647e044ba18bbff5e..d4f4f9800f568bbc851f467e6933d12863c1d918 100644 (file)
--- a/tuple.h
+++ b/tuple.h
@@ -65,7 +65,7 @@ struct Rollback_
 #define set_nullfield_int4(FLD, VAL)       ((VAL) != -1 ? set_tuplefield_int4(FLD, (VAL)) : set_tuplefield_null(FLD))
 
 void       set_tuplefield_null(TupleField *tuple_field);
-void       set_tuplefield_string(TupleField *tuple_field, char *string);
+void       set_tuplefield_string(TupleField *tuple_field, const char *string);
 void       set_tuplefield_int2(TupleField *tuple_field, Int2 value);
 void       set_tuplefield_int4(TupleField *tuple_field, Int4 value);