options.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:15k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /* Module:          options.c
  2.  *
  3.  * Description:     This module contains routines for getting/setting
  4.  *                  connection and statement options.
  5.  *
  6.  * Classes:         n/a
  7.  *
  8.  * API functions:   SQLSetConnectOption, SQLSetStmtOption, SQLGetConnectOption,
  9.  *                  SQLGetStmtOption
  10.  *
  11.  * Comments:        See "notice.txt" for copyright and license information.
  12.  *
  13.  */
  14. #ifdef HAVE_CONFIG_H
  15. #include "config.h"
  16. #endif
  17. #include "psqlodbc.h"
  18. #ifndef WIN32
  19. #include "iodbc.h"
  20. #include "isql.h"
  21. #include "isqlext.h"
  22. #else
  23. #include <windows.h>
  24. #include <sql.h>
  25. #include <sqlext.h>
  26. #endif
  27. #include "environ.h"
  28. #include "connection.h"
  29. #include "statement.h"
  30. #include "qresult.h"
  31. extern GLOBAL_VALUES globals;
  32. RETCODE set_statement_option(ConnectionClass *conn, 
  33.  StatementClass *stmt, 
  34.  UWORD   fOption,
  35.  UDWORD  vParam);
  36. RETCODE set_statement_option(ConnectionClass *conn, 
  37.  StatementClass *stmt, 
  38.  UWORD   fOption,
  39.  UDWORD  vParam)
  40. {
  41. static char *func="set_statement_option";
  42. char changed = FALSE;
  43. switch(fOption) {
  44. case SQL_ASYNC_ENABLE:/* ignored */
  45. break;
  46. case SQL_BIND_TYPE:
  47. /* now support multi-column and multi-row binding */
  48. if (conn) conn->stmtOptions.bind_size = vParam;
  49. if (stmt) stmt->options.bind_size = vParam;
  50. break;
  51. case SQL_CONCURRENCY:
  52. /* positioned update isn't supported so cursor concurrency is read-only */
  53. if (conn) conn->stmtOptions.scroll_concurrency = vParam;
  54. if (stmt) stmt->options.scroll_concurrency = vParam;
  55. break;
  56. /*
  57. if (globals.lie) {
  58. if (conn) conn->stmtOptions.scroll_concurrency = vParam;
  59. if (stmt) stmt->options.scroll_concurrency = vParam;
  60. }
  61. else {
  62. if (conn) conn->stmtOptions.scroll_concurrency = SQL_CONCUR_READ_ONLY;
  63. if (stmt) stmt->options.scroll_concurrency = SQL_CONCUR_READ_ONLY;
  64. if (vParam != SQL_CONCUR_READ_ONLY)
  65. changed = TRUE;
  66. }
  67. break;
  68. */
  69. case SQL_CURSOR_TYPE:
  70. /* if declare/fetch, then type can only be forward.
  71. otherwise, it can only be forward or static.
  72. */
  73. mylog("SetStmtOption(): SQL_CURSOR_TYPE = %dn", vParam);
  74. if (globals.lie) {
  75. if (conn) conn->stmtOptions.cursor_type = vParam;
  76. if (stmt) stmt->options.cursor_type = vParam;
  77. }
  78. else {
  79. if (globals.use_declarefetch) {
  80. if (conn) conn->stmtOptions.cursor_type = SQL_CURSOR_FORWARD_ONLY;
  81. if (stmt) stmt->options.cursor_type = SQL_CURSOR_FORWARD_ONLY;
  82. if (vParam != SQL_CURSOR_FORWARD_ONLY) 
  83. changed = TRUE;
  84. }
  85. else {
  86. if (vParam == SQL_CURSOR_FORWARD_ONLY || vParam == SQL_CURSOR_STATIC) {
  87. if (conn) conn->stmtOptions.cursor_type = vParam; // valid type
  88. if (stmt) stmt->options.cursor_type = vParam; // valid type
  89. }
  90. else {
  91. if (conn) conn->stmtOptions.cursor_type = SQL_CURSOR_STATIC;
  92. if (stmt) stmt->options.cursor_type = SQL_CURSOR_STATIC;
  93. changed = TRUE;
  94. }
  95. }
  96. }
  97. break;
  98. case SQL_KEYSET_SIZE: /* ignored, but saved and returned  */
  99. mylog("SetStmtOption(): SQL_KEYSET_SIZE, vParam = %dn", vParam);
  100. if (conn) conn->stmtOptions.keyset_size = vParam;
  101. if (stmt) stmt->options.keyset_size = vParam;
  102. break;
  103. /*
  104. if (globals.lie)
  105. stmt->keyset_size = vParam;
  106. else {
  107. stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
  108. stmt->errormsg = "Driver does not support keyset size option";
  109. SC_log_error(func, "", stmt);
  110. return SQL_ERROR;
  111. }
  112. */
  113. case SQL_MAX_LENGTH:/* ignored, but saved */
  114. mylog("SetStmtOption(): SQL_MAX_LENGTH, vParam = %dn", vParam);
  115. if (conn) conn->stmtOptions.maxLength = vParam;
  116. if (stmt) stmt->options.maxLength = vParam;
  117. break;
  118. case SQL_MAX_ROWS: /* ignored, but saved */
  119. mylog("SetStmtOption(): SQL_MAX_ROWS, vParam = %dn", vParam);
  120. if (conn) conn->stmtOptions.maxRows = vParam;
  121. if (stmt) stmt->options.maxRows = vParam;
  122. break;
  123. case SQL_NOSCAN: /* ignored */
  124. mylog("SetStmtOption: SQL_NOSCAN, vParam = %dn", vParam);
  125. break;
  126. case SQL_QUERY_TIMEOUT: /* ignored */
  127. mylog("SetStmtOption: SQL_QUERY_TIMEOUT, vParam = %dn", vParam);
  128. // "0" returned in SQLGetStmtOption
  129. break;
  130. case SQL_RETRIEVE_DATA: /* ignored, but saved */
  131. mylog("SetStmtOption(): SQL_RETRIEVE_DATA, vParam = %dn", vParam);
  132. if (conn) conn->stmtOptions.retrieve_data = vParam;
  133. if (stmt) stmt->options.retrieve_data = vParam;
  134. break;
  135. case SQL_ROWSET_SIZE:
  136. mylog("SetStmtOption(): SQL_ROWSET_SIZE, vParam = %dn", vParam);
  137. /* Save old rowset size for SQLExtendedFetch purposes 
  138. If the rowset_size is being changed since the last call
  139. to fetch rows.
  140. */
  141. if (stmt && stmt->save_rowset_size <= 0 && stmt->last_fetch_count > 0 )
  142. stmt->save_rowset_size = stmt->options.rowset_size;
  143. if (vParam < 1) {
  144. vParam = 1;
  145. changed = TRUE;
  146. }
  147. if (conn) conn->stmtOptions.rowset_size = vParam;
  148. if (stmt) stmt->options.rowset_size = vParam;
  149. break;
  150. case SQL_SIMULATE_CURSOR: /* NOT SUPPORTED */
  151. if (stmt) {
  152. stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
  153. stmt->errormsg = "Simulated positioned update/delete not supported.  Use the cursor library.";
  154. SC_log_error(func, "", stmt);
  155. }
  156. if (conn) {
  157. conn->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
  158. conn->errormsg = "Simulated positioned update/delete not supported.  Use the cursor library.";
  159. CC_log_error(func, "", conn);
  160. }
  161. return SQL_ERROR;
  162. case SQL_USE_BOOKMARKS:
  163. if (stmt) stmt->options.use_bookmarks = vParam;
  164. if (conn) conn->stmtOptions.use_bookmarks = vParam;
  165. break;
  166.     default:
  167. {
  168. char option[64];
  169. if (stmt) {
  170. stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
  171. stmt->errormsg = "Unknown statement option (Set)";
  172. sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
  173. SC_log_error(func, option, stmt);
  174. }
  175. if (conn) {
  176. conn->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
  177. conn->errormsg = "Unknown statement option (Set)";
  178. sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
  179. CC_log_error(func, option, conn);
  180. }
  181.         return SQL_ERROR;
  182. }
  183.     }
  184. if (changed) {
  185. if (stmt) {
  186. stmt->errormsg = "Requested value changed.";
  187. stmt->errornumber = STMT_OPTION_VALUE_CHANGED;
  188. }
  189. if (conn) {
  190. conn->errormsg = "Requested value changed.";
  191. conn->errornumber = STMT_OPTION_VALUE_CHANGED;
  192. }
  193. return SQL_SUCCESS_WITH_INFO;
  194. }
  195. else
  196. return SQL_SUCCESS;
  197. }
  198. /* Implements only SQL_AUTOCOMMIT */
  199. RETCODE SQL_API SQLSetConnectOption(
  200.         HDBC    hdbc,
  201.         UWORD   fOption,
  202.         UDWORD  vParam)
  203. {
  204. static char *func="SQLSetConnectOption";
  205. ConnectionClass *conn = (ConnectionClass *) hdbc;
  206. char changed = FALSE;
  207. RETCODE retval;
  208. int i;
  209. mylog("%s: entering...n", func);
  210. if ( ! conn)  {
  211. CC_log_error(func, "", NULL);
  212. return SQL_INVALID_HANDLE;
  213. }
  214. switch (fOption) {
  215. /* Statement Options 
  216.    (apply to all stmts on the connection and become defaults for new stmts)
  217. */
  218. case SQL_ASYNC_ENABLE:
  219. case SQL_BIND_TYPE:
  220. case SQL_CONCURRENCY:
  221. case SQL_CURSOR_TYPE:
  222. case SQL_KEYSET_SIZE: 
  223. case SQL_MAX_LENGTH:
  224. case SQL_MAX_ROWS:
  225. case SQL_NOSCAN: 
  226. case SQL_QUERY_TIMEOUT:
  227. case SQL_RETRIEVE_DATA:
  228. case SQL_ROWSET_SIZE:
  229. case SQL_SIMULATE_CURSOR:
  230. case SQL_USE_BOOKMARKS:
  231. /* Affect all current Statements */
  232. for (i = 0; i < conn->num_stmts; i++) {
  233. if ( conn->stmts[i]) {
  234. set_statement_option(NULL, conn->stmts[i], fOption, vParam);
  235. }
  236. }
  237. /* Become the default for all future statements on this connection */
  238. retval = set_statement_option(conn, NULL, fOption, vParam);
  239. if (retval == SQL_SUCCESS_WITH_INFO)
  240. changed = TRUE;
  241. else if (retval == SQL_ERROR)
  242. return SQL_ERROR;
  243. break;
  244. /**********************************/
  245. /***** Connection Options  *******/
  246. /**********************************/
  247. case SQL_ACCESS_MODE: /* ignored */
  248. break;
  249. case SQL_AUTOCOMMIT:
  250. /*  Since we are almost always in a transaction, this is now ok.
  251. Even if we were, the logic will handle it by sending a commit
  252. after the statement.
  253. if (CC_is_in_trans(conn)) {
  254. conn->errormsg = "Cannot switch commit mode while a transaction is in progres";
  255. conn->errornumber = CONN_TRANSACT_IN_PROGRES;
  256. CC_log_error(func, "", conn);
  257. return SQL_ERROR;
  258. }
  259. */
  260. mylog("SQLSetConnectOption: AUTOCOMMIT: transact_status=%d, vparam=%dn", conn->transact_status, vParam);
  261. switch(vParam) {
  262. case SQL_AUTOCOMMIT_OFF:
  263. CC_set_autocommit_off(conn);
  264. break;
  265. case SQL_AUTOCOMMIT_ON:
  266. CC_set_autocommit_on(conn);
  267. break;
  268. default:
  269. conn->errormsg = "Illegal parameter value for SQL_AUTOCOMMIT";
  270. conn->errornumber = CONN_INVALID_ARGUMENT_NO;
  271. CC_log_error(func, "", conn);
  272. return SQL_ERROR;
  273. }
  274. break;
  275. case SQL_CURRENT_QUALIFIER: /* ignored */
  276. break;
  277. case SQL_LOGIN_TIMEOUT: /* ignored */
  278. break;
  279. case SQL_PACKET_SIZE: /* ignored */
  280. break;
  281. case SQL_QUIET_MODE: /* ignored */
  282. break;
  283. case SQL_TXN_ISOLATION: /* ignored */
  284. break;
  285. /* These options should be handled by driver manager */
  286. case SQL_ODBC_CURSORS:
  287. case SQL_OPT_TRACE:
  288. case SQL_OPT_TRACEFILE:
  289. case SQL_TRANSLATE_DLL:
  290. case SQL_TRANSLATE_OPTION:
  291. CC_log_error(func, "This connect option (Set) is only used by the Driver Manager", conn);
  292. break;
  293. default:
  294. char option[64];
  295. conn->errormsg = "Unknown connect option (Set)";
  296. conn->errornumber = CONN_UNSUPPORTED_OPTION;
  297. sprintf(option, "fOption=%d, vParam=%ld", fOption, vParam);
  298. CC_log_error(func, option, conn);
  299. return SQL_ERROR;
  300. }
  301. }    
  302. if (changed) {
  303. conn->errornumber = CONN_OPTION_VALUE_CHANGED;
  304. conn->errormsg = "Requested value changed.";
  305. return SQL_SUCCESS_WITH_INFO;
  306. }
  307. else
  308. return SQL_SUCCESS;
  309. }
  310. //      -       -       -       -       -       -       -       -       -
  311. /* This function just can tell you whether you are in Autcommit mode or not */
  312. RETCODE SQL_API SQLGetConnectOption(
  313.         HDBC    hdbc,
  314.         UWORD   fOption,
  315.         PTR     pvParam)
  316. {
  317. static char *func="SQLGetConnectOption";
  318. ConnectionClass *conn = (ConnectionClass *) hdbc;
  319. mylog("%s: entering...n", func);
  320. if (! conn)  {
  321. CC_log_error(func, "", NULL);
  322. return SQL_INVALID_HANDLE;
  323. }
  324. switch (fOption) {
  325. case SQL_ACCESS_MODE:/* NOT SUPPORTED */
  326. *((UDWORD *) pvParam) = SQL_MODE_READ_WRITE;
  327. break;
  328. case SQL_AUTOCOMMIT:
  329. *((UDWORD *)pvParam) = (UDWORD)( CC_is_in_autocommit(conn) ?
  330. SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
  331. break;
  332. case SQL_CURRENT_QUALIFIER: /* don't use qualifiers */
  333. if(pvParam)
  334. strcpy(pvParam, "");
  335. break;
  336. case SQL_LOGIN_TIMEOUT: /* NOT SUPPORTED */
  337. *((UDWORD *) pvParam) = 0;
  338. break;
  339. case SQL_PACKET_SIZE: /* NOT SUPPORTED */
  340. *((UDWORD *) pvParam) = globals.socket_buffersize;
  341. break;
  342. case SQL_QUIET_MODE:/* NOT SUPPORTED */
  343. *((UDWORD *) pvParam) = (UDWORD) NULL;
  344. break;
  345. case SQL_TXN_ISOLATION:/* NOT SUPPORTED */
  346. *((UDWORD *) pvParam) = SQL_TXN_SERIALIZABLE;
  347. break;
  348. /* These options should be handled by driver manager */
  349. case SQL_ODBC_CURSORS:
  350. case SQL_OPT_TRACE:
  351. case SQL_OPT_TRACEFILE:
  352. case SQL_TRANSLATE_DLL:
  353. case SQL_TRANSLATE_OPTION:
  354. CC_log_error(func, "This connect option (Get) is only used by the Driver Manager", conn);
  355. break;
  356. default:
  357. {
  358. char option[64];
  359. conn->errormsg = "Unknown connect option (Get)";
  360. conn->errornumber = CONN_UNSUPPORTED_OPTION;
  361. sprintf(option, "fOption=%d", fOption);
  362. CC_log_error(func, option, conn);
  363. return SQL_ERROR;
  364. break;
  365. }
  366. }    
  367. return SQL_SUCCESS;
  368. }
  369. //      -       -       -       -       -       -       -       -       -
  370. RETCODE SQL_API SQLSetStmtOption(
  371.         HSTMT   hstmt,
  372.         UWORD   fOption,
  373.         UDWORD  vParam)
  374. {
  375. static char *func="SQLSetStmtOption";
  376. StatementClass *stmt = (StatementClass *) hstmt;
  377. char changed = FALSE;
  378. mylog("%s: entering...n", func);
  379.     // thought we could fake Access out by just returning SQL_SUCCESS
  380.     // all the time, but it tries to set a huge value for SQL_MAX_LENGTH
  381.     // and expects the driver to reduce it to the real value
  382. if( ! stmt) {
  383. SC_log_error(func, "", NULL);
  384. return SQL_INVALID_HANDLE;
  385. }
  386. return set_statement_option(NULL, stmt, fOption, vParam);
  387. }
  388. //      -       -       -       -       -       -       -       -       -
  389. RETCODE SQL_API SQLGetStmtOption(
  390.         HSTMT   hstmt,
  391.         UWORD   fOption,
  392.         PTR     pvParam)
  393. {
  394. static char *func="SQLGetStmtOption";
  395. StatementClass *stmt = (StatementClass *) hstmt;
  396. QResultClass *res;
  397. mylog("%s: entering...n", func);
  398.     // thought we could fake Access out by just returning SQL_SUCCESS
  399.     // all the time, but it tries to set a huge value for SQL_MAX_LENGTH
  400.     // and expects the driver to reduce it to the real value
  401. if( ! stmt) {
  402. SC_log_error(func, "", NULL);
  403. return SQL_INVALID_HANDLE;
  404. }
  405. switch(fOption) {
  406. case SQL_GET_BOOKMARK:
  407. case SQL_ROW_NUMBER:
  408. res = stmt->result;
  409. if ( stmt->manual_result || ! globals.use_declarefetch) {
  410. // make sure we're positioned on a valid row
  411. if((stmt->currTuple < 0) ||
  412.    (stmt->currTuple >= QR_get_num_tuples(res))) {
  413. stmt->errormsg = "Not positioned on a valid row.";
  414. stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
  415. SC_log_error(func, "", stmt);
  416. return SQL_ERROR;
  417. }
  418. }
  419. else {
  420. if (stmt->currTuple == -1 || ! res || ! res->tupleField) {
  421. stmt->errormsg = "Not positioned on a valid row.";
  422. stmt->errornumber = STMT_INVALID_CURSOR_STATE_ERROR;
  423. SC_log_error(func, "", stmt);
  424. return SQL_ERROR;
  425. }
  426. }
  427. if (fOption == SQL_GET_BOOKMARK && stmt->options.use_bookmarks == SQL_UB_OFF) {
  428. stmt->errormsg = "Operation invalid because use bookmarks not enabled.";
  429. stmt->errornumber = STMT_OPERATION_INVALID;
  430. SC_log_error(func, "", stmt);
  431. return SQL_ERROR;
  432. }
  433. *((UDWORD *) pvParam) = SC_get_bookmark(stmt);
  434. break;
  435. case SQL_ASYNC_ENABLE: /* NOT SUPPORTED */
  436. *((SDWORD *) pvParam) = SQL_ASYNC_ENABLE_OFF;
  437. break;
  438. case SQL_BIND_TYPE:
  439. *((SDWORD *) pvParam) = stmt->options.bind_size;
  440. break;
  441. case SQL_CONCURRENCY: /* NOT REALLY SUPPORTED */
  442. mylog("GetStmtOption(): SQL_CONCURRENCYn");
  443. *((SDWORD *)pvParam) = stmt->options.scroll_concurrency;
  444. break;
  445. case SQL_CURSOR_TYPE: /* PARTIAL SUPPORT */
  446. mylog("GetStmtOption(): SQL_CURSOR_TYPEn");
  447. *((SDWORD *)pvParam) = stmt->options.cursor_type;
  448. break;
  449. case SQL_KEYSET_SIZE: /* NOT SUPPORTED, but saved */
  450. mylog("GetStmtOption(): SQL_KEYSET_SIZEn");
  451. *((SDWORD *)pvParam) = stmt->options.keyset_size;
  452. break;
  453. case SQL_MAX_LENGTH: /* NOT SUPPORTED, but saved */
  454. *((SDWORD *)pvParam) = stmt->options.maxLength;
  455. break;
  456. case SQL_MAX_ROWS: /* NOT SUPPORTED, but saved */
  457. *((SDWORD *)pvParam) = stmt->options.maxRows;
  458. mylog("GetSmtOption: MAX_ROWS, returning %dn", stmt->options.maxRows);
  459. break;
  460. case SQL_NOSCAN:/* NOT SUPPORTED */
  461. *((SDWORD *) pvParam) = SQL_NOSCAN_ON;
  462. break;
  463. case SQL_QUERY_TIMEOUT: /* NOT SUPPORTED */
  464. *((SDWORD *) pvParam) = 0;
  465. break;
  466. case SQL_RETRIEVE_DATA: /* NOT SUPPORTED, but saved */
  467. *((SDWORD *) pvParam) = stmt->options.retrieve_data;
  468. break;
  469. case SQL_ROWSET_SIZE:
  470. *((SDWORD *) pvParam) = stmt->options.rowset_size;
  471. break;
  472. case SQL_SIMULATE_CURSOR:/* NOT SUPPORTED */
  473. *((SDWORD *) pvParam) = SQL_SC_NON_UNIQUE;
  474. break;
  475. case SQL_USE_BOOKMARKS:
  476. *((SDWORD *) pvParam) = stmt->options.use_bookmarks;
  477. break;
  478. default:
  479. {
  480. char option[64];
  481. stmt->errornumber = STMT_NOT_IMPLEMENTED_ERROR;
  482. stmt->errormsg = "Unknown statement option (Get)";
  483. sprintf(option, "fOption=%d", fOption);
  484. SC_log_error(func, option, stmt);
  485. return SQL_ERROR;
  486. }
  487. }
  488. return SQL_SUCCESS;
  489. }
  490. //      -       -       -       -       -       -       -       -       -