]> granicus.if.org Git - postgresql/blob - src/interfaces/odbc/bind.c
ce1723654865d07fb70103c69ac7f0d4f22ce64b
[postgresql] / src / interfaces / odbc / bind.c
1 /*-------
2  * Module:                      bind.c
3  *
4  * Description:         This module contains routines related to binding
5  *                                      columns and parameters.
6  *
7  * Classes:                     BindInfoClass, ParameterInfoClass
8  *
9  * API functions:       SQLBindParameter, SQLBindCol, SQLDescribeParam, SQLNumParams,
10  *                                      SQLParamOptions(NI)
11  *
12  * Comments:            See "notice.txt" for copyright and license information.
13  *-------
14  */
15
16 #include "bind.h"
17
18 #include "environ.h"
19 #include "statement.h"
20 #include "qresult.h"
21 #include "pgtypes.h"
22 #include <stdlib.h>
23 #include <string.h>
24
25 #ifndef WIN32
26 #include "iodbc.h"
27 #include "isql.h"
28 #include "isqlext.h"
29 #else
30 #include "sql.h"
31 #include "sqlext.h"
32 #endif
33 #include "pgapifunc.h"
34
35
36 /*              Bind parameters on a statement handle */
37 RETCODE SQL_API
38 PGAPI_BindParameter(
39                                  HSTMT hstmt,
40                                  UWORD ipar,
41                                  SWORD fParamType,
42                                  SWORD fCType,
43                                  SWORD fSqlType,
44                                  UDWORD cbColDef,
45                                  SWORD ibScale,
46                                  PTR rgbValue,
47                                  SDWORD cbValueMax,
48                                  SDWORD FAR *pcbValue)
49 {
50         StatementClass *stmt = (StatementClass *) hstmt;
51         static char *func = "PGAPI_BindParameter";
52
53         mylog("%s: entering...\n", func);
54
55         if (!stmt)
56         {
57                 SC_log_error(func, "", NULL);
58                 return SQL_INVALID_HANDLE;
59         }
60         SC_clear_error(stmt);
61
62         if (stmt->parameters_allocated < ipar)
63         {
64                 ParameterInfoClass *old_parameters;
65                 int                     i,
66                                         old_parameters_allocated;
67
68                 old_parameters = stmt->parameters;
69                 old_parameters_allocated = stmt->parameters_allocated;
70
71                 stmt->parameters = (ParameterInfoClass *) malloc(sizeof(ParameterInfoClass) * (ipar));
72                 if (!stmt->parameters)
73                 {
74                         stmt->errornumber = STMT_NO_MEMORY_ERROR;
75                         stmt->errormsg = "Could not allocate memory for statement parameters";
76                         SC_log_error(func, "", stmt);
77                         return SQL_ERROR;
78                 }
79
80                 stmt->parameters_allocated = ipar;
81
82                 /* copy the old parameters over */
83                 for (i = 0; i < old_parameters_allocated; i++)
84                 {
85                         /* a structure copy should work */
86                         stmt->parameters[i] = old_parameters[i];
87                 }
88
89                 /* get rid of the old parameters, if there were any */
90                 if (old_parameters)
91                         free(old_parameters);
92
93                 /*
94                  * zero out the newly allocated parameters (in case they skipped
95                  * some,
96                  */
97                 /* so we don't accidentally try to use them later) */
98                 for (; i < stmt->parameters_allocated; i++)
99                 {
100                         stmt->parameters[i].buflen = 0;
101                         stmt->parameters[i].buffer = 0;
102                         stmt->parameters[i].used = 0;
103                         stmt->parameters[i].paramType = 0;
104                         stmt->parameters[i].CType = 0;
105                         stmt->parameters[i].SQLType = 0;
106                         stmt->parameters[i].precision = 0;
107                         stmt->parameters[i].scale = 0;
108                         stmt->parameters[i].data_at_exec = FALSE;
109                         stmt->parameters[i].lobj_oid = 0;
110                         stmt->parameters[i].EXEC_used = NULL;
111                         stmt->parameters[i].EXEC_buffer = NULL;
112                 }
113         }
114
115         /* use zero based column numbers for the below part */
116         ipar--;
117
118         /* store the given info */
119         stmt->parameters[ipar].buflen = cbValueMax;
120         stmt->parameters[ipar].buffer = rgbValue;
121         stmt->parameters[ipar].used = pcbValue;
122         stmt->parameters[ipar].paramType = fParamType;
123         stmt->parameters[ipar].CType = fCType;
124         stmt->parameters[ipar].SQLType = fSqlType;
125         stmt->parameters[ipar].precision = cbColDef;
126         stmt->parameters[ipar].scale = ibScale;
127
128         /*
129          * If rebinding a parameter that had data-at-exec stuff in it, then
130          * free that stuff
131          */
132         if (stmt->parameters[ipar].EXEC_used)
133         {
134                 free(stmt->parameters[ipar].EXEC_used);
135                 stmt->parameters[ipar].EXEC_used = NULL;
136         }
137
138         if (stmt->parameters[ipar].EXEC_buffer)
139         {
140                 if (stmt->parameters[ipar].SQLType != SQL_LONGVARBINARY)
141                         free(stmt->parameters[ipar].EXEC_buffer);
142                 stmt->parameters[ipar].EXEC_buffer = NULL;
143         }
144
145         /* Data at exec macro only valid for C char/binary data */
146         if (pcbValue && (*pcbValue == SQL_DATA_AT_EXEC ||
147                                          *pcbValue <= SQL_LEN_DATA_AT_EXEC_OFFSET))
148                 stmt->parameters[ipar].data_at_exec = TRUE;
149         else
150                 stmt->parameters[ipar].data_at_exec = FALSE;
151
152         /* Clear premature result */
153         if (stmt->status == STMT_PREMATURE)
154                 SC_recycle_statement(stmt);
155
156         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, stmt->parameters[ipar].data_at_exec);
157
158         return SQL_SUCCESS;
159 }
160
161
162 /*      Associate a user-supplied buffer with a database column. */
163 RETCODE SQL_API
164 PGAPI_BindCol(
165                    HSTMT hstmt,
166                    UWORD icol,
167                    SWORD fCType,
168                    PTR rgbValue,
169                    SDWORD cbValueMax,
170                    SDWORD FAR *pcbValue)
171 {
172         StatementClass *stmt = (StatementClass *) hstmt;
173         static char *func = "PGAPI_BindCol";
174
175         mylog("%s: entering...\n", func);
176
177         mylog("**** PGAPI_BindCol: stmt = %u, icol = %d\n", stmt, icol);
178 mylog("**** : fCType=%d rgb=%x valusMax=%d pcb=%x\n", fCType, rgbValue, cbValueMax, pcbValue);
179
180         if (!stmt)
181         {
182                 SC_log_error(func, "", NULL);
183                 return SQL_INVALID_HANDLE;
184         }
185
186
187         SC_clear_error(stmt);
188
189         if (stmt->status == STMT_EXECUTING)
190         {
191                 stmt->errormsg = "Can't bind columns while statement is still executing.";
192                 stmt->errornumber = STMT_SEQUENCE_ERROR;
193                 SC_log_error(func, "", stmt);
194                 return SQL_ERROR;
195         }
196
197         /* If the bookmark column is being bound, then just save it */
198         if (icol == 0)
199         {
200                 if (rgbValue == NULL)
201                 {
202                         stmt->bookmark.buffer = NULL;
203                         stmt->bookmark.used = NULL;
204                 }
205                 else
206                 {
207                         /* Make sure it is the bookmark data type */
208                         if (fCType != SQL_C_BOOKMARK)
209                         {
210                                 stmt->errormsg = "Column 0 is not of type SQL_C_BOOKMARK";
211                                 stmt->errornumber = STMT_PROGRAM_TYPE_OUT_OF_RANGE;
212                                 SC_log_error(func, "", stmt);
213                                 return SQL_ERROR;
214                         }
215
216                         stmt->bookmark.buffer = rgbValue;
217                         stmt->bookmark.used = pcbValue;
218                 }
219                 return SQL_SUCCESS;
220         }
221
222         /*
223          * Allocate enough bindings if not already done. Most likely,
224          * execution of a statement would have setup the necessary bindings.
225          * But some apps call BindCol before any statement is executed.
226          */
227         if (icol > stmt->bindings_allocated)
228                 extend_bindings(stmt, icol);
229
230         /* check to see if the bindings were allocated */
231         if (!stmt->bindings)
232         {
233                 stmt->errormsg = "Could not allocate memory for bindings.";
234                 stmt->errornumber = STMT_NO_MEMORY_ERROR;
235                 SC_log_error(func, "", stmt);
236                 return SQL_ERROR;
237         }
238
239         /* use zero based col numbers from here out */
240         icol--;
241
242         /* Reset for SQLGetData */
243         stmt->bindings[icol].data_left = -1;
244
245         if (rgbValue == NULL)
246         {
247                 /* we have to unbind the column */
248                 stmt->bindings[icol].buflen = 0;
249                 stmt->bindings[icol].buffer = NULL;
250                 stmt->bindings[icol].used = NULL;
251                 stmt->bindings[icol].returntype = SQL_C_CHAR;
252         }
253         else
254         {
255                 /* ok, bind that column */
256                 stmt->bindings[icol].buflen = cbValueMax;
257                 stmt->bindings[icol].buffer = rgbValue;
258                 stmt->bindings[icol].used = pcbValue;
259                 stmt->bindings[icol].returntype = fCType;
260
261                 mylog("       bound buffer[%d] = %u\n", icol, stmt->bindings[icol].buffer);
262         }
263
264         return SQL_SUCCESS;
265 }
266
267
268 /*
269  *      Returns the description of a parameter marker.
270  *      This function is listed as not being supported by SQLGetFunctions() because it is
271  *      used to describe "parameter markers" (not bound parameters), in which case,
272  *      the dbms should return info on the markers.  Since Postgres doesn't support that,
273  *      it is best to say this function is not supported and let the application assume a
274  *      data type (most likely varchar).
275  */
276 RETCODE SQL_API
277 PGAPI_DescribeParam(
278                                  HSTMT hstmt,
279                                  UWORD ipar,
280                                  SWORD FAR *pfSqlType,
281                                  UDWORD FAR *pcbColDef,
282                                  SWORD FAR *pibScale,
283                                  SWORD FAR *pfNullable)
284 {
285         StatementClass *stmt = (StatementClass *) hstmt;
286         static char *func = "PGAPI_DescribeParam";
287
288         mylog("%s: entering...\n", func);
289
290         if (!stmt)
291         {
292                 SC_log_error(func, "", NULL);
293                 return SQL_INVALID_HANDLE;
294         }
295         SC_clear_error(stmt);
296
297         if ((ipar < 1) || (ipar > stmt->parameters_allocated))
298         {
299                 stmt->errormsg = "Invalid parameter number for PGAPI_DescribeParam.";
300                 stmt->errornumber = STMT_BAD_PARAMETER_NUMBER_ERROR;
301                 SC_log_error(func, "", stmt);
302                 return SQL_ERROR;
303         }
304
305         ipar--;
306
307         /*
308          * This implementation is not very good, since it is supposed to
309          * describe
310          */
311         /* parameter markers, not bound parameters.  */
312         if (pfSqlType)
313                 *pfSqlType = stmt->parameters[ipar].SQLType;
314
315         if (pcbColDef)
316                 *pcbColDef = stmt->parameters[ipar].precision;
317
318         if (pibScale)
319                 *pibScale = stmt->parameters[ipar].scale;
320
321         if (pfNullable)
322                 *pfNullable = pgtype_nullable(stmt, stmt->parameters[ipar].paramType);
323
324         return SQL_SUCCESS;
325 }
326
327
328 /*      Sets multiple values (arrays) for the set of parameter markers. */
329 RETCODE SQL_API
330 PGAPI_ParamOptions(
331                                 HSTMT hstmt,
332                                 UDWORD crow,
333                                 UDWORD FAR *pirow)
334 {
335         static char *func = "PGAPI_ParamOptions";
336         StatementClass  *stmt = (StatementClass *) hstmt;
337
338         mylog("%s: entering... %d %x\n", func, crow, pirow);
339
340         if (crow == 1) /* temporary solution and must be rewritten later */
341         {
342                 if (pirow)
343                         *pirow = 1;
344                 return SQL_SUCCESS;
345         }
346         stmt->errornumber = CONN_UNSUPPORTED_OPTION;
347         stmt->errormsg = "Function not implemented";
348         SC_log_error(func, "Function not implemented", (StatementClass *) hstmt);
349         return SQL_ERROR;
350 }
351
352
353 /*
354  *      This function should really talk to the dbms to determine the number of
355  *      "parameter markers" (not bound parameters) in the statement.  But, since
356  *      Postgres doesn't support that, the driver should just count the number of markers
357  *      and return that.  The reason the driver just can't say this function is unsupported
358  *      like it does for SQLDescribeParam is that some applications don't care and try
359  *      to call it anyway.
360  *      If the statement does not have parameters, it should just return 0.
361  */
362 RETCODE SQL_API
363 PGAPI_NumParams(
364                          HSTMT hstmt,
365                          SWORD FAR *pcpar)
366 {
367         StatementClass *stmt = (StatementClass *) hstmt;
368         char            in_quote = FALSE;
369         unsigned int i;
370         static char *func = "PGAPI_NumParams";
371
372         mylog("%s: entering...\n", func);
373
374         if (!stmt)
375         {
376                 SC_log_error(func, "", NULL);
377                 return SQL_INVALID_HANDLE;
378         }
379         SC_clear_error(stmt);
380
381         if (pcpar)
382                 *pcpar = 0;
383         else
384         {
385                 SC_log_error(func, "pcpar was null", stmt);
386                 return SQL_ERROR;
387         }
388
389
390         if (!stmt->statement)
391         {
392                 /* no statement has been allocated */
393                 stmt->errormsg = "PGAPI_NumParams called with no statement ready.";
394                 stmt->errornumber = STMT_SEQUENCE_ERROR;
395                 SC_log_error(func, "", stmt);
396                 return SQL_ERROR;
397         }
398         else
399         {
400                 for (i = 0; i < strlen(stmt->statement); i++)
401                 {
402                         if (stmt->statement[i] == '?' && !in_quote)
403                                 (*pcpar)++;
404                         else
405                         {
406                                 if (stmt->statement[i] == '\'')
407                                         in_quote = (in_quote ? FALSE : TRUE);
408                         }
409                 }
410                 return SQL_SUCCESS;
411         }
412 }
413
414
415 /*
416  *       Bindings Implementation
417  */
418 BindInfoClass *
419 create_empty_bindings(int num_columns)
420 {
421         BindInfoClass *new_bindings;
422         int                     i;
423
424         new_bindings = (BindInfoClass *) malloc(num_columns * sizeof(BindInfoClass));
425         if (!new_bindings)
426                 return 0;
427
428         for (i = 0; i < num_columns; i++)
429         {
430                 new_bindings[i].buflen = 0;
431                 new_bindings[i].buffer = NULL;
432                 new_bindings[i].used = NULL;
433                 new_bindings[i].data_left = -1;
434         }
435
436         return new_bindings;
437 }
438
439
440 void
441 extend_bindings(StatementClass *stmt, int num_columns)
442 {
443         static char *func = "extend_bindings";
444         BindInfoClass *new_bindings;
445         int                     i;
446
447         mylog("%s: entering ... stmt=%u, bindings_allocated=%d, num_columns=%d\n", func, stmt, stmt->bindings_allocated, num_columns);
448
449         /*
450          * if we have too few, allocate room for more, and copy the old
451          * entries into the new structure
452          */
453         if (stmt->bindings_allocated < num_columns)
454         {
455                 new_bindings = create_empty_bindings(num_columns);
456                 if (!new_bindings)
457                 {
458                         mylog("%s: unable to create %d new bindings from %d old bindings\n", func, num_columns, stmt->bindings_allocated);
459
460                         if (stmt->bindings)
461                         {
462                                 free(stmt->bindings);
463                                 stmt->bindings = NULL;
464                         }
465                         stmt->bindings_allocated = 0;
466                         return;
467                 }
468
469                 if (stmt->bindings)
470                 {
471                         for (i = 0; i < stmt->bindings_allocated; i++)
472                                 new_bindings[i] = stmt->bindings[i];
473
474                         free(stmt->bindings);
475                 }
476
477                 stmt->bindings = new_bindings;
478                 stmt->bindings_allocated = num_columns;
479         }
480
481         /*
482          * There is no reason to zero out extra bindings if there are more
483          * than needed.  If an app has allocated extra bindings, let it worry
484          * about it by unbinding those columns.
485          */
486
487         /* SQLBindCol(1..) ... SQLBindCol(10...)   # got 10 bindings */
488         /* SQLExecDirect(...)  # returns 5 cols */
489         /* SQLExecDirect(...)  # returns 10 cols  (now OK) */
490
491         mylog("exit extend_bindings\n");
492 }