aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi Inoue <inoue@tpf.co.jp>2001-04-23 01:00:49 +0000
committerHiroshi Inoue <inoue@tpf.co.jp>2001-04-23 01:00:49 +0000
commitcc6bdb3e4898cf5411005871e9dad7a341a07f20 (patch)
tree6923039c5f5038bde728892a3850685caa402a1f
parent0e29d760f4884d6cc194cf6d95605417e825a145 (diff)
downloadpostgresql-cc6bdb3e4898cf5411005871e9dad7a341a07f20.tar.gz
postgresql-cc6bdb3e4898cf5411005871e9dad7a341a07f20.zip
A patch to fix the following bugs.
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
-rw-r--r--src/interfaces/odbc/bind.c7
-rw-r--r--src/interfaces/odbc/convert.c29
-rw-r--r--src/interfaces/odbc/execute.c108
-rw-r--r--src/interfaces/odbc/pgtypes.c53
-rw-r--r--src/interfaces/odbc/pgtypes.h1
-rw-r--r--src/interfaces/odbc/statement.c27
-rw-r--r--src/interfaces/odbc/statement.h3
7 files changed, 181 insertions, 47 deletions
diff --git a/src/interfaces/odbc/bind.c b/src/interfaces/odbc/bind.c
index 5bade8b3956..c70f78d4fb7 100644
--- a/src/interfaces/odbc/bind.c
+++ b/src/interfaces/odbc/bind.c
@@ -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;
diff --git a/src/interfaces/odbc/convert.c b/src/interfaces/odbc/convert.c
index 595235bf9b6..8b41fb1c173 100644
--- a/src/interfaces/odbc/convert.c
+++ b/src/interfaces/odbc/convert.c
@@ -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;
diff --git a/src/interfaces/odbc/execute.c b/src/interfaces/odbc/execute.c
index 5fc2661331d..9777f4324c2 100644
--- a/src/interfaces/odbc/execute.c
+++ b/src/interfaces/odbc/execute.c
@@ -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';
}
}
}
diff --git a/src/interfaces/odbc/pgtypes.c b/src/interfaces/odbc/pgtypes.c
index 4b5b4db74e6..f033be5f7d7 100644
--- a/src/interfaces/odbc/pgtypes.c
+++ b/src/interfaces/odbc/pgtypes.c
@@ -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;
+ }
+}
diff --git a/src/interfaces/odbc/pgtypes.h b/src/interfaces/odbc/pgtypes.h
index 7130bd423c9..03cc2babd16 100644
--- a/src/interfaces/odbc/pgtypes.h
+++ b/src/interfaces/odbc/pgtypes.h
@@ -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
diff --git a/src/interfaces/odbc/statement.c b/src/interfaces/odbc/statement.c
index 8b7a67babd3..497364ba84d 100644
--- a/src/interfaces/odbc/statement.c
+++ b/src/interfaces/odbc/statement.c
@@ -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;
}
}
diff --git a/src/interfaces/odbc/statement.h b/src/interfaces/odbc/statement.h
index 69f8274615c..00b39962d6c 100644
--- a/src/interfaces/odbc/statement.h
+++ b/src/interfaces/odbc/statement.h
@@ -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)