]> granicus.if.org Git - postgresql/commitdiff
A patch to fix the following bugs.
authorHiroshi Inoue <inoue@tpf.co.jp>
Mon, 23 Apr 2001 01:00:49 +0000 (01:00 +0000)
committerHiroshi Inoue <inoue@tpf.co.jp>
Mon, 23 Apr 2001 01:00:49 +0000 (01:00 +0000)
1) [ODBC] Psqlodbc and Centura: here it is a patch
        posted by Matteo Cavalleli
2) [ODBC] pgsqODBC binding parameters II
        posted by Ludek Finstrle
3) Invalid Page Fault in PSQLODBC.DLL
        personal mail from Johann Zuschlag

   Hiroki Kataoka   kataoka@interwiz.koganei.tokyo.jp

src/interfaces/odbc/bind.c
src/interfaces/odbc/convert.c
src/interfaces/odbc/execute.c
src/interfaces/odbc/pgtypes.c
src/interfaces/odbc/pgtypes.h
src/interfaces/odbc/statement.c
src/interfaces/odbc/statement.h

index 5bade8b39560848e692ca3cc89e54f34529d2798..c70f78d4fb72db720da35ed30b432f87792259dc 100644 (file)
@@ -143,11 +143,16 @@ SQLBindParameter(
        }
 
        /* Data at exec macro only valid for C char/binary data */
-       if ((fSqlType == SQL_LONGVARBINARY || fSqlType == SQL_LONGVARCHAR) && pcbValue && *pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET)
+       if (pcbValue && (*pcbValue == SQL_DATA_AT_EXEC ||
+                       *pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET))
                stmt->parameters[ipar].data_at_exec = TRUE;
        else
                stmt->parameters[ipar].data_at_exec = FALSE;
 
+       /* Clear premature result */
+       if (stmt->status == STMT_PREMATURE)
+               SC_recycle_statement(stmt);
+
        mylog("SQLBindParamater: 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, stmt->parameters[ipar].data_at_exec);
 
        return SQL_SUCCESS;
index 595235bf9b63ff7b5d178e7ac7c9d1c49bc12626..8b41fb1c17333f4f7da1b859880b27a3ad12bda9 100644 (file)
@@ -838,7 +838,20 @@ copy_statement_with_parameters(StatementClass *stmt)
                param_number++;
 
                if (param_number >= stmt->parameters_allocated)
-                       break;
+               {
+                       if (stmt->pre_executing)
+                       {
+                               strcpy(&new_statement[npos], "NULL");
+                               npos += 4;
+                               stmt->inaccurate_result = TRUE;
+                               continue;
+                       }
+                       else
+                       {
+                               new_statement[npos++] = '?';
+                               continue;
+                       }
+               }
 
                /* Assign correct buffers based on data at exec param or not */
                if (stmt->parameters[param_number].data_at_exec)
@@ -866,8 +879,18 @@ copy_statement_with_parameters(StatementClass *stmt)
                 */
                if (!buffer)
                {
-                       new_statement[npos++] = '?';
-                       continue;
+                       if (stmt->pre_executing)
+                       {
+                               strcpy(&new_statement[npos], "NULL");
+                               npos += 4;
+                               stmt->inaccurate_result = TRUE;
+                               continue;
+                       }
+                       else
+                       {
+                               new_statement[npos++] = '?';
+                               continue;
+                       }
                }
 
                param_ctype = stmt->parameters[param_number].CType;
index 5fc2661331d3875dce379c4a5da8abf7915d8c5c..9777f4324c2db4a4ac4792bcff9df96c2f8c8d63 100644 (file)
@@ -33,6 +33,7 @@
 #include "qresult.h"
 #include "convert.h"
 #include "bind.h"
+#include "pgtypes.h"
 #include "lobj.h"
 
 extern GLOBAL_VALUES globals;
@@ -222,17 +223,22 @@ SQLExecute(
         */
        if (stmt->prepare && stmt->status == STMT_PREMATURE)
        {
-               stmt->status = STMT_FINISHED;
-               if (stmt->errormsg == NULL)
-               {
-                       mylog("%s: premature statement but return SQL_SUCCESS\n", func);
-                       return SQL_SUCCESS;
-               }
+               if (stmt->inaccurate_result)
+                       SC_recycle_statement(stmt);
                else
                {
-                       SC_log_error(func, "", stmt);
-                       mylog("%s: premature statement so return SQL_ERROR\n", func);
-                       return SQL_ERROR;
+                       stmt->status = STMT_FINISHED;
+                       if (stmt->errormsg == NULL)
+                       {
+                               mylog("%s: premature statement but return SQL_SUCCESS\n", func);
+                               return SQL_SUCCESS;
+                       }
+                       else
+                       {
+                               SC_log_error(func, "", stmt);
+                               mylog("%s: premature statement so return SQL_ERROR\n", func);
+                               return SQL_ERROR;
+                       }
                }
        }
 
@@ -283,30 +289,36 @@ SQLExecute(
        }
 
 
-       /*
-        * The bound parameters could have possibly changed since the last
-        * execute of this statement?  Therefore check for params and re-copy.
-        */
-       stmt->data_at_exec = -1;
-       for (i = 0; i < stmt->parameters_allocated; i++)
+       /* Check if statement has any data-at-execute parameters when it is not in SC_pre_execute. */
+       if (!stmt->pre_executing)
        {
-               /* Check for data at execution parameters */
-               if (stmt->parameters[i].data_at_exec == TRUE)
+
+               /*
+                * The bound parameters could have possibly changed since the last
+                * execute of this statement?  Therefore check for params and re-copy.
+                */
+               stmt->data_at_exec = -1;
+               for (i = 0; i < stmt->parameters_allocated; i++)
                {
-                       if (stmt->data_at_exec < 0)
-                               stmt->data_at_exec = 1;
-                       else
-                               stmt->data_at_exec++;
+                       /* Check for data at execution parameters */
+                       if (stmt->parameters[i].data_at_exec == TRUE)
+                       {
+                               if (stmt->data_at_exec < 0)
+                                       stmt->data_at_exec = 1;
+                               else
+                                       stmt->data_at_exec++;
+                       }
                }
-       }
-       /* If there are some data at execution parameters, return need data */
+               /* If there are some data at execution parameters, return need data */
 
-       /*
-        * SQLParamData and SQLPutData will be used to send params and execute
-        * the statement.
-        */
-       if (stmt->data_at_exec > 0)
-               return SQL_NEED_DATA;
+               /*
+                * SQLParamData and SQLPutData will be used to send params and execute
+                * the statement.
+                */
+               if (stmt->data_at_exec > 0)
+                       return SQL_NEED_DATA;
+
+       }
 
 
        mylog("%s: copying statement params: trans_status=%d, len=%d, stmt='%s'\n", func, conn->transact_status, strlen(stmt->statement), stmt->statement);
@@ -777,8 +789,7 @@ SQLPutData(
 
                }
                else
-               {                                               /* for handling text fields and small
-                                                                * binaries */
+               {                                               /* for handling fields */
 
                        if (cbValue == SQL_NTS)
                        {
@@ -793,16 +804,35 @@ SQLPutData(
                        }
                        else
                        {
-                               current_param->EXEC_buffer = malloc(cbValue + 1);
-                               if (!current_param->EXEC_buffer)
+                               Int2 ctype = current_param->CType;
+                               if (ctype == SQL_C_DEFAULT)
+                                       ctype = sqltype_to_default_ctype(current_param->SQLType);
+                               if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
                                {
-                                       stmt->errornumber = STMT_NO_MEMORY_ERROR;
-                                       stmt->errormsg = "Out of memory in SQLPutData (2)";
-                                       SC_log_error(func, "", stmt);
-                                       return SQL_ERROR;
+                                       current_param->EXEC_buffer = malloc(cbValue + 1);
+                                       if (!current_param->EXEC_buffer)
+                                       {
+                                               stmt->errornumber = STMT_NO_MEMORY_ERROR;
+                                               stmt->errormsg = "Out of memory in SQLPutData (2)";
+                                               SC_log_error(func, "", stmt);
+                                               return SQL_ERROR;
+                                       }
+                                       memcpy(current_param->EXEC_buffer, rgbValue, cbValue);
+                                       current_param->EXEC_buffer[cbValue] = '\0';
+                               }
+                               else
+                               {
+                                       Int4 used = ctype_length(ctype);
+                                       current_param->EXEC_buffer = malloc(used);
+                                       if (!current_param->EXEC_buffer)
+                                       {
+                                               stmt->errornumber = STMT_NO_MEMORY_ERROR;
+                                               stmt->errormsg = "Out of memory in SQLPutData (2)";
+                                               SC_log_error(func, "", stmt);
+                                               return SQL_ERROR;
+                                       }
+                                       memcpy(current_param->EXEC_buffer, rgbValue, used);
                                }
-                               memcpy(current_param->EXEC_buffer, rgbValue, cbValue);
-                               current_param->EXEC_buffer[cbValue] = '\0';
                        }
                }
        }
index 4b5b4db74e63845ced266807378cd6a4e4fd4203..f033be5f7d75bc54554d238df29892f41d14b159 100644 (file)
@@ -955,3 +955,56 @@ sqltype_to_default_ctype(Int2 sqltype)
                        return SQL_C_CHAR;
        }
 }
+
+Int4
+ctype_length(Int2 ctype)
+{
+       switch (ctype)
+       {
+               case SQL_C_SSHORT:
+               case SQL_C_SHORT:
+                       return sizeof(SWORD);
+
+               case SQL_C_USHORT:
+                       return sizeof(UWORD);
+
+               case SQL_C_SLONG:
+               case SQL_C_LONG:
+                       return sizeof(SDWORD);
+
+               case SQL_C_ULONG:
+                       return sizeof(UDWORD);
+
+               case SQL_C_FLOAT:
+                       return sizeof(SFLOAT);
+
+               case SQL_C_DOUBLE:
+                       return sizeof(SDOUBLE);
+
+               case SQL_C_BIT:
+                       return sizeof(UCHAR);
+
+               case SQL_C_STINYINT:
+               case SQL_C_TINYINT:
+                       return sizeof(SCHAR);
+
+               case SQL_C_UTINYINT:
+                       return sizeof(UCHAR);
+
+               case SQL_C_DATE:
+                       return sizeof(DATE_STRUCT);
+
+               case SQL_C_TIME:
+                       return sizeof(TIME_STRUCT);
+
+               case SQL_C_TIMESTAMP:
+                       return sizeof(TIMESTAMP_STRUCT);
+
+               case SQL_C_BINARY:
+               case SQL_C_CHAR:
+                       return 0;
+
+               default:                                /* should never happen */
+                       return 0;
+       }
+}
index 7130bd423c9e47c3ebc8ab579d5677f2959718c6..03cc2babd16a1f2d32daafa270cac76cfe7b4793 100644 (file)
@@ -92,5 +92,6 @@ char     *pgtype_literal_suffix(StatementClass *stmt, Int4 type);
 char      *pgtype_create_params(StatementClass *stmt, Int4 type);
 
 Int2           sqltype_to_default_ctype(Int2 sqltype);
+Int4           ctype_length(Int2 ctype);
 
 #endif
index 8b7a67babd30c03b724f057a026386d91bc5142e..497364ba84d633e0714dd3f5a663684baa3116d4 100644 (file)
@@ -291,6 +291,9 @@ SC_Constructor(void)
 
                /* Clear Statement Options -- defaults will be set in AllocStmt */
                memset(&rv->options, 0, sizeof(StatementOptions));
+
+               rv->pre_executing = FALSE;
+               rv->inaccurate_result = FALSE;
        }
        return rv;
 }
@@ -518,6 +521,7 @@ SC_recycle_statement(StatementClass *self)
                QR_Destructor(self->result);
                self->result = NULL;
        }
+       self->inaccurate_result = FALSE;
 
        /****************************************************************/
        /* Reset only parameters that have anything to do with results */
@@ -550,18 +554,33 @@ SC_recycle_statement(StatementClass *self)
 void
 SC_pre_execute(StatementClass *self)
 {
-
        mylog("SC_pre_execute: status = %d\n", self->status);
 
        if (self->status == STMT_READY)
        {
                mylog("              preprocess: status = READY\n");
 
-               SQLExecute(self);
+               if (self->statement_type == STMT_TYPE_SELECT)
+               {
+                       char old_pre_executing = self->pre_executing;
+                       self->pre_executing = TRUE;
+                       self->inaccurate_result = FALSE;
+
+                       SQLExecute(self);
+
+                       self->pre_executing = old_pre_executing;
 
-               if (self->status == STMT_FINISHED)
+                       if (self->status == STMT_FINISHED)
+                       {
+                               mylog("              preprocess: after status = FINISHED, so set PREMATURE\n");
+                               self->status = STMT_PREMATURE;
+                       }
+               }
+               else
                {
-                       mylog("              preprocess: after status = FINISHED, so set PREMATURE\n");
+                       self->result = QR_Constructor();
+                       QR_set_status(self->result, PGRES_TUPLES_OK);
+                       self->inaccurate_result = TRUE;
                        self->status = STMT_PREMATURE;
                }
        }
index 69f8274615c36ff252bffeda13b717795bf1da1f..00b39962d6ca0f401c15a80c1a340cfc417a16c8 100644 (file)
@@ -214,6 +214,9 @@ struct StatementClass_
                                                                                                                 * parameter
                                                                                                                 * substitution */
 
+       char            pre_executing;  /* This statement is prematurely executing */
+       char            inaccurate_result;              /* Current status is PREMATURE
+                                                                                * but result is inaccurate */
 };
 
 #define SC_get_conn(a)   (a->hdbc)