4
* Description: This module contains routines related to binding
5
* columns and parameters.
7
* Classes: BindInfoClass, ParameterInfoClass
9
* API functions: SQLBindParameter, SQLBindCol, SQLDescribeParam, SQLNumParams,
12
* Comments: See "notice.txt" for copyright and license information.
19
#include "statement.h"
20
#include "descriptor.h"
26
#include "pgapifunc.h"
29
/* Bind parameters on a statement handle */
41
SDWORD FAR * pcbValue)
43
StatementClass *stmt = (StatementClass *) hstmt;
44
CSTR func = "PGAPI_BindParameter";
48
mylog("%s: entering...\n", func);
52
SC_log_error(func, "", NULL);
53
return SQL_INVALID_HANDLE;
57
apdopts = SC_get_APD(stmt);
58
if (apdopts->allocated < ipar)
59
extend_parameter_bindings(apdopts, ipar);
60
ipdopts = SC_get_IPD(stmt);
61
if (ipdopts->allocated < ipar)
62
extend_iparameter_bindings(ipdopts, ipar);
64
/* use zero based column numbers for the below part */
67
/* store the given info */
68
apdopts->parameters[ipar].buflen = cbValueMax;
69
apdopts->parameters[ipar].buffer = rgbValue;
70
apdopts->parameters[ipar].used = pcbValue;
71
apdopts->parameters[ipar].paramType = fParamType;
72
apdopts->parameters[ipar].CType = fCType;
73
ipdopts->parameters[ipar].SQLType = fSqlType;
74
ipdopts->parameters[ipar].paramType = fParamType;
75
ipdopts->parameters[ipar].column_size = cbColDef;
76
ipdopts->parameters[ipar].decimal_digits = ibScale;
77
ipdopts->parameters[ipar].precision = 0;
78
ipdopts->parameters[ipar].scale = 0;
79
ipdopts->parameters[ipar].PGType = sqltype_to_pgtype(stmt, fSqlType);
80
#if (ODBCVER >= 0x0300)
85
ipdopts->parameters[ipar].precision = (UInt2) cbColDef;
87
ipdopts->parameters[ipar].scale = ibScale;
89
case SQL_C_TYPE_TIMESTAMP:
91
ipdopts->parameters[ipar].precision = ibScale;
94
apdopts->parameters[ipar].precision = ipdopts->parameters[ipar].precision;
95
apdopts->parameters[ipar].scale = ipdopts->parameters[ipar].scale;
99
* If rebinding a parameter that had data-at-exec stuff in it, then
102
if (apdopts->parameters[ipar].EXEC_used)
104
free(apdopts->parameters[ipar].EXEC_used);
105
apdopts->parameters[ipar].EXEC_used = NULL;
108
if (apdopts->parameters[ipar].EXEC_buffer)
110
free(apdopts->parameters[ipar].EXEC_buffer);
111
apdopts->parameters[ipar].EXEC_buffer = NULL;
114
if (pcbValue && apdopts->param_offset_ptr)
115
pcbValue += (*apdopts->param_offset_ptr >> 2);
116
/* Data at exec macro only valid for C char/binary data */
117
if (pcbValue && (*pcbValue == SQL_DATA_AT_EXEC ||
118
*pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET))
119
apdopts->parameters[ipar].data_at_exec = TRUE;
121
apdopts->parameters[ipar].data_at_exec = FALSE;
123
/* Clear premature result */
124
if (stmt->status == STMT_PREMATURE)
125
SC_recycle_statement(stmt);
127
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);
133
/* Associate a user-supplied buffer with a database column. */
141
SDWORD FAR * pcbValue)
143
StatementClass *stmt = (StatementClass *) hstmt;
144
CSTR func = "PGAPI_BindCol";
147
mylog("%s: entering...\n", func);
149
mylog("**** PGAPI_BindCol: stmt = %u, icol = %d\n", stmt, icol);
150
mylog("**** : fCType=%d rgb=%x valusMax=%d pcb=%x\n", fCType, rgbValue, cbValueMax, pcbValue);
154
SC_log_error(func, "", NULL);
155
return SQL_INVALID_HANDLE;
160
opts = SC_get_ARD(stmt);
161
if (stmt->status == STMT_EXECUTING)
163
SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Can't bind columns while statement is still executing.");
164
SC_log_error(func, "", stmt);
168
SC_clear_error(stmt);
169
/* If the bookmark column is being bound, then just save it */
172
if (rgbValue == NULL)
174
opts->bookmark->buffer = NULL;
175
opts->bookmark->used = NULL;
179
/* Make sure it is the bookmark data type */
183
#if (ODBCVER >= 0x0300)
184
case SQL_C_VARBOOKMARK:
188
SC_set_error(stmt, STMT_PROGRAM_TYPE_OUT_OF_RANGE, "Bind column 0 is not of type SQL_C_BOOKMARK");
189
inolog("Bind column 0 is type %d not of type SQL_C_BOOKMARK", fCType);
190
SC_log_error(func, "", stmt);
194
opts->bookmark->buffer = rgbValue;
195
opts->bookmark->used = pcbValue;
196
opts->bookmark->buflen = cbValueMax;
197
opts->bookmark->returntype = fCType;
203
* Allocate enough bindings if not already done. Most likely,
204
* execution of a statement would have setup the necessary bindings.
205
* But some apps call BindCol before any statement is executed.
207
if (icol > opts->allocated)
208
extend_column_bindings(opts, icol);
210
/* check to see if the bindings were allocated */
213
SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Could not allocate memory for bindings.");
214
SC_log_error(func, "", stmt);
218
/* use zero based col numbers from here out */
221
/* Reset for SQLGetData */
222
opts->bindings[icol].data_left = -1;
224
if (rgbValue == NULL)
226
/* we have to unbind the column */
227
opts->bindings[icol].buflen = 0;
228
opts->bindings[icol].buffer = NULL;
229
opts->bindings[icol].used = NULL;
230
opts->bindings[icol].returntype = SQL_C_CHAR;
231
if (opts->bindings[icol].ttlbuf)
232
free(opts->bindings[icol].ttlbuf);
233
opts->bindings[icol].ttlbuf = NULL;
234
opts->bindings[icol].ttlbuflen = 0;
235
opts->bindings[icol].ttlbufused = 0;
236
opts->bindings[icol].precision = 0;
237
opts->bindings[icol].scale = 0;
241
/* ok, bind that column */
242
opts->bindings[icol].buflen = cbValueMax;
243
opts->bindings[icol].buffer = rgbValue;
244
opts->bindings[icol].used = pcbValue;
245
opts->bindings[icol].returntype = fCType;
246
#if (ODBCVER >= 0x0300)
247
if (SQL_C_NUMERIC == fCType)
248
opts->bindings[icol].precision = 32;
251
opts->bindings[icol].precision = 0;
252
opts->bindings[icol].scale = 0;
254
mylog(" bound buffer[%d] = %u\n", icol, opts->bindings[icol].buffer);
262
* Returns the description of a parameter marker.
263
* This function is listed as not being supported by SQLGetFunctions() because it is
264
* used to describe "parameter markers" (not bound parameters), in which case,
265
* the dbms should return info on the markers. Since Postgres doesn't support that,
266
* it is best to say this function is not supported and let the application assume a
267
* data type (most likely varchar).
273
SWORD FAR * pfSqlType,
274
UDWORD FAR * pcbColDef,
275
SWORD FAR * pibScale,
276
SWORD FAR * pfNullable)
278
StatementClass *stmt = (StatementClass *) hstmt;
279
CSTR func = "PGAPI_DescribeParam";
283
mylog("%s: entering...\n", func);
287
SC_log_error(func, "", NULL);
288
return SQL_INVALID_HANDLE;
290
SC_clear_error(stmt);
292
apdopts = SC_get_APD(stmt);
293
if ((ipar < 1) || (ipar > apdopts->allocated))
295
SC_set_error(stmt, STMT_BAD_PARAMETER_NUMBER_ERROR, "Invalid parameter number for PGAPI_DescribeParam.");
296
SC_log_error(func, "", stmt);
299
ipdopts = SC_get_IPD(stmt);
304
* This implementation is not very good, since it is supposed to
307
/* parameter markers, not bound parameters. */
309
*pfSqlType = ipdopts->parameters[ipar].SQLType;
312
*pcbColDef = ipdopts->parameters[ipar].column_size;
315
*pibScale = ipdopts->parameters[ipar].decimal_digits;
318
*pfNullable = pgtype_nullable(stmt, apdopts->parameters[ipar].paramType);
324
/* Sets multiple values (arrays) for the set of parameter markers. */
331
CSTR func = "PGAPI_ParamOptions";
332
StatementClass *stmt = (StatementClass *) hstmt;
335
mylog("%s: entering... %d %x\n", func, crow, pirow);
337
apdopts = SC_get_APD(stmt);
338
apdopts->paramset_size = crow;
339
SC_get_IPD(stmt)->param_processed_ptr = (UInt4 *) pirow;
345
* This function should really talk to the dbms to determine the number of
346
* "parameter markers" (not bound parameters) in the statement. But, since
347
* Postgres doesn't support that, the driver should just count the number of markers
348
* and return that. The reason the driver just can't say this function is unsupported
349
* like it does for SQLDescribeParam is that some applications don't care and try
351
* If the statement does not have parameters, it should just return 0.
358
StatementClass *stmt = (StatementClass *) hstmt;
359
char in_quote = FALSE;
361
CSTR func = "PGAPI_NumParams";
363
mylog("%s: entering...\n", func);
367
SC_log_error(func, "", NULL);
368
return SQL_INVALID_HANDLE;
375
SC_log_error(func, "pcpar was null", stmt);
380
if (!stmt->statement)
382
/* no statement has been allocated */
383
SC_set_error(stmt, STMT_SEQUENCE_ERROR, "PGAPI_NumParams called with no statement ready.");
384
SC_log_error(func, "", stmt);
389
for (i = 0; i < strlen(stmt->statement); i++)
391
if (stmt->statement[i] == '?' && !in_quote)
395
if (stmt->statement[i] == '\'')
396
in_quote = (in_quote ? FALSE : TRUE);
405
* Bindings Implementation
408
create_empty_bindings(int num_columns)
410
BindInfoClass *new_bindings;
413
new_bindings = (BindInfoClass *) malloc(num_columns * sizeof(BindInfoClass));
417
for (i = 0; i < num_columns; i++)
419
new_bindings[i].buflen = 0;
420
new_bindings[i].buffer = NULL;
421
new_bindings[i].used = NULL;
422
new_bindings[i].data_left = -1;
423
new_bindings[i].ttlbuf = NULL;
424
new_bindings[i].ttlbuflen = 0;
425
new_bindings[i].ttlbufused = 0;
432
extend_parameter_bindings(APDFields *self, int num_params)
434
CSTR func = "extend_parameter_bindings";
435
ParameterInfoClass *new_bindings;
437
mylog("%s: entering ... self=%u, parameters_allocated=%d, num_params=%d\n", func, self, self->allocated, num_params);
440
* if we have too few, allocate room for more, and copy the old
441
* entries into the new structure
443
if (self->allocated < num_params)
445
new_bindings = (ParameterInfoClass *) realloc(self->parameters, sizeof(ParameterInfoClass) * num_params);
448
mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_params, self->allocated);
450
self->parameters = NULL;
454
memset(&new_bindings[self->allocated], 0,
455
sizeof(ParameterInfoClass) * (num_params - self->allocated));
457
self->parameters = new_bindings;
458
self->allocated = num_params;
461
mylog("exit extend_parameter_bindings\n");
465
extend_iparameter_bindings(IPDFields *self, int num_params)
467
CSTR func = "extend_iparameter_bindings";
468
ParameterImplClass *new_bindings;
470
mylog("%s: entering ... self=%u, parameters_allocated=%d, num_params=%d\n", func, self, self->allocated, num_params);
473
* if we have too few, allocate room for more, and copy the old
474
* entries into the new structure
476
if (self->allocated < num_params)
478
new_bindings = (ParameterImplClass *) realloc(self->parameters, sizeof(ParameterImplClass) * num_params);
481
mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_params, self->allocated);
483
self->parameters = NULL;
487
memset(&new_bindings[self->allocated], 0,
488
sizeof(ParameterImplClass) * (num_params - self->allocated));
490
self->parameters = new_bindings;
491
self->allocated = num_params;
494
mylog("exit extend_iparameter_bindings\n");
498
reset_a_parameter_binding(APDFields *self, int ipar)
500
CSTR func = "reset_a_parameter_binding";
502
mylog("%s: entering ... self=%u, parameters_allocated=%d, ipar=%d\n", func, self, self->allocated, ipar);
504
if (ipar < 1 || ipar > self->allocated)
508
self->parameters[ipar].buflen = 0;
509
self->parameters[ipar].buffer = 0;
510
self->parameters[ipar].used = 0;
511
self->parameters[ipar].paramType = 0;
512
self->parameters[ipar].CType = 0;
513
self->parameters[ipar].data_at_exec = FALSE;
514
if (self->parameters[ipar].EXEC_used)
516
free(self->parameters[ipar].EXEC_used);
517
self->parameters[ipar].EXEC_used = NULL;
520
if (self->parameters[ipar].EXEC_buffer)
522
free(self->parameters[ipar].EXEC_buffer);
523
self->parameters[ipar].EXEC_buffer = NULL;
525
self->parameters[ipar].lobj_oid = 0;
526
self->parameters[ipar].precision = 0;
527
self->parameters[ipar].scale = 0;
531
reset_a_iparameter_binding(IPDFields *self, int ipar)
533
CSTR func = "reset_a_iparameter_binding";
535
mylog("%s: entering ... self=%u, parameters_allocated=%d, ipar=%d\n", func, self, self->allocated, ipar);
537
if (ipar < 1 || ipar > self->allocated)
541
self->parameters[ipar].paramType = 0;
542
self->parameters[ipar].SQLType = 0;
543
self->parameters[ipar].column_size = 0;
544
self->parameters[ipar].decimal_digits = 0;
545
self->parameters[ipar].precision = 0;
546
self->parameters[ipar].scale = 0;
550
* Free parameters and free the memory.
553
APD_free_params(APDFields *apdopts, char option)
557
mylog("APD_free_params: ENTER, self=%d\n", apdopts);
559
if (!apdopts->parameters)
562
for (i = 0; i < apdopts->allocated; i++)
564
if (apdopts->parameters[i].data_at_exec)
566
if (apdopts->parameters[i].EXEC_used)
568
free(apdopts->parameters[i].EXEC_used);
569
apdopts->parameters[i].EXEC_used = NULL;
571
if (apdopts->parameters[i].EXEC_buffer)
573
free(apdopts->parameters[i].EXEC_buffer);
574
apdopts->parameters[i].EXEC_buffer = NULL;
579
if (option == STMT_FREE_PARAMS_ALL)
581
if (apdopts->parameters)
582
free(apdopts->parameters);
583
apdopts->parameters = NULL;
584
apdopts->allocated = 0;
587
mylog("APD_free_params: EXIT\n");
591
* Free parameters and free the memory.
594
IPD_free_params(IPDFields *ipdopts, char option)
596
mylog("IPD_free_params: ENTER, self=%d\n", ipdopts);
598
if (ipdopts->parameters &&
599
option == STMT_FREE_PARAMS_ALL)
601
if (ipdopts->parameters)
602
free(ipdopts->parameters);
603
ipdopts->parameters = NULL;
604
ipdopts->allocated = 0;
607
mylog("IPD_free_params: EXIT\n");
611
extend_column_bindings(ARDFields *self, int num_columns)
613
CSTR func = "extend_column_bindings";
614
BindInfoClass *new_bindings;
617
mylog("%s: entering ... self=%u, bindings_allocated=%d, num_columns=%d\n", func, self, self->allocated, num_columns);
620
* if we have too few, allocate room for more, and copy the old
621
* entries into the new structure
623
if (self->allocated < num_columns)
625
new_bindings = create_empty_bindings(num_columns);
628
mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_columns, self->allocated);
632
free(self->bindings);
633
self->bindings = NULL;
641
for (i = 0; i < self->allocated; i++)
642
new_bindings[i] = self->bindings[i];
644
free(self->bindings);
647
self->bindings = new_bindings;
648
self->allocated = num_columns;
652
* There is no reason to zero out extra bindings if there are more
653
* than needed. If an app has allocated extra bindings, let it worry
654
* about it by unbinding those columns.
657
/* SQLBindCol(1..) ... SQLBindCol(10...) # got 10 bindings */
658
/* SQLExecDirect(...) # returns 5 cols */
659
/* SQLExecDirect(...) # returns 10 cols (now OK) */
661
mylog("exit extend_column_bindings\n");
665
reset_a_column_binding(ARDFields *self, int icol)
667
CSTR func = "reset_a_column_binding";
669
mylog("%s: entering ... self=%u, bindings_allocated=%d, icol=%d\n", func, self, self->allocated, icol);
671
if (icol > self->allocated)
674
/* use zero based col numbers from here out */
677
self->bookmark->buffer = NULL;
678
self->bookmark->used = NULL;
684
/* we have to unbind the column */
685
self->bindings[icol].buflen = 0;
686
self->bindings[icol].buffer = NULL;
687
self->bindings[icol].used = NULL;
688
self->bindings[icol].data_left = -1;
689
self->bindings[icol].returntype = SQL_C_CHAR;
690
if (self->bindings[icol].ttlbuf)
691
free(self->bindings[icol].ttlbuf);
692
self->bindings[icol].ttlbuf = NULL;
693
self->bindings[icol].ttlbuflen = 0;
694
self->bindings[icol].ttlbufused = 0;
698
void ARD_unbind_cols(ARDFields *self, BOOL freeall)
702
for (lf = 1; lf <= self->allocated; lf++)
703
reset_a_column_binding(self, lf);
707
free(self->bindings);
708
self->bindings = NULL;