2 * Description: This module contains routines related to binding
3 * columns and parameters.
11 #include "statement.h"
12 #include "descriptor.h"
15 #include "multibyte.h"
17 #include "pgapifunc.h"
20 /* Bind parameters on a statement handle */
22 PGAPI_BindParameter(HSTMT hstmt
,
24 SQLSMALLINT fParamType
,
30 SQLLEN cbValueMax
, SQLLEN FAR
* pcbValue
)
32 StatementClass
*stmt
= (StatementClass
*) hstmt
;
33 CSTR func
= "PGAPI_BindParameter";
34 mylog("PGAPI_BindParameter not yet implemented");
35 SC_log_error(func
, "PGAPI_BindParameter not yet implemented", stmt
);
40 /* Associate a user-supplied buffer with a database column. */
42 PGAPI_BindCol(HSTMT hstmt
,
45 PTR rgbValue
, SQLLEN cbValueMax
, SQLLEN FAR
* pcbValue
)
47 CSTR func
= "PGAPI_BindCol";
48 StatementClass
*stmt
= (StatementClass
*) hstmt
;
50 GetDataInfo
*gdata_info
;
51 BindInfoClass
*bookmark
;
52 RETCODE ret
= SQL_SUCCESS
;
54 mylog("Entering(%p, %d)\n", stmt
, icol
);
55 mylog("fCType=%d rgb=%p valusMax=%d pcb=%p\n",
56 fCType
, rgbValue
, cbValueMax
, pcbValue
);
60 SC_log_error(func
, "", NULL
);
61 return SQL_INVALID_HANDLE
;
64 opts
= SC_get_ARDF(stmt
);
65 if (stmt
->status
== STMT_EXECUTING
)
67 SC_set_error(stmt
, STMT_SEQUENCE_ERROR
,
68 "Can't bind columns while statement is still executing.",
72 #define return DONT_CALL_RETURN_FROM_HERE ???
74 /* If the bookmark column is being bound, then just save it */
77 bookmark
= opts
->bookmark
;
82 bookmark
->buffer
= NULL
;
83 bookmark
->used
= bookmark
->indicator
= NULL
;
88 /* Make sure it is the bookmark data type */
92 case SQL_C_VARBOOKMARK
:
95 SC_set_error(stmt
, STMT_PROGRAM_TYPE_OUT_OF_RANGE
,
96 "Bind column 0 is not of type SQL_C_BOOKMARK",
99 ("Bind column 0 is type %d not of type SQL_C_BOOKMARK",
105 bookmark
= ARD_AllocBookmark(opts
);
106 bookmark
->buffer
= (char *)rgbValue
;
107 bookmark
->used
= bookmark
->indicator
= pcbValue
;
108 bookmark
->buflen
= cbValueMax
;
109 bookmark
->returntype
= fCType
;
115 * Allocate enough bindings if not already done. Most likely,
116 * execution of a statement would have setup the necessary bindings.
117 * But some apps call BindCol before any statement is executed.
119 if (icol
> opts
->allocated
)
120 extend_column_bindings(opts
, icol
);
121 gdata_info
= SC_get_GDTI(stmt
);
122 if (icol
> gdata_info
->allocated
)
123 extend_getdata_info(gdata_info
, icol
, FALSE
);
125 /* check to see if the bindings were allocated */
128 SC_set_error(stmt
, STMT_NO_MEMORY_ERROR
,
129 "Could not allocate memory for bindings.", func
);
134 /* use zero based col numbers from here out */
137 /* Reset for SQLGetData */
138 gdata_info
->gdata
[icol
].data_left
= -1;
140 if (rgbValue
== NULL
)
142 /* we have to unbind the column */
143 opts
->bindings
[icol
].buflen
= 0;
144 opts
->bindings
[icol
].buffer
= NULL
;
145 opts
->bindings
[icol
].used
=
146 opts
->bindings
[icol
].indicator
= NULL
;
147 opts
->bindings
[icol
].returntype
= SQL_C_CHAR
;
148 opts
->bindings
[icol
].precision
= 0;
149 opts
->bindings
[icol
].scale
= 0;
150 if (gdata_info
->gdata
[icol
].ttlbuf
)
151 free(gdata_info
->gdata
[icol
].ttlbuf
);
152 gdata_info
->gdata
[icol
].ttlbuf
= NULL
;
153 gdata_info
->gdata
[icol
].ttlbuflen
= 0;
154 gdata_info
->gdata
[icol
].ttlbufused
= 0;
158 /* ok, bind that column */
159 opts
->bindings
[icol
].buflen
= cbValueMax
;
160 opts
->bindings
[icol
].buffer
= (char *)rgbValue
;
161 opts
->bindings
[icol
].used
=
162 opts
->bindings
[icol
].indicator
= pcbValue
;
163 opts
->bindings
[icol
].returntype
= fCType
;
164 if (SQL_C_NUMERIC
== fCType
)
165 opts
->bindings
[icol
].precision
= 32;
167 opts
->bindings
[icol
].precision
= 0;
168 opts
->bindings
[icol
].scale
= 0;
170 mylog("bound buffer[%d] = %p\n", icol
,
171 opts
->bindings
[icol
].buffer
);
177 ret
= DiscardStatementSvp(stmt
, ret
, FALSE
);
183 * Returns the description of a parameter marker.
184 * This function is listed as not being supported by SQLGetFunctions() because it is
185 * used to describe "parameter markers" (not bound parameters), in which case,
186 * the dbms should return info on the markers. Since Postgres doesn't support that,
187 * it is best to say this function is not supported and let the application assume a
188 * data type (most likely varchar).
191 PGAPI_DescribeParam(HSTMT hstmt
,
193 SQLSMALLINT FAR
* pfSqlType
,
194 SQLULEN FAR
* pcbParamDef
,
195 SQLSMALLINT FAR
* pibScale
,
196 SQLSMALLINT FAR
* pfNullable
)
198 StatementClass
*stmt
= (StatementClass
*) hstmt
;
199 CSTR func
= "PGAPI_DescribeParam";
200 SC_set_error(stmt
, STMT_EXEC_ERROR
,
201 "SQLDescribeParam is not yet supported", func
);
207 * This function should really talk to the dbms to determine the number of
208 * "parameter markers" (not bound parameters) in the statement. But, since
209 * Postgres doesn't support that, the driver should just count the number
210 * of markers and return that. The reason the driver just can't say this
211 * function is unsupported like it does for SQLDescribeParam is that some
212 * applications don't care and try to call it anyway. If the statement does
213 * not have parameters, it should just return 0.
215 RETCODE SQL_API
PGAPI_NumParams(HSTMT hstmt
, SQLSMALLINT FAR
* pcpar
)
217 StatementClass
*stmt
= (StatementClass
*) hstmt
;
218 CSTR func
= "PGAPI_NumParams";
220 SC_set_error(stmt
, STMT_EXEC_ERROR
,
221 "PGAPI_NumParams is not yet supported", func
);
227 * Bindings Implementation
229 static BindInfoClass
*create_empty_bindings(int num_columns
)
231 BindInfoClass
*new_bindings
;
235 (BindInfoClass
*) malloc(num_columns
* sizeof(BindInfoClass
));
239 for (i
= 0; i
< num_columns
; i
++)
241 new_bindings
[i
].buflen
= 0;
242 new_bindings
[i
].buffer
= NULL
;
243 new_bindings
[i
].used
= new_bindings
[i
].indicator
= NULL
;
250 int CountParameters(const StatementClass
* self
, Int2
* inputCount
,
251 Int2
* ioCount
, Int2
* outputCount
)
253 IPDFields
*ipdopts
= SC_get_IPDF(self
);
254 int i
, num_params
, valid_count
;
264 num_params
= self
->num_params
;
265 if (ipdopts
->allocated
< num_params
)
266 num_params
= ipdopts
->allocated
;
267 for (i
= 0, valid_count
= 0; i
< num_params
; i
++)
269 if (SQL_PARAM_OUTPUT
== ipdopts
->parameters
[i
].paramType
)
276 } else if (SQL_PARAM_INPUT_OUTPUT
==
277 ipdopts
->parameters
[i
].paramType
)
284 } else if (inputCount
)
294 * Free parameters and free the memory.
296 void APD_free_params(APDFields
* apdopts
, char option
)
298 CSTR func
= "APD_free_params";
299 mylog("%s: ENTER, self=%p\n", func
, apdopts
);
301 if (!apdopts
->parameters
)
304 if (option
== STMT_FREE_PARAMS_ALL
)
306 free(apdopts
->parameters
);
307 apdopts
->parameters
= NULL
;
308 apdopts
->allocated
= 0;
311 mylog("%s: EXIT\n", func
);
315 * Free parameters and free the memory.
317 void IPD_free_params(IPDFields
* ipdopts
, char option
)
319 CSTR func
= "IPD_free_params";
321 mylog("%s: ENTER, self=%p\n", func
, ipdopts
);
323 if (!ipdopts
->parameters
)
325 if (option
== STMT_FREE_PARAMS_ALL
)
327 free(ipdopts
->parameters
);
328 ipdopts
->parameters
= NULL
;
329 ipdopts
->allocated
= 0;
332 mylog("%s: EXIT\n", func
);
335 void extend_column_bindings(ARDFields
* self
, int num_columns
)
337 CSTR func
= "extend_column_bindings";
338 BindInfoClass
*new_bindings
;
342 ("%s: entering ... self=%p, bindings_allocated=%d, num_columns=%d\n",
343 func
, self
, self
->allocated
, num_columns
);
346 * if we have too few, allocate room for more, and copy the old
347 * entries into the new structure
349 if (self
->allocated
< num_columns
)
351 new_bindings
= create_empty_bindings(num_columns
);
355 ("%s: unable to create %d new bindings from %d old bindings\n",
356 func
, num_columns
, self
->allocated
);
360 free(self
->bindings
);
361 self
->bindings
= NULL
;
369 for (i
= 0; i
< self
->allocated
; i
++)
370 new_bindings
[i
] = self
->bindings
[i
];
372 free(self
->bindings
);
375 self
->bindings
= new_bindings
;
376 self
->allocated
= num_columns
;
380 * There is no reason to zero out extra bindings if there are more
381 * than needed. If an app has allocated extra bindings, let it worry
382 * about it by unbinding those columns.
385 /* SQLBindCol(1..) ... SQLBindCol(10...) # got 10 bindings */
386 /* SQLExecDirect(...) # returns 5 cols */
387 /* SQLExecDirect(...) # returns 10 cols (now OK) */
389 mylog("exit %s=%p\n", func
, self
->bindings
);
392 void reset_a_column_binding(ARDFields
* self
, int icol
)
394 BindInfoClass
*bookmark
;
396 mylog("self=%p, allocated=%d, icol=%d\n",
397 self
, self
->allocated
, icol
);
399 if (icol
> self
->allocated
)
402 /* use zero based col numbers from here out */
405 if (bookmark
= self
->bookmark
, bookmark
!= NULL
)
407 bookmark
->buffer
= NULL
;
408 bookmark
->used
= bookmark
->indicator
= NULL
;
414 /* we have to unbind the column */
415 self
->bindings
[icol
].buflen
= 0;
416 self
->bindings
[icol
].buffer
= NULL
;
417 self
->bindings
[icol
].used
=
418 self
->bindings
[icol
].indicator
= NULL
;
419 self
->bindings
[icol
].returntype
= SQL_C_CHAR
;
423 void ARD_unbind_cols(ARDFields
* self
, BOOL freeall
)
427 inolog("ARD_unbind_cols freeall=%d allocated=%d bindings=%p",
428 freeall
, self
->allocated
, self
->bindings
);
429 for (lf
= 1; lf
<= self
->allocated
; lf
++)
430 reset_a_column_binding(self
, lf
);
434 free(self
->bindings
);
435 self
->bindings
= NULL
;
439 void GDATA_unbind_cols(GetDataInfo
* self
, BOOL freeall
)
443 inolog("GDATA_unbind_cols freeall=%d allocated=%d gdata=%p",
444 freeall
, self
->allocated
, self
->gdata
);
445 if (self
->fdata
.ttlbuf
)
447 free(self
->fdata
.ttlbuf
);
448 self
->fdata
.ttlbuf
= NULL
;
450 self
->fdata
.ttlbuflen
= self
->fdata
.ttlbufused
= 0;
451 self
->fdata
.data_left
= -1;
452 for (lf
= 1; lf
<= self
->allocated
; lf
++)
453 reset_a_getdata_info(self
, lf
);
463 void GetDataInfoInitialize(GetDataInfo
* gdata_info
)
465 gdata_info
->fdata
.data_left
= -1;
466 gdata_info
->fdata
.ttlbuf
= NULL
;
467 gdata_info
->fdata
.ttlbuflen
= gdata_info
->fdata
.ttlbufused
= 0;
468 gdata_info
->allocated
= 0;
469 gdata_info
->gdata
= NULL
;
471 static GetDataClass
*create_empty_gdata(int num_columns
)
473 GetDataClass
*new_gdata
;
477 (GetDataClass
*) malloc(num_columns
* sizeof(GetDataClass
));
481 for (i
= 0; i
< num_columns
; i
++)
483 new_gdata
[i
].data_left
= -1;
484 new_gdata
[i
].ttlbuf
= NULL
;
485 new_gdata
[i
].ttlbuflen
= 0;
486 new_gdata
[i
].ttlbufused
= 0;
492 void extend_getdata_info(GetDataInfo
* self
, int num_columns
, BOOL shrink
)
494 GetDataClass
*new_gdata
;
496 mylog("self=%p, allocated=%d, num_columns=%d\n",
497 self
, self
->allocated
, num_columns
);
500 * if we have too few, allocate room for more, and copy the old
501 * entries into the new structure
503 if (self
->allocated
< num_columns
)
505 new_gdata
= create_empty_gdata(num_columns
);
509 ("unable to create %d new gdata from %d old gdata\n",
510 num_columns
, self
->allocated
);
524 for (i
= 0; i
< self
->allocated
; i
++)
525 new_gdata
[i
] = self
->gdata
[i
];
528 self
->gdata
= new_gdata
;
529 self
->allocated
= num_columns
;
530 } else if (shrink
&& self
->allocated
> num_columns
)
534 for (i
= self
->allocated
; i
> num_columns
; i
--)
535 reset_a_getdata_info(self
, i
);
536 self
->allocated
= num_columns
;
537 if (0 == num_columns
)
545 * There is no reason to zero out extra gdata if there are more
546 * than needed. If an app has allocated extra gdata, let it worry
547 * about it by unbinding those columns.
550 mylog("exit(%p)\n", self
->gdata
);
553 void reset_a_getdata_info(GetDataInfo
* gdata_info
, int icol
)
555 if (icol
< 1 || icol
> gdata_info
->allocated
)
558 if (gdata_info
->gdata
[icol
].ttlbuf
)
560 free(gdata_info
->gdata
[icol
].ttlbuf
);
561 gdata_info
->gdata
[icol
].ttlbuf
= NULL
;
563 gdata_info
->gdata
[icol
].ttlbuflen
=
564 gdata_info
->gdata
[icol
].ttlbufused
= 0;
565 gdata_info
->gdata
[icol
].data_left
= -1;