1 /*-------
2 * Module: execute.c
3 *
4 * Description: This module contains routines related to
5 * preparing and executing an SQL statement.
6 *
7 * Classes: n/a
8 *
9 * API functions: SQLPrepare, SQLExecute, SQLExecDirect, SQLTransact,
10 * SQLCancel, SQLNativeSql, SQLParamData, SQLPutData
11 *
12 * Comments: See "readme.txt" for copyright and license information.
13 *-------
14 */
15
16 #include "psqlodbc.h"
17 #include "misc.h"
18
19 #include <stdio.h>
20 #include <string.h>
21
22 #ifndef WIN32
23 #include <ctype.h>
24 #endif /* WIN32 */
25
26 #include "environ.h"
27 #include "connection.h"
28 #include "statement.h"
29 #include "qresult.h"
30 #include "convert.h"
31 #include "bind.h"
32 #include "pgtypes.h"
33 #include "lobj.h"
34 #include "pgapifunc.h"
35
36 /* Perform a Prepare on the SQL statement */
37 RETCODE SQL_API
PGAPI_Prepare(HSTMT hstmt,const SQLCHAR * szSqlStr,SQLINTEGER cbSqlStr)38 PGAPI_Prepare(HSTMT hstmt,
39 const SQLCHAR * szSqlStr,
40 SQLINTEGER cbSqlStr)
41 {
42 CSTR func = "PGAPI_Prepare";
43 StatementClass *self = (StatementClass *) hstmt;
44 RETCODE retval = SQL_SUCCESS;
45 BOOL prepared;
46
47 MYLOG(0, "entering...\n");
48
49 #define return DONT_CALL_RETURN_FROM_HERE???
50 /* StartRollbackState(self); */
51
52 /*
53 * According to the ODBC specs it is valid to call SQLPrepare multiple
54 * times. In that case, the bound SQL statement is replaced by the new
55 * one
56 */
57
58 prepared = self->prepared;
59 SC_set_prepared(self, NOT_YET_PREPARED);
60 switch (self->status)
61 {
62 case STMT_DESCRIBED:
63 MYLOG(0, "**** STMT_DESCRIBED, recycle\n");
64 SC_recycle_statement(self); /* recycle the statement, but do
65 * not remove parameter bindings */
66 break;
67
68 case STMT_FINISHED:
69 MYLOG(0, "**** STMT_FINISHED, recycle\n");
70 SC_recycle_statement(self); /* recycle the statement, but do
71 * not remove parameter bindings */
72 break;
73
74 case STMT_ALLOCATED:
75 MYLOG(0, "**** STMT_ALLOCATED, copy\n");
76 self->status = STMT_READY;
77 break;
78
79 case STMT_READY:
80 MYLOG(0, "**** STMT_READY, change SQL\n");
81 if (NOT_YET_PREPARED != prepared)
82 SC_recycle_statement(self); /* recycle the statement */
83 break;
84
85 case STMT_EXECUTING:
86 MYLOG(0, "**** STMT_EXECUTING, error!\n");
87
88 SC_set_error(self, STMT_SEQUENCE_ERROR, "PGAPI_Prepare(): The handle does not point to a statement that is ready to be executed", func);
89
90 retval = SQL_ERROR;
91 goto cleanup;
92
93 default:
94 SC_set_error(self, STMT_INTERNAL_ERROR, "An Internal Error has occured -- Unknown statement status.", func);
95 retval = SQL_ERROR;
96 goto cleanup;
97 }
98
99 SC_initialize_stmts(self, TRUE);
100
101 if (!szSqlStr)
102 {
103 SC_set_error(self, STMT_NO_MEMORY_ERROR, "the query is NULL", func);
104 retval = SQL_ERROR;
105 goto cleanup;
106 }
107 if (!szSqlStr[0])
108 self->statement = strdup("");
109 else
110 self->statement = make_string(szSqlStr, cbSqlStr, NULL, 0);
111 if (!self->statement)
112 {
113 SC_set_error(self, STMT_NO_MEMORY_ERROR, "No memory available to store statement", func);
114 retval = SQL_ERROR;
115 goto cleanup;
116 }
117
118 self->prepare = PREPARE_STATEMENT;
119 self->statement_type = statement_type(self->statement);
120
121 /* Check if connection is onlyread (only selects are allowed) */
122 if (CC_is_onlyread(SC_get_conn(self)) && STMT_UPDATE(self))
123 {
124 SC_set_error(self, STMT_EXEC_ERROR, "Connection is readonly, only select statements are allowed.", func);
125 retval = SQL_ERROR;
126 goto cleanup;
127 }
128
129 cleanup:
130 #undef return
131 MYLOG(DETAIL_LOG_LEVEL, "leaving %d\n", retval);
132 return retval;
133 }
134
135
136 /* Performs the equivalent of SQLPrepare, followed by SQLExecute. */
137 RETCODE SQL_API
PGAPI_ExecDirect(HSTMT hstmt,const SQLCHAR * szSqlStr,SQLINTEGER cbSqlStr,UWORD flag)138 PGAPI_ExecDirect(HSTMT hstmt,
139 const SQLCHAR * szSqlStr,
140 SQLINTEGER cbSqlStr,
141 UWORD flag)
142 {
143 StatementClass *stmt = (StatementClass *) hstmt;
144 RETCODE result;
145 CSTR func = "PGAPI_ExecDirect";
146 const ConnectionClass *conn = SC_get_conn(stmt);
147
148 MYLOG(0, "entering...%x\n", flag);
149
150 if (result = SC_initialize_and_recycle(stmt), SQL_SUCCESS != result)
151 return result;
152
153 /*
154 * keep a copy of the un-parametrized statement, in case they try to
155 * execute this statement again
156 */
157 stmt->statement = make_string(szSqlStr, cbSqlStr, NULL, 0);
158 MYLOG(DETAIL_LOG_LEVEL, "a2\n");
159 if (!stmt->statement)
160 {
161 SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "No memory available to store statement", func);
162 return SQL_ERROR;
163 }
164
165 MYLOG(0, "**** hstmt=%p, statement='%s'\n", hstmt, stmt->statement);
166
167 if (0 != (flag & PODBC_WITH_HOLD))
168 SC_set_with_hold(stmt);
169 if (0 != (flag & PODBC_RDONLY))
170 SC_set_readonly(stmt);
171
172 /*
173 * If an SQLPrepare was performed prior to this, but was left in the
174 * described state because an error occurred prior to SQLExecute then
175 * set the statement to finished so it can be recycled.
176 */
177 if (stmt->status == STMT_DESCRIBED)
178 stmt->status = STMT_FINISHED;
179
180 stmt->statement_type = statement_type(stmt->statement);
181
182 /* Check if connection is onlyread (only selects are allowed) */
183 if (CC_is_onlyread(conn) && STMT_UPDATE(stmt))
184 {
185 SC_set_error(stmt, STMT_EXEC_ERROR, "Connection is readonly, only select statements are allowed.", func);
186 return SQL_ERROR;
187 }
188
189 MYLOG(0, "calling PGAPI_Execute...\n");
190
191 result = PGAPI_Execute(hstmt, flag);
192
193 MYLOG(0, "leaving %hd\n", result);
194 return result;
195 }
196
197 static int
inquireHowToPrepare(const StatementClass * stmt)198 inquireHowToPrepare(const StatementClass *stmt)
199 {
200 ConnectionClass *conn;
201 ConnInfo *ci;
202 int ret = 0;
203
204 conn = SC_get_conn(stmt);
205 ci = &(conn->connInfo);
206 if (!stmt->use_server_side_prepare)
207 {
208 /* Do prepare operations by the driver itself */
209 return PREPARE_BY_THE_DRIVER;
210 }
211 if (NOT_YET_PREPARED == stmt->prepared)
212 {
213 SQLSMALLINT num_params;
214
215 if (STMT_TYPE_DECLARE == stmt->statement_type &&
216 PG_VERSION_LT(conn, 8.0))
217 {
218 return PREPARE_BY_THE_DRIVER;
219 }
220 if (stmt->multi_statement < 0)
221 PGAPI_NumParams((StatementClass *) stmt, &num_params);
222 if (stmt->multi_statement > 0)
223 {
224 /*
225 * divide the query into multiple commands and apply V3 parse
226 * requests for each of them
227 */
228 ret = PARSE_REQ_FOR_INFO;
229 }
230 else
231 {
232 if (SC_may_use_cursor(stmt))
233 {
234 if (ci->drivers.use_declarefetch)
235 return PARSE_REQ_FOR_INFO;
236 else if (SQL_CURSOR_FORWARD_ONLY != stmt->options.cursor_type)
237 ret = PARSE_REQ_FOR_INFO;
238 else
239 ret = PARSE_TO_EXEC_ONCE;
240 }
241 else
242 ret = PARSE_TO_EXEC_ONCE;
243 }
244 }
245 if (SC_is_prepare_statement(stmt) && (PARSE_TO_EXEC_ONCE == ret))
246 ret = NAMED_PARSE_REQUEST;
247
248 return ret;
249 }
250
251 int
decideHowToPrepare(StatementClass * stmt,BOOL force)252 decideHowToPrepare(StatementClass *stmt, BOOL force)
253 {
254 int method = SC_get_prepare_method(stmt);
255
256 if (0 != method) /* a method was already determined */
257 return method;
258 switch (stmt->prepare)
259 {
260 case NON_PREPARE_STATEMENT: /* not a prepare statement */
261 if (!force)
262 return method;
263 break;
264 }
265 method = inquireHowToPrepare(stmt);
266 stmt->prepare |= method;
267 if (PREPARE_BY_THE_DRIVER == method)
268 stmt->discard_output_params = 1;
269 return method;
270 }
271
272 /* dont/should/can send Parse request ? */
273 enum {
274 doNothing = 0
275 ,allowParse
276 ,preferParse
277 ,shouldParse
278 ,usingCommand
279 };
280
281 #define ONESHOT_CALL_PARSE allowParse
282 #define NOPARAM_ONESHOT_CALL_PARSE doNothing
283
284 static
HowToPrepareBeforeExec(StatementClass * stmt,BOOL checkOnly)285 int HowToPrepareBeforeExec(StatementClass *stmt, BOOL checkOnly)
286 {
287 SQLSMALLINT num_params = stmt->num_params;
288 ConnectionClass *conn = SC_get_conn(stmt);
289 ConnInfo *ci = &(conn->connInfo);
290 int nCallParse = doNothing, how_to_prepare = 0;
291 BOOL bNeedsTrans = FALSE;
292
293 if (num_params < 0)
294 PGAPI_NumParams(stmt, &num_params);
295 how_to_prepare = decideHowToPrepare(stmt, checkOnly);
296 if (checkOnly)
297 {
298 if (num_params <= 0)
299 return doNothing;
300 }
301 else
302 {
303 switch (how_to_prepare)
304 {
305 case NAMED_PARSE_REQUEST:
306 return shouldParse;
307 case PARSE_TO_EXEC_ONCE:
308 switch (stmt->prepared)
309 {
310 case PREPARED_TEMPORARILY:
311 nCallParse = preferParse;
312 break;
313 default:
314 if (num_params <= 0)
315 nCallParse = NOPARAM_ONESHOT_CALL_PARSE;
316 else
317 nCallParse = ONESHOT_CALL_PARSE;
318 }
319 break;
320 default:
321 return doNothing;
322 }
323 }
324
325 if (num_params > 0)
326 {
327 int param_number = -1;
328 ParameterInfoClass *apara;
329 ParameterImplClass *ipara;
330 OID pgtype;
331
332 while (TRUE)
333 {
334 SC_param_next(stmt, ¶m_number, &apara, &ipara);
335 if (!ipara || !apara)
336 break;
337 pgtype = PIC_get_pgtype(*ipara);
338 if (checkOnly)
339 {
340 switch (ipara->SQLType)
341 {
342 case SQL_LONGVARBINARY:
343 if (0 == pgtype)
344 {
345 if (ci->bytea_as_longvarbinary &&
346 0 != conn->lobj_type)
347 nCallParse = shouldParse;
348 }
349 break;
350 case SQL_CHAR:
351 if (ci->cvt_null_date_string)
352 nCallParse = shouldParse;
353 break;
354 case SQL_VARCHAR:
355 if (ci->drivers.bools_as_char &&
356 PG_WIDTH_OF_BOOLS_AS_CHAR == ipara->column_size)
357 nCallParse = shouldParse;
358 break;
359 }
360 }
361 else
362 {
363 BOOL bBytea = FALSE;
364
365 switch (ipara->SQLType)
366 {
367 case SQL_LONGVARBINARY:
368 if (conn->lobj_type == pgtype || PG_TYPE_OID == pgtype)
369 bNeedsTrans = TRUE;
370 else if (PG_TYPE_BYTEA == pgtype)
371 bBytea = TRUE;
372 else if (0 == pgtype)
373 {
374 if (ci->bytea_as_longvarbinary)
375 bBytea = TRUE;
376 else
377 bNeedsTrans = TRUE;
378 }
379 if (bBytea)
380 if (nCallParse < preferParse)
381 nCallParse = preferParse;
382 break;
383 }
384 }
385 }
386 }
387 if (bNeedsTrans &&
388 PARSE_TO_EXEC_ONCE == how_to_prepare)
389 {
390 if (!CC_is_in_trans(conn) && CC_does_autocommit(conn))
391 nCallParse = doNothing;
392 }
393 return nCallParse;
394 }
395
396 static
GetSvpName(const ConnectionClass * conn,char * wrk,int wrksize)397 const char *GetSvpName(const ConnectionClass *conn, char *wrk, int wrksize)
398 {
399 snprintf(wrk, wrksize, "_EXEC_SVP_%p", conn);
400 return wrk;
401 }
402
403 /*
404 * The execution after all parameters were resolved.
405 */
406
407 #define INVALID_EXPBUFFER PQExpBufferDataBroken(stmt->stmt_deffered)
408 #define VALID_EXPBUFFER (!PQExpBufferDataBroken(stmt->stmt_deffered))
409
410 static
param_status_batch_update(IPDFields * ipdopts,RETCODE retval,SQLLEN target_row,int count_of_deffered)411 void param_status_batch_update(IPDFields *ipdopts, RETCODE retval, SQLLEN target_row, int count_of_deffered)
412 {
413 int i, j;
414 if (NULL != ipdopts->param_status_ptr)
415 {
416 for (i = target_row, j = 0; i >= 0 && j <= count_of_deffered; i--)
417 {
418 if (SQL_PARAM_UNUSED != ipdopts->param_status_ptr[i])
419 {
420 ipdopts->param_status_ptr[i] = retval;
421 j++;
422 }
423 }
424 }
425 }
426
427 static
Exec_with_parameters_resolved(StatementClass * stmt,EXEC_TYPE exec_type,BOOL * exec_end)428 RETCODE Exec_with_parameters_resolved(StatementClass *stmt, EXEC_TYPE exec_type, BOOL *exec_end)
429 {
430 CSTR func = "Exec_with_parameters_resolved";
431 RETCODE retval;
432 SQLLEN start_row, end_row;
433 SQLINTEGER cursor_type, scroll_concurrency;
434 ConnectionClass *conn;
435 QResultClass *res;
436 APDFields *apdopts;
437 IPDFields *ipdopts;
438 BOOL prepare_before_exec = FALSE;
439 char *stmt_with_params;
440 SQLLEN status_row = stmt->exec_current_row;
441 int count_of_deffered;
442
443 *exec_end = FALSE;
444 conn = SC_get_conn(stmt);
445 MYLOG(0, "copying statement params: trans_status=%d, len=" FORMAT_SIZE_T ", stmt='%s'\n", conn->transact_status, strlen(stmt->statement), stmt->statement);
446
447 #define return DONT_CALL_RETURN_FROM_HERE???
448 #define RETURN(code) { retval = code; goto cleanup; }
449 ENTER_CONN_CS(conn);
450 /* save the cursor's info before the execution */
451 cursor_type = stmt->options.cursor_type;
452 scroll_concurrency = stmt->options.scroll_concurrency;
453 /* Prepare the statement if possible at backend side */
454 if (HowToPrepareBeforeExec(stmt, FALSE) >= allowParse)
455 prepare_before_exec = TRUE;
456
457 MYLOG(DETAIL_LOG_LEVEL, "prepare_before_exec=%d srv=%d\n", prepare_before_exec, stmt->use_server_side_prepare);
458 /* Create the statement with parameters substituted. */
459 stmt_with_params = stmt->stmt_with_params;
460 if (LAST_EXEC == exec_type)
461 {
462 if (NULL != stmt_with_params)
463 {
464 free(stmt_with_params);
465 stmt_with_params = stmt->stmt_with_params = NULL;
466 }
467 if (INVALID_EXPBUFFER ||
468 !stmt->stmt_deffered.data[0])
469 RETURN(SQL_SUCCESS);
470 }
471 else
472 {
473 retval = copy_statement_with_parameters(stmt, prepare_before_exec);
474 stmt->current_exec_param = -1;
475 if (retval != SQL_SUCCESS)
476 {
477 stmt->exec_current_row = -1;
478 *exec_end = TRUE;
479 RETURN(retval) /* error msg is passed from the above */
480 }
481 stmt_with_params = stmt->stmt_with_params;
482 if (!stmt_with_params) // Extended Protocol
483 exec_type = DIRECT_EXEC;
484 }
485
486 MYLOG(0, " stmt_with_params = '%s'\n", stmt->stmt_with_params);
487
488 /*
489 * The real execution.
490 */
491 MYLOG(0, "about to begin SC_execute exec_type=%d\n", exec_type);
492 ipdopts = SC_get_IPDF(stmt);
493 apdopts = SC_get_APDF(stmt);
494 if (start_row = stmt->exec_start_row, start_row < 0)
495 start_row = 0;
496 if (end_row = stmt->exec_end_row, end_row < 0)
497 {
498 end_row = (SQLINTEGER) apdopts->paramset_size - 1;
499 if (end_row < 0)
500 end_row = 0;
501 }
502 if (LAST_EXEC == exec_type &&
503 NULL != ipdopts->param_status_ptr)
504 {
505 int i;
506 for (i = end_row; i >= start_row; i--)
507 {
508 if (SQL_PARAM_UNUSED != ipdopts->param_status_ptr[i])
509 {
510 status_row = i;
511 break;
512 }
513 }
514 }
515 count_of_deffered = stmt->count_of_deffered;
516 if (DIRECT_EXEC == exec_type)
517 {
518 retval = SC_execute(stmt);
519 stmt->count_of_deffered = 0;
520 }
521 else if (DEFFERED_EXEC == exec_type &&
522 stmt->exec_current_row < end_row &&
523 stmt->count_of_deffered + 1 < stmt->batch_size)
524 {
525 if (INVALID_EXPBUFFER)
526 initPQExpBuffer(&stmt->stmt_deffered);
527 if (INVALID_EXPBUFFER)
528 {
529 retval = SQL_ERROR;
530 SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory", __FUNCTION__);
531 }
532 else
533 {
534 if (NULL != stmt_with_params)
535 {
536 if (stmt->stmt_deffered.data[0])
537 appendPQExpBuffer(&stmt->stmt_deffered, ";%s", stmt_with_params);
538 else
539 printfPQExpBuffer(&stmt->stmt_deffered, "%s", stmt_with_params);
540 }
541 if (NULL != ipdopts->param_status_ptr)
542 ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS; // set without exec
543 stmt->count_of_deffered++;
544 stmt->exec_current_row++;
545 RETURN(SQL_SUCCESS);
546 }
547 }
548 else
549 {
550 if (VALID_EXPBUFFER)
551 {
552 if (NULL != stmt_with_params)
553 appendPQExpBuffer(&stmt->stmt_deffered, ";%s", stmt_with_params);
554 stmt->stmt_with_params = stmt->stmt_deffered.data;
555 }
556 retval = SC_execute(stmt);
557 stmt->stmt_with_params = stmt_with_params;
558 stmt->count_of_deffered = 0;
559 if (VALID_EXPBUFFER)
560 resetPQExpBuffer(&stmt->stmt_deffered);
561 }
562 if (retval == SQL_ERROR)
563 {
564 MYLOG(0, "count_of_deffered=%d\n", count_of_deffered);
565 param_status_batch_update(ipdopts, SQL_PARAM_ERROR, stmt->exec_current_row, count_of_deffered);
566 stmt->exec_current_row = -1;
567 *exec_end = TRUE;
568 RETURN(retval)
569 }
570 res = SC_get_Result(stmt);
571 /* special handling of result for keyset driven cursors */
572 if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type &&
573 SQL_CONCUR_READ_ONLY != stmt->options.scroll_concurrency)
574 {
575 QResultClass *kres;
576
577 if (kres = QR_nextr(res), kres)
578 {
579 QR_set_fields(kres, QR_get_fields(res));
580 QR_set_fields(res, NULL);
581 kres->num_fields = res->num_fields;
582 QR_detach(res);
583 SC_set_Result(stmt, kres);
584 res = kres;
585 }
586 }
587 ipdopts = SC_get_IPDF(stmt);
588 if (ipdopts->param_status_ptr)
589 {
590 switch (retval)
591 {
592 case SQL_SUCCESS:
593 ipdopts->param_status_ptr[status_row] = SQL_PARAM_SUCCESS;
594 break;
595 case SQL_SUCCESS_WITH_INFO:
596 MYLOG(0, "count_of_deffered=%d has_notice=%d\n", count_of_deffered, stmt->has_notice);
597 param_status_batch_update(ipdopts, (count_of_deffered > 0 && !stmt->has_notice) ? SQL_PARAM_SUCCESS : SQL_PARAM_SUCCESS_WITH_INFO, status_row, count_of_deffered);
598 break;
599 default:
600 param_status_batch_update(ipdopts, SQL_PARAM_ERROR, status_row, count_of_deffered);
601 break;
602 }
603 }
604 stmt->has_notice = 0;
605 if (stmt->exec_current_row >= end_row)
606 {
607 *exec_end = TRUE;
608 stmt->exec_current_row = -1;
609 }
610 else
611 stmt->exec_current_row++;
612 if (res)
613 {
614 EnvironmentClass *env = (EnvironmentClass *) CC_get_env(conn);
615 const char *cmd = QR_get_command(res);
616
617 if (retval == SQL_SUCCESS &&
618 NULL != cmd &&
619 start_row >= end_row &&
620 NULL != env &&
621 EN_is_odbc3(env))
622 {
623 int count;
624
625 if (sscanf(cmd , "UPDATE %d", &count) == 1)
626 ;
627 else if (sscanf(cmd , "DELETE %d", &count) == 1)
628 ;
629 else
630 count = -1;
631 if (0 == count)
632 retval = SQL_NO_DATA;
633 }
634 stmt->diag_row_count = res->recent_processed_row_count;
635 }
636 /*
637 * The cursor's info was changed ?
638 */
639 if (retval == SQL_SUCCESS &&
640 (stmt->options.cursor_type != cursor_type ||
641 stmt->options.scroll_concurrency != scroll_concurrency))
642 {
643 SC_set_error(stmt, STMT_OPTION_VALUE_CHANGED, "cursor updatability changed", func);
644 retval = SQL_SUCCESS_WITH_INFO;
645 }
646
647 cleanup:
648 #undef RETURN
649 #undef return
650 LEAVE_CONN_CS(conn);
651 return retval;
652 }
653
654 int
StartRollbackState(StatementClass * stmt)655 StartRollbackState(StatementClass *stmt)
656 {
657 int ret;
658 ConnectionClass *conn;
659 ConnInfo *ci = NULL;
660
661 MYLOG(DETAIL_LOG_LEVEL, "entering %p->external=%d\n", stmt, stmt->external);
662 conn = SC_get_conn(stmt);
663 if (conn)
664 ci = &conn->connInfo;
665
666 if (!ci || ci->rollback_on_error < 0) /* default */
667 {
668 if (conn && PG_VERSION_GE(conn, 8.0))
669 ret = 2; /* statement rollback */
670 else
671 ret = 1; /* transaction rollback */
672 }
673 else
674 {
675 ret = ci->rollback_on_error;
676 if (2 == ret && PG_VERSION_LT(conn, 8.0))
677 ret = 1;
678 }
679
680 switch (ret)
681 {
682 case 1:
683 SC_start_tc_stmt(stmt);
684 break;
685 case 2:
686 SC_start_rb_stmt(stmt);
687 break;
688 }
689 return ret;
690 }
691
692 int
GenerateSvpCommand(ConnectionClass * conn,int type,char * cmd,int buflen)693 GenerateSvpCommand(ConnectionClass *conn, int type, char *cmd, int buflen)
694 {
695 char esavepoint[50];
696 int rtn = -1;
697
698 cmd[0] = '\0';
699 switch (type)
700 {
701 case INTERNAL_SAVEPOINT_OPERATION: /* savepoint */
702 #ifdef _RELEASE_INTERNAL_SAVEPOINT
703 if (conn->internal_svp)
704 rtn = snprintf(cmd, buflen, "RELEASE %s;", GetSvpName(conn, esavepoint, sizeof(esavepoint)));
705 #endif /* _RELEASE_INTERNAL_SAVEPOINT */
706 rtn = snprintfcat(cmd, buflen, "SAVEPOINT %s", GetSvpName(conn, esavepoint, sizeof(esavepoint)));
707 break;
708 case INTERNAL_ROLLBACK_OPERATION: /* rollback */
709 if (conn->internal_svp)
710 rtn = snprintf(cmd, buflen, "ROLLBACK TO %s", GetSvpName(conn, esavepoint, sizeof(esavepoint)));
711 else
712 rtn = snprintf(cmd, buflen, "ROLLBACK");
713
714 break;
715 }
716
717 return rtn;
718 }
719
720 /*
721 * Must be in a transaction or the subsequent execution
722 * invokes a transaction.
723 */
724 RETCODE
SetStatementSvp(StatementClass * stmt,unsigned int option)725 SetStatementSvp(StatementClass *stmt, unsigned int option)
726 {
727 CSTR func = "SetStatementSvp";
728 char cmd[128];
729 ConnectionClass *conn = SC_get_conn(stmt);
730 QResultClass *res;
731 RETCODE ret = SQL_SUCCESS_WITH_INFO;
732
733 if (NULL == conn->pqconn)
734 {
735 SC_set_error(stmt, STMT_COMMUNICATION_ERROR, "The connection has been lost", __FUNCTION__);
736 return SQL_ERROR;
737 }
738 if (CC_is_in_error_trans(conn))
739 return ret;
740
741 if (!stmt->lock_CC_for_rb)
742 {
743 ENTER_CONN_CS(conn);
744 stmt->lock_CC_for_rb = TRUE;
745 }
746 MYLOG(DETAIL_LOG_LEVEL, " %p->accessed=%d opt=%u in_progress=%u prev=%u\n", conn, CC_accessed_db(conn), option, conn->opt_in_progress, conn->opt_previous);
747 conn->opt_in_progress &= option;
748 switch (stmt->statement_type)
749 {
750 case STMT_TYPE_SPECIAL:
751 case STMT_TYPE_TRANSACTION:
752 return ret;
753 }
754 /* If rbpoint is not yet started and the previous statement was not read-only */
755 if (!CC_started_rbpoint(conn) && 0 == (conn->opt_previous & SVPOPT_RDONLY))
756 {
757 BOOL need_savep = FALSE;
758
759 if (SC_is_rb_stmt(stmt))
760 {
761 if (CC_is_in_trans(conn)) /* needless to issue SAVEPOINT before the 1st command */
762 {
763 need_savep = TRUE;
764 }
765 }
766 if (need_savep)
767 {
768 if (0 != (option & SVPOPT_REDUCE_ROUNDTRIP))
769 {
770 conn->internal_op = PREPEND_IN_PROGRESS;
771 CC_set_accessed_db(conn);
772 return ret;
773 }
774 GenerateSvpCommand(conn, INTERNAL_SAVEPOINT_OPERATION, cmd, sizeof(cmd));
775 conn->internal_op = SAVEPOINT_IN_PROGRESS;
776 res = CC_send_query(conn, cmd, NULL, 0, NULL);
777 conn->internal_op = 0;
778 if (QR_command_maybe_successful(res))
779 ret = SQL_SUCCESS;
780 else
781 {
782 SC_set_error(stmt, STMT_INTERNAL_ERROR, "internal SAVEPOINT failed", func);
783 ret = SQL_ERROR;
784 }
785 QR_Destructor(res);
786 }
787 }
788 CC_set_accessed_db(conn);
789 MYLOG(DETAIL_LOG_LEVEL, "leaving %p->accessed=%d\n", conn, CC_accessed_db(conn));
790 return ret;
791 }
792
793 RETCODE
DiscardStatementSvp(StatementClass * stmt,RETCODE ret,BOOL errorOnly)794 DiscardStatementSvp(StatementClass *stmt, RETCODE ret, BOOL errorOnly)
795 {
796 CSTR func = "DiscardStatementSvp";
797 ConnectionClass *conn = SC_get_conn(stmt);
798 BOOL start_stmt = FALSE;
799
800 MYLOG(DETAIL_LOG_LEVEL, "entering %p->accessed=%d is_in=%d is_rb=%d is_tc=%d\n", conn, CC_accessed_db(conn),
801 CC_is_in_trans(conn), SC_is_rb_stmt(stmt), SC_is_tc_stmt(stmt));
802 if (stmt->lock_CC_for_rb)
803 MYLOG(0, "in_progress=%u previous=%d\n", conn->opt_in_progress, conn->opt_previous);
804 switch (ret)
805 {
806 case SQL_NEED_DATA:
807 break;
808 case SQL_ERROR:
809 start_stmt = TRUE;
810 break;
811 default:
812 if (!errorOnly)
813 start_stmt = TRUE;
814 break;
815 }
816 if (!CC_accessed_db(conn) || !CC_is_in_trans(conn))
817 goto cleanup;
818 if (!SC_is_rb_stmt(stmt) && !SC_is_tc_stmt(stmt))
819 goto cleanup;
820 if (SQL_ERROR == ret)
821 {
822 if (CC_started_rbpoint(conn) && conn->internal_svp)
823 {
824 int cmd_success = CC_internal_rollback(conn, PER_STATEMENT_ROLLBACK, FALSE);
825
826 if (!cmd_success)
827 {
828 SC_set_error(stmt, STMT_INTERNAL_ERROR, "internal ROLLBACK failed", func);
829 goto cleanup;
830 }
831 }
832 else
833 {
834 CC_abort(conn);
835 goto cleanup;
836 }
837 }
838 else if (errorOnly)
839 return ret;
840 MYLOG(DETAIL_LOG_LEVEL, "\tret=%d\n", ret);
841 cleanup:
842 #ifdef NOT_USED
843 if (!SC_is_prepare_statement(stmt) && ONCE_DESCRIBED == stmt->prepared)
844 SC_set_prepared(stmt, NOT_YET_PREPARED);
845 #endif
846 if (start_stmt || SQL_ERROR == ret)
847 {
848 stmt->execinfo = 0;
849 if (SQL_ERROR != ret && CC_accessed_db(conn))
850 {
851 conn->opt_previous = conn->opt_in_progress;
852 CC_init_opt_in_progress(conn);
853 }
854 if (stmt->lock_CC_for_rb)
855 {
856 stmt->lock_CC_for_rb = FALSE;
857 LEAVE_CONN_CS(conn);
858 MYLOG(DETAIL_LOG_LEVEL, " release conn_lock\n");
859 }
860 CC_start_stmt(conn);
861 }
862 MYLOG(DETAIL_LOG_LEVEL, "leaving %d\n", ret);
863 return ret;
864 }
865
866 /*
867 * Given a SQL statement, see if it is an INSERT INTO statement and extract
868 * the name of the table (with schema) of the table that was inserted to.
869 * (It is needed to resolve any @@identity references in the future.)
870 */
871 void
SC_setInsertedTable(StatementClass * stmt,RETCODE retval)872 SC_setInsertedTable(StatementClass *stmt, RETCODE retval)
873 {
874 const char *cmd = stmt->statement;
875 ConnectionClass *conn;
876 size_t len;
877
878 if (STMT_TYPE_INSERT != stmt->statement_type)
879 return;
880 if (!SQL_SUCCEEDED(retval))
881 return;
882 conn = SC_get_conn(stmt);
883 #ifdef NOT_USED /* give up the use of lastval() */
884 if (PG_VERSION_GE(conn, 8.1)) /* lastval() is available */
885 return;
886 #endif /* NOT_USED */
887 /*if (!CC_fake_mss(conn))
888 return;*/
889
890 /*
891 * Parse a statement that was just executed. If it looks like an INSERT INTO
892 * statement, try to extract the table name (and schema) of the table that
893 * we inserted into.
894 *
895 * This is by no means fool-proof, we don't implement the whole backend
896 * lexer and grammar here, but should handle most simple INSERT statements.
897 */
898 while (isspace((UCHAR) *cmd)) cmd++;
899 if (!*cmd)
900 return;
901 len = 6;
902 if (strnicmp(cmd, "insert", len))
903 return;
904 cmd += len;
905 while (isspace((UCHAR) *(++cmd)));
906 if (!*cmd)
907 return;
908 len = 4;
909 if (strnicmp(cmd, "into", len))
910 return;
911 cmd += len;
912 while (isspace((UCHAR) *cmd)) cmd++;
913 if (!*cmd)
914 return;
915 NULL_THE_NAME(conn->schemaIns);
916 NULL_THE_NAME(conn->tableIns);
917
918 eatTableIdentifiers((const UCHAR *) cmd, conn->ccsc, &conn->tableIns, &conn->schemaIns);
919 if (!NAME_IS_VALID(conn->tableIns))
920 NULL_THE_NAME(conn->schemaIns);
921 }
922
923 /* Execute a prepared SQL statement */
924 RETCODE SQL_API
PGAPI_Execute(HSTMT hstmt,UWORD flag)925 PGAPI_Execute(HSTMT hstmt, UWORD flag)
926 {
927 CSTR func = "PGAPI_Execute";
928 StatementClass *stmt = (StatementClass *) hstmt;
929 RETCODE retval = SQL_SUCCESS;
930 ConnectionClass *conn;
931 APDFields *apdopts;
932 IPDFields *ipdopts;
933 SQLLEN i, start_row, end_row;
934 BOOL exec_end = FALSE, recycled = FALSE, recycle = TRUE;
935 SQLSMALLINT num_params;
936
937 MYLOG(0, "entering...%x %p status=%d\n", flag, stmt, stmt->status);
938
939 stmt->has_notice = 0;
940 conn = SC_get_conn(stmt);
941 apdopts = SC_get_APDF(stmt);
942
943 /*
944 * If the statement was previously described, just recycle the old result
945 * set that contained just the column information.
946 */
947 if ((stmt->prepare && stmt->status == STMT_DESCRIBED) ||
948 (stmt->status == STMT_FINISHED && 0 != (flag & PODBC_RECYCLE_STATEMENT)))
949 {
950 stmt->exec_current_row = -1;
951 SC_recycle_statement(stmt);
952 }
953
954 MYLOG(0, "clear errors...\n");
955
956 SC_clear_error(stmt);
957 if (!stmt->statement)
958 {
959 SC_set_error(stmt, STMT_NO_STMTSTRING, "This handle does not have a SQL statement stored in it", func);
960 MYLOG(0, "problem with handle\n");
961 return SQL_ERROR;
962 }
963
964 #define return DONT_CALL_RETURN_FROM_HERE???
965
966 if (stmt->exec_current_row > 0)
967 {
968 /*
969 * executing an array of parameters.
970 * Don't recycle the statement.
971 */
972 recycle = FALSE;
973 }
974 else if (PREPARED_PERMANENTLY == stmt->prepared ||
975 PREPARED_TEMPORARILY == stmt->prepared)
976 {
977 /*
978 * re-executing an prepared statement.
979 * Don't recycle the statement but
980 * discard the old result.
981 */
982 recycle = FALSE;
983 SC_reset_result_for_rerun(stmt);
984 }
985 /*
986 * If SQLExecute is being called again, recycle the statement. Note
987 * this should have been done by the application in a call to
988 * SQLFreeStmt(SQL_CLOSE) or SQLCancel.
989 */
990 else if (stmt->status == STMT_FINISHED)
991 {
992 MYLOG(0, "recycling statement (should have been done by app)...\n");
993 /******** Is this really NEEDED ? ******/
994 SC_recycle_statement(stmt);
995 recycled = TRUE;
996 }
997 /* Check if the statement is in the correct state */
998 else if ((stmt->prepare && stmt->status != STMT_READY) ||
999 (stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY))
1000 {
1001 SC_set_error(stmt, STMT_STATUS_ERROR, "The handle does not point to a statement that is ready to be executed", func);
1002 MYLOG(0, "problem with statement\n");
1003 retval = SQL_ERROR;
1004 goto cleanup;
1005 }
1006
1007 if (start_row = stmt->exec_start_row, start_row < 0)
1008 start_row = 0;
1009 if (end_row = stmt->exec_end_row, end_row < 0)
1010 {
1011 end_row = (SQLINTEGER) apdopts->paramset_size - 1;
1012 if (end_row < 0)
1013 end_row = 0;
1014 }
1015 if (stmt->exec_current_row < 0)
1016 stmt->exec_current_row = start_row;
1017 ipdopts = SC_get_IPDF(stmt);
1018 num_params = stmt->num_params;
1019 if (num_params < 0)
1020 PGAPI_NumParams(stmt, &num_params);
1021 if (stmt->exec_current_row == start_row)
1022 {
1023 /*
1024 We sometimes need to know about the PG type of binding
1025 parameters even in case of non-prepared statements.
1026 */
1027 int nCallParse = doNothing;
1028 BOOL maybeBatch = FALSE;
1029
1030 if (end_row > start_row &&
1031 SQL_CURSOR_FORWARD_ONLY == stmt->options.cursor_type &&
1032 SQL_CONCUR_READ_ONLY == stmt->options.scroll_concurrency &&
1033 stmt->batch_size > 1)
1034 maybeBatch = TRUE;
1035 MYLOG(0, "prepare=%d prepared=%d batch_size=%d start_row=" FORMAT_LEN "end_row=" FORMAT_LEN " => maybeBatch=%d\n", stmt->prepare, stmt->prepared, stmt->batch_size, start_row, end_row, maybeBatch);
1036 if (NOT_YET_PREPARED == stmt->prepared)
1037 {
1038 if (maybeBatch)
1039 stmt->use_server_side_prepare = 0;
1040 switch (nCallParse = HowToPrepareBeforeExec(stmt, TRUE))
1041 {
1042 case shouldParse:
1043 if (retval = prepareParameters(stmt, FALSE), SQL_ERROR == retval)
1044 goto cleanup;
1045 break;
1046 }
1047 }
1048 MYLOG(0, "prepareParameters was %s called, prepare state:%d\n", shouldParse == nCallParse ? "" : "not", stmt->prepare);
1049
1050 if (shouldParse == nCallParse &&
1051 PREPARE_BY_THE_DRIVER == stmt->prepare)
1052 {
1053 SC_set_Result(stmt, NULL);
1054 }
1055 if (0 != (PREPARE_BY_THE_DRIVER & stmt->prepare) &&
1056 maybeBatch)
1057 stmt->exec_type = DEFFERED_EXEC;
1058 else
1059 stmt->exec_type = DIRECT_EXEC;
1060
1061 MYLOG(0, "prepare=%d maybeBatch=%d exec_type=%d\n", stmt->prepare, maybeBatch, stmt->exec_type);
1062 if (ipdopts->param_processed_ptr)
1063 *ipdopts->param_processed_ptr = 0;
1064 /*
1065 * Initialize param_status_ptr
1066 */
1067 if (ipdopts->param_status_ptr)
1068 {
1069 for (i = 0; i <= end_row; i++)
1070 ipdopts->param_status_ptr[i] = SQL_PARAM_UNUSED;
1071 }
1072 if (recycle && !recycled)
1073 SC_recycle_statement(stmt);
1074 if (isSqlServr() &&
1075 stmt->external &&
1076 0 != stmt->prepare &&
1077 PG_VERSION_LT(conn, 8.4) &&
1078 SC_can_parse_statement(stmt))
1079 parse_sqlsvr(stmt);
1080 }
1081
1082 next_param_row:
1083 if (stmt->exec_current_row > end_row)
1084 exec_end = TRUE;
1085 else if (apdopts->param_operation_ptr)
1086 {
1087 while (apdopts->param_operation_ptr[stmt->exec_current_row] == SQL_PARAM_IGNORE)
1088 {
1089 if (stmt->exec_current_row >= end_row)
1090 {
1091 exec_end = TRUE;
1092 break;
1093 }
1094 ++stmt->exec_current_row;
1095 }
1096 }
1097 if (exec_end)
1098 {
1099 if (DEFFERED_EXEC == stmt->exec_type )
1100 retval = Exec_with_parameters_resolved(stmt, LAST_EXEC, &exec_end);
1101 stmt->exec_current_row = -1;
1102 goto cleanup;
1103 }
1104 /*
1105 * Initialize the current row status
1106 */
1107 if (ipdopts->param_status_ptr)
1108 ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
1109
1110 /*
1111 * Free any data at exec params before the statement is
1112 * executed again or the next set of parameters is processed.
1113 * If not, then there will be a memory leak when the next
1114 * SQLParamData/SQLPutData is called.
1115 */
1116 SC_free_params(stmt, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY);
1117
1118 /*
1119 * Check if statement has any data-at-execute parameters when it is
1120 * not in SC_pre_execute.
1121 */
1122 {
1123 /*
1124 * The bound parameters could have possibly changed since the last
1125 * execute of this statement? Therefore check for params and
1126 * re-copy.
1127 */
1128 SQLULEN offset = apdopts->param_offset_ptr ? *apdopts->param_offset_ptr : 0;
1129 SQLINTEGER bind_size = apdopts->param_bind_type;
1130 SQLLEN current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
1131 Int4 num_p = num_params < apdopts->allocated ? num_params : apdopts->allocated;
1132
1133 /*
1134 * Increment the number of currently processed rows
1135 */
1136 if (ipdopts->param_processed_ptr)
1137 (*ipdopts->param_processed_ptr)++;
1138 stmt->data_at_exec = -1;
1139 for (i = 0; i < num_p; i++)
1140 {
1141 SQLLEN *pcVal = apdopts->parameters[i].used;
1142
1143 apdopts->parameters[i].data_at_exec = FALSE;
1144 if (pcVal)
1145 {
1146 if (bind_size > 0)
1147 pcVal = LENADDR_SHIFT(pcVal, offset + bind_size * current_row);
1148 else
1149 pcVal = LENADDR_SHIFT(pcVal, offset) + current_row;
1150 if (*pcVal == SQL_DATA_AT_EXEC || *pcVal <= SQL_LEN_DATA_AT_EXEC_OFFSET)
1151 apdopts->parameters[i].data_at_exec = TRUE;
1152 }
1153 /* Check for data at execution parameters */
1154 if (apdopts->parameters[i].data_at_exec)
1155 {
1156 MYLOG(0, "The " FORMAT_LEN "th parameter of " FORMAT_LEN "-row is data at exec(" FORMAT_LEN ")\n", i, current_row, pcVal ? (*pcVal) : -1);
1157 if (stmt->data_at_exec < 0)
1158 stmt->data_at_exec = 1;
1159 else
1160 stmt->data_at_exec++;
1161 }
1162 }
1163
1164 /*
1165 * If there are some data at execution parameters, return need
1166 * data
1167 */
1168
1169 /*
1170 * SQLParamData and SQLPutData will be used to send params and
1171 * execute the statement.
1172 */
1173 if (stmt->data_at_exec > 0)
1174 {
1175 retval = SQL_NEED_DATA;
1176 goto cleanup;
1177 }
1178 }
1179
1180 if (0 != (flag & PODBC_WITH_HOLD))
1181 SC_set_with_hold(stmt);
1182 retval = Exec_with_parameters_resolved(stmt, stmt->exec_type, &exec_end);
1183 if (!exec_end)
1184 {
1185 goto next_param_row;
1186 }
1187 cleanup:
1188 MYLOG(0, "leaving %p retval=%d status=%d\n", stmt, retval, stmt->status);
1189 SC_setInsertedTable(stmt, retval);
1190 #undef return
1191 if (SQL_SUCCESS == retval &&
1192 STMT_OK > SC_get_errornumber(stmt))
1193 retval = SQL_SUCCESS_WITH_INFO;
1194 return retval;
1195 }
1196
1197
1198 RETCODE SQL_API
PGAPI_Transact(HENV henv,HDBC hdbc,SQLUSMALLINT fType)1199 PGAPI_Transact(HENV henv,
1200 HDBC hdbc,
1201 SQLUSMALLINT fType)
1202 {
1203 CSTR func = "PGAPI_Transact";
1204 ConnectionClass *conn;
1205 char ok;
1206 int lf;
1207
1208 MYLOG(0, "entering hdbc=%p, henv=%p\n", hdbc, henv);
1209
1210 if (hdbc == SQL_NULL_HDBC && henv == SQL_NULL_HENV)
1211 {
1212 CC_log_error(func, "", NULL);
1213 return SQL_INVALID_HANDLE;
1214 }
1215
1216 /*
1217 * If hdbc is null and henv is valid, it means transact all
1218 * connections on that henv.
1219 */
1220 if (hdbc == SQL_NULL_HDBC && henv != SQL_NULL_HENV)
1221 {
1222 ConnectionClass * const *conns = getConnList();
1223 const int conn_count = getConnCount();
1224 for (lf = 0; lf < conn_count; lf++)
1225 {
1226 conn = conns[lf];
1227
1228 if (conn && CC_get_env(conn) == henv)
1229 if (PGAPI_Transact(henv, (HDBC) conn, fType) != SQL_SUCCESS)
1230 return SQL_ERROR;
1231 }
1232 return SQL_SUCCESS;
1233 }
1234
1235 conn = (ConnectionClass *) hdbc;
1236
1237 if (fType != SQL_COMMIT &&
1238 fType != SQL_ROLLBACK)
1239 {
1240 CC_set_error(conn, CONN_INVALID_ARGUMENT_NO, "PGAPI_Transact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter", func);
1241 return SQL_ERROR;
1242 }
1243
1244 /* If manual commit and in transaction, then proceed. */
1245 if (CC_loves_visible_trans(conn) && CC_is_in_trans(conn))
1246 {
1247 MYLOG(0, "sending on conn %p '%d'\n", conn, fType);
1248
1249 ok = (SQL_COMMIT == fType) ? CC_commit(conn) : CC_abort(conn);
1250 if (!ok)
1251 {
1252 /* error msg will be in the connection */
1253 CC_on_abort(conn, NO_TRANS);
1254 CC_log_error(func, "", conn);
1255 return SQL_ERROR;
1256 }
1257 }
1258 return SQL_SUCCESS;
1259 }
1260
1261
1262 RETCODE SQL_API
PGAPI_Cancel(HSTMT hstmt)1263 PGAPI_Cancel(HSTMT hstmt) /* Statement to cancel. */
1264 {
1265 CSTR func = "PGAPI_Cancel";
1266 StatementClass *stmt = (StatementClass *) hstmt, *estmt;
1267 ConnectionClass *conn;
1268 RETCODE ret = SQL_SUCCESS;
1269
1270 MYLOG(0, "entering...\n");
1271
1272 /* Check if this can handle canceling in the middle of a SQLPutData? */
1273 if (!stmt)
1274 {
1275 SC_log_error(func, "", NULL);
1276 return SQL_INVALID_HANDLE;
1277 }
1278 conn = SC_get_conn(stmt);
1279
1280 if (stmt->execute_delegate)
1281 estmt = stmt->execute_delegate;
1282 else
1283 estmt = stmt;
1284
1285 /*
1286 * SQLCancel works differently depending on what the statement is
1287 * currently doing:
1288 *
1289 * 1. In the middle of SQLParamData / SQLPutData
1290 * -> cancel the statement
1291 *
1292 * 2. Running a query asynchronously. (asynchronous mode is not supported
1293 * by psqlODBC)
1294 *
1295 * 3. Busy running a function in another thread.
1296 * -> Send a query cancel request to the server
1297 *
1298 * 4. Not doing anything.
1299 * -> in ODBC version 2.0, same as SQLFreeStmt(SQL_CLOSE). In version
1300 * 3.5, it has no effect.
1301 *
1302 * XXX: Checking for these conditions is racy. For example, we might
1303 * see that the statement is waiting for SQLParamdata/SQLPutData, but
1304 * before we acquire the lock on the statement, another thread has
1305 * supplied the data and started executing. In that case, we'll block
1306 * on the lock until the execution finishes.
1307 */
1308 if (estmt->data_at_exec >= 0)
1309 {
1310 /* Waiting for more data from SQLParamData/SQLPutData. Cancel that. */
1311 /*
1312 * Note, any previous data-at-exec buffers will be freed
1313 * if they call SQLExecDirect or SQLExecute again.
1314 */
1315
1316 ENTER_STMT_CS(stmt);
1317 SC_clear_error(stmt);
1318 estmt->data_at_exec = -1;
1319 estmt->current_exec_param = -1;
1320 estmt->put_data = FALSE;
1321 cancelNeedDataState(estmt);
1322 LEAVE_STMT_CS(stmt);
1323 return ret;
1324 }
1325 else if (estmt->status == STMT_EXECUTING)
1326 {
1327 /*
1328 * Busy executing in a different thread. Send a cancel request to
1329 * the server.
1330 */
1331 if (!CC_send_cancel_request(conn))
1332 return SQL_ERROR;
1333 else
1334 return SQL_SUCCESS;
1335 }
1336 else
1337 {
1338 /*
1339 * The statement is not executing, and it's not waiting for params
1340 * either. Looks like it's not doing anything.
1341 */
1342 return SQL_SUCCESS;
1343 }
1344 }
1345
1346
1347 /*
1348 * Returns the SQL string as modified by the driver.
1349 * Currently, just copy the input string without modification
1350 * observing buffer limits and truncation.
1351 */
1352 RETCODE SQL_API
PGAPI_NativeSql(HDBC hdbc,const SQLCHAR * szSqlStrIn,SQLINTEGER cbSqlStrIn,SQLCHAR * szSqlStr,SQLINTEGER cbSqlStrMax,SQLINTEGER * pcbSqlStr)1353 PGAPI_NativeSql(HDBC hdbc,
1354 const SQLCHAR * szSqlStrIn,
1355 SQLINTEGER cbSqlStrIn,
1356 SQLCHAR * szSqlStr,
1357 SQLINTEGER cbSqlStrMax,
1358 SQLINTEGER * pcbSqlStr)
1359 {
1360 CSTR func = "PGAPI_NativeSql";
1361 size_t len = 0;
1362 char *ptr;
1363 ConnectionClass *conn = (ConnectionClass *) hdbc;
1364 RETCODE result;
1365
1366 MYLOG(0, "entering...cbSqlStrIn=" FORMAT_INTEGER "\n", cbSqlStrIn);
1367
1368 ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL, 0);
1369 if (!ptr)
1370 {
1371 CC_set_error(conn, CONN_NO_MEMORY_ERROR, "No memory available to store native sql string", func);
1372 return SQL_ERROR;
1373 }
1374
1375 result = SQL_SUCCESS;
1376 len = strlen(ptr);
1377
1378 if (szSqlStr)
1379 {
1380 strncpy_null((char *) szSqlStr, ptr, cbSqlStrMax);
1381
1382 if (len >= cbSqlStrMax)
1383 {
1384 result = SQL_SUCCESS_WITH_INFO;
1385 CC_set_error(conn, CONN_TRUNCATED, "The buffer was too small for the NativeSQL.", func);
1386 }
1387 }
1388
1389 if (pcbSqlStr)
1390 *pcbSqlStr = (SQLINTEGER) len;
1391
1392 if (cbSqlStrIn)
1393 free(ptr);
1394
1395 return result;
1396 }
1397
1398
1399 /*
1400 * Supplies parameter data at execution time.
1401 * Used in conjuction with SQLPutData.
1402 */
1403 RETCODE SQL_API
PGAPI_ParamData(HSTMT hstmt,PTR * prgbValue)1404 PGAPI_ParamData(HSTMT hstmt,
1405 PTR * prgbValue)
1406 {
1407 CSTR func = "PGAPI_ParamData";
1408 StatementClass *stmt = (StatementClass *) hstmt, *estmt;
1409 APDFields *apdopts;
1410 IPDFields *ipdopts;
1411 RETCODE retval;
1412 int i;
1413 Int2 num_p;
1414 ConnectionClass *conn = NULL;
1415
1416 MYLOG(0, "entering...\n");
1417
1418 conn = SC_get_conn(stmt);
1419
1420 estmt = stmt->execute_delegate ? stmt->execute_delegate : stmt;
1421 apdopts = SC_get_APDF(estmt);
1422 MYLOG(0, "\tdata_at_exec=%d, params_alloc=%d\n", estmt->data_at_exec, apdopts->allocated);
1423
1424 #define return DONT_CALL_RETURN_FROM_HERE???
1425 if (SC_AcceptedCancelRequest(stmt))
1426 {
1427 SC_set_error(stmt, STMT_OPERATION_CANCELLED, "Cancel the statement, sorry", func);
1428 retval = SQL_ERROR;
1429 goto cleanup;
1430 }
1431 if (estmt->data_at_exec < 0)
1432 {
1433 SC_set_error(stmt, STMT_SEQUENCE_ERROR, "No execution-time parameters for this statement", func);
1434 retval = SQL_ERROR;
1435 goto cleanup;
1436 }
1437
1438 if (estmt->data_at_exec > apdopts->allocated)
1439 {
1440 SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Too many execution-time parameters were present", func);
1441 retval = SQL_ERROR;
1442 goto cleanup;
1443 }
1444
1445 /* close the large object */
1446 if (estmt->lobj_fd >= 0)
1447 {
1448 odbc_lo_close(conn, estmt->lobj_fd);
1449
1450 /* commit transaction if needed */
1451 if (!CC_cursor_count(conn) && CC_does_autocommit(conn))
1452 {
1453 if (!CC_commit(conn))
1454 {
1455 SC_set_error(stmt, STMT_EXEC_ERROR, "Could not commit (in-line) a transaction", func);
1456 retval = SQL_ERROR;
1457 goto cleanup;
1458 }
1459 }
1460 estmt->lobj_fd = -1;
1461 }
1462
1463 /* Done, now copy the params and then execute the statement */
1464 ipdopts = SC_get_IPDF(estmt);
1465 MYLOG(DETAIL_LOG_LEVEL, "ipdopts=%p\n", ipdopts);
1466 if (estmt->data_at_exec == 0)
1467 {
1468 BOOL exec_end;
1469 UWORD flag = SC_is_with_hold(stmt) ? PODBC_WITH_HOLD : 0;
1470
1471 retval = Exec_with_parameters_resolved(estmt, stmt->exec_type, &exec_end);
1472 if (exec_end)
1473 {
1474 /**SC_reset_delegate(retval, stmt);**/
1475 retval = dequeueNeedDataCallback(retval, stmt);
1476 goto cleanup;
1477 }
1478
1479 if (retval = PGAPI_Execute(estmt, flag), SQL_NEED_DATA != retval)
1480 {
1481 goto cleanup;
1482 }
1483 }
1484
1485 /*
1486 * Set beginning param; if first time SQLParamData is called , start
1487 * at 0. Otherwise, start at the last parameter + 1.
1488 */
1489 i = estmt->current_exec_param >= 0 ? estmt->current_exec_param + 1 : 0;
1490
1491 num_p = estmt->num_params;
1492 if (num_p < 0)
1493 PGAPI_NumParams(estmt, &num_p);
1494 MYLOG(DETAIL_LOG_LEVEL, "i=%d allocated=%d num_p=%d\n", i, apdopts->allocated, num_p);
1495 if (num_p > apdopts->allocated)
1496 num_p = apdopts->allocated;
1497 /* At least 1 data at execution parameter, so Fill in the token value */
1498 for (; i < num_p; i++)
1499 {
1500 MYLOG(DETAIL_LOG_LEVEL, "i=%d", i);
1501 if (apdopts->parameters[i].data_at_exec)
1502 {
1503 MYPRINTF(DETAIL_LOG_LEVEL, " at exec buffer=%p", apdopts->parameters[i].buffer);
1504 estmt->data_at_exec--;
1505 estmt->current_exec_param = i;
1506 estmt->put_data = FALSE;
1507 if (prgbValue)
1508 {
1509 /* returns token here */
1510 if (stmt->execute_delegate)
1511 {
1512 SQLULEN offset = apdopts->param_offset_ptr ? *apdopts->param_offset_ptr : 0;
1513 SQLLEN perrow = apdopts->param_bind_type > 0 ? apdopts->param_bind_type : apdopts->parameters[i].buflen;
1514
1515 MYPRINTF(DETAIL_LOG_LEVEL, " offset=" FORMAT_LEN " perrow=" FORMAT_LEN, offset, perrow);
1516 *prgbValue = apdopts->parameters[i].buffer + offset + estmt->exec_current_row * perrow;
1517 }
1518 else
1519 *prgbValue = apdopts->parameters[i].buffer;
1520 }
1521 break;
1522 }
1523 MYPRINTF(DETAIL_LOG_LEVEL, "\n");
1524 }
1525
1526 retval = SQL_NEED_DATA;
1527 MYLOG(DETAIL_LOG_LEVEL, "return SQL_NEED_DATA\n");
1528 cleanup:
1529 #undef return
1530 SC_setInsertedTable(stmt, retval);
1531 MYLOG(0, "leaving %d\n", retval);
1532 return retval;
1533 }
1534
1535
1536 /*
1537 * Supplies parameter data at execution time.
1538 * Used in conjunction with SQLParamData.
1539 */
1540 RETCODE SQL_API
PGAPI_PutData(HSTMT hstmt,PTR rgbValue,SQLLEN cbValue)1541 PGAPI_PutData(HSTMT hstmt,
1542 PTR rgbValue,
1543 SQLLEN cbValue)
1544 {
1545 CSTR func = "PGAPI_PutData";
1546 StatementClass *stmt = (StatementClass *) hstmt, *estmt;
1547 ConnectionClass *conn;
1548 RETCODE retval = SQL_SUCCESS;
1549 APDFields *apdopts;
1550 IPDFields *ipdopts;
1551 PutDataInfo *pdata;
1552 SQLLEN old_pos;
1553 ParameterInfoClass *current_param;
1554 ParameterImplClass *current_iparam;
1555 PutDataClass *current_pdata;
1556 char *putbuf, *allocbuf = NULL;
1557 Int2 ctype;
1558 SQLLEN putlen;
1559 BOOL lenset = FALSE, handling_lo = FALSE;
1560
1561 MYLOG(0, "entering...\n");
1562
1563 #define return DONT_CALL_RETURN_FROM_HERE???
1564 if (SC_AcceptedCancelRequest(stmt))
1565 {
1566 SC_set_error(stmt, STMT_OPERATION_CANCELLED, "Cancel the statement, sorry.", func);
1567 retval = SQL_ERROR;
1568 goto cleanup;
1569 }
1570
1571 estmt = stmt->execute_delegate ? stmt->execute_delegate : stmt;
1572 apdopts = SC_get_APDF(estmt);
1573 if (estmt->current_exec_param < 0)
1574 {
1575 SC_set_error(stmt, STMT_SEQUENCE_ERROR, "Previous call was not SQLPutData or SQLParamData", func);
1576 retval = SQL_ERROR;
1577 goto cleanup;
1578 }
1579
1580 current_param = &(apdopts->parameters[estmt->current_exec_param]);
1581 ipdopts = SC_get_IPDF(estmt);
1582 current_iparam = &(ipdopts->parameters[estmt->current_exec_param]);
1583 pdata = SC_get_PDTI(estmt);
1584 current_pdata = &(pdata->pdata[estmt->current_exec_param]);
1585 ctype = current_param->CType;
1586
1587 conn = SC_get_conn(estmt);
1588 if (ctype == SQL_C_DEFAULT)
1589 {
1590 ctype = sqltype_to_default_ctype(conn, current_iparam->SQLType);
1591 #ifdef UNICODE_SUPPORT
1592 if (SQL_C_WCHAR == ctype &&
1593 CC_default_is_c(conn))
1594 ctype = SQL_C_CHAR;
1595 #endif
1596 }
1597 if (SQL_NTS == cbValue)
1598 {
1599 #ifdef UNICODE_SUPPORT
1600 if (SQL_C_WCHAR == ctype)
1601 {
1602 putlen = WCLEN * ucs2strlen((SQLWCHAR *) rgbValue);
1603 lenset = TRUE;
1604 }
1605 else
1606 #endif /* UNICODE_SUPPORT */
1607 if (SQL_C_CHAR == ctype)
1608 {
1609 putlen = strlen(rgbValue);
1610 lenset = TRUE;
1611 }
1612 }
1613 if (!lenset)
1614 {
1615 if (cbValue < 0)
1616 putlen = cbValue;
1617 else
1618 #ifdef UNICODE_SUPPORT
1619 if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY || ctype == SQL_C_WCHAR)
1620 #else
1621 if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
1622 #endif /* UNICODE_SUPPORT */
1623 putlen = cbValue;
1624 else
1625 putlen = ctype_length(ctype);
1626 }
1627 putbuf = rgbValue;
1628 handling_lo = (PIC_dsp_pgtype(conn, *current_iparam) == conn->lobj_type);
1629 if (handling_lo && SQL_C_CHAR == ctype)
1630 {
1631 allocbuf = malloc(putlen / 2 + 1);
1632 if (allocbuf)
1633 {
1634 pg_hex2bin(rgbValue, allocbuf, putlen);
1635 putbuf = allocbuf;
1636 putlen /= 2;
1637 }
1638 }
1639
1640 if (!estmt->put_data)
1641 { /* first call */
1642 MYLOG(0, "(1) cbValue = " FORMAT_LEN "\n", cbValue);
1643
1644 estmt->put_data = TRUE;
1645
1646 current_pdata->EXEC_used = (SQLLEN *) malloc(sizeof(SQLLEN));
1647 if (!current_pdata->EXEC_used)
1648 {
1649 SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (1)", func);
1650 retval = SQL_ERROR;
1651 goto cleanup;
1652 }
1653
1654 *current_pdata->EXEC_used = putlen;
1655
1656 if (cbValue == SQL_NULL_DATA)
1657 {
1658 retval = SQL_SUCCESS;
1659 goto cleanup;
1660 }
1661
1662 /* Handle Long Var Binary with Large Objects */
1663 /* if (current_iparam->SQLType == SQL_LONGVARBINARY) */
1664 if (handling_lo)
1665 {
1666 /* begin transaction if needed */
1667 if (!CC_is_in_trans(conn))
1668 {
1669 if (!CC_begin(conn))
1670 {
1671 SC_set_error(stmt, STMT_EXEC_ERROR, "Could not begin (in-line) a transaction", func);
1672 retval = SQL_ERROR;
1673 goto cleanup;
1674 }
1675 }
1676
1677 /* store the oid */
1678 current_pdata->lobj_oid = odbc_lo_creat(conn, INV_READ | INV_WRITE);
1679 if (current_pdata->lobj_oid == 0)
1680 {
1681 SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt create large object.", func);
1682 retval = SQL_ERROR;
1683 goto cleanup;
1684 }
1685
1686 /*
1687 * major hack -- to allow convert to see somethings there have
1688 * to modify convert to handle this better
1689 */
1690 /***current_param->EXEC_buffer = (char *) ¤t_param->lobj_oid;***/
1691
1692 /* store the fd */
1693 estmt->lobj_fd = odbc_lo_open(conn, current_pdata->lobj_oid, INV_WRITE);
1694 if (estmt->lobj_fd < 0)
1695 {
1696 SC_set_error(stmt, STMT_EXEC_ERROR, "Couldnt open large object for writing.", func);
1697 retval = SQL_ERROR;
1698 goto cleanup;
1699 }
1700
1701 retval = odbc_lo_write(conn, estmt->lobj_fd, putbuf, (Int4) putlen);
1702 MYLOG(0, "lo_write: cbValue=" FORMAT_LEN ", wrote %d bytes\n", putlen, retval);
1703 }
1704 else
1705 {
1706 current_pdata->EXEC_buffer = malloc(putlen + 1);
1707 if (!current_pdata->EXEC_buffer)
1708 {
1709 SC_set_error(stmt, STMT_NO_MEMORY_ERROR, "Out of memory in PGAPI_PutData (2)", func);
1710 retval = SQL_ERROR;
1711 goto cleanup;
1712 }
1713 memcpy(current_pdata->EXEC_buffer, putbuf, putlen);
1714 current_pdata->EXEC_buffer[putlen] = '\0';
1715 }
1716 }
1717 else
1718 {
1719 /* calling SQLPutData more than once */
1720 MYLOG(0, "(>1) cbValue = " FORMAT_LEN "\n", cbValue);
1721
1722 /* if (current_iparam->SQLType == SQL_LONGVARBINARY) */
1723 if (handling_lo)
1724 {
1725 /* the large object fd is in EXEC_buffer */
1726 retval = odbc_lo_write(conn, estmt->lobj_fd, putbuf, (Int4) putlen);
1727 MYLOG(0, "lo_write(2): cbValue = " FORMAT_LEN ", wrote %d bytes\n", putlen, retval);
1728
1729 *current_pdata->EXEC_used += putlen;
1730 }
1731 else
1732 {
1733 old_pos = *current_pdata->EXEC_used;
1734 if (putlen > 0)
1735 {
1736 SQLLEN used = *current_pdata->EXEC_used + putlen;
1737 SQLLEN allocsize;
1738 char *buffer;
1739
1740 for (allocsize = (1 << 4); allocsize <= used; allocsize <<= 1) ;
1741 MYLOG(0, " cbValue = " FORMAT_LEN ", old_pos = " FORMAT_LEN ", *used = " FORMAT_LEN "\n", putlen, old_pos, used);
1742
1743 /* dont lose the old pointer in case out of memory */
1744 buffer = realloc(current_pdata->EXEC_buffer, allocsize);
1745 if (!buffer)
1746 {
1747 SC_set_error(stmt, STMT_NO_MEMORY_ERROR,"Out of memory in PGAPI_PutData (3)", func);
1748 retval = SQL_ERROR;
1749 goto cleanup;
1750 }
1751
1752 memcpy(&buffer[old_pos], putbuf, putlen);
1753 buffer[used] = '\0';
1754
1755 /* reassign buffer incase realloc moved it */
1756 *current_pdata->EXEC_used = used;
1757 current_pdata->EXEC_buffer = buffer;
1758 }
1759 else
1760 {
1761 SC_set_error(stmt, STMT_INTERNAL_ERROR, "bad cbValue", func);
1762 retval = SQL_ERROR;
1763 goto cleanup;
1764 }
1765 }
1766 }
1767
1768 retval = SQL_SUCCESS;
1769 cleanup:
1770 #undef return
1771 if (allocbuf)
1772 free(allocbuf);
1773
1774 return retval;
1775 }
1776