Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)