4
* Description: This module contains routines for getting/setting
5
* connection and statement options.
9
* API functions: SQLSetConnectOption, SQLSetStmtOption, SQLGetConnectOption,
12
* Comments: See "notice.txt" for copyright and license information.
20
#include "connection.h"
21
#include "statement.h"
23
#include "pgapifunc.h"
27
RETCODE set_statement_option(ConnectionClass *conn,
34
set_statement_option(ConnectionClass *conn,
39
CSTR func = "set_statement_option";
45
ci = &(conn->connInfo);
47
ci = &(SC_get_conn(stmt)->connInfo);
50
case SQL_ASYNC_ENABLE: /* ignored */
54
/* now support multi-column and multi-row binding */
56
conn->ardOptions.bind_size = vParam;
58
SC_get_ARD(stmt)->bind_size = vParam;
64
* positioned update isn't supported so cursor concurrency is
67
mylog("SetStmtOption(): SQL_CONCURRENCY = %d ", vParam);
68
setval = SQL_CONCUR_READ_ONLY;
69
if (SQL_CONCUR_READ_ONLY == vParam)
71
else if (ci->drivers.lie)
73
else if (ci->updatable_cursors)
74
setval = SQL_CONCUR_ROWVER;
76
conn->stmtOptions.scroll_concurrency = setval;
79
if (SC_get_Result(stmt))
81
SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "The attr can't be changed because the cursor is open.");
82
SC_log_error(func, "", stmt);
85
stmt->options.scroll_concurrency =
86
stmt->options_orig.scroll_concurrency = setval;
90
mylog("-> %d\n", setval);
96
* if declare/fetch, then type can only be forward. otherwise,
97
* it can only be forward or static.
99
mylog("SetStmtOption(): SQL_CURSOR_TYPE = %d ", vParam);
100
setval = SQL_CURSOR_FORWARD_ONLY;
103
#ifdef DECLAREFETCH_FORWARDONLY
104
else if (ci->drivers.use_declarefetch)
106
#endif /* DECLAREFETCH_FORWARDONLY */
107
else if (SQL_CURSOR_STATIC == vParam)
109
else if (SQL_CURSOR_KEYSET_DRIVEN == vParam)
111
if (ci->updatable_cursors)
114
setval = SQL_CURSOR_STATIC; /* at least scrollable */
117
conn->stmtOptions.cursor_type = setval;
120
if (SC_get_Result(stmt))
122
SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "The attr can't be changed because the cursor is open.");
123
SC_log_error(func, "", stmt);
126
stmt->options_orig.cursor_type =
127
stmt->options.cursor_type = setval;
129
if (setval != vParam)
131
mylog("-> %d\n", setval);
134
case SQL_KEYSET_SIZE: /* ignored, but saved and returned */
135
mylog("SetStmtOption(): SQL_KEYSET_SIZE, vParam = %d\n", vParam);
138
conn->stmtOptions.keyset_size = vParam;
141
stmt->options_orig.keyset_size = vParam;
142
if (!SC_get_Result(stmt))
143
stmt->options.keyset_size = vParam;
144
if (stmt->options.keyset_size != (int)vParam)
151
* if (ci->drivers.lie)
152
* stmt->keyset_size = vParam;
155
* stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
156
* stmt->errormsg = "Driver does not support keyset size option";
157
* SC_log_error(func, "", stmt);
163
case SQL_MAX_LENGTH: /* ignored, but saved */
164
mylog("SetStmtOption(): SQL_MAX_LENGTH, vParam = %d\n", vParam);
166
conn->stmtOptions.maxLength = vParam;
169
stmt->options_orig.maxLength = vParam;
170
if (!SC_get_Result(stmt))
171
stmt->options.maxLength = vParam;
172
if (stmt->options.maxLength != (int)vParam)
177
case SQL_MAX_ROWS: /* ignored, but saved */
178
mylog("SetStmtOption(): SQL_MAX_ROWS, vParam = %d\n", vParam);
180
conn->stmtOptions.maxRows = vParam;
183
stmt->options_orig.maxRows = vParam;
184
if (!SC_get_Result(stmt))
185
stmt->options.maxRows = vParam;
186
if (stmt->options.maxRows != (int)vParam)
191
case SQL_NOSCAN: /* ignored */
192
mylog("SetStmtOption: SQL_NOSCAN, vParam = %d\n", vParam);
195
case SQL_QUERY_TIMEOUT: /* ignored */
196
mylog("SetStmtOption: SQL_QUERY_TIMEOUT, vParam = %d\n", vParam);
197
/* "0" returned in SQLGetStmtOption */
200
case SQL_RETRIEVE_DATA:
201
mylog("SetStmtOption(): SQL_RETRIEVE_DATA, vParam = %d\n", vParam);
203
conn->stmtOptions.retrieve_data = vParam;
205
stmt->options.retrieve_data = vParam;
208
case SQL_ROWSET_SIZE:
209
mylog("SetStmtOption(): SQL_ROWSET_SIZE, vParam = %d\n", vParam);
212
* Save old rowset size for SQLExtendedFetch purposes If the
213
* rowset_size is being changed since the last call to fetch
217
if (stmt && stmt->save_rowset_size <= 0 && stmt->last_fetch_count > 0)
218
stmt->save_rowset_size = SC_get_ARD(stmt)->size_of_rowset_odbc2;
227
conn->ardOptions.size_of_rowset_odbc2 = vParam;
229
SC_get_ARD(stmt)->size_of_rowset_odbc2 = vParam;
232
case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */
235
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Simulated positioned update/delete not supported. Use the cursor library.");
236
SC_log_error(func, "", stmt);
240
CC_set_error(conn, STMT_NOT_IMPLEMENTED_ERROR, "Simulated positioned update/delete not supported. Use the cursor library.");
241
CC_log_error(func, "", conn);
245
case SQL_USE_BOOKMARKS:
247
stmt->options.use_bookmarks = vParam;
249
conn->stmtOptions.use_bookmarks = vParam;
256
SC_set_error(stmt, STMT_OPTION_NOT_FOR_THE_DRIVER, "The option may be for MS SQL Server(Set)");
260
CC_set_error(conn, STMT_OPTION_NOT_FOR_THE_DRIVER, "The option may be for MS SQL Server(Set)");
269
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Unknown statement option (Set)");
270
sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
271
SC_log_error(func, option, stmt);
275
CC_set_error(conn, STMT_NOT_IMPLEMENTED_ERROR, "Unknown statement option (Set)");
276
sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
277
CC_log_error(func, option, conn);
288
SC_set_error(stmt, STMT_OPTION_VALUE_CHANGED, "Requested value changed.");
292
CC_set_error(conn, STMT_OPTION_VALUE_CHANGED, "Requested value changed.");
294
return SQL_SUCCESS_WITH_INFO;
301
/* Implements only SQL_AUTOCOMMIT */
303
PGAPI_SetConnectOption(
308
CSTR func = "PGAPI_SetConnectOption";
309
ConnectionClass *conn = (ConnectionClass *) hdbc;
310
char changed = FALSE;
314
mylog("%s: entering fOption = %d vParam = %d\n", func, fOption, vParam);
317
CC_log_error(func, "", NULL);
318
return SQL_INVALID_HANDLE;
324
* Statement Options (apply to all stmts on the connection and
325
* become defaults for new stmts)
327
case SQL_ASYNC_ENABLE:
329
case SQL_CONCURRENCY:
330
case SQL_CURSOR_TYPE:
331
case SQL_KEYSET_SIZE:
335
case SQL_QUERY_TIMEOUT:
336
case SQL_RETRIEVE_DATA:
337
case SQL_ROWSET_SIZE:
338
case SQL_SIMULATE_CURSOR:
339
case SQL_USE_BOOKMARKS:
341
/* Affect all current Statements */
342
for (i = 0; i < conn->num_stmts; i++)
345
set_statement_option(NULL, conn->stmts[i], fOption, vParam);
349
* Become the default for all future statements on this
352
retval = set_statement_option(conn, NULL, fOption, vParam);
354
if (retval == SQL_SUCCESS_WITH_INFO)
356
else if (retval == SQL_ERROR)
365
case SQL_ACCESS_MODE: /* ignored */
369
if (vParam == SQL_AUTOCOMMIT_ON && CC_is_in_autocommit(conn))
371
else if (vParam == SQL_AUTOCOMMIT_OFF && !CC_is_in_autocommit(conn))
373
if (CC_is_in_trans(conn))
376
mylog("PGAPI_SetConnectOption: AUTOCOMMIT: transact_status=%d, vparam=%d\n", conn->transact_status, vParam);
380
case SQL_AUTOCOMMIT_OFF:
381
CC_set_autocommit_off(conn);
384
case SQL_AUTOCOMMIT_ON:
385
CC_set_autocommit_on(conn);
389
CC_set_error(conn, CONN_INVALID_ARGUMENT_NO, "Illegal parameter value for SQL_AUTOCOMMIT");
390
CC_log_error(func, "", conn);
395
case SQL_CURRENT_QUALIFIER: /* ignored */
398
case SQL_LOGIN_TIMEOUT: /* ignored */
401
case SQL_PACKET_SIZE: /* ignored */
404
case SQL_QUIET_MODE: /* ignored */
407
case SQL_TXN_ISOLATION: /* ignored */
408
retval = SQL_SUCCESS;
409
if (CC_is_in_trans(conn))
411
CC_set_error(conn, CONN_TRANSACT_IN_PROGRES, "Cannot switch isolation level while a transaction is in progress");
412
CC_log_error(func, "", conn);
415
if (conn->isolation == vParam)
419
case SQL_TXN_SERIALIZABLE:
420
if (PG_VERSION_GE(conn, 6.5) &&
421
PG_VERSION_LE(conn, 7.0))
424
case SQL_TXN_READ_COMMITTED:
425
if (PG_VERSION_LT(conn, 6.5))
431
if (SQL_ERROR == retval)
433
CC_set_error(conn, CONN_INVALID_ARGUMENT_NO, "Illegal parameter value for SQL_TXN_ISOLATION");
434
CC_log_error(func, "", conn);
442
if (vParam == SQL_TXN_SERIALIZABLE)
443
query = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE";
445
query = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL READ COMMITTED";
446
res = CC_send_query(conn, query, NULL, 0);
447
if (!res || !QR_command_maybe_successful(res))
450
conn->isolation = vParam;
453
if (SQL_ERROR == retval)
455
CC_set_error(conn, STMT_EXEC_ERROR, "ISOLATION change request to the server error");
461
/* These options should be handled by driver manager */
462
case SQL_ODBC_CURSORS:
464
case SQL_OPT_TRACEFILE:
465
case SQL_TRANSLATE_DLL:
466
case SQL_TRANSLATE_OPTION:
467
CC_log_error(func, "This connect option (Set) is only used by the Driver Manager", conn);
474
CC_set_error(conn, CONN_UNSUPPORTED_OPTION, "Unknown connect option (Set)");
475
sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
476
if (fOption == 30002 && vParam)
479
#ifdef UNICODE_SUPPORT
483
asPara = ucs2_to_utf8((SQLWCHAR *) vParam, -1, NULL, FALSE);
484
cmp = strcmp(asPara, "Microsoft Jet");
488
#endif /* UNICODE_SUPPORT */
489
cmp = strncmp((char *) vParam, "Microsoft Jet", 13);
492
mylog("Microsoft Jet !!!!\n");
493
CC_set_errornumber(conn, 0);
498
CC_log_error(func, option, conn);
505
CC_set_error(conn, CONN_OPTION_VALUE_CHANGED, "Requested value changed.");
506
return SQL_SUCCESS_WITH_INFO;
513
/* This function just can tell you whether you are in Autcommit mode or not */
515
PGAPI_GetConnectOption(
520
CSTR func = "PGAPI_GetConnectOption";
521
ConnectionClass *conn = (ConnectionClass *) hdbc;
522
ConnInfo *ci = &(conn->connInfo);
524
mylog("%s: entering...\n", func);
528
CC_log_error(func, "", NULL);
529
return SQL_INVALID_HANDLE;
534
case SQL_ACCESS_MODE: /* NOT SUPPORTED */
535
*((UDWORD *) pvParam) = SQL_MODE_READ_WRITE;
539
*((UDWORD *) pvParam) = (UDWORD) (CC_is_in_autocommit(conn) ?
540
SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
543
case SQL_CURRENT_QUALIFIER: /* don't use qualifiers */
545
((char *) pvParam)[0] = ((char *) pvParam)[1] = '\0';
549
case SQL_LOGIN_TIMEOUT: /* NOT SUPPORTED */
550
*((UDWORD *) pvParam) = 0;
553
case SQL_PACKET_SIZE: /* NOT SUPPORTED */
554
*((UDWORD *) pvParam) = ci->drivers.socket_buffersize;
557
case SQL_QUIET_MODE: /* NOT SUPPORTED */
558
*((UDWORD *) pvParam) = (UDWORD) NULL;
561
case SQL_TXN_ISOLATION:
562
*((UDWORD *) pvParam) = conn->isolation;
565
#ifdef SQL_ATTR_CONNECTION_DEAD
566
case SQL_ATTR_CONNECTION_DEAD:
569
#endif /* SQL_ATTR_CONNECTION_DEAD */
570
mylog("CONNECTION_DEAD status=%d", conn->status);
571
*((SQLUINTEGER *) pvParam) = (conn->status == CONN_NOT_CONNECTED || conn->status == CONN_DOWN);
572
mylog(" val=%d\n", *((SQLUINTEGER *) pvParam));
575
/* These options should be handled by driver manager */
576
case SQL_ODBC_CURSORS:
578
case SQL_OPT_TRACEFILE:
579
case SQL_TRANSLATE_DLL:
580
case SQL_TRANSLATE_OPTION:
581
CC_log_error(func, "This connect option (Get) is only used by the Driver Manager", conn);
588
CC_set_error(conn, CONN_UNSUPPORTED_OPTION, "Unknown connect option (Get)");
589
sprintf(option, "fOption=%d", fOption);
590
CC_log_error(func, option, conn);
606
CSTR func = "PGAPI_SetStmtOption";
607
StatementClass *stmt = (StatementClass *) hstmt;
609
mylog("%s: entering...\n", func);
612
* Though we could fake Access out by just returning SQL_SUCCESS all
613
* the time, but it tries to set a huge value for SQL_MAX_LENGTH and
614
* expects the driver to reduce it to the real value.
618
SC_log_error(func, "", NULL);
619
return SQL_INVALID_HANDLE;
622
return set_statement_option(NULL, stmt, fOption, vParam);
632
CSTR func = "PGAPI_GetStmtOption";
633
StatementClass *stmt = (StatementClass *) hstmt;
635
ConnInfo *ci = &(SC_get_conn(stmt)->connInfo);
638
mylog("%s: entering...\n", func);
641
* thought we could fake Access out by just returning SQL_SUCCESS all
642
* the time, but it tries to set a huge value for SQL_MAX_LENGTH and
643
* expects the driver to reduce it to the real value
647
SC_log_error(func, "", NULL);
648
return SQL_INVALID_HANDLE;
653
case SQL_GET_BOOKMARK:
656
res = SC_get_Curres(stmt);
659
SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "The cursor has no result.");
660
SC_log_error(func, "", stmt);
664
ridx = GIdx2ResultIdx(stmt->currTuple, stmt, res);
665
if (stmt->manual_result || !SC_is_fetchcursor(stmt))
667
/* make sure we're positioned on a valid row */
669
(ridx >= QR_get_num_backend_tuples(res)))
671
SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Not positioned on a valid row.");
672
SC_log_error(func, "", stmt);
678
if (stmt->currTuple < 0 || !res->tupleField)
680
SC_set_error(stmt, STMT_INVALID_CURSOR_STATE_ERROR, "Not positioned on a valid row.");
681
SC_log_error(func, "", stmt);
686
if (fOption == SQL_GET_BOOKMARK && stmt->options.use_bookmarks == SQL_UB_OFF)
688
SC_set_error(stmt, STMT_OPERATION_INVALID, "Operation invalid because use bookmarks not enabled.");
689
SC_log_error(func, "", stmt);
693
*((UDWORD *) pvParam) = SC_get_bookmark(stmt);
697
case SQL_ASYNC_ENABLE: /* NOT SUPPORTED */
698
*((SDWORD *) pvParam) = SQL_ASYNC_ENABLE_OFF;
702
*((SDWORD *) pvParam) = SC_get_ARD(stmt)->bind_size;
705
case SQL_CONCURRENCY: /* NOT REALLY SUPPORTED */
706
mylog("GetStmtOption(): SQL_CONCURRENCY %d\n", stmt->options.scroll_concurrency);
707
*((SDWORD *) pvParam) = stmt->options.scroll_concurrency;
710
case SQL_CURSOR_TYPE: /* PARTIAL SUPPORT */
711
mylog("GetStmtOption(): SQL_CURSOR_TYPE %d\n", stmt->options.cursor_type);
712
*((SDWORD *) pvParam) = stmt->options.cursor_type;
715
case SQL_KEYSET_SIZE: /* NOT SUPPORTED, but saved */
716
mylog("GetStmtOption(): SQL_KEYSET_SIZE\n");
717
*((SDWORD *) pvParam) = stmt->options.keyset_size;
720
case SQL_MAX_LENGTH: /* NOT SUPPORTED, but saved */
721
*((SDWORD *) pvParam) = stmt->options.maxLength;
724
case SQL_MAX_ROWS: /* NOT SUPPORTED, but saved */
725
*((SDWORD *) pvParam) = stmt->options.maxRows;
726
mylog("GetSmtOption: MAX_ROWS, returning %d\n", stmt->options.maxRows);
729
case SQL_NOSCAN: /* NOT SUPPORTED */
730
*((SDWORD *) pvParam) = SQL_NOSCAN_ON;
733
case SQL_QUERY_TIMEOUT: /* NOT SUPPORTED */
734
*((SDWORD *) pvParam) = 0;
737
case SQL_RETRIEVE_DATA:
738
*((SDWORD *) pvParam) = stmt->options.retrieve_data;
741
case SQL_ROWSET_SIZE:
742
*((SDWORD *) pvParam) = SC_get_ARD(stmt)->size_of_rowset_odbc2;
745
case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */
746
*((SDWORD *) pvParam) = SQL_SC_NON_UNIQUE;
749
case SQL_USE_BOOKMARKS:
750
*((SDWORD *) pvParam) = stmt->options.use_bookmarks;
757
SC_set_error(stmt, STMT_NOT_IMPLEMENTED_ERROR, "Unknown statement option (Get)");
758
sprintf(option, "fOption=%d", fOption);
759
SC_log_error(func, option, stmt);