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

数据库系统

开发平台:

Unix_Linux

  1. /* Module:          statement.c
  2.  *
  3.  * Description:     This module contains functions related to creating
  4.  *                  and manipulating a statement.
  5.  *
  6.  * Classes:         StatementClass (Functions prefix: "SC_")
  7.  *
  8.  * API functions:   SQLAllocStmt, SQLFreeStmt
  9.  *
  10.  * Comments:        See "notice.txt" for copyright and license information.
  11.  *
  12.  */
  13. #ifdef HAVE_CONFIG_H
  14. #include "config.h"
  15. #endif
  16. #include "statement.h"
  17. #include "bind.h"
  18. #include "connection.h"
  19. #include "qresult.h"
  20. #include "convert.h"
  21. #include "environ.h"
  22. #include <stdio.h>
  23. #include <string.h>
  24. #ifndef WIN32
  25. #include "iodbc.h"
  26. #include "isql.h"
  27. #else
  28. #include <windows.h>
  29. #include <sql.h>
  30. #endif
  31. extern GLOBAL_VALUES globals;
  32. #ifndef WIN32
  33. #ifndef HAVE_STRICMP
  34. #define stricmp(s1,s2)  strcasecmp(s1,s2)
  35. #define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
  36. #endif
  37. #endif
  38. /* Map sql commands to statement types */
  39. static struct {
  40. int  type;
  41. char *s;
  42. } Statement_Type[] = {
  43. { STMT_TYPE_SELECT, "SELECT" },
  44. { STMT_TYPE_INSERT, "INSERT" },
  45. { STMT_TYPE_UPDATE, "UPDATE" },
  46. { STMT_TYPE_DELETE, "DELETE" },
  47. { STMT_TYPE_CREATE, "CREATE" },
  48. { STMT_TYPE_ALTER,  "ALTER"  },
  49. { STMT_TYPE_DROP,   "DROP"   },
  50. { STMT_TYPE_GRANT,  "GRANT"  },
  51. { STMT_TYPE_REVOKE, "REVOKE" },
  52. {      0,            NULL    }
  53. };
  54. RETCODE SQL_API SQLAllocStmt(HDBC      hdbc,
  55.                              HSTMT FAR *phstmt)
  56. {
  57. static char *func="SQLAllocStmt";
  58. ConnectionClass *conn = (ConnectionClass *) hdbc;
  59. StatementClass *stmt;
  60. mylog("%s: entering...n", func);
  61. if( ! conn) {
  62. CC_log_error(func, "", NULL);
  63. return SQL_INVALID_HANDLE;
  64. }
  65. stmt = SC_Constructor();
  66. mylog("**** SQLAllocStmt: hdbc = %u, stmt = %un", hdbc, stmt);
  67. if ( ! stmt) {
  68. conn->errornumber = CONN_STMT_ALLOC_ERROR;
  69. conn->errormsg = "No more memory to allocate a further SQL-statement";
  70. *phstmt = SQL_NULL_HSTMT;
  71. CC_log_error(func, "", conn);
  72. return SQL_ERROR;
  73. }
  74.     if ( ! CC_add_statement(conn, stmt)) {
  75.         conn->errormsg = "Maximum number of connections exceeded.";
  76.         conn->errornumber = CONN_STMT_ALLOC_ERROR;
  77. CC_log_error(func, "", conn);
  78.         SC_Destructor(stmt);
  79. *phstmt = SQL_NULL_HSTMT;
  80.         return SQL_ERROR;
  81.     }
  82. *phstmt = (HSTMT) stmt;
  83. /* Copy default statement options based from Connection options
  84. */
  85. stmt->options = conn->stmtOptions;
  86. /* Save the handle for later */
  87. stmt->phstmt = phstmt;
  88.     return SQL_SUCCESS;
  89. }
  90. RETCODE SQL_API SQLFreeStmt(HSTMT     hstmt,
  91.                             UWORD     fOption)
  92. {
  93. static char *func="SQLFreeStmt";
  94. StatementClass *stmt = (StatementClass *) hstmt;
  95. mylog("%s: entering...hstmt=%u, fOption=%dn", func, hstmt, fOption);
  96. if ( ! stmt) {
  97. SC_log_error(func, "", NULL);
  98. return SQL_INVALID_HANDLE;
  99. }
  100. if (fOption == SQL_DROP) {
  101. ConnectionClass *conn = stmt->hdbc;
  102. /* Remove the statement from the connection's statement list */
  103. if ( conn) {
  104. if ( ! CC_remove_statement(conn, stmt)) {
  105. stmt->errornumber = STMT_SEQUENCE_ERROR;
  106. stmt->errormsg = "Statement is currently executing a transaction.";
  107. SC_log_error(func, "", stmt);
  108. return SQL_ERROR;  /* stmt may be executing a transaction */
  109. }
  110. /* Free any cursors and discard any result info */
  111. if (stmt->result) {
  112. QR_Destructor(stmt->result);
  113. stmt->result = NULL;
  114. }
  115. }
  116. /* Destroy the statement and free any results, cursors, etc. */
  117. SC_Destructor(stmt);
  118.     } else if (fOption == SQL_UNBIND) {
  119. SC_unbind_cols(stmt);
  120.     } else if (fOption == SQL_CLOSE) {
  121. /* this should discard all the results, but leave the statement */
  122. /* itself in place (it can be executed again) */
  123.         if (!SC_recycle_statement(stmt)) {
  124. // errormsg passed in above
  125. SC_log_error(func, "", stmt);
  126.             return SQL_ERROR;
  127. }
  128.     } else if(fOption == SQL_RESET_PARAMS) {
  129. SC_free_params(stmt, STMT_FREE_PARAMS_ALL);
  130.     } else {
  131.         stmt->errormsg = "Invalid option passed to SQLFreeStmt.";
  132.         stmt->errornumber = STMT_OPTION_OUT_OF_RANGE_ERROR;
  133. SC_log_error(func, "", stmt);
  134.         return SQL_ERROR;
  135.     }
  136.     
  137.     return SQL_SUCCESS;
  138. }
  139. /**********************************************************************
  140.  * StatementClass implementation
  141.  */
  142. void
  143. InitializeStatementOptions(StatementOptions *opt)
  144. {
  145. opt->maxRows = 0; // driver returns all rows
  146. opt->maxLength = 0; // driver returns all data for char/binary
  147. opt->rowset_size = 1;
  148. opt->keyset_size = 0; // fully keyset driven is the default
  149. opt->scroll_concurrency = SQL_CONCUR_READ_ONLY;
  150. opt->cursor_type = SQL_CURSOR_FORWARD_ONLY;
  151. opt->bind_size = 0; /* default is to bind by column */
  152. opt->retrieve_data = SQL_RD_ON;
  153. opt->use_bookmarks = SQL_UB_OFF;
  154. }
  155. StatementClass *
  156. SC_Constructor(void)
  157. {
  158. StatementClass *rv;
  159. rv = (StatementClass *) malloc(sizeof(StatementClass));
  160. if (rv) {
  161. rv->hdbc = NULL;       /* no connection associated yet */
  162. rv->phstmt = NULL;
  163. rv->result = NULL;
  164. rv->manual_result = FALSE;
  165. rv->prepare = FALSE;
  166. rv->status = STMT_ALLOCATED;
  167. rv->internal = FALSE;
  168. rv->errormsg = NULL;
  169. rv->errornumber = 0;
  170. rv->errormsg_created = FALSE;
  171. rv->statement = NULL;
  172. rv->stmt_with_params[0] = '';
  173. rv->statement_type = STMT_TYPE_UNKNOWN;
  174. rv->bindings = NULL;
  175. rv->bindings_allocated = 0;
  176. rv->bookmark.buffer = NULL;
  177. rv->bookmark.used = NULL;
  178. rv->parameters_allocated = 0;
  179. rv->parameters = 0;
  180. rv->currTuple = -1;
  181. rv->rowset_start = -1;
  182. rv->current_col = -1;
  183. rv->bind_row = 0;
  184. rv->last_fetch_count = 0;
  185. rv->save_rowset_size = -1;
  186. rv->data_at_exec = -1;
  187. rv->current_exec_param = -1;
  188. rv->put_data = FALSE;
  189. rv->lobj_fd = -1;
  190. rv->cursor_name[0] = '';
  191. /* Parse Stuff */
  192. rv->ti = NULL;
  193. rv->fi = NULL;
  194. rv->ntab = 0;
  195. rv->nfld = 0;
  196. rv->parse_status = STMT_PARSE_NONE;
  197. /*  Clear Statement Options -- defaults will be set in AllocStmt */
  198. memset(&rv->options, 0, sizeof(StatementOptions));
  199. }
  200. return rv;
  201. }
  202. char
  203. SC_Destructor(StatementClass *self)
  204. {
  205. mylog("SC_Destructor: self=%u, self->result=%u, self->hdbc=%un", self, self->result, self->hdbc);
  206. if (STMT_EXECUTING == self->status) {
  207. self->errornumber = STMT_SEQUENCE_ERROR;
  208. self->errormsg = "Statement is currently executing a transaction.";
  209. return FALSE;
  210. }
  211. if (self->result) {
  212. if ( ! self->hdbc)
  213. self->result->conn = NULL;  /* prevent any dbase activity */
  214. QR_Destructor(self->result);
  215. }
  216. if (self->statement)
  217. free(self->statement);
  218. SC_free_params(self, STMT_FREE_PARAMS_ALL);
  219. /* the memory pointed to by the bindings is not deallocated by the driver */
  220. /* by by the application that uses that driver, so we don't have to care  */
  221. /* about that here. */
  222. if (self->bindings)
  223. free(self->bindings);
  224. /* Free the parsed table information */
  225. if (self->ti) {
  226. int i;
  227. for (i = 0; i < self->ntab; i++) {
  228. free(self->ti[i]);
  229. }
  230. free(self->ti);
  231. }
  232. /* Free the parsed field information */
  233. if (self->fi) {
  234. int i;
  235. for (i = 0; i < self->nfld; i++) {
  236. free(self->fi[i]);
  237. }
  238. free(self->fi);
  239. }
  240. free(self);
  241. mylog("SC_Destructor: EXITn");
  242. return TRUE;
  243. }
  244. /* Free parameters and free the memory from the 
  245. data-at-execution parameters that was allocated in SQLPutData.
  246. */
  247. void
  248. SC_free_params(StatementClass *self, char option)
  249. {
  250. int i;
  251. mylog("SC_free_params:  ENTER, self=%dn", self);
  252. if( ! self->parameters)
  253. return;
  254. for (i = 0; i < self->parameters_allocated; i++) {
  255. if (self->parameters[i].data_at_exec == TRUE) {
  256. if (self->parameters[i].EXEC_used) {
  257. free(self->parameters[i].EXEC_used);
  258. self->parameters[i].EXEC_used = NULL;
  259. }
  260. if (self->parameters[i].EXEC_buffer) {
  261. free(self->parameters[i].EXEC_buffer);
  262. self->parameters[i].EXEC_buffer = NULL;
  263. }
  264. }
  265. }
  266. self->data_at_exec = -1;
  267. self->current_exec_param = -1;
  268. self->put_data = FALSE;
  269. if (option == STMT_FREE_PARAMS_ALL) {
  270. free(self->parameters);
  271. self->parameters = NULL;
  272. self->parameters_allocated = 0;
  273. }
  274. mylog("SC_free_params:  EXITn");
  275. }
  276. int 
  277. statement_type(char *statement)
  278. {
  279. int i;
  280. for (i = 0; Statement_Type[i].s; i++)
  281. if ( ! strnicmp(statement, Statement_Type[i].s, strlen(Statement_Type[i].s)))
  282. return Statement_Type[i].type;
  283. return STMT_TYPE_OTHER;
  284. }
  285. /* Called from SQLPrepare if STMT_PREMATURE, or
  286. from SQLExecute if STMT_FINISHED, or
  287. from SQLFreeStmt(SQL_CLOSE)
  288.  */
  289. char 
  290. SC_recycle_statement(StatementClass *self)
  291. {
  292. ConnectionClass *conn;
  293. mylog("recycle statement: self= %un", self);
  294. /* This would not happen */    
  295. if (self->status == STMT_EXECUTING) {
  296. self->errornumber = STMT_SEQUENCE_ERROR;
  297. self->errormsg = "Statement is currently executing a transaction.";
  298. return FALSE;
  299. }
  300. self->errormsg = NULL;
  301. self->errornumber = 0;
  302. self->errormsg_created = FALSE;
  303. switch (self->status) {
  304. case STMT_ALLOCATED:
  305. /* this statement does not need to be recycled */
  306. return TRUE;
  307. case STMT_READY:
  308. break;
  309. case STMT_PREMATURE:
  310. /* Premature execution of the statement might have caused the start of a transaction.
  311. If so, we have to rollback that transaction.
  312. */
  313. conn = SC_get_conn(self);
  314. if ( ! CC_is_in_autocommit(conn) && CC_is_in_trans(conn)) {             
  315. CC_send_query(conn, "ABORT", NULL);
  316. CC_set_no_trans(conn);
  317. }
  318. break;
  319. case STMT_FINISHED:
  320. break;
  321. default:
  322. self->errormsg = "An internal error occured while recycling statements";
  323. self->errornumber = STMT_INTERNAL_ERROR;
  324. return FALSE;
  325. }
  326. /* Free the parsed table information */
  327. if (self->ti) {
  328. int i;
  329. for (i = 0; i < self->ntab; i++) {
  330. free(self->ti[i]);
  331. }
  332. free(self->ti);
  333. self->ti = NULL;
  334. self->ntab = 0;
  335. }
  336. /* Free the parsed field information */
  337. if (self->fi) {
  338. int i;
  339. for (i = 0; i < self->nfld; i++) {
  340. free(self->fi[i]);
  341. }
  342. free(self->fi);
  343. self->fi = NULL;
  344. self->nfld = 0;
  345. }
  346. self->parse_status = STMT_PARSE_NONE;
  347. /* Free any cursors */
  348. if (self->result) {
  349. QR_Destructor(self->result);
  350. self->result = NULL;
  351. }
  352. /****************************************************************/
  353. /* Reset only parameters that have anything to do with results */
  354. /****************************************************************/
  355. self->status = STMT_READY;
  356. self->manual_result = FALSE; // very important
  357. self->currTuple = -1;
  358. self->rowset_start = -1;
  359. self->current_col = -1;
  360. self->bind_row = 0;
  361. self->last_fetch_count = 0;
  362. self->errormsg = NULL;
  363. self->errornumber = 0;
  364. self->errormsg_created = FALSE;
  365. self->lobj_fd = -1;
  366. // Free any data at exec params before the statement is executed
  367. // again.  If not, then there will be a memory leak when
  368. // the next SQLParamData/SQLPutData is called.
  369. SC_free_params(self, STMT_FREE_PARAMS_DATA_AT_EXEC_ONLY);
  370. return TRUE;
  371. }
  372. /* Pre-execute a statement (SQLPrepare/SQLDescribeCol) */
  373. void 
  374. SC_pre_execute(StatementClass *self)
  375. {
  376. mylog("SC_pre_execute: status = %dn", self->status);
  377. if (self->status == STMT_READY) {
  378. mylog("              preprocess: status = READYn");
  379. SQLExecute(self);
  380. if (self->status == STMT_FINISHED) {
  381. mylog("              preprocess: after status = FINISHED, so set PREMATUREn");
  382. self->status = STMT_PREMATURE;
  383. }
  384. }  
  385. }
  386. /* This is only called from SQLFreeStmt(SQL_UNBIND) */
  387. char 
  388. SC_unbind_cols(StatementClass *self)
  389. {
  390. Int2 lf;
  391. for(lf = 0; lf < self->bindings_allocated; lf++) {
  392. self->bindings[lf].data_left = -1;
  393. self->bindings[lf].buflen = 0;
  394. self->bindings[lf].buffer = NULL;
  395. self->bindings[lf].used = NULL;
  396. self->bindings[lf].returntype = SQL_C_CHAR;
  397. }
  398. self->bookmark.buffer = NULL;
  399. self->bookmark.used = NULL;
  400.     return 1;
  401. }
  402. void 
  403. SC_clear_error(StatementClass *self)
  404. {
  405. self->errornumber = 0;
  406. self->errormsg = NULL;
  407. self->errormsg_created = FALSE;
  408. }
  409. // This function creates an error msg which is the concatenation
  410. // of the result, statement, connection, and socket messages.
  411. char *
  412. SC_create_errormsg(StatementClass *self)
  413. {
  414. QResultClass *res = self->result;
  415. ConnectionClass *conn = self->hdbc;
  416. int pos;
  417. static char msg[4096];
  418. msg[0] = '';
  419. if (res && res->message)
  420. strcpy(msg, res->message);
  421. else if (self->errormsg)
  422. strcpy(msg, self->errormsg);
  423. if (conn) {
  424. SocketClass *sock = conn->sock;
  425. if (conn->errormsg && conn->errormsg[0] != '') {
  426. pos = strlen(msg);
  427. sprintf(&msg[pos], ";n%s", conn->errormsg);
  428. }
  429. if (sock && sock->errormsg && sock->errormsg[0] != '') {
  430. pos = strlen(msg);
  431. sprintf(&msg[pos], ";n%s", sock->errormsg);
  432. }
  433. }
  434. return msg;
  435. }
  436. char 
  437. SC_get_error(StatementClass *self, int *number, char **message)
  438. {
  439. char rv;
  440. // Create a very informative errormsg if it hasn't been done yet.
  441. if ( ! self->errormsg_created) {
  442. self->errormsg = SC_create_errormsg(self);
  443. self->errormsg_created = TRUE;
  444. }
  445. if ( self->errornumber) {
  446. *number = self->errornumber;
  447. *message = self->errormsg;
  448. self->errormsg = NULL;
  449. }
  450. rv = (self->errornumber != 0);
  451. self->errornumber = 0;
  452. return rv;
  453. }
  454. /* Currently, the driver offers very simple bookmark support -- it is
  455. just the current row number.  But it could be more sophisticated 
  456. someday, such as mapping a key to a 32 bit value
  457. */
  458. unsigned long
  459. SC_get_bookmark(StatementClass *self)
  460. {
  461. return (self->currTuple + 1);
  462. }
  463. RETCODE
  464. SC_fetch(StatementClass *self)
  465. {
  466. static char *func = "SC_fetch";
  467. QResultClass *res = self->result;
  468. int retval, result;
  469. Int2 num_cols, lf;
  470. Oid type;
  471. char *value;
  472. ColumnInfoClass *ci;
  473. // TupleField *tupleField;
  474. self->last_fetch_count = 0;
  475. ci = QR_get_fields(res); /* the column info */
  476. mylog("manual_result = %d, use_declarefetch = %dn", self->manual_result, globals.use_declarefetch);
  477.  
  478. if ( self->manual_result || ! globals.use_declarefetch) {
  479. if (self->currTuple >= QR_get_num_tuples(res) -1 || 
  480. (self->options.maxRows > 0 && self->currTuple == self->options.maxRows - 1)) {
  481. /* if at the end of the tuples, return "no data found" 
  482. and set the cursor past the end of the result set 
  483. */
  484. self->currTuple = QR_get_num_tuples(res);
  485. return SQL_NO_DATA_FOUND;
  486. }
  487.  
  488. mylog("**** SQLFetch: manual_resultn");
  489. (self->currTuple)++;
  490. }
  491. else {
  492. // read from the cache or the physical next tuple
  493. retval = QR_next_tuple(res);
  494. if (retval < 0) {
  495. mylog("**** SQLFetch: end_tuplesn");
  496. return SQL_NO_DATA_FOUND;
  497. }
  498. else if (retval > 0)
  499. (self->currTuple)++; // all is well
  500. else {
  501. mylog("SQLFetch: errorn");
  502. self->errornumber = STMT_EXEC_ERROR;
  503. self->errormsg = "Error fetching next row";
  504. SC_log_error(func, "", self);
  505. return SQL_ERROR;
  506. }
  507. }
  508. num_cols = QR_NumResultCols(res);
  509. result = SQL_SUCCESS;
  510. self->last_fetch_count = 1;
  511. /* If the bookmark column was bound then return a bookmark.
  512. Since this is used with SQLExtendedFetch, and the rowset size 
  513. may be greater than 1, and an application can use row or column wise
  514. binding, use the code in copy_and_convert_field() to handle that.
  515. */
  516. if (self->bookmark.buffer) {
  517. char buf[32];
  518. sprintf(buf, "%ld", SC_get_bookmark(self));
  519. result = copy_and_convert_field(self, 0, buf, 
  520. SQL_C_ULONG, self->bookmark.buffer, 0, self->bookmark.used);
  521. }
  522. for (lf=0; lf < num_cols; lf++) {
  523. mylog("fetch: cols=%d, lf=%d, self = %u, self->bindings = %u, buffer[] = %un", num_cols, lf, self, self->bindings, self->bindings[lf].buffer);
  524. /* reset for SQLGetData */
  525. self->bindings[lf].data_left = -1;
  526. if (self->bindings[lf].buffer != NULL) {
  527.             // this column has a binding
  528.             // type = QR_get_field_type(res, lf);
  529. type = CI_get_oid(ci, lf); /* speed things up */
  530. mylog("type = %dn", type);
  531. if (self->manual_result) {
  532. value = QR_get_value_manual(res, self->currTuple, lf);
  533. mylog("manual_resultn");
  534. }
  535. else if (globals.use_declarefetch)
  536. value = QR_get_value_backend(res, lf);
  537. else {
  538. value = QR_get_value_backend_row(res, self->currTuple, lf);
  539. }
  540. mylog("value = '%s'n",  (value==NULL)?"<NULL>":value);
  541. retval = copy_and_convert_field_bindinfo(self, type, value, lf);
  542. mylog("copy_and_convert: retval = %dn", retval);
  543. switch(retval) {
  544. case COPY_OK:
  545. break; /* OK, do next bound column */
  546. case COPY_UNSUPPORTED_TYPE:
  547. self->errormsg = "Received an unsupported type from Postgres.";
  548. self->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;
  549. SC_log_error(func, "", self);
  550. result = SQL_ERROR;
  551. break;
  552. case COPY_UNSUPPORTED_CONVERSION:
  553. self->errormsg = "Couldn't handle the necessary data type conversion.";
  554. self->errornumber = STMT_RESTRICTED_DATA_TYPE_ERROR;
  555. SC_log_error(func, "", self);
  556. result = SQL_ERROR;
  557. break;
  558. case COPY_RESULT_TRUNCATED:
  559. self->errornumber = STMT_TRUNCATED;
  560. self->errormsg = "The buffer was too small for the result.";
  561. result = SQL_SUCCESS_WITH_INFO;
  562. break;
  563. case COPY_GENERAL_ERROR: /* error msg already filled in */
  564. SC_log_error(func, "", self);
  565. result = SQL_ERROR;
  566. break;
  567. /*  This would not be meaningful in SQLFetch. */
  568. case COPY_NO_DATA_FOUND:
  569. break;
  570. default:
  571. self->errormsg = "Unrecognized return value from copy_and_convert_field.";
  572. self->errornumber = STMT_INTERNAL_ERROR;
  573. SC_log_error(func, "", self);
  574. result = SQL_ERROR;
  575. break;
  576. }
  577. }
  578. }
  579. return result;
  580. }
  581. RETCODE SC_execute(StatementClass *self)
  582. {
  583. static char *func="SC_execute";
  584. ConnectionClass *conn;
  585. QResultClass *res;
  586. char ok, was_ok, was_nonfatal;
  587. Int2 oldstatus, numcols;
  588. QueryInfo qi;
  589. conn = SC_get_conn(self);
  590. /* Begin a transaction if one is not already in progress */
  591. /* The reason is because we can't use declare/fetch cursors without
  592. starting a transaction first.
  593. */
  594. if ( ! self->internal && ! CC_is_in_trans(conn) && (globals.use_declarefetch || STMT_UPDATE(self))) {
  595. mylog("   about to begin a transaction on statement = %un", self);
  596. res = CC_send_query(conn, "BEGIN", NULL);
  597. if ( ! res) {
  598. self->errormsg = "Could not begin a transaction";
  599. self->errornumber = STMT_EXEC_ERROR;
  600. SC_log_error(func, "", self);
  601. return SQL_ERROR;
  602. }
  603. ok = QR_command_successful(res);   
  604. mylog("SQLExecute: ok = %d, status = %dn", ok, QR_get_status(res));
  605. QR_Destructor(res);
  606. if (!ok) {
  607. self->errormsg = "Could not begin a transaction";
  608. self->errornumber = STMT_EXEC_ERROR;
  609. SC_log_error(func, "", self);
  610. return SQL_ERROR;
  611. }
  612. else
  613. CC_set_in_trans(conn);
  614. }
  615. oldstatus = conn->status;
  616. conn->status = CONN_EXECUTING;
  617. self->status = STMT_EXECUTING;
  618. // If its a SELECT statement, use a cursor.
  619. // Note that the declare cursor has already been prepended to the statement
  620. // in copy_statement...
  621. if (self->statement_type == STMT_TYPE_SELECT) {
  622. char fetch[128];
  623. mylog("       Sending SELECT statement on stmt=%u, cursor_name='%s'n", self, self->cursor_name);
  624. /* send the declare/select */
  625. self->result = CC_send_query(conn, self->stmt_with_params, NULL);
  626. if (globals.use_declarefetch && self->result != NULL) {
  627. QR_Destructor(self->result);
  628. /* That worked, so now send the fetch to start getting data back */
  629. qi.result_in = NULL;
  630. qi.cursor = self->cursor_name;
  631. qi.row_size = globals.fetch_max;
  632. /* Most likely the rowset size will not be set by the application until 
  633. after the statement is executed, so might as well use the cache size.  
  634. The qr_next_tuple() function will correct for any discrepancies in 
  635. sizes and adjust the cache accordingly.
  636. */
  637. sprintf(fetch, "fetch %d in %s", qi.row_size, self->cursor_name);
  638. self->result = CC_send_query( conn, fetch, &qi);
  639. }
  640. mylog("     done sending the query:n");
  641. }
  642. else  { // not a SELECT statement so don't use a cursor   
  643. mylog("      its NOT a select statement: stmt=%un", self);
  644. self->result = CC_send_query(conn, self->stmt_with_params, NULL);
  645. // If we are in autocommit, we must send the commit.
  646. if ( ! self->internal && CC_is_in_autocommit(conn) && STMT_UPDATE(self)) {
  647. CC_send_query(conn, "COMMIT", NULL);
  648. CC_set_no_trans(conn);
  649. }
  650. }
  651. conn->status = oldstatus;
  652. self->status = STMT_FINISHED;
  653. /* Check the status of the result */
  654. if (self->result) {
  655. was_ok = QR_command_successful(self->result);
  656. was_nonfatal = QR_command_nonfatal(self->result);
  657. if ( was_ok)
  658. self->errornumber = STMT_OK;
  659. else
  660. self->errornumber = was_nonfatal ? STMT_INFO_ONLY : STMT_ERROR_TAKEN_FROM_BACKEND;
  661. self->currTuple = -1; /* set cursor before the first tuple in the list */
  662. self->current_col = -1;
  663. self->rowset_start = -1;
  664. /* see if the query did return any result columns */
  665. numcols = QR_NumResultCols(self->result);
  666. /* now allocate the array to hold the binding info */
  667. if (numcols > 0) {
  668. extend_bindings(self, numcols);
  669. if (self->bindings == NULL) {
  670. self->errornumber = STMT_NO_MEMORY_ERROR;
  671. self->errormsg = "Could not get enough free memory to store the binding information";
  672. SC_log_error(func, "", self);
  673. return SQL_ERROR;
  674. }
  675. }
  676. } else { /* Bad Error -- The error message will be in the Connection */
  677. if (self->statement_type == STMT_TYPE_CREATE) {
  678. self->errornumber = STMT_CREATE_TABLE_ERROR;
  679. self->errormsg = "Error creating the table";
  680. /* This would allow the table to already exists, thus appending
  681. rows to it.  BUT, if the table didn't have the same attributes,
  682. it would fail.
  683. return SQL_SUCCESS_WITH_INFO;
  684. */
  685. }
  686. else {
  687. self->errornumber = STMT_EXEC_ERROR;
  688. self->errormsg = "Error while executing the query";
  689. }
  690. if ( ! self->internal)
  691. CC_abort(conn);
  692. }
  693. if (self->errornumber == STMT_OK)
  694. return SQL_SUCCESS;
  695. else if (self->errornumber == STMT_INFO_ONLY)
  696. return SQL_SUCCESS_WITH_INFO;
  697. else {
  698. SC_log_error(func, "", self);
  699. return SQL_ERROR;
  700. }
  701. }
  702. void
  703. SC_log_error(char *func, char *desc, StatementClass *self)
  704. {
  705. if (self) {
  706. qlog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'n", func, desc, self->errornumber, self->errormsg);
  707. mylog("STATEMENT ERROR: func=%s, desc='%s', errnum=%d, errmsg='%s'n", func, desc, self->errornumber, self->errormsg);
  708. qlog("                 ------------------------------------------------------------n");
  709. qlog("                 hdbc=%u, stmt=%u, result=%un", self->hdbc, self, self->result);
  710. qlog("                 manual_result=%d, prepare=%d, internal=%dn", self->manual_result, self->prepare, self->internal);
  711. qlog("                 bindings=%u, bindings_allocated=%dn", self->bindings, self->bindings_allocated);
  712. qlog("                 parameters=%u, parameters_allocated=%dn", self->parameters, self->parameters_allocated);
  713. qlog("                 statement_type=%d, statement='%s'n", self->statement_type, self->statement);
  714. qlog("                 stmt_with_params='%s'n", self->stmt_with_params);
  715. qlog("                 data_at_exec=%d, current_exec_param=%d, put_data=%dn", self->data_at_exec, self->current_exec_param, self->put_data);
  716. qlog("                 currTuple=%d, current_col=%d, lobj_fd=%dn", self->currTuple, self->current_col, self->lobj_fd);
  717. qlog("                 maxRows=%d, rowset_size=%d, keyset_size=%d, cursor_type=%d, scroll_concurrency=%dn", self->options.maxRows, self->options.rowset_size, self->options.keyset_size, self->options.cursor_type, self->options.scroll_concurrency);
  718. qlog("                 cursor_name='%s'n", self->cursor_name);
  719. qlog("                 ----------------QResult Info -------------------------------n");
  720. if (self->result) {
  721. QResultClass *res = self->result;
  722. qlog("                 fields=%u, manual_tuples=%u, backend_tuples=%u, tupleField=%d, conn=%un", res->fields, res->manual_tuples, res->backend_tuples, res->tupleField, res->conn);
  723. qlog("                 fetch_count=%d, fcount=%d, num_fields=%d, cursor='%s'n", res->fetch_count, res->fcount, res->num_fields, res->cursor);
  724. qlog("                 message='%s', command='%s', notice='%s'n", res->message, res->command, res->notice);
  725. qlog("                 status=%d, inTuples=%dn", res->status, res->inTuples);
  726. }
  727. // Log the connection error if there is one
  728. CC_log_error(func, desc, self->hdbc);
  729. }
  730. else
  731. qlog("INVALID STATEMENT HANDLE ERROR: func=%s, desc='%s'n", func, desc);
  732. }