Skip to content

Commit cc6bdb3

Browse files
author
Hiroshi Inoue
committed
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
1 parent 0e29d76 commit cc6bdb3

File tree

7 files changed

+181
-47
lines changed

7 files changed

+181
-47
lines changed

src/interfaces/odbc/bind.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,16 @@ SQLBindParameter(
143143
}
144144

145145
/* Data at exec macro only valid for C char/binary data */
146-
if ((fSqlType == SQL_LONGVARBINARY || fSqlType == SQL_LONGVARCHAR) && pcbValue && *pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET)
146+
if (pcbValue && (*pcbValue == SQL_DATA_AT_EXEC ||
147+
*pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET))
147148
stmt->parameters[ipar].data_at_exec = TRUE;
148149
else
149150
stmt->parameters[ipar].data_at_exec = FALSE;
150151

152+
/* Clear premature result */
153+
if (stmt->status == STMT_PREMATURE)
154+
SC_recycle_statement(stmt);
155+
151156
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);
152157

153158
return SQL_SUCCESS;

src/interfaces/odbc/convert.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,20 @@ copy_statement_with_parameters(StatementClass *stmt)
838838
param_number++;
839839

840840
if (param_number >= stmt->parameters_allocated)
841-
break;
841+
{
842+
if (stmt->pre_executing)
843+
{
844+
strcpy(&new_statement[npos], "NULL");
845+
npos += 4;
846+
stmt->inaccurate_result = TRUE;
847+
continue;
848+
}
849+
else
850+
{
851+
new_statement[npos++] = '?';
852+
continue;
853+
}
854+
}
842855

843856
/* Assign correct buffers based on data at exec param or not */
844857
if (stmt->parameters[param_number].data_at_exec)
@@ -866,8 +879,18 @@ copy_statement_with_parameters(StatementClass *stmt)
866879
*/
867880
if (!buffer)
868881
{
869-
new_statement[npos++] = '?';
870-
continue;
882+
if (stmt->pre_executing)
883+
{
884+
strcpy(&new_statement[npos], "NULL");
885+
npos += 4;
886+
stmt->inaccurate_result = TRUE;
887+
continue;
888+
}
889+
else
890+
{
891+
new_statement[npos++] = '?';
892+
continue;
893+
}
871894
}
872895

873896
param_ctype = stmt->parameters[param_number].CType;

src/interfaces/odbc/execute.c

Lines changed: 69 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "qresult.h"
3434
#include "convert.h"
3535
#include "bind.h"
36+
#include "pgtypes.h"
3637
#include "lobj.h"
3738

3839
extern GLOBAL_VALUES globals;
@@ -222,17 +223,22 @@ SQLExecute(
222223
*/
223224
if (stmt->prepare && stmt->status == STMT_PREMATURE)
224225
{
225-
stmt->status = STMT_FINISHED;
226-
if (stmt->errormsg == NULL)
227-
{
228-
mylog("%s: premature statement but return SQL_SUCCESS\n", func);
229-
return SQL_SUCCESS;
230-
}
226+
if (stmt->inaccurate_result)
227+
SC_recycle_statement(stmt);
231228
else
232229
{
233-
SC_log_error(func, "", stmt);
234-
mylog("%s: premature statement so return SQL_ERROR\n", func);
235-
return SQL_ERROR;
230+
stmt->status = STMT_FINISHED;
231+
if (stmt->errormsg == NULL)
232+
{
233+
mylog("%s: premature statement but return SQL_SUCCESS\n", func);
234+
return SQL_SUCCESS;
235+
}
236+
else
237+
{
238+
SC_log_error(func, "", stmt);
239+
mylog("%s: premature statement so return SQL_ERROR\n", func);
240+
return SQL_ERROR;
241+
}
236242
}
237243
}
238244

@@ -283,30 +289,36 @@ SQLExecute(
283289
}
284290

285291

286-
/*
287-
* The bound parameters could have possibly changed since the last
288-
* execute of this statement? Therefore check for params and re-copy.
289-
*/
290-
stmt->data_at_exec = -1;
291-
for (i = 0; i < stmt->parameters_allocated; i++)
292+
/* Check if statement has any data-at-execute parameters when it is not in SC_pre_execute. */
293+
if (!stmt->pre_executing)
292294
{
293-
/* Check for data at execution parameters */
294-
if (stmt->parameters[i].data_at_exec == TRUE)
295+
296+
/*
297+
* The bound parameters could have possibly changed since the last
298+
* execute of this statement? Therefore check for params and re-copy.
299+
*/
300+
stmt->data_at_exec = -1;
301+
for (i = 0; i < stmt->parameters_allocated; i++)
295302
{
296-
if (stmt->data_at_exec < 0)
297-
stmt->data_at_exec = 1;
298-
else
299-
stmt->data_at_exec++;
303+
/* Check for data at execution parameters */
304+
if (stmt->parameters[i].data_at_exec == TRUE)
305+
{
306+
if (stmt->data_at_exec < 0)
307+
stmt->data_at_exec = 1;
308+
else
309+
stmt->data_at_exec++;
310+
}
300311
}
301-
}
302-
/* If there are some data at execution parameters, return need data */
312+
/* If there are some data at execution parameters, return need data */
303313

304-
/*
305-
* SQLParamData and SQLPutData will be used to send params and execute
306-
* the statement.
307-
*/
308-
if (stmt->data_at_exec > 0)
309-
return SQL_NEED_DATA;
314+
/*
315+
* SQLParamData and SQLPutData will be used to send params and execute
316+
* the statement.
317+
*/
318+
if (stmt->data_at_exec > 0)
319+
return SQL_NEED_DATA;
320+
321+
}
310322

311323

312324
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(
777789

778790
}
779791
else
780-
{ /* for handling text fields and small
781-
* binaries */
792+
{ /* for handling fields */
782793

783794
if (cbValue == SQL_NTS)
784795
{
@@ -793,16 +804,35 @@ SQLPutData(
793804
}
794805
else
795806
{
796-
current_param->EXEC_buffer = malloc(cbValue + 1);
797-
if (!current_param->EXEC_buffer)
807+
Int2 ctype = current_param->CType;
808+
if (ctype == SQL_C_DEFAULT)
809+
ctype = sqltype_to_default_ctype(current_param->SQLType);
810+
if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
798811
{
799-
stmt->errornumber = STMT_NO_MEMORY_ERROR;
800-
stmt->errormsg = "Out of memory in SQLPutData (2)";
801-
SC_log_error(func, "", stmt);
802-
return SQL_ERROR;
812+
current_param->EXEC_buffer = malloc(cbValue + 1);
813+
if (!current_param->EXEC_buffer)
814+
{
815+
stmt->errornumber = STMT_NO_MEMORY_ERROR;
816+
stmt->errormsg = "Out of memory in SQLPutData (2)";
817+
SC_log_error(func, "", stmt);
818+
return SQL_ERROR;
819+
}
820+
memcpy(current_param->EXEC_buffer, rgbValue, cbValue);
821+
current_param->EXEC_buffer[cbValue] = '\0';
822+
}
823+
else
824+
{
825+
Int4 used = ctype_length(ctype);
826+
current_param->EXEC_buffer = malloc(used);
827+
if (!current_param->EXEC_buffer)
828+
{
829+
stmt->errornumber = STMT_NO_MEMORY_ERROR;
830+
stmt->errormsg = "Out of memory in SQLPutData (2)";
831+
SC_log_error(func, "", stmt);
832+
return SQL_ERROR;
833+
}
834+
memcpy(current_param->EXEC_buffer, rgbValue, used);
803835
}
804-
memcpy(current_param->EXEC_buffer, rgbValue, cbValue);
805-
current_param->EXEC_buffer[cbValue] = '\0';
806836
}
807837
}
808838
}

src/interfaces/odbc/pgtypes.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,3 +955,56 @@ sqltype_to_default_ctype(Int2 sqltype)
955955
return SQL_C_CHAR;
956956
}
957957
}
958+
959+
Int4
960+
ctype_length(Int2 ctype)
961+
{
962+
switch (ctype)
963+
{
964+
case SQL_C_SSHORT:
965+
case SQL_C_SHORT:
966+
return sizeof(SWORD);
967+
968+
case SQL_C_USHORT:
969+
return sizeof(UWORD);
970+
971+
case SQL_C_SLONG:
972+
case SQL_C_LONG:
973+
return sizeof(SDWORD);
974+
975+
case SQL_C_ULONG:
976+
return sizeof(UDWORD);
977+
978+
case SQL_C_FLOAT:
979+
return sizeof(SFLOAT);
980+
981+
case SQL_C_DOUBLE:
982+
return sizeof(SDOUBLE);
983+
984+
case SQL_C_BIT:
985+
return sizeof(UCHAR);
986+
987+
case SQL_C_STINYINT:
988+
case SQL_C_TINYINT:
989+
return sizeof(SCHAR);
990+
991+
case SQL_C_UTINYINT:
992+
return sizeof(UCHAR);
993+
994+
case SQL_C_DATE:
995+
return sizeof(DATE_STRUCT);
996+
997+
case SQL_C_TIME:
998+
return sizeof(TIME_STRUCT);
999+
1000+
case SQL_C_TIMESTAMP:
1001+
return sizeof(TIMESTAMP_STRUCT);
1002+
1003+
case SQL_C_BINARY:
1004+
case SQL_C_CHAR:
1005+
return 0;
1006+
1007+
default: /* should never happen */
1008+
return 0;
1009+
}
1010+
}

src/interfaces/odbc/pgtypes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,6 @@ char *pgtype_literal_suffix(StatementClass *stmt, Int4 type);
9292
char *pgtype_create_params(StatementClass *stmt, Int4 type);
9393

9494
Int2 sqltype_to_default_ctype(Int2 sqltype);
95+
Int4 ctype_length(Int2 ctype);
9596

9697
#endif

src/interfaces/odbc/statement.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,9 @@ SC_Constructor(void)
291291

292292
/* Clear Statement Options -- defaults will be set in AllocStmt */
293293
memset(&rv->options, 0, sizeof(StatementOptions));
294+
295+
rv->pre_executing = FALSE;
296+
rv->inaccurate_result = FALSE;
294297
}
295298
return rv;
296299
}
@@ -518,6 +521,7 @@ SC_recycle_statement(StatementClass *self)
518521
QR_Destructor(self->result);
519522
self->result = NULL;
520523
}
524+
self->inaccurate_result = FALSE;
521525

522526
/****************************************************************/
523527
/* Reset only parameters that have anything to do with results */
@@ -550,18 +554,33 @@ SC_recycle_statement(StatementClass *self)
550554
void
551555
SC_pre_execute(StatementClass *self)
552556
{
553-
554557
mylog("SC_pre_execute: status = %d\n", self->status);
555558

556559
if (self->status == STMT_READY)
557560
{
558561
mylog(" preprocess: status = READY\n");
559562

560-
SQLExecute(self);
563+
if (self->statement_type == STMT_TYPE_SELECT)
564+
{
565+
char old_pre_executing = self->pre_executing;
566+
self->pre_executing = TRUE;
567+
self->inaccurate_result = FALSE;
568+
569+
SQLExecute(self);
570+
571+
self->pre_executing = old_pre_executing;
561572

562-
if (self->status == STMT_FINISHED)
573+
if (self->status == STMT_FINISHED)
574+
{
575+
mylog(" preprocess: after status = FINISHED, so set PREMATURE\n");
576+
self->status = STMT_PREMATURE;
577+
}
578+
}
579+
else
563580
{
564-
mylog(" preprocess: after status = FINISHED, so set PREMATURE\n");
581+
self->result = QR_Constructor();
582+
QR_set_status(self->result, PGRES_TUPLES_OK);
583+
self->inaccurate_result = TRUE;
565584
self->status = STMT_PREMATURE;
566585
}
567586
}

src/interfaces/odbc/statement.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ struct StatementClass_
214214
* parameter
215215
* substitution */
216216

217+
char pre_executing; /* This statement is prematurely executing */
218+
char inaccurate_result; /* Current status is PREMATURE
219+
* but result is inaccurate */
217220
};
218221

219222
#define SC_get_conn(a) (a->hdbc)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy