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

数据库系统

开发平台:

Unix_Linux

  1. /* Module:          execute.c
  2.  *
  3.  * Description:     This module contains routines related to 
  4.  *                  preparing and executing an SQL statement.
  5.  *
  6.  * Classes:         n/a
  7.  *
  8.  * API functions:   SQLPrepare, SQLExecute, SQLExecDirect, SQLTransact,
  9.  *                  SQLCancel, SQLNativeSql, SQLParamData, SQLPutData
  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. #include <stdio.h>
  19. #include <string.h>
  20. #ifndef WIN32
  21. #include "iodbc.h"
  22. #include "isqlext.h"
  23. #else
  24. #include <windows.h>
  25. #include <sqlext.h>
  26. #endif
  27. #include "connection.h"
  28. #include "statement.h"
  29. #include "qresult.h"
  30. #include "convert.h"
  31. #include "bind.h"
  32. #include "lobj.h"
  33. extern GLOBAL_VALUES globals;
  34. //      Perform a Prepare on the SQL statement
  35. RETCODE SQL_API SQLPrepare(HSTMT     hstmt,
  36.                            UCHAR FAR *szSqlStr,
  37.                            SDWORD    cbSqlStr)
  38. {
  39. static char *func = "SQLPrepare";
  40. StatementClass *self = (StatementClass *) hstmt;
  41. mylog( "%s: entering...n", func);
  42. if ( ! self) {
  43. SC_log_error(func, "", NULL);
  44. return SQL_INVALID_HANDLE;
  45. }
  46.     
  47. /* According to the ODBC specs it is valid to call SQLPrepare mulitple times.
  48. In that case, the bound SQL statement is replaced by the new one 
  49. */
  50. switch(self->status) {
  51. case STMT_PREMATURE:
  52. mylog("**** SQLPrepare: STMT_PREMATURE, recyclen");
  53. SC_recycle_statement(self); /* recycle the statement, but do not remove parameter bindings */
  54. break;
  55. case STMT_FINISHED:
  56. mylog("**** SQLPrepare: STMT_FINISHED, recyclen");
  57. SC_recycle_statement(self); /* recycle the statement, but do not remove parameter bindings */
  58. break;
  59. case STMT_ALLOCATED:
  60. mylog("**** SQLPrepare: STMT_ALLOCATED, copyn");
  61. self->status = STMT_READY;
  62. break;
  63. case STMT_READY:
  64. mylog("**** SQLPrepare: STMT_READY, change SQLn");
  65. break;
  66. case STMT_EXECUTING:
  67. mylog("**** SQLPrepare: STMT_EXECUTING, error!n");
  68. self->errornumber = STMT_SEQUENCE_ERROR;
  69. self->errormsg = "SQLPrepare(): The handle does not point to a statement that is ready to be executed";
  70. SC_log_error(func, "", self);
  71. return SQL_ERROR;
  72. default:
  73. self->errornumber = STMT_INTERNAL_ERROR;
  74. self->errormsg = "An Internal Error has occured -- Unknown statement status.";
  75. SC_log_error(func, "", self);
  76. return SQL_ERROR;
  77. }
  78. if (self->statement)
  79. free(self->statement);
  80. self->statement = make_string(szSqlStr, cbSqlStr, NULL);
  81. if ( ! self->statement) {
  82. self->errornumber = STMT_NO_MEMORY_ERROR;
  83. self->errormsg = "No memory available to store statement";
  84. SC_log_error(func, "", self);
  85. return SQL_ERROR;
  86. }
  87. self->prepare = TRUE;
  88. self->statement_type = statement_type(self->statement);
  89. // Check if connection is readonly (only selects are allowed)
  90. if ( CC_is_readonly(self->hdbc) && STMT_UPDATE(self)) {
  91. self->errornumber = STMT_EXEC_ERROR;
  92. self->errormsg = "Connection is readonly, only select statements are allowed.";
  93. SC_log_error(func, "", self);
  94. return SQL_ERROR;
  95. }
  96. return SQL_SUCCESS;
  97. }
  98. //      -       -       -       -       -       -       -       -       -
  99. //      Performs the equivalent of SQLPrepare, followed by SQLExecute.
  100. RETCODE SQL_API SQLExecDirect(
  101.         HSTMT     hstmt,
  102.         UCHAR FAR *szSqlStr,
  103.         SDWORD    cbSqlStr)
  104. {
  105. StatementClass *stmt = (StatementClass *) hstmt;
  106. RETCODE result;
  107. static char *func = "SQLExecDirect";
  108. mylog( "%s: entering...n", func);
  109.     
  110. if ( ! stmt) {
  111. SC_log_error(func, "", NULL);
  112. return SQL_INVALID_HANDLE;
  113. }
  114. if (stmt->statement)
  115. free(stmt->statement);
  116. // keep a copy of the un-parametrized statement, in case
  117. // they try to execute this statement again
  118. stmt->statement = make_string(szSqlStr, cbSqlStr, NULL);
  119. if ( ! stmt->statement) {
  120. stmt->errornumber = STMT_NO_MEMORY_ERROR;
  121. stmt->errormsg = "No memory available to store statement";
  122. SC_log_error(func, "", stmt);
  123. return SQL_ERROR;
  124. }
  125. mylog("**** %s: hstmt=%u, statement='%s'n", func, hstmt, stmt->statement);
  126. stmt->prepare = FALSE;
  127. stmt->statement_type = statement_type(stmt->statement);
  128. // Check if connection is readonly (only selects are allowed)
  129. if ( CC_is_readonly(stmt->hdbc) && STMT_UPDATE(stmt)) {
  130. stmt->errornumber = STMT_EXEC_ERROR;
  131. stmt->errormsg = "Connection is readonly, only select statements are allowed.";
  132. SC_log_error(func, "", stmt);
  133. return SQL_ERROR;
  134. }
  135. mylog("%s: calling SQLExecute...n", func);
  136. result = SQLExecute(hstmt);
  137. mylog("%s: returned %hd from SQLExecuten", func, result);
  138. return result;
  139. }
  140. //      Execute a prepared SQL statement
  141. RETCODE SQL_API SQLExecute(
  142.         HSTMT   hstmt)
  143. {
  144. static char *func="SQLExecute";
  145. StatementClass *stmt = (StatementClass *) hstmt;
  146. ConnectionClass *conn;
  147. int i, retval;
  148. mylog("%s: entering...n", func);
  149. if ( ! stmt) {
  150. SC_log_error(func, "", NULL);
  151. mylog("%s: NULL statement so return SQL_INVALID_HANDLEn", func);
  152. return SQL_INVALID_HANDLE;
  153. }
  154. /*  If the statement is premature, it means we already executed
  155. it from an SQLPrepare/SQLDescribeCol type of scenario.  So
  156. just return success.
  157. */
  158. if ( stmt->prepare && stmt->status == STMT_PREMATURE) {
  159. stmt->status = STMT_FINISHED;       
  160. if (stmt->errormsg == NULL) {
  161. mylog("%s: premature statement but return SQL_SUCCESSn", func);
  162. return SQL_SUCCESS;
  163. }
  164. else {
  165. SC_log_error(func, "", stmt);
  166. mylog("%s: premature statement so return SQL_ERRORn", func);
  167. return SQL_ERROR;
  168. }
  169. }  
  170. mylog("%s: clear errors...n", func);
  171. SC_clear_error(stmt);
  172. conn = SC_get_conn(stmt);
  173. if (conn->status == CONN_EXECUTING) {
  174. stmt->errormsg = "Connection is already in use.";
  175. stmt->errornumber = STMT_SEQUENCE_ERROR;
  176. SC_log_error(func, "", stmt);
  177. mylog("%s: problem with connectionn", func);
  178. return SQL_ERROR;
  179. }
  180. if ( ! stmt->statement) {
  181. stmt->errornumber = STMT_NO_STMTSTRING;
  182. stmt->errormsg = "This handle does not have a SQL statement stored in it";
  183. SC_log_error(func, "", stmt);
  184. mylog("%s: problem with handlen", func);
  185. return SQL_ERROR;
  186. }
  187. /* If SQLExecute is being called again, recycle the statement.
  188. Note this should have been done by the application in a call
  189. to SQLFreeStmt(SQL_CLOSE) or SQLCancel.
  190. */
  191. if (stmt->status == STMT_FINISHED) {
  192. mylog("%s: recycling statement (should have been done by app)...n", func);
  193. SC_recycle_statement(stmt);
  194. }
  195. /* Check if the statement is in the correct state */
  196. if ((stmt->prepare && stmt->status != STMT_READY) || 
  197. (stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY)) {
  198. stmt->errornumber = STMT_STATUS_ERROR;
  199. stmt->errormsg = "The handle does not point to a statement that is ready to be executed";
  200. SC_log_error(func, "", stmt);
  201. mylog("%s: problem with statementn", func);
  202. return SQL_ERROR;
  203. }
  204. /* The bound parameters could have possibly changed since the last execute
  205. of this statement?  Therefore check for params and re-copy.
  206. */
  207. stmt->data_at_exec = -1;
  208. for (i = 0; i < stmt->parameters_allocated; i++) {
  209. /* Check for data at execution parameters */
  210. if ( stmt->parameters[i].data_at_exec == TRUE) {
  211. if (stmt->data_at_exec < 0)
  212. stmt->data_at_exec = 1;
  213. else
  214. stmt->data_at_exec++;
  215. }
  216. }
  217. // If there are some data at execution parameters, return need data
  218. // SQLParamData and SQLPutData will be used to send params and execute the statement.
  219. if (stmt->data_at_exec > 0)
  220. return SQL_NEED_DATA;
  221. mylog("%s: copying statement params: trans_status=%d, len=%d, stmt='%s'n", func, conn->transact_status, strlen(stmt->statement), stmt->statement);
  222. // Create the statement with parameters substituted.
  223. retval = copy_statement_with_parameters(stmt);
  224. if( retval != SQL_SUCCESS)
  225. /* error msg passed from above */
  226. return retval;
  227. mylog("   stmt_with_params = '%s'n", stmt->stmt_with_params);
  228. return SC_execute(stmt);
  229. }
  230. //      -       -       -       -       -       -       -       -       -
  231. RETCODE SQL_API SQLTransact(
  232.         HENV    henv,
  233.         HDBC    hdbc,
  234.         UWORD   fType)
  235. {
  236. static char *func = "SQLTransact";
  237. extern ConnectionClass *conns[];
  238. ConnectionClass *conn;
  239. QResultClass *res;
  240. char ok, *stmt_string;
  241. int lf;
  242. mylog("entering %s: hdbc=%u, henv=%un", func, hdbc, henv);
  243. if (hdbc == SQL_NULL_HDBC && henv == SQL_NULL_HENV) {
  244. CC_log_error(func, "", NULL);
  245. return SQL_INVALID_HANDLE;
  246. }
  247. /* If hdbc is null and henv is valid,
  248. it means transact all connections on that henv.  
  249. */
  250. if (hdbc == SQL_NULL_HDBC && henv != SQL_NULL_HENV) {
  251. for (lf=0; lf <MAX_CONNECTIONS; lf++) {
  252. conn = conns[lf];
  253. if (conn && conn->henv == henv)
  254. if ( SQLTransact(henv, (HDBC) conn, fType) != SQL_SUCCESS)
  255. return SQL_ERROR;
  256. }
  257. return SQL_SUCCESS;       
  258. }
  259. conn = (ConnectionClass *) hdbc;
  260. if (fType == SQL_COMMIT) {
  261. stmt_string = "COMMIT";
  262. } else if (fType == SQL_ROLLBACK) {
  263. stmt_string = "ROLLBACK";
  264. } else {
  265. conn->errornumber = CONN_INVALID_ARGUMENT_NO;
  266. conn->errormsg ="SQLTransact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter";
  267. CC_log_error(func, "", conn);
  268. return SQL_ERROR;
  269. }    
  270. /* If manual commit and in transaction, then proceed. */
  271. if ( ! CC_is_in_autocommit(conn) &&  CC_is_in_trans(conn)) {
  272. mylog("SQLTransact: sending on conn %d '%s'n", conn, stmt_string);
  273. res = CC_send_query(conn, stmt_string, NULL);
  274. CC_set_no_trans(conn);
  275. if ( ! res) {
  276. // error msg will be in the connection
  277. CC_log_error(func, "", conn);
  278. return SQL_ERROR;
  279. }
  280. ok = QR_command_successful(res);   
  281. QR_Destructor(res);
  282. if (!ok) {
  283. CC_log_error(func, "", conn);
  284. return SQL_ERROR;
  285. }
  286. }    
  287. return SQL_SUCCESS;
  288. }
  289. //      -       -       -       -       -       -       -       -       -
  290. RETCODE SQL_API SQLCancel(
  291.         HSTMT   hstmt)  // Statement to cancel.
  292. {
  293. static char *func="SQLCancel";
  294. StatementClass *stmt = (StatementClass *) hstmt;
  295. RETCODE result;
  296. #ifdef WIN32
  297. HMODULE hmodule;
  298. FARPROC addr;
  299. #endif
  300. mylog( "%s: entering...n", func);
  301. // Check if this can handle canceling in the middle of a SQLPutData?
  302. if ( ! stmt) {
  303. SC_log_error(func, "", NULL);
  304. return SQL_INVALID_HANDLE;
  305. }
  306. // Not in the middle of SQLParamData/SQLPutData so cancel like a close.
  307. if (stmt->data_at_exec < 0) {
  308. /* MAJOR HACK for Windows to reset the driver manager's cursor state:
  309. Because of what seems like a bug in the Odbc driver manager,
  310. SQLCancel does not act like a SQLFreeStmt(CLOSE), as many
  311. applications depend on this behavior.  So, this 
  312. brute force method calls the driver manager's function on
  313. behalf of the application.  
  314. */
  315. #ifdef WIN32
  316. if (globals.cancel_as_freestmt) {
  317. hmodule = GetModuleHandle("ODBC32");
  318. addr = GetProcAddress(hmodule, "SQLFreeStmt");
  319. result = addr( (char *) (stmt->phstmt) - 96, SQL_CLOSE);
  320. }
  321. else {
  322. result = SQLFreeStmt( hstmt, SQL_CLOSE);
  323. }
  324. #else
  325. result = SQLFreeStmt( hstmt, SQL_CLOSE);
  326. #endif
  327. mylog("SQLCancel:  SQLFreeStmt returned %dn", result);
  328. SC_clear_error(hstmt);
  329. return SQL_SUCCESS;
  330. }
  331. // In the middle of SQLParamData/SQLPutData, so cancel that.
  332. // Note, any previous data-at-exec buffers will be freed in the recycle
  333. // if they call SQLExecDirect or SQLExecute again.
  334. stmt->data_at_exec = -1;
  335. stmt->current_exec_param = -1;
  336. stmt->put_data = FALSE;
  337. return SQL_SUCCESS;
  338. }
  339. //      -       -       -       -       -       -       -       -       -
  340. //      Returns the SQL string as modified by the driver.
  341. // Currently, just copy the input string without modification
  342. // observing buffer limits and truncation.
  343. RETCODE SQL_API SQLNativeSql(
  344.         HDBC      hdbc,
  345.         UCHAR FAR *szSqlStrIn,
  346.         SDWORD     cbSqlStrIn,
  347.         UCHAR FAR *szSqlStr,
  348.         SDWORD     cbSqlStrMax,
  349.         SDWORD FAR *pcbSqlStr)
  350. {
  351. static char *func="SQLNativeSql";
  352. int len = 0;
  353. char *ptr;
  354. ConnectionClass *conn = (ConnectionClass *) hdbc;
  355. RETCODE result;
  356. mylog( "%s: entering...cbSqlStrIn=%dn", func, cbSqlStrIn);
  357. ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL);
  358. if ( ! ptr) {
  359. conn->errornumber = CONN_NO_MEMORY_ERROR;
  360. conn->errormsg = "No memory available to store native sql string";
  361. CC_log_error(func, "", conn);
  362. return SQL_ERROR;
  363. }
  364. result = SQL_SUCCESS;
  365. len = strlen(ptr);
  366. if (szSqlStr) {
  367. strncpy_null(szSqlStr, ptr, cbSqlStrMax);
  368. if (len >= cbSqlStrMax)  {
  369. result = SQL_SUCCESS_WITH_INFO;
  370. conn->errornumber = STMT_TRUNCATED;
  371. conn->errormsg = "The buffer was too small for the result.";
  372. }
  373. }
  374. if (pcbSqlStr)
  375. *pcbSqlStr = len;
  376. free(ptr);
  377.     return result;
  378. }
  379. //      -       -       -       -       -       -       -       -       -
  380. //      Supplies parameter data at execution time.      Used in conjuction with
  381. //      SQLPutData.
  382. RETCODE SQL_API SQLParamData(
  383.         HSTMT   hstmt,
  384.         PTR FAR *prgbValue)
  385. {
  386. static char *func = "SQLParamData";
  387. StatementClass *stmt = (StatementClass *) hstmt;
  388. int i, retval;
  389. mylog( "%s: entering...n", func);
  390. if ( ! stmt) {
  391. SC_log_error(func, "", NULL);
  392. return SQL_INVALID_HANDLE;
  393. }
  394. mylog("%s: data_at_exec=%d, params_alloc=%dn", func, stmt->data_at_exec, stmt->parameters_allocated);
  395. if (stmt->data_at_exec < 0) {
  396. stmt->errornumber = STMT_SEQUENCE_ERROR;
  397. stmt->errormsg = "No execution-time parameters for this statement";
  398. SC_log_error(func, "", stmt);
  399. return SQL_ERROR;
  400. }
  401. if (stmt->data_at_exec > stmt->parameters_allocated) {
  402. stmt->errornumber = STMT_SEQUENCE_ERROR;
  403. stmt->errormsg = "Too many execution-time parameters were present";
  404. SC_log_error(func, "", stmt);
  405. return SQL_ERROR;
  406. }
  407. /* close the large object */
  408. if ( stmt->lobj_fd >= 0) {
  409. lo_close(stmt->hdbc, stmt->lobj_fd);
  410. stmt->lobj_fd = -1;
  411. }
  412. /* Done, now copy the params and then execute the statement */
  413. if (stmt->data_at_exec == 0) {
  414. retval = copy_statement_with_parameters(stmt);
  415. if (retval != SQL_SUCCESS)
  416. return retval;
  417. stmt->current_exec_param = -1;
  418. return SC_execute(stmt);
  419. }
  420. /* Set beginning param;  if first time SQLParamData is called , start at 0.
  421. Otherwise, start at the last parameter + 1.
  422. */
  423. i = stmt->current_exec_param >= 0 ? stmt->current_exec_param+1 : 0;
  424. /* At least 1 data at execution parameter, so Fill in the token value */
  425. for ( ; i < stmt->parameters_allocated; i++) {
  426. if (stmt->parameters[i].data_at_exec == TRUE) {
  427. stmt->data_at_exec--;
  428. stmt->current_exec_param = i;
  429. stmt->put_data = FALSE;
  430. *prgbValue = stmt->parameters[i].buffer; /* token */
  431. break;
  432. }
  433. }
  434. return SQL_NEED_DATA;
  435. }
  436. //      -       -       -       -       -       -       -       -       -
  437. //      Supplies parameter data at execution time.      Used in conjunction with
  438. //      SQLParamData.
  439. RETCODE SQL_API SQLPutData(
  440.         HSTMT   hstmt,
  441.         PTR     rgbValue,
  442.         SDWORD  cbValue)
  443. {
  444. static char *func = "SQLPutData";
  445. StatementClass *stmt = (StatementClass *) hstmt;
  446. int old_pos, retval;
  447. ParameterInfoClass *current_param;
  448. char *buffer;
  449. mylog( "%s: entering...n", func);
  450. if ( ! stmt) {
  451. SC_log_error(func, "", NULL);
  452. return SQL_INVALID_HANDLE;
  453. }
  454. if (stmt->current_exec_param < 0) {
  455. stmt->errornumber = STMT_SEQUENCE_ERROR;
  456. stmt->errormsg = "Previous call was not SQLPutData or SQLParamData";
  457. SC_log_error(func, "", stmt);
  458. return SQL_ERROR;
  459. }
  460. current_param = &(stmt->parameters[stmt->current_exec_param]);
  461. if ( ! stmt->put_data) { /* first call */
  462. mylog("SQLPutData: (1) cbValue = %dn", cbValue);
  463. stmt->put_data = TRUE;
  464. current_param->EXEC_used = (SDWORD *) malloc(sizeof(SDWORD));
  465. if ( ! current_param->EXEC_used) {
  466. stmt->errornumber = STMT_NO_MEMORY_ERROR;
  467. stmt->errormsg = "Out of memory in SQLPutData (1)";
  468. SC_log_error(func, "", stmt);
  469. return SQL_ERROR;
  470. }
  471. *current_param->EXEC_used = cbValue;
  472. if (cbValue == SQL_NULL_DATA)
  473. return SQL_SUCCESS;
  474. /* Handle Long Var Binary with Large Objects */
  475. if ( current_param->SQLType == SQL_LONGVARBINARY) {
  476. /* store the oid */
  477. current_param->lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE);
  478. if (current_param->lobj_oid == 0) {
  479. stmt->errornumber = STMT_EXEC_ERROR;
  480. stmt->errormsg = "Couldnt create large object.";
  481. SC_log_error(func, "", stmt);
  482. return SQL_ERROR;
  483. }
  484. /* major hack -- to allow convert to see somethings there */
  485. /* have to modify convert to handle this better */
  486. current_param->EXEC_buffer = (char *) &current_param->lobj_oid;
  487. /* store the fd */
  488. stmt->lobj_fd = lo_open(stmt->hdbc, current_param->lobj_oid, INV_WRITE);
  489. if ( stmt->lobj_fd < 0) {
  490. stmt->errornumber = STMT_EXEC_ERROR;
  491. stmt->errormsg = "Couldnt open large object for writing.";
  492. SC_log_error(func, "", stmt);
  493. return SQL_ERROR;
  494. }
  495. retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
  496. mylog("lo_write: cbValue=%d, wrote %d bytesn", cbValue, retval);
  497. }
  498. else { /* for handling text fields and small binaries */
  499. if (cbValue == SQL_NTS) {
  500. current_param->EXEC_buffer = strdup(rgbValue);
  501. if ( ! current_param->EXEC_buffer) {
  502. stmt->errornumber = STMT_NO_MEMORY_ERROR;
  503. stmt->errormsg = "Out of memory in SQLPutData (2)";
  504. SC_log_error(func, "", stmt);
  505. return SQL_ERROR;
  506. }
  507. }
  508. else {
  509. current_param->EXEC_buffer = malloc(cbValue + 1);
  510. if ( ! current_param->EXEC_buffer) {
  511. stmt->errornumber = STMT_NO_MEMORY_ERROR;
  512. stmt->errormsg = "Out of memory in SQLPutData (2)";
  513. SC_log_error(func, "", stmt);
  514. return SQL_ERROR;
  515. }
  516. memcpy(current_param->EXEC_buffer, rgbValue, cbValue);
  517. current_param->EXEC_buffer[cbValue] = '';
  518. }
  519. }
  520. }
  521. else { /* calling SQLPutData more than once */
  522. mylog("SQLPutData: (>1) cbValue = %dn", cbValue);
  523. if (current_param->SQLType == SQL_LONGVARBINARY) {
  524. /* the large object fd is in EXEC_buffer */
  525. retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue);
  526. mylog("lo_write(2): cbValue = %d, wrote %d bytesn", cbValue, retval);
  527. *current_param->EXEC_used += cbValue;
  528. } else {
  529. buffer = current_param->EXEC_buffer;
  530. if (cbValue == SQL_NTS) {
  531. buffer = realloc(buffer, strlen(buffer) + strlen(rgbValue) + 1);
  532. if ( ! buffer) {
  533. stmt->errornumber = STMT_NO_MEMORY_ERROR;
  534. stmt->errormsg = "Out of memory in SQLPutData (3)";
  535. SC_log_error(func, "", stmt);
  536. return SQL_ERROR;
  537. }
  538. strcat(buffer, rgbValue);
  539. mylog("       cbValue = SQL_NTS: strlen(buffer) = %dn", strlen(buffer));
  540. *current_param->EXEC_used = cbValue;
  541. /* reassign buffer incase realloc moved it */
  542. current_param->EXEC_buffer = buffer;
  543. }
  544. else if (cbValue > 0) {
  545. old_pos = *current_param->EXEC_used;
  546. *current_param->EXEC_used += cbValue;
  547. mylog("        cbValue = %d, old_pos = %d, *used = %dn", cbValue, old_pos, *current_param->EXEC_used);
  548. /* dont lose the old pointer in case out of memory */
  549. buffer = realloc(current_param->EXEC_buffer, *current_param->EXEC_used + 1);
  550. if ( ! buffer) {
  551. stmt->errornumber = STMT_NO_MEMORY_ERROR;
  552. stmt->errormsg = "Out of memory in SQLPutData (3)";
  553. SC_log_error(func, "", stmt);
  554. return SQL_ERROR;
  555. }
  556. memcpy(&buffer[old_pos], rgbValue, cbValue);
  557. buffer[*current_param->EXEC_used] = '';
  558. /* reassign buffer incase realloc moved it */
  559. current_param->EXEC_buffer = buffer;
  560. }
  561. else {
  562. SC_log_error(func, "bad cbValue", stmt);
  563. return SQL_ERROR;
  564. }
  565. }
  566. }
  567. return SQL_SUCCESS;
  568. }