2 * Description: This module contains routines for getting/setting
3 * connection and statement options.
10 #include "connection.h"
11 #include "statement.h"
13 #include "pgapifunc.h"
18 set_statement_option(ConnectionClass
* conn
,
19 StatementClass
* stmt
,
20 SQLUSMALLINT fOption
, SQLULEN vParam
)
22 CSTR func
= "set_statement_option";
28 ci
= &(conn
->connInfo
);
30 ci
= &(SC_get_conn(stmt
)->connInfo
);
33 case SQL_ASYNC_ENABLE
: /* ignored */
37 /* now support multi-column and multi-row binding */
39 conn
->ardOptions
.bind_size
= (SQLUINTEGER
) vParam
;
41 SC_get_ARDF(stmt
)->bind_size
= (SQLUINTEGER
) vParam
;
47 * positioned update isn't supported so cursor concurrency is
50 mylog("SetStmtOption(): SQL_CONCURRENCY = %d ", vParam
);
51 setval
= SQL_CONCUR_READ_ONLY
;
52 if (SQL_CONCUR_READ_ONLY
== vParam
)
54 else if (0 != ci
->updatable_cursors
)
55 setval
= SQL_CONCUR_ROWVER
;
57 conn
->stmtOptions
.scroll_concurrency
= (SQLUINTEGER
) setval
;
60 if (SC_get_Result(stmt
))
62 SC_set_error(stmt
, STMT_INVALID_CURSOR_STATE_ERROR
,
63 "The attr can't be changed because the cursor is open.",
67 stmt
->options
.scroll_concurrency
=
68 stmt
->options_orig
.scroll_concurrency
=
73 mylog("-> %d\n", setval
);
79 * if declare/fetch, then type can only be forward. otherwise,
80 * it can only be forward or static.
82 mylog("SetStmtOption(): SQL_CURSOR_TYPE = %d ", vParam
);
83 setval
= SQL_CURSOR_FORWARD_ONLY
;
84 if (SQL_CURSOR_STATIC
== vParam
)
86 else if (SQL_CURSOR_KEYSET_DRIVEN
== vParam
||
87 SQL_CURSOR_DYNAMIC
== vParam
)
90 (ci
->updatable_cursors
& ALLOW_KEYSET_DRIVEN_CURSORS
))
93 setval
= SQL_CURSOR_STATIC
; /* at least scrollable */
96 conn
->stmtOptions
.cursor_type
= (SQLUINTEGER
) setval
;
99 if (SC_get_Result(stmt
))
101 SC_set_error(stmt
, STMT_INVALID_CURSOR_STATE_ERROR
,
102 "The attr can't be changed because the cursor is open.",
106 stmt
->options_orig
.cursor_type
=
107 stmt
->options
.cursor_type
= (SQLUINTEGER
) setval
;
109 if (setval
!= vParam
)
111 mylog("-> %d\n", setval
);
114 case SQL_KEYSET_SIZE
: /* ignored, but saved and returned */
115 mylog("SetStmtOption(): SQL_KEYSET_SIZE, vParam = %d\n",
119 conn
->stmtOptions
.keyset_size
= vParam
;
122 stmt
->options_orig
.keyset_size
= vParam
;
123 if (!SC_get_Result(stmt
))
124 stmt
->options
.keyset_size
= vParam
;
125 if (stmt
->options
.keyset_size
!= (int) vParam
)
131 case SQL_MAX_LENGTH
: /* ignored, but saved */
132 mylog("SetStmtOption(): SQL_MAX_LENGTH, vParam = %d\n", vParam
);
134 conn
->stmtOptions
.maxLength
= vParam
;
137 stmt
->options_orig
.maxLength
= vParam
;
138 if (!SC_get_Result(stmt
))
139 stmt
->options
.maxLength
= vParam
;
140 if (stmt
->options
.maxLength
!= (int) vParam
)
145 case SQL_MAX_ROWS
: /* ignored, but saved */
146 mylog("SetStmtOption(): SQL_MAX_ROWS, vParam = %d\n", vParam
);
148 conn
->stmtOptions
.maxRows
= vParam
;
151 stmt
->options_orig
.maxRows
= vParam
;
152 if (!SC_get_Result(stmt
))
153 stmt
->options
.maxRows
= vParam
;
154 if (stmt
->options
.maxRows
!= (int) vParam
)
159 case SQL_NOSCAN
: /* ignored */
160 mylog("SetStmtOption: SQL_NOSCAN, vParam = %d\n", vParam
);
163 case SQL_QUERY_TIMEOUT
: /* ignored */
164 mylog("SetStmtOption: SQL_QUERY_TIMEOUT, vParam = %d\n",
166 /* "0" returned in SQLGetStmtOption */
169 case SQL_RETRIEVE_DATA
:
170 mylog("SetStmtOption(): SQL_RETRIEVE_DATA, vParam = %d\n",
173 conn
->stmtOptions
.retrieve_data
= (SQLUINTEGER
) vParam
;
175 stmt
->options
.retrieve_data
= (SQLUINTEGER
) vParam
;
178 case SQL_ROWSET_SIZE
:
179 mylog("SetStmtOption(): SQL_ROWSET_SIZE, vParam = %d\n",
183 * Save old rowset size for SQLExtendedFetch purposes If the
184 * rowset_size is being changed since the last call to fetch
188 if (stmt
&& stmt
->save_rowset_size
<= 0
189 && stmt
->last_fetch_count
> 0)
190 stmt
->save_rowset_size
=
191 SC_get_ARDF(stmt
)->size_of_rowset_odbc2
;
200 conn
->ardOptions
.size_of_rowset_odbc2
= vParam
;
202 SC_get_ARDF(stmt
)->size_of_rowset_odbc2
= vParam
;
205 case SQL_SIMULATE_CURSOR
: /* NOT SUPPORTED */
208 SC_set_error(stmt
, STMT_NOT_IMPLEMENTED_ERROR
,
209 "Simulated positioned update/delete not supported. Use the cursor library.",
214 CC_set_error(conn
, CONN_NOT_IMPLEMENTED_ERROR
,
215 "Simulated positioned update/delete not supported. Use the cursor library.",
220 case SQL_USE_BOOKMARKS
:
223 mylog("USE_BOOKMARKS %s\n",
225 SQL_UB_OFF
) ? "off" : ((vParam
==
226 SQL_UB_VARIABLE
) ? "variable"
229 stmt
->options
.use_bookmarks
= (SQLUINTEGER
) setval
;
232 conn
->stmtOptions
.use_bookmarks
= (SQLUINTEGER
) vParam
;
235 case 1204: /* SQL_COPT_SS_PRESERVE_CURSORS ? */
236 case 1227: /* SQL_SOPT_SS_HIDDEN_COLUMNS ? */
237 case 1228: /* SQL_SOPT_SS_NOBROWSETABLE ? */
240 SC_set_error(stmt
, STMT_OPTION_NOT_FOR_THE_DRIVER
,
241 "The option may be for MS SQL Server(Set)",
245 CC_set_error(conn
, CONN_OPTION_NOT_FOR_THE_DRIVER
,
246 "The option may be for MS SQL Server(Set)",
256 SC_set_error(stmt
, STMT_NOT_IMPLEMENTED_ERROR
,
257 "Unknown statement option (Set)", NULL
);
258 sprintf(option
, "fOption=%d, vParam=" FORMAT_LEN
,
260 SC_log_error(func
, option
, stmt
);
264 CC_set_error(conn
, CONN_NOT_IMPLEMENTED_ERROR
,
265 "Unknown statement option (Set)", func
);
266 sprintf(option
, "fOption=%d, vParam=" FORMAT_LEN
,
268 CC_log_error(func
, option
, conn
);
279 SC_set_error(stmt
, STMT_OPTION_VALUE_CHANGED
,
280 "Requested value changed.", func
);
284 CC_set_error(conn
, CONN_OPTION_VALUE_CHANGED
,
285 "Requested value changed.", func
);
287 return SQL_SUCCESS_WITH_INFO
;
293 // VX_CLEANUP: Some of these are probably irrelevant
294 /* Implements only SQL_AUTOCOMMIT */
296 PGAPI_SetConnectOption(HDBC hdbc
, SQLUSMALLINT fOption
, SQLULEN vParam
)
298 CSTR func
= "PGAPI_SetConnectOption";
299 ConnectionClass
*conn
= (ConnectionClass
*) hdbc
;
300 char changed
= FALSE
;
303 mylog("%s: entering fOption = %d vParam = %d\n", func
, fOption
,
307 CC_log_error(func
, "", NULL
);
308 return SQL_INVALID_HANDLE
;
314 * Statement Options (apply to all stmts on the connection and
315 * become defaults for new stmts)
317 case SQL_ASYNC_ENABLE
:
319 case SQL_CONCURRENCY
:
320 case SQL_CURSOR_TYPE
:
321 case SQL_KEYSET_SIZE
:
325 case SQL_QUERY_TIMEOUT
:
326 case SQL_RETRIEVE_DATA
:
327 case SQL_ROWSET_SIZE
:
328 case SQL_SIMULATE_CURSOR
:
329 case SQL_USE_BOOKMARKS
:
331 * Become the default for all future statements on this
334 retval
= set_statement_option(conn
, NULL
, fOption
, vParam
);
336 if (retval
== SQL_SUCCESS_WITH_INFO
)
338 else if (retval
== SQL_ERROR
)
347 case SQL_ACCESS_MODE
: /* ignored */
352 mylog("Attempt to set SQL_AUTOCOMMIT ignored\n");
355 case SQL_CURRENT_QUALIFIER
: /* ignored */
358 case SQL_LOGIN_TIMEOUT
:
359 conn
->login_timeout
= (SQLUINTEGER
) vParam
;
362 case SQL_PACKET_SIZE
: /* ignored */
365 case SQL_QUIET_MODE
: /* ignored */
368 case SQL_TXN_ISOLATION
: /* ignored */
369 retval
= SQL_SUCCESS
;
370 if (conn
->isolation
== vParam
)
374 case SQL_TXN_SERIALIZABLE
:
375 if (PG_VERSION_GE(conn
, 6.5) && PG_VERSION_LE(conn
, 7.0))
378 case SQL_TXN_READ_COMMITTED
:
379 if (PG_VERSION_LT(conn
, 6.5))
385 if (SQL_ERROR
== retval
)
387 CC_set_error(conn
, CONN_INVALID_ARGUMENT_NO
,
388 "Illegal parameter value for SQL_TXN_ISOLATION",
396 if (vParam
== SQL_TXN_SERIALIZABLE
)
398 "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE";
401 "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL READ COMMITTED";
402 res
= CC_send_query(conn
, query
, NULL
, 0, NULL
);
403 if (!QR_command_maybe_successful(res
))
406 conn
->isolation
= (UInt4
) vParam
;
408 if (SQL_ERROR
== retval
)
410 CC_set_error(conn
, CONN_EXEC_ERROR
,
411 "ISOLATION change request to the server error",
418 /* These options should be handled by driver manager */
419 case SQL_ODBC_CURSORS
:
421 case SQL_OPT_TRACEFILE
:
422 case SQL_TRANSLATE_DLL
:
423 case SQL_TRANSLATE_OPTION
:
425 "This connect option (Set) is only used by the Driver Manager",
433 CC_set_error(conn
, CONN_UNSUPPORTED_OPTION
,
434 "Unknown connect option (Set)", func
);
435 sprintf(option
, "fOption=%d, vParam=" FORMAT_LEN
, fOption
,
437 if (fOption
== 30002 && vParam
)
440 #ifdef UNICODE_SUPPORT
441 if (CC_is_in_unicode_driver(conn
))
444 ucs2_to_utf8((SQLWCHAR
*) vParam
, SQL_NTS
, NULL
,
446 cmp
= strcmp(asPara
, "Microsoft Jet");
449 #endif /* UNICODE_SUPPORT */
450 cmp
= strncmp((char *) vParam
, "Microsoft Jet", 13);
453 mylog("Microsoft Jet !!!!\n");
454 CC_set_errornumber(conn
, 0);
459 CC_log_error(func
, option
, conn
);
466 CC_set_error(conn
, CONN_OPTION_VALUE_CHANGED
,
467 "Requested value changed.", func
);
468 return SQL_SUCCESS_WITH_INFO
;
474 // VX_CLEANUP: Most of these are probably irrelevant
475 /* This function just can tell you whether you are in Autcommit mode or not */
477 PGAPI_GetConnectOption(HDBC hdbc
,
478 SQLUSMALLINT fOption
,
480 SQLINTEGER
* StringLength
,
481 SQLINTEGER BufferLength
)
483 CSTR func
= "PGAPI_GetConnectOption";
484 ConnectionClass
*conn
= (ConnectionClass
*) hdbc
;
485 const char *p
= NULL
;
486 SQLLEN len
= sizeof(SQLINTEGER
);
487 SQLRETURN result
= SQL_SUCCESS
;
489 mylog("%s: entering...\n", func
);
493 CC_log_error(func
, "", NULL
);
494 return SQL_INVALID_HANDLE
;
499 case SQL_ACCESS_MODE
: /* NOT SUPPORTED */
500 *((SQLUINTEGER
*) pvParam
) = SQL_MODE_READ_WRITE
;
504 // VX_CLEANUP: FIXME: We don't do any committing at all, does that
505 // mean autocommit is on or off?
506 *((SQLUINTEGER
*) pvParam
) = (SQLUINTEGER
) SQL_AUTOCOMMIT_OFF
;
509 case SQL_CURRENT_QUALIFIER
: /* don't use qualifiers */
511 p
= CurrCatString(conn
);
514 case SQL_LOGIN_TIMEOUT
:
515 *((SQLUINTEGER
*) pvParam
) = conn
->login_timeout
;
518 case SQL_PACKET_SIZE
: /* NOT SUPPORTED */
519 *((SQLUINTEGER
*) pvParam
) = SOCK_BUFFER_SIZE
;
522 case SQL_QUIET_MODE
: /* NOT SUPPORTED */
523 *((SQLULEN
*) pvParam
) = (SQLULEN
) NULL
;
526 case SQL_TXN_ISOLATION
:
527 *((SQLUINTEGER
*) pvParam
) = conn
->isolation
;
530 #ifdef SQL_ATTR_CONNECTION_DEAD
531 case SQL_ATTR_CONNECTION_DEAD
:
534 #endif /* SQL_ATTR_CONNECTION_DEAD */
535 mylog("CONNECTION_DEAD status=%d", conn
->status
);
536 *((SQLUINTEGER
*) pvParam
) = (conn
->status
== CONN_NOT_CONNECTED
537 || conn
->status
== CONN_DOWN
);
538 mylog(" val=%d\n", *((SQLUINTEGER
*) pvParam
));
541 case SQL_ATTR_ANSI_APP
:
542 *((SQLUINTEGER
*) pvParam
) = CC_is_in_ansi_app(conn
);
543 mylog("ANSI_APP val=%d\n", *((SQLUINTEGER
*) pvParam
));
546 /* These options should be handled by driver manager */
547 case SQL_ODBC_CURSORS
:
549 case SQL_OPT_TRACEFILE
:
550 case SQL_TRANSLATE_DLL
:
551 case SQL_TRANSLATE_OPTION
:
553 "This connect option (Get) is only used by the Driver Manager",
561 CC_set_error(conn
, CONN_UNSUPPORTED_OPTION
,
562 "Unknown connect option (Get)", func
);
563 sprintf(option
, "fOption=%d", fOption
);
564 CC_log_error(func
, option
, conn
);
570 if (NULL
!= p
&& 0 == len
)
572 /* char/binary data */
577 #ifdef UNICODE_SUPPORT
578 if (CC_is_in_unicode_driver(conn
))
581 utf8_to_ucs2(p
, len
, (SQLWCHAR
*) pvParam
,
582 BufferLength
/ WCLEN
);
585 #endif /* UNICODE_SUPPORT */
586 strncpy_null((char *) pvParam
, p
,
587 (size_t) BufferLength
);
589 if (len
>= BufferLength
)
591 result
= SQL_SUCCESS_WITH_INFO
;
592 CC_set_error(conn
, CONN_TRUNCATED
,
593 "The buffer was too small for the pvParam.",
599 *StringLength
= (SQLINTEGER
) len
;
605 PGAPI_SetStmtOption(HSTMT hstmt
, SQLUSMALLINT fOption
, SQLULEN vParam
)
607 CSTR func
= "PGAPI_SetStmtOption";
608 StatementClass
*stmt
= (StatementClass
*) hstmt
;
611 mylog("%s: entering...\n", func
);
614 * Though we could fake Access out by just returning SQL_SUCCESS all
615 * the time, but it tries to set a huge value for SQL_MAX_LENGTH and
616 * expects the driver to reduce it to the real value.
620 SC_log_error(func
, "", NULL
);
621 return SQL_INVALID_HANDLE
;
624 /* StartRollbackState(stmt); */
625 retval
= set_statement_option(NULL
, stmt
, fOption
, vParam
);
627 retval
= DiscardStatementSvp(stmt
, retval
, FALSE
);
633 PGAPI_GetStmtOption(HSTMT hstmt
,
634 SQLUSMALLINT fOption
,
636 SQLINTEGER
* StringLength
, SQLINTEGER BufferLength
)
638 CSTR func
= "PGAPI_GetStmtOption";
639 StatementClass
*stmt
= (StatementClass
*) hstmt
;
642 SQLINTEGER len
= sizeof(SQLINTEGER
);
644 mylog("%s: entering...\n", func
);
647 * thought we could fake Access out by just returning SQL_SUCCESS all
648 * the time, but it tries to set a huge value for SQL_MAX_LENGTH and
649 * expects the driver to reduce it to the real value
653 SC_log_error(func
, "", NULL
);
654 return SQL_INVALID_HANDLE
;
659 case SQL_GET_BOOKMARK
:
662 res
= SC_get_Curres(stmt
);
665 SC_set_error(stmt
, STMT_INVALID_CURSOR_STATE_ERROR
,
666 "The cursor has no result.", func
);
670 ridx
= GIdx2CacheIdx(stmt
->currTuple
, stmt
, res
);
672 /* make sure we're positioned on a valid row */
673 if ((ridx
< 0) || (ridx
>= QR_get_num_cached_tuples(res
)))
675 SC_set_error(stmt
, STMT_INVALID_CURSOR_STATE_ERROR
,
676 "Not positioned on a valid row.", func
);
681 if (fOption
== SQL_GET_BOOKMARK
682 && stmt
->options
.use_bookmarks
== SQL_UB_OFF
)
684 SC_set_error(stmt
, STMT_OPERATION_INVALID
,
685 "Operation invalid because use bookmarks not enabled.",
690 *((SQLULEN
*) pvParam
) = SC_get_bookmark(stmt
);
694 case SQL_ASYNC_ENABLE
: /* NOT SUPPORTED */
695 *((SQLINTEGER
*) pvParam
) = SQL_ASYNC_ENABLE_OFF
;
699 *((SQLINTEGER
*) pvParam
) = SC_get_ARDF(stmt
)->bind_size
;
702 case SQL_CONCURRENCY
: /* NOT REALLY SUPPORTED */
703 mylog("GetStmtOption(): SQL_CONCURRENCY %d\n",
704 stmt
->options
.scroll_concurrency
);
705 *((SQLINTEGER
*) pvParam
) = stmt
->options
.scroll_concurrency
;
708 case SQL_CURSOR_TYPE
: /* PARTIAL SUPPORT */
709 mylog("GetStmtOption(): SQL_CURSOR_TYPE %d\n",
710 stmt
->options
.cursor_type
);
711 *((SQLINTEGER
*) pvParam
) = stmt
->options
.cursor_type
;
714 case SQL_KEYSET_SIZE
: /* NOT SUPPORTED, but saved */
715 mylog("GetStmtOption(): SQL_KEYSET_SIZE\n");
716 *((SQLLEN
*) pvParam
) = stmt
->options
.keyset_size
;
719 case SQL_MAX_LENGTH
: /* NOT SUPPORTED, but saved */
720 *((SQLLEN
*) pvParam
) = stmt
->options
.maxLength
;
723 case SQL_MAX_ROWS
: /* NOT SUPPORTED, but saved */
724 *((SQLLEN
*) pvParam
) = stmt
->options
.maxRows
;
725 mylog("GetSmtOption: MAX_ROWS, returning %d\n",
726 stmt
->options
.maxRows
);
729 case SQL_NOSCAN
: /* NOT SUPPORTED */
730 *((SQLINTEGER
*) pvParam
) = SQL_NOSCAN_ON
;
733 case SQL_QUERY_TIMEOUT
: /* NOT SUPPORTED */
734 *((SQLINTEGER
*) pvParam
) = 0;
737 case SQL_RETRIEVE_DATA
:
738 *((SQLINTEGER
*) pvParam
) = stmt
->options
.retrieve_data
;
741 case SQL_ROWSET_SIZE
:
742 *((SQLLEN
*) pvParam
) = SC_get_ARDF(stmt
)->size_of_rowset_odbc2
;
745 case SQL_SIMULATE_CURSOR
: /* NOT SUPPORTED */
746 *((SQLINTEGER
*) pvParam
) = SQL_SC_NON_UNIQUE
;
749 case SQL_USE_BOOKMARKS
:
750 *((SQLINTEGER
*) pvParam
) = stmt
->options
.use_bookmarks
;
757 SC_set_error(stmt
, STMT_NOT_IMPLEMENTED_ERROR
,
758 "Unknown statement option (Get)", NULL
);
759 sprintf(option
, "fOption=%d", fOption
);
760 SC_log_error(func
, option
, stmt
);