2 * Description: This module contains routines related to
3 * preparing and executing an SQL statement.
15 #include "connection.h"
16 #include "statement.h"
21 #include "pgapifunc.h"
22 #include "vxhelpers.h"
24 /*extern GLOBAL_VALUES globals;*/
27 /* Perform a Prepare on the SQL statement */
29 PGAPI_Prepare(HSTMT hstmt
,
30 const SQLCHAR FAR
* szSqlStr
, SQLINTEGER cbSqlStr
)
32 CSTR func
= "PGAPI_Prepare";
33 StatementClass
*self
= (StatementClass
*) hstmt
;
34 RETCODE retval
= SQL_SUCCESS
;
36 mylog("%s: entering...\n", func
);
38 #define return DONT_CALL_RETURN_FROM_HERE???
39 /* StartRollbackState(self); */
42 SC_log_error(func
, "", NULL
);
43 retval
= SQL_INVALID_HANDLE
;
48 * According to the ODBC specs it is valid to call SQLPrepare multiple
49 * times. In that case, the bound SQL statement is replaced by the new
53 SC_set_prepared(self
, NOT_YET_PREPARED
);
57 mylog("**** PGAPI_Prepare: STMT_PREMATURE, recycle\n");
58 SC_recycle_statement(self
); /* recycle the statement, but do
59 * not remove parameter bindings */
63 mylog("**** PGAPI_Prepare: STMT_FINISHED, recycle\n");
64 SC_recycle_statement(self
); /* recycle the statement, but do
65 * not remove parameter bindings */
69 mylog("**** PGAPI_Prepare: STMT_ALLOCATED, copy\n");
70 self
->status
= STMT_READY
;
74 mylog("**** PGAPI_Prepare: STMT_READY, change SQL\n");
78 mylog("**** PGAPI_Prepare: STMT_EXECUTING, error!\n");
80 SC_set_error(self
, STMT_SEQUENCE_ERROR
,
81 "PGAPI_Prepare(): The handle does not point to a statement that is ready to be executed",
88 SC_set_error(self
, STMT_INTERNAL_ERROR
,
89 "An Internal Error has occured -- Unknown statement status.",
95 SC_initialize_stmts(self
, TRUE
);
99 SC_set_error(self
, STMT_NO_MEMORY_ERROR
, "the query is NULL",
105 self
->statement
= strdup("");
107 self
->statement
= make_string(szSqlStr
, cbSqlStr
, NULL
, 0);
108 if (!self
->statement
)
110 SC_set_error(self
, STMT_NO_MEMORY_ERROR
,
111 "No memory available to store statement", func
);
116 self
->prepare
= PREPARE_STATEMENT
;
117 self
->statement_type
= statement_type(self
->statement
);
119 /* Check if connection is onlyread (only selects are allowed) */
120 if (CC_is_onlyread(SC_get_conn(self
)) && STMT_UPDATE(self
))
122 SC_set_error(self
, STMT_EXEC_ERROR
,
123 "Connection is readonly, only select statements are allowed.",
131 inolog("SQLPrepare return=%d\n", retval
);
133 retval
= DiscardStatementSvp(self
, retval
, FALSE
);
139 // VX_CLEANUP: Anything calling this is obviously broken, but it's not so
140 // obvious whether the callers should be fixed to call PGAPI_ExecDirect_Vx or
142 /* Performs the equivalent of SQLPrepare, followed by SQLExecute. */
144 PGAPI_ExecDirect(HSTMT hstmt
,
145 const SQLCHAR FAR
* szSqlStr
,
146 SQLINTEGER cbSqlStr
, UWORD flag
)
148 StatementClass
*stmt
= (StatementClass
*) hstmt
;
150 CSTR func
= "PGAPI_ExecDirect";
151 SC_set_error(stmt
, STMT_EXEC_ERROR
,
152 "PGAPI_ExecDirect is not supported, call PGAPI_ExecDirect_Vx",
158 /* Performs the equivalent of SQLPrepare, followed by SQLExecute. */
160 PGAPI_ExecDirect_Vx(HSTMT hstmt
,
161 const SQLCHAR FAR
* szSqlStr
,
162 SQLINTEGER cbSqlStr
, UWORD flag
)
164 StatementClass
*stmt
= (StatementClass
*)hstmt
;
166 VxStatement
st(stmt
);
169 st
.runquery(rs
, "ExecChunkRecordset", (const char *)szSqlStr
);
171 stmt
->statement
= strdup((const char *)szSqlStr
);
172 stmt
->catalog_result
= FALSE
;
173 stmt
->statement_type
= STMT_TYPE_SELECT
;
174 // SC_set_parse_forced(stmt);
181 /* Execute a prepared SQL statement */
182 RETCODE SQL_API
PGAPI_Execute_Vx(HSTMT hstmt
, UWORD flag
)
184 StatementClass
*stmt
= (StatementClass
*)hstmt
;
186 VxStatement
st(stmt
);
188 st
.runquery(rs
, "ExecChunkRecordset", stmt
->statement
);
196 static int inquireHowToPrepare(const StatementClass
* stmt
)
198 ConnectionClass
*conn
;
202 conn
= SC_get_conn(stmt
);
203 ci
= &(conn
->connInfo
);
204 if (!ci
->use_server_side_prepare
|| PG_VERSION_LT(conn
, 7.3))
206 /* Do prepare operations by the driver itself */
207 return PREPARE_BY_THE_DRIVER
;
209 if (NOT_YET_PREPARED
== stmt
->prepared
)
211 SQLSMALLINT num_params
;
213 if (STMT_TYPE_DECLARE
== stmt
->statement_type
&&
214 PG_VERSION_LT(conn
, 8.0))
216 return PREPARE_BY_THE_DRIVER
;
218 if (stmt
->multi_statement
< 0)
219 PGAPI_NumParams((StatementClass
*) stmt
, &num_params
);
220 if (stmt
->multi_statement
> 0) /* would divide the query into multiple commands and apply V3 parse requests for each of them */
221 ret
= PARSE_REQ_FOR_INFO
;
222 else if (PROTOCOL_74(ci
))
224 if (STMT_TYPE_SELECT
== stmt
->statement_type
)
226 if (SQL_CURSOR_FORWARD_ONLY
!=
227 stmt
->options
.cursor_type
)
228 ret
= PARSE_REQ_FOR_INFO
;
230 ret
= PARSE_TO_EXEC_ONCE
;
232 ret
= PARSE_TO_EXEC_ONCE
;
235 if (STMT_TYPE_SELECT
== stmt
->statement_type
&&
236 (SQL_CURSOR_FORWARD_ONLY
!= stmt
->options
.cursor_type
))
237 ret
= PREPARE_BY_THE_DRIVER
;
239 ret
= USING_PREPARE_COMMAND
;
242 if (SC_is_prepare_statement(stmt
) && (PARSE_TO_EXEC_ONCE
== ret
))
243 ret
= NAMED_PARSE_REQUEST
;
249 // VX_CLEANUP: This is called all over the place, it'll be a pain to extract.
250 int StartRollbackState(StatementClass
* stmt
)
252 CSTR func
= "StartRollbackState";
257 // VX_CLEANUP: SetStatementSvp was killed in or around r225; one might think
258 // that would make this function totally redundant, but it's still called all
259 // over the place, and breaks the unit tests if it returns an error.
261 DiscardStatementSvp(StatementClass
* stmt
, RETCODE ret
, BOOL errorOnly
)
263 CSTR func
= "DiscardStatementSvp";
268 void SC_setInsertedTable(StatementClass
* stmt
, RETCODE retval
)
270 const char *cmd
= stmt
->statement
, *ptr
;
271 ConnectionClass
*conn
;
274 if (STMT_TYPE_INSERT
!= stmt
->statement_type
)
276 if (SQL_NEED_DATA
== retval
)
278 conn
= SC_get_conn(stmt
);
279 if (PG_VERSION_GE(conn
, 8.1)) /* lastval() is available */
281 /*if (!CC_fake_mss(conn))
283 while (isspace((UCHAR
) * cmd
))
288 if (strnicmp(cmd
, "insert", len
))
291 while (isspace((UCHAR
) * (++cmd
)));
295 if (strnicmp(cmd
, "into", len
))
298 while (isspace((UCHAR
) * (++cmd
)));
301 NULL_THE_NAME(conn
->schemaIns
);
302 NULL_THE_NAME(conn
->tableIns
);
303 if (!SQL_SUCCEEDED(retval
))
306 if (IDENTIFIER_QUOTE
== *cmd
)
308 if (ptr
= strchr(cmd
+ 1, IDENTIFIER_QUOTE
), NULL
== ptr
)
313 STRN_TO_NAME(conn
->schemaIns
, cmd
+ 1, len
);
319 if (ptr
= strchr(cmd
+ 1, '.'), NULL
!= ptr
)
322 STRN_TO_NAME(conn
->schemaIns
, cmd
, len
);
327 if (IDENTIFIER_QUOTE
== *cmd
&& NULL
== ptr
)
329 if (ptr
= strchr(cmd
+ 1, IDENTIFIER_QUOTE
), NULL
== ptr
)
332 if (IDENTIFIER_QUOTE
== *cmd
)
335 STRN_TO_NAME(conn
->tableIns
, cmd
+ 1, len
);
339 while (*ptr
&& !isspace((UCHAR
) * ptr
))
342 STRN_TO_NAME(conn
->tableIns
, cmd
, len
);
346 /* Execute a prepared SQL statement */
347 RETCODE SQL_API
PGAPI_Execute(HSTMT hstmt
, UWORD flag
)
349 CSTR func
= "PGAPI_Execute";
350 StatementClass
*stmt
= (StatementClass
*) hstmt
;
351 SC_set_error(stmt
, STMT_EXEC_ERROR
,
352 "PGAPI_Execute is not supported, call PGAPI_ExecDirect_Vx",
358 RETCODE SQL_API
PGAPI_Transact(HENV henv
, HDBC hdbc
, SQLUSMALLINT fType
)
360 CSTR func
= "PGAPI_Transact";
362 CC_set_error((ConnectionClass
*)hdbc
, CONN_NOT_IMPLEMENTED_ERROR
,
363 "PGAPI_Transact is not yet implemented",
369 // VX_CLEANUP: A lot of this is probably related to transactions, hence
371 RETCODE SQL_API
PGAPI_Cancel(HSTMT hstmt
) /* Statement to cancel. */
373 CSTR func
= "PGAPI_Cancel";
374 StatementClass
*stmt
= (StatementClass
*) hstmt
, *estmt
;
375 ConnectionClass
*conn
;
376 RETCODE ret
= SQL_SUCCESS
;
377 BOOL entered_cs
= FALSE
;
380 mylog("%s: entering...\n", func
);
382 /* Check if this can handle canceling in the middle of a SQLPutData? */
385 SC_log_error(func
, "", NULL
);
386 return SQL_INVALID_HANDLE
;
388 conn
= SC_get_conn(stmt
);
389 ci
= &(conn
->connInfo
);
391 #define return DONT_CALL_RETURN_FROM_HERE???
392 /* StartRollbackState(stmt); */
394 if (stmt
->execute_delegate
)
395 estmt
= stmt
->execute_delegate
;
399 * Not in the middle of SQLParamData/SQLPutData so cancel like a
402 if (estmt
->data_at_exec
< 0)
405 * Tell the Backend that we're cancelling this request
407 mylog("Cancelling while in the middle of SQLParamData/SQLPutData not "
413 /* In the middle of SQLParamData/SQLPutData, so cancel that. */
415 * Note, any previous data-at-exec buffers will be freed in the
418 /* if they call SQLExecDirect or SQLExecute again. */
422 SC_clear_error(stmt
);
423 estmt
->data_at_exec
= -1;
424 estmt
->current_exec_param
= -1;
425 estmt
->put_data
= FALSE
;
426 cancelNeedDataState(estmt
);
433 ret
= DiscardStatementSvp(stmt
, ret
, FALSE
);
441 * Returns the SQL string as modified by the driver.
442 * Currently, just copy the input string without modification
443 * observing buffer limits and truncation.
446 PGAPI_NativeSql(HDBC hdbc
,
447 const SQLCHAR FAR
* szSqlStrIn
,
448 SQLINTEGER cbSqlStrIn
,
449 SQLCHAR FAR
* szSqlStr
,
450 SQLINTEGER cbSqlStrMax
, SQLINTEGER FAR
* pcbSqlStr
)
452 CSTR func
= "PGAPI_NativeSql";
455 ConnectionClass
*conn
= (ConnectionClass
*) hdbc
;
458 mylog("%s: entering...cbSqlStrIn=%d\n", func
, cbSqlStrIn
);
461 (cbSqlStrIn
== 0) ? "" : make_string(szSqlStrIn
, cbSqlStrIn
,
465 CC_set_error(conn
, CONN_NO_MEMORY_ERROR
,
466 "No memory available to store native sql string",
471 result
= SQL_SUCCESS
;
476 strncpy_null((char *)szSqlStr
, ptr
, cbSqlStrMax
);
478 if (len
>= cbSqlStrMax
)
480 result
= SQL_SUCCESS_WITH_INFO
;
481 CC_set_error(conn
, CONN_TRUNCATED
,
482 "The buffer was too small for the NativeSQL.",
488 *pcbSqlStr
= (SQLINTEGER
) len
;
498 * Supplies parameter data at execution time.
499 * Used in conjuction with SQLPutData.
501 RETCODE SQL_API
PGAPI_ParamData(HSTMT hstmt
, PTR FAR
* prgbValue
)
503 CSTR func
= "PGAPI_ParamData";
504 StatementClass
*stmt
= (StatementClass
*) hstmt
, *estmt
;
505 SC_log_error(func
, "PGAPI_ParamData is not yet implemented", stmt
);
511 * Supplies parameter data at execution time.
512 * Used in conjunction with SQLParamData.
514 RETCODE SQL_API
PGAPI_PutData(HSTMT hstmt
, PTR rgbValue
, SQLLEN cbValue
)
516 CSTR func
= "PGAPI_PutData";
517 StatementClass
*stmt
= (StatementClass
*) hstmt
, *estmt
;
518 ConnectionClass
*conn
;
519 RETCODE retval
= SQL_SUCCESS
;
523 ParameterInfoClass
*current_param
;
524 ParameterImplClass
*current_iparam
;
525 PutDataClass
*current_pdata
;
526 char *buffer
, *putbuf
, *allocbuf
= NULL
;
531 mylog("%s: entering...\n", func
);
533 #define return DONT_CALL_RETURN_FROM_HERE???
536 SC_log_error(func
, "", NULL
);
537 retval
= SQL_INVALID_HANDLE
;
540 if (SC_AcceptedCancelRequest(stmt
))
542 SC_set_error(stmt
, STMT_OPERATION_CANCELLED
,
543 "Cancel the statement, sorry.", func
);
548 estmt
= stmt
->execute_delegate
? stmt
->execute_delegate
: stmt
;
549 apdopts
= SC_get_APDF(estmt
);
550 if (estmt
->current_exec_param
< 0)
552 SC_set_error(stmt
, STMT_SEQUENCE_ERROR
,
553 "Previous call was not SQLPutData or SQLParamData",
559 current_param
= &(apdopts
->parameters
[estmt
->current_exec_param
]);
560 ipdopts
= SC_get_IPDF(estmt
);
561 current_iparam
= &(ipdopts
->parameters
[estmt
->current_exec_param
]);
562 ctype
= current_param
->CType
;
564 conn
= SC_get_conn(estmt
);
565 if (ctype
== SQL_C_DEFAULT
)
567 ctype
= sqltype_to_default_ctype(conn
, current_iparam
->SQLType
);
568 if (SQL_C_WCHAR
== ctype
&& CC_default_is_c(conn
))
571 if (SQL_NTS
== cbValue
)
573 #ifdef UNICODE_SUPPORT
574 if (SQL_C_WCHAR
== ctype
)
576 putlen
= WCLEN
* ucs2strlen((SQLWCHAR
*) rgbValue
);
579 #endif /* UNICODE_SUPPORT */
580 if (SQL_C_CHAR
== ctype
)
582 putlen
= strlen((const char *)rgbValue
);
591 #ifdef UNICODE_SUPPORT
592 if (ctype
== SQL_C_CHAR
|| ctype
== SQL_C_BINARY
593 || ctype
== SQL_C_WCHAR
)
595 if (ctype
== SQL_C_CHAR
|| ctype
== SQL_C_BINARY
)
596 #endif /* UNICODE_SUPPORT */
599 putlen
= ctype_length(ctype
);
601 putbuf
= (char *)rgbValue
;
603 if (!estmt
->put_data
)
605 mylog("PGAPI_PutData: (1) cbValue = %d\n", cbValue
);
607 estmt
->put_data
= TRUE
;
609 current_pdata
->EXEC_used
= (SQLLEN
*) malloc(sizeof(SQLLEN
));
610 if (!current_pdata
->EXEC_used
)
612 SC_set_error(stmt
, STMT_NO_MEMORY_ERROR
,
613 "Out of memory in PGAPI_PutData (1)", func
);
618 *current_pdata
->EXEC_used
= putlen
;
620 if (cbValue
== SQL_NULL_DATA
)
622 retval
= SQL_SUCCESS
;
626 current_pdata
->EXEC_buffer
= (char *)malloc(putlen
+ 1);
627 if (!current_pdata
->EXEC_buffer
)
629 SC_set_error(stmt
, STMT_NO_MEMORY_ERROR
,
630 "Out of memory in PGAPI_PutData (2)",
635 memcpy(current_pdata
->EXEC_buffer
, putbuf
, putlen
);
636 current_pdata
->EXEC_buffer
[putlen
] = '\0';
639 /* calling SQLPutData more than once */
640 mylog("PGAPI_PutData: (>1) cbValue = %d\n", cbValue
);
642 buffer
= current_pdata
->EXEC_buffer
;
643 old_pos
= *current_pdata
->EXEC_used
;
647 *current_pdata
->EXEC_used
+ putlen
, allocsize
;
648 for (allocsize
= (1 << 4); allocsize
<= used
;
651 (" cbValue = %d, old_pos = %d, *used = %d\n",
652 putlen
, old_pos
, used
);
654 /* dont lose the old pointer in case out of memory */
655 buffer
= (char *)realloc(current_pdata
->EXEC_buffer
, allocsize
);
658 SC_set_error(stmt
, STMT_NO_MEMORY_ERROR
,
659 "Out of memory in PGAPI_PutData (3)",
665 memcpy(&buffer
[old_pos
], putbuf
, putlen
);
668 /* reassign buffer incase realloc moved it */
669 *current_pdata
->EXEC_used
= used
;
670 current_pdata
->EXEC_buffer
= buffer
;
673 SC_set_error(stmt
, STMT_INTERNAL_ERROR
, "bad cbValue",
680 retval
= SQL_SUCCESS
;
686 retval
= DiscardStatementSvp(stmt
, retval
, TRUE
);