diff options
author | Hiroshi Inoue <inoue@tpf.co.jp> | 2002-01-11 06:01:47 +0000 |
---|---|---|
committer | Hiroshi Inoue <inoue@tpf.co.jp> | 2002-01-11 06:01:47 +0000 |
commit | d91b4451175dcd1996e8b5fdaa375d2bcf74d9a5 (patch) | |
tree | 2102451d41d2932d3a5ccd870407e1d25a35854c /src/interfaces/odbc/windev/execute.c | |
parent | 3b3b73072859a2b465e4c392abcb954626507856 (diff) | |
download | postgresql-d91b4451175dcd1996e8b5fdaa375d2bcf74d9a5.tar.gz postgresql-d91b4451175dcd1996e8b5fdaa375d2bcf74d9a5.zip |
*** empty log message ***
Diffstat (limited to 'src/interfaces/odbc/windev/execute.c')
-rw-r--r-- | src/interfaces/odbc/windev/execute.c | 955 |
1 files changed, 0 insertions, 955 deletions
diff --git a/src/interfaces/odbc/windev/execute.c b/src/interfaces/odbc/windev/execute.c deleted file mode 100644 index 5a693b71638..00000000000 --- a/src/interfaces/odbc/windev/execute.c +++ /dev/null @@ -1,955 +0,0 @@ -/*------- - * Module: execute.c - * - * Description: This module contains routines related to - * preparing and executing an SQL statement. - * - * Classes: n/a - * - * API functions: SQLPrepare, SQLExecute, SQLExecDirect, SQLTransact, - * SQLCancel, SQLNativeSql, SQLParamData, SQLPutData - * - * Comments: See "notice.txt" for copyright and license information. - *------- - */ - -#include "psqlodbc.h" - -#include <stdio.h> -#include <string.h> - -#include "connection.h" -#include "statement.h" -#include "qresult.h" -#include "convert.h" -#include "bind.h" -#include "pgtypes.h" -#include "lobj.h" -#include "pgapifunc.h" - -/*extern GLOBAL_VALUES globals;*/ - - -/* Perform a Prepare on the SQL statement */ -RETCODE SQL_API -PGAPI_Prepare(HSTMT hstmt, - UCHAR FAR * szSqlStr, - SDWORD cbSqlStr) -{ - static char *func = "PGAPI_Prepare"; - StatementClass *self = (StatementClass *) hstmt; - - mylog("%s: entering...\n", func); - - if (!self) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - /* - * According to the ODBC specs it is valid to call SQLPrepare mulitple - * times. In that case, the bound SQL statement is replaced by the new - * one - */ - - switch (self->status) - { - case STMT_PREMATURE: - mylog("**** PGAPI_Prepare: STMT_PREMATURE, recycle\n"); - SC_recycle_statement(self); /* recycle the statement, but do - * not remove parameter bindings */ - break; - - case STMT_FINISHED: - mylog("**** PGAPI_Prepare: STMT_FINISHED, recycle\n"); - SC_recycle_statement(self); /* recycle the statement, but do - * not remove parameter bindings */ - break; - - case STMT_ALLOCATED: - mylog("**** PGAPI_Prepare: STMT_ALLOCATED, copy\n"); - self->status = STMT_READY; - break; - - case STMT_READY: - mylog("**** PGAPI_Prepare: STMT_READY, change SQL\n"); - break; - - case STMT_EXECUTING: - mylog("**** PGAPI_Prepare: STMT_EXECUTING, error!\n"); - - self->errornumber = STMT_SEQUENCE_ERROR; - self->errormsg = "PGAPI_Prepare(): The handle does not point to a statement that is ready to be executed"; - SC_log_error(func, "", self); - - return SQL_ERROR; - - default: - self->errornumber = STMT_INTERNAL_ERROR; - self->errormsg = "An Internal Error has occured -- Unknown statement status."; - SC_log_error(func, "", self); - return SQL_ERROR; - } - - if (self->statement) - free(self->statement); - - self->statement = make_string(szSqlStr, cbSqlStr, NULL); - if (!self->statement) - { - self->errornumber = STMT_NO_MEMORY_ERROR; - self->errormsg = "No memory available to store statement"; - SC_log_error(func, "", self); - return SQL_ERROR; - } - - self->prepare = TRUE; - self->statement_type = statement_type(self->statement); - - /* Check if connection is onlyread (only selects are allowed) */ - if (CC_is_onlyread(self->hdbc) && STMT_UPDATE(self)) - { - self->errornumber = STMT_EXEC_ERROR; - self->errormsg = "Connection is readonly, only select statements are allowed."; - SC_log_error(func, "", self); - return SQL_ERROR; - } - - return SQL_SUCCESS; -} - - -/* Performs the equivalent of SQLPrepare, followed by SQLExecute. */ -RETCODE SQL_API -PGAPI_ExecDirect( - HSTMT hstmt, - UCHAR FAR * szSqlStr, - SDWORD cbSqlStr) -{ - StatementClass *stmt = (StatementClass *) hstmt; - RETCODE result; - static char *func = "PGAPI_ExecDirect"; - - mylog("%s: entering...\n", func); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - if (stmt->statement) - free(stmt->statement); - - /* - * keep a copy of the un-parametrized statement, in case they try to - * execute this statement again - */ - stmt->statement = make_string(szSqlStr, cbSqlStr, NULL); - if (!stmt->statement) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "No memory available to store statement"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - mylog("**** %s: hstmt=%u, statement='%s'\n", func, hstmt, stmt->statement); - - stmt->prepare = FALSE; - - /* - * If an SQLPrepare was performed prior to this, but was left in the - * premature state because an error occurred prior to SQLExecute then - * set the statement to finished so it can be recycled. - */ - if (stmt->status == STMT_PREMATURE) - stmt->status = STMT_FINISHED; - - stmt->statement_type = statement_type(stmt->statement); - - /* Check if connection is onlyread (only selects are allowed) */ - if (CC_is_onlyread(stmt->hdbc) && STMT_UPDATE(stmt)) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Connection is readonly, only select statements are allowed."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - mylog("%s: calling PGAPI_Execute...\n", func); - - result = PGAPI_Execute(hstmt); - - mylog("%s: returned %hd from PGAPI_Execute\n", func, result); - return result; -} - - -/* Execute a prepared SQL statement */ -RETCODE SQL_API -PGAPI_Execute( - HSTMT hstmt) -{ - static char *func = "PGAPI_Execute"; - StatementClass *stmt = (StatementClass *) hstmt; - ConnectionClass *conn; - int i, - retval; - - mylog("%s: entering...\n", func); - - if (!stmt) - { - SC_log_error(func, "", NULL); - mylog("%s: NULL statement so return SQL_INVALID_HANDLE\n", func); - return SQL_INVALID_HANDLE; - } - - /* - * If the statement is premature, it means we already executed it from - * an SQLPrepare/SQLDescribeCol type of scenario. So just return - * success. - */ - if (stmt->prepare && stmt->status == STMT_PREMATURE) - { - if (stmt->inaccurate_result) - SC_recycle_statement(stmt); - else - { - stmt->status = STMT_FINISHED; - if (stmt->errormsg == NULL) - { - mylog("%s: premature statement but return SQL_SUCCESS\n", func); - return SQL_SUCCESS; - } - else - { - SC_log_error(func, "", stmt); - mylog("%s: premature statement so return SQL_ERROR\n", func); - return SQL_ERROR; - } - } - } - - mylog("%s: clear errors...\n", func); - - SC_clear_error(stmt); - - conn = SC_get_conn(stmt); - if (conn->status == CONN_EXECUTING) - { - stmt->errormsg = "Connection is already in use."; - stmt->errornumber = STMT_SEQUENCE_ERROR; - SC_log_error(func, "", stmt); - mylog("%s: problem with connection\n", func); - return SQL_ERROR; - } - - if (!stmt->statement) - { - stmt->errornumber = STMT_NO_STMTSTRING; - stmt->errormsg = "This handle does not have a SQL statement stored in it"; - SC_log_error(func, "", stmt); - mylog("%s: problem with handle\n", func); - return SQL_ERROR; - } - - /* - * If SQLExecute is being called again, recycle the statement. Note - * this should have been done by the application in a call to - * SQLFreeStmt(SQL_CLOSE) or SQLCancel. - */ - if (stmt->status == STMT_FINISHED) - { - mylog("%s: recycling statement (should have been done by app)...\n", func); - SC_recycle_statement(stmt); - } - - /* Check if the statement is in the correct state */ - if ((stmt->prepare && stmt->status != STMT_READY) || - (stmt->status != STMT_ALLOCATED && stmt->status != STMT_READY)) - { - stmt->errornumber = STMT_STATUS_ERROR; - stmt->errormsg = "The handle does not point to a statement that is ready to be executed"; - SC_log_error(func, "", stmt); - mylog("%s: problem with statement\n", func); - return SQL_ERROR; - } - - /* - * Check if statement has any data-at-execute parameters when it is - * not in SC_pre_execute. - */ - if (!stmt->pre_executing) - { - /* - * The bound parameters could have possibly changed since the last - * execute of this statement? Therefore check for params and - * re-copy. - */ - stmt->data_at_exec = -1; - for (i = 0; i < stmt->parameters_allocated; i++) - { - Int4 *pcVal = stmt->parameters[i].used; - - if (pcVal && (*pcVal == SQL_DATA_AT_EXEC || *pcVal <= SQL_LEN_DATA_AT_EXEC_OFFSET)) - stmt->parameters[i].data_at_exec = TRUE; - else - stmt->parameters[i].data_at_exec = FALSE; - /* Check for data at execution parameters */ - if (stmt->parameters[i].data_at_exec == TRUE) - { - if (stmt->data_at_exec < 0) - stmt->data_at_exec = 1; - else - stmt->data_at_exec++; - } - } - - /* - * If there are some data at execution parameters, return need - * data - */ - - /* - * SQLParamData and SQLPutData will be used to send params and - * execute the statement. - */ - if (stmt->data_at_exec > 0) - return SQL_NEED_DATA; - - } - - - mylog("%s: copying statement params: trans_status=%d, len=%d, stmt='%s'\n", func, conn->transact_status, strlen(stmt->statement), stmt->statement); - - /* Create the statement with parameters substituted. */ - retval = copy_statement_with_parameters(stmt); - if (retval != SQL_SUCCESS) - /* error msg passed from above */ - return retval; - - mylog(" stmt_with_params = '%s'\n", stmt->stmt_with_params); - - /* - * Get the field info for the prepared query using dummy backward - * fetch. - */ - if (stmt->inaccurate_result && conn->connInfo.disallow_premature) - { - if (SC_is_pre_executable(stmt)) - { - BOOL in_trans = CC_is_in_trans(conn); - BOOL issued_begin = FALSE, - begin_included = FALSE; - QResultClass *res; - - if (strnicmp(stmt->stmt_with_params, "BEGIN;", 6) == 0) - begin_included = TRUE; - else if (!in_trans) - { - res = CC_send_query(conn, "BEGIN", NULL); - if (res && !QR_aborted(res)) - issued_begin = TRUE; - if (res) - QR_Destructor(res); - if (!issued_begin) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Handle prepare error"; - return SQL_ERROR; - } - } - /* we are now in a transaction */ - CC_set_in_trans(conn); - stmt->result = res = CC_send_query(conn, stmt->stmt_with_params, NULL); - if (!res || QR_aborted(res)) - { - CC_abort(conn); - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Handle prepare error"; - return SQL_ERROR; - } - else - { - if (CC_is_in_autocommit(conn)) - { - if (issued_begin) - { - res = CC_send_query(conn, "COMMIT", NULL); - CC_set_no_trans(conn); - if (res) - QR_Destructor(res); - } - else if (!in_trans && begin_included) - CC_set_no_trans(conn); - } - stmt->status = STMT_FINISHED; - return SQL_SUCCESS; - } - } - else - return SQL_SUCCESS; - } - - return SC_execute(stmt); -} - - -RETCODE SQL_API -PGAPI_Transact( - HENV henv, - HDBC hdbc, - UWORD fType) -{ - static char *func = "PGAPI_Transact"; - extern ConnectionClass *conns[]; - ConnectionClass *conn; - QResultClass *res; - char ok, - *stmt_string; - int lf; - - mylog("entering %s: hdbc=%u, henv=%u\n", func, hdbc, henv); - - if (hdbc == SQL_NULL_HDBC && henv == SQL_NULL_HENV) - { - CC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - /* - * If hdbc is null and henv is valid, it means transact all - * connections on that henv. - */ - if (hdbc == SQL_NULL_HDBC && henv != SQL_NULL_HENV) - { - for (lf = 0; lf < MAX_CONNECTIONS; lf++) - { - conn = conns[lf]; - - if (conn && conn->henv == henv) - if (PGAPI_Transact(henv, (HDBC) conn, fType) != SQL_SUCCESS) - return SQL_ERROR; - } - return SQL_SUCCESS; - } - - conn = (ConnectionClass *) hdbc; - - if (fType == SQL_COMMIT) - stmt_string = "COMMIT"; - else if (fType == SQL_ROLLBACK) - stmt_string = "ROLLBACK"; - else - { - conn->errornumber = CONN_INVALID_ARGUMENT_NO; - conn->errormsg = "PGAPI_Transact can only be called with SQL_COMMIT or SQL_ROLLBACK as parameter"; - CC_log_error(func, "", conn); - return SQL_ERROR; - } - - /* If manual commit and in transaction, then proceed. */ - if (!CC_is_in_autocommit(conn) && CC_is_in_trans(conn)) - { - mylog("PGAPI_Transact: sending on conn %d '%s'\n", conn, stmt_string); - - res = CC_send_query(conn, stmt_string, NULL); - CC_set_no_trans(conn); - - if (!res) - { - /* error msg will be in the connection */ - CC_log_error(func, "", conn); - return SQL_ERROR; - } - - ok = QR_command_successful(res); - QR_Destructor(res); - - if (!ok) - { - CC_log_error(func, "", conn); - return SQL_ERROR; - } - } - return SQL_SUCCESS; -} - - -RETCODE SQL_API -PGAPI_Cancel( - HSTMT hstmt) /* Statement to cancel. */ -{ - static char *func = "PGAPI_Cancel"; - StatementClass *stmt = (StatementClass *) hstmt; - RETCODE result; - ConnInfo *ci; - -#ifdef WIN32 - HMODULE hmodule; - FARPROC addr; -#endif - - mylog("%s: entering...\n", func); - - /* Check if this can handle canceling in the middle of a SQLPutData? */ - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - ci = &(SC_get_conn(stmt)->connInfo); - - /* - * Not in the middle of SQLParamData/SQLPutData so cancel like a - * close. - */ - if (stmt->data_at_exec < 0) - { - /* - * MAJOR HACK for Windows to reset the driver manager's cursor - * state: Because of what seems like a bug in the Odbc driver - * manager, SQLCancel does not act like a SQLFreeStmt(CLOSE), as - * many applications depend on this behavior. So, this brute - * force method calls the driver manager's function on behalf of - * the application. - */ - -#ifdef WIN32 - if (ci->drivers.cancel_as_freestmt) - { - hmodule = GetModuleHandle("ODBC32"); - addr = GetProcAddress(hmodule, "SQLFreeStmt"); - result = addr((char *) (stmt->phstmt) - 96, SQL_CLOSE); - } - else - result = PGAPI_FreeStmt(hstmt, SQL_CLOSE); -#else - result = PGAPI_FreeStmt(hstmt, SQL_CLOSE); -#endif - - mylog("PGAPI_Cancel: PGAPI_FreeStmt returned %d\n", result); - - SC_clear_error(hstmt); - return SQL_SUCCESS; - } - - /* In the middle of SQLParamData/SQLPutData, so cancel that. */ - - /* - * Note, any previous data-at-exec buffers will be freed in the - * recycle - */ - /* if they call SQLExecDirect or SQLExecute again. */ - - stmt->data_at_exec = -1; - stmt->current_exec_param = -1; - stmt->put_data = FALSE; - - return SQL_SUCCESS; -} - - -/* - * Returns the SQL string as modified by the driver. - * Currently, just copy the input string without modification - * observing buffer limits and truncation. - */ -RETCODE SQL_API -PGAPI_NativeSql( - HDBC hdbc, - UCHAR FAR * szSqlStrIn, - SDWORD cbSqlStrIn, - UCHAR FAR * szSqlStr, - SDWORD cbSqlStrMax, - SDWORD FAR * pcbSqlStr) -{ - static char *func = "PGAPI_NativeSql"; - int len = 0; - char *ptr; - ConnectionClass *conn = (ConnectionClass *) hdbc; - RETCODE result; - - mylog("%s: entering...cbSqlStrIn=%d\n", func, cbSqlStrIn); - - ptr = (cbSqlStrIn == 0) ? "" : make_string(szSqlStrIn, cbSqlStrIn, NULL); - if (!ptr) - { - conn->errornumber = CONN_NO_MEMORY_ERROR; - conn->errormsg = "No memory available to store native sql string"; - CC_log_error(func, "", conn); - return SQL_ERROR; - } - - result = SQL_SUCCESS; - len = strlen(ptr); - - if (szSqlStr) - { - strncpy_null(szSqlStr, ptr, cbSqlStrMax); - - if (len >= cbSqlStrMax) - { - result = SQL_SUCCESS_WITH_INFO; - conn->errornumber = STMT_TRUNCATED; - conn->errormsg = "The buffer was too small for the NativeSQL."; - } - } - - if (pcbSqlStr) - *pcbSqlStr = len; - - if (cbSqlStrIn) - free(ptr); - - return result; -} - - -/* - * Supplies parameter data at execution time. - * Used in conjuction with SQLPutData. - */ -RETCODE SQL_API -PGAPI_ParamData( - HSTMT hstmt, - PTR FAR * prgbValue) -{ - static char *func = "PGAPI_ParamData"; - StatementClass *stmt = (StatementClass *) hstmt; - int i, - retval; - ConnInfo *ci; - - mylog("%s: entering...\n", func); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - ci = &(SC_get_conn(stmt)->connInfo); - - mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, stmt->data_at_exec, stmt->parameters_allocated); - - if (stmt->data_at_exec < 0) - { - stmt->errornumber = STMT_SEQUENCE_ERROR; - stmt->errormsg = "No execution-time parameters for this statement"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - if (stmt->data_at_exec > stmt->parameters_allocated) - { - stmt->errornumber = STMT_SEQUENCE_ERROR; - stmt->errormsg = "Too many execution-time parameters were present"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* close the large object */ - if (stmt->lobj_fd >= 0) - { - lo_close(stmt->hdbc, stmt->lobj_fd); - - /* commit transaction if needed */ - if (!ci->drivers.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) - { - QResultClass *res; - char ok; - - res = CC_send_query(stmt->hdbc, "COMMIT", NULL); - if (!res) - { - stmt->errormsg = "Could not commit (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - ok = QR_command_successful(res); - CC_set_no_trans(stmt->hdbc); - QR_Destructor(res); - if (!ok) - { - stmt->errormsg = "Could not commit (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - } - stmt->lobj_fd = -1; - } - - /* Done, now copy the params and then execute the statement */ - if (stmt->data_at_exec == 0) - { - retval = copy_statement_with_parameters(stmt); - if (retval != SQL_SUCCESS) - return retval; - - stmt->current_exec_param = -1; - - return SC_execute(stmt); - } - - /* - * Set beginning param; if first time SQLParamData is called , start - * at 0. Otherwise, start at the last parameter + 1. - */ - i = stmt->current_exec_param >= 0 ? stmt->current_exec_param + 1 : 0; - - /* At least 1 data at execution parameter, so Fill in the token value */ - for (; i < stmt->parameters_allocated; i++) - { - if (stmt->parameters[i].data_at_exec == TRUE) - { - stmt->data_at_exec--; - stmt->current_exec_param = i; - stmt->put_data = FALSE; - *prgbValue = stmt->parameters[i].buffer; /* token */ - break; - } - } - - return SQL_NEED_DATA; -} - - -/* - * Supplies parameter data at execution time. - * Used in conjunction with SQLParamData. - */ -RETCODE SQL_API -PGAPI_PutData( - HSTMT hstmt, - PTR rgbValue, - SDWORD cbValue) -{ - static char *func = "PGAPI_PutData"; - StatementClass *stmt = (StatementClass *) hstmt; - int old_pos, - retval; - ParameterInfoClass *current_param; - char *buffer; - - mylog("%s: entering...\n", func); - - if (!stmt) - { - SC_log_error(func, "", NULL); - return SQL_INVALID_HANDLE; - } - - if (stmt->current_exec_param < 0) - { - stmt->errornumber = STMT_SEQUENCE_ERROR; - stmt->errormsg = "Previous call was not SQLPutData or SQLParamData"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - current_param = &(stmt->parameters[stmt->current_exec_param]); - - if (!stmt->put_data) - { /* first call */ - mylog("PGAPI_PutData: (1) cbValue = %d\n", cbValue); - - stmt->put_data = TRUE; - - current_param->EXEC_used = (SDWORD *) malloc(sizeof(SDWORD)); - if (!current_param->EXEC_used) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Out of memory in PGAPI_PutData (1)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - *current_param->EXEC_used = cbValue; - - if (cbValue == SQL_NULL_DATA) - return SQL_SUCCESS; - - /* Handle Long Var Binary with Large Objects */ - if (current_param->SQLType == SQL_LONGVARBINARY) - { - /* begin transaction if needed */ - if (!CC_is_in_trans(stmt->hdbc)) - { - QResultClass *res; - char ok; - - res = CC_send_query(stmt->hdbc, "BEGIN", NULL); - if (!res) - { - stmt->errormsg = "Could not begin (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - ok = QR_command_successful(res); - QR_Destructor(res); - if (!ok) - { - stmt->errormsg = "Could not begin (in-line) a transaction"; - stmt->errornumber = STMT_EXEC_ERROR; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - CC_set_in_trans(stmt->hdbc); - } - - /* store the oid */ - current_param->lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE); - if (current_param->lobj_oid == 0) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Couldnt create large object."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - /* - * major hack -- to allow convert to see somethings there have - * to modify convert to handle this better - */ - current_param->EXEC_buffer = (char *) ¤t_param->lobj_oid; - - /* store the fd */ - stmt->lobj_fd = lo_open(stmt->hdbc, current_param->lobj_oid, INV_WRITE); - if (stmt->lobj_fd < 0) - { - stmt->errornumber = STMT_EXEC_ERROR; - stmt->errormsg = "Couldnt open large object for writing."; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue); - mylog("lo_write: cbValue=%d, wrote %d bytes\n", cbValue, retval); - } - else - { - /* for handling fields */ - if (cbValue == SQL_NTS) - { - current_param->EXEC_buffer = strdup(rgbValue); - if (!current_param->EXEC_buffer) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Out of memory in PGAPI_PutData (2)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - } - else - { - Int2 ctype = current_param->CType; - - if (ctype == SQL_C_DEFAULT) - ctype = sqltype_to_default_ctype(current_param->SQLType); - if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY) - { - current_param->EXEC_buffer = malloc(cbValue + 1); - if (!current_param->EXEC_buffer) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Out of memory in PGAPI_PutData (2)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - memcpy(current_param->EXEC_buffer, rgbValue, cbValue); - current_param->EXEC_buffer[cbValue] = '\0'; - } - else - { - Int4 used = ctype_length(ctype); - - current_param->EXEC_buffer = malloc(used); - if (!current_param->EXEC_buffer) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Out of memory in PGAPI_PutData (2)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - memcpy(current_param->EXEC_buffer, rgbValue, used); - } - } - } - } - else - { - /* calling SQLPutData more than once */ - mylog("PGAPI_PutData: (>1) cbValue = %d\n", cbValue); - - if (current_param->SQLType == SQL_LONGVARBINARY) - { - /* the large object fd is in EXEC_buffer */ - retval = lo_write(stmt->hdbc, stmt->lobj_fd, rgbValue, cbValue); - mylog("lo_write(2): cbValue = %d, wrote %d bytes\n", cbValue, retval); - - *current_param->EXEC_used += cbValue; - } - else - { - buffer = current_param->EXEC_buffer; - - if (cbValue == SQL_NTS) - { - buffer = realloc(buffer, strlen(buffer) + strlen(rgbValue) + 1); - if (!buffer) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Out of memory in PGAPI_PutData (3)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - strcat(buffer, rgbValue); - - mylog(" cbValue = SQL_NTS: strlen(buffer) = %d\n", strlen(buffer)); - - *current_param->EXEC_used = cbValue; - - /* reassign buffer incase realloc moved it */ - current_param->EXEC_buffer = buffer; - } - else if (cbValue > 0) - { - old_pos = *current_param->EXEC_used; - - *current_param->EXEC_used += cbValue; - - mylog(" cbValue = %d, old_pos = %d, *used = %d\n", cbValue, old_pos, *current_param->EXEC_used); - - /* dont lose the old pointer in case out of memory */ - buffer = realloc(current_param->EXEC_buffer, *current_param->EXEC_used + 1); - if (!buffer) - { - stmt->errornumber = STMT_NO_MEMORY_ERROR; - stmt->errormsg = "Out of memory in PGAPI_PutData (3)"; - SC_log_error(func, "", stmt); - return SQL_ERROR; - } - - memcpy(&buffer[old_pos], rgbValue, cbValue); - buffer[*current_param->EXEC_used] = '\0'; - - /* reassign buffer incase realloc moved it */ - current_param->EXEC_buffer = buffer; - } - else - { - SC_log_error(func, "bad cbValue", stmt); - return SQL_ERROR; - } - } - } - - return SQL_SUCCESS; -} |