aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/odbc/execute.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/odbc/execute.c')
-rw-r--r--src/interfaces/odbc/execute.c1090
1 files changed, 0 insertions, 1090 deletions
diff --git a/src/interfaces/odbc/execute.c b/src/interfaces/odbc/execute.c
deleted file mode 100644
index 598c2a2f61a..00000000000
--- a/src/interfaces/odbc/execute.c
+++ /dev/null
@@ -1,1090 +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);
- if (self->stmt_with_params)
- free(self->stmt_with_params);
- self->stmt_with_params = NULL;
- if (self->load_statement)
- free(self->load_statement);
- self->load_statement = NULL;
-
- 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);
- if (stmt->stmt_with_params)
- free(stmt->stmt_with_params);
- stmt->stmt_with_params = NULL;
- if (stmt->load_statement)
- free(stmt->load_statement);
- stmt->load_statement = NULL;
-
- /*
- * 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;
- APDFields *opts;
- IPDFields *ipdopts;
- ConnectionClass *conn;
- int i,
- retval, start_row, end_row;
- int cursor_type, scroll_concurrency;
- QResultClass *res;
-
- 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;
- }
-
- opts = SC_get_APD(stmt);
- cursor_type = stmt->options.cursor_type;
- scroll_concurrency = stmt->options.scroll_concurrency;
- /*
- * 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)
- {
- stmt->exec_current_row = -1;
- 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);
-/******** Is this really NEEDED ? ******/
- 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;
- }
-
- if (start_row = stmt->exec_start_row, start_row < 0)
- start_row = 0;
- if (end_row = stmt->exec_end_row, end_row < 0)
- end_row = opts->paramset_size - 1;
- if (stmt->exec_current_row < 0)
- stmt->exec_current_row = start_row;
- ipdopts = SC_get_IPD(stmt);
- if (stmt->exec_current_row == start_row)
- {
- if (ipdopts->param_processed_ptr)
- *ipdopts->param_processed_ptr = 0;
- SC_recycle_statement(stmt);
- }
-
-next_param_row:
-#if (ODBCVER >= 0x0300)
- if (opts->param_operation_ptr)
- {
- while (opts->param_operation_ptr[stmt->exec_current_row] == SQL_PARAM_IGNORE)
- {
- if (ipdopts->param_status_ptr)
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_UNUSED;
- if (stmt->exec_current_row >= end_row)
- {
- stmt->exec_current_row = -1;
- return SQL_SUCCESS;
- }
- ++stmt->exec_current_row;
- }
- }
-#endif /* ODBCVER */
- /*
- * 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.
- */
- UInt4 offset = opts->param_offset_ptr ? *opts->param_offset_ptr : 0;
- Int4 bind_size = opts->param_bind_type;
- Int4 current_row = stmt->exec_current_row < 0 ? 0 : stmt->exec_current_row;
-
- stmt->data_at_exec = -1;
- for (i = 0; i < opts->allocated; i++)
- {
- Int4 *pcVal = opts->parameters[i].used;
-
- opts->parameters[i].data_at_exec = FALSE;
- if (pcVal)
- {
- if (bind_size > 0)
- pcVal = (Int4 *)((char *)pcVal + offset + bind_size * current_row);
- else
- pcVal = (Int4 *)((char *)pcVal + offset + sizeof(SDWORD) * current_row);
- if (*pcVal == SQL_DATA_AT_EXEC || *pcVal <= SQL_LEN_DATA_AT_EXEC_OFFSET)
- opts->parameters[i].data_at_exec = TRUE;
- }
- /* Check for data at execution parameters */
- if (opts->parameters[i].data_at_exec)
- {
- 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);
-
- if (!stmt->inaccurate_result || !conn->connInfo.disallow_premature)
- {
- retval = SC_execute(stmt);
- if (retval != SQL_ERROR)
- {
- if (ipdopts->param_processed_ptr)
- (*ipdopts->param_processed_ptr)++;
- /* special handling of result for keyset driven cursors */
- if (SQL_CURSOR_KEYSET_DRIVEN == stmt->options.cursor_type &&
- SQL_CONCUR_READ_ONLY != stmt->options.scroll_concurrency)
- {
- QResultClass *kres;
-
- res = SC_get_Result(stmt);
- if (kres = res->next, kres)
- {
- kres->fields = res->fields;
- res->fields = NULL;
- kres->num_fields = res->num_fields;
- res->next = NULL;
- QR_Destructor(res);
- SC_set_Result(stmt, kres);
- }
- }
- }
-#if (ODBCVER >= 0x0300)
- if (ipdopts->param_status_ptr)
- {
- switch (retval)
- {
- case SQL_SUCCESS:
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS;
- break;
- case SQL_SUCCESS_WITH_INFO:
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS_WITH_INFO;
- break;
- default:
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
- break;
- }
- }
-#endif /* ODBCVER */
- if (retval == SQL_ERROR ||
- stmt->inaccurate_result ||
- stmt->exec_current_row >= end_row)
- {
- stmt->exec_current_row = -1;
- return retval;
- }
- stmt->exec_current_row++;
- goto next_param_row;
- }
- /*
- * Get the field info for the prepared query using dummy backward
- * fetch.
- */
- if (SC_is_pre_executable(stmt))
- {
- BOOL in_trans = CC_is_in_trans(conn);
- BOOL issued_begin = FALSE,
- begin_included = FALSE;
- QResultClass *curres;
-
- if (strnicmp(stmt->stmt_with_params, "BEGIN;", 6) == 0)
- begin_included = TRUE;
- else if (!in_trans)
- {
- if (issued_begin = CC_begin(conn), !issued_begin)
- {
- stmt->errornumber = STMT_EXEC_ERROR;
- stmt->errormsg = "Handle prepare error";
- return SQL_ERROR;
- }
- }
- /* we are now in a transaction */
- res = CC_send_query(conn, stmt->stmt_with_params, NULL, CLEAR_RESULT_ON_ABORT);
- if (!res)
- {
- CC_abort(conn);
- stmt->errornumber = STMT_EXEC_ERROR;
- stmt->errormsg = "Handle prepare error";
- return SQL_ERROR;
- }
- SC_set_Result(stmt, res);
- for (curres = res; !curres->num_fields; curres = curres->next)
- ;
- SC_set_Curres(stmt, curres);
- if (CC_is_in_autocommit(conn))
- {
- if (issued_begin)
- CC_commit(conn);
- }
- stmt->status = STMT_FINISHED;
- return SQL_SUCCESS;
- }
- if (res = SC_get_Curres(stmt), res)
- stmt->diag_row_count = res->recent_processed_row_count;
- if (stmt->options.cursor_type != cursor_type ||
- stmt->options.scroll_concurrency != scroll_concurrency)
- {
- stmt->errornumber = STMT_OPTION_VALUE_CHANGED;
- stmt->errormsg = "cursor updatability changed";
- return SQL_SUCCESS_WITH_INFO;
- }
- else
- return SQL_SUCCESS;
-}
-
-
-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, CLEAR_RESULT_ON_ABORT);
- if (!res)
- {
- /* error msg will be in the connection */
- CC_on_abort(conn, NO_TRANS);
- CC_log_error(func, "", conn);
- return SQL_ERROR;
- }
-
- ok = QR_command_maybe_successful(res);
- QR_Destructor(res);
-
- if (!ok)
- {
- CC_on_abort(conn, NO_TRANS);
- 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;
- ConnectionClass *conn;
- 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;
- }
- conn = SC_get_conn(stmt);
- ci = &(conn->connInfo);
-
- /*
- * Not in the middle of SQLParamData/SQLPutData so cancel like a
- * close.
- */
- if (stmt->data_at_exec < 0)
- {
- /*
- * Tell the Backend that we're cancelling this request
- */
- if (stmt->status == STMT_EXECUTING)
- CC_send_cancel_request(conn);
- /*
- * 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;
- APDFields *opts;
- IPDFields *ipdopts;
- 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);
- opts = SC_get_APD(stmt);
-
- mylog("%s: data_at_exec=%d, params_alloc=%d\n", func, stmt->data_at_exec, opts->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 > opts->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))
- {
- if (!CC_commit(stmt->hdbc))
- {
- 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 */
- ipdopts = SC_get_IPD(stmt);
- if (stmt->data_at_exec == 0)
- {
- int end_row;
-
- retval = copy_statement_with_parameters(stmt);
- if (retval != SQL_SUCCESS)
- return retval;
-
- stmt->current_exec_param = -1;
-
- retval = SC_execute(stmt);
- if (retval != SQL_ERROR)
- {
- if (ipdopts->param_processed_ptr)
- (*ipdopts->param_processed_ptr)++;
- }
-#if (ODBCVER >= 0x0300)
- if (ipdopts->param_status_ptr)
- {
- switch (retval)
- {
- case SQL_SUCCESS:
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS;
- break;
- case SQL_SUCCESS_WITH_INFO:
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_SUCCESS_WITH_INFO;
- break;
- default:
- ipdopts->param_status_ptr[stmt->exec_current_row] = SQL_PARAM_ERROR;
- break;
- }
- }
-#endif /* ODBCVER */
- end_row = stmt->exec_end_row;
- if (end_row < 0)
- end_row = opts->paramset_size - 1;
- if (retval == SQL_ERROR ||
- stmt->exec_current_row >= end_row)
- {
- stmt->exec_current_row = -1;
- return retval;
- }
- stmt->exec_current_row++;
- return PGAPI_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 < opts->allocated; i++)
- {
- if (opts->parameters[i].data_at_exec)
- {
- stmt->data_at_exec--;
- stmt->current_exec_param = i;
- stmt->put_data = FALSE;
- *prgbValue = opts->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;
- APDFields *opts;
- 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;
- }
-
- opts = SC_get_APD(stmt);
- 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 = &(opts->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))
- {
- if (!CC_begin(stmt->hdbc))
- {
- stmt->errormsg = "Could not begin (in-line) a transaction";
- stmt->errornumber = STMT_EXEC_ERROR;
- SC_log_error(func, "", stmt);
- return SQL_ERROR;
- }
- }
-
- /* 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 *) &current_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
- {
- Int2 ctype = current_param->CType;
- if (ctype == SQL_C_DEFAULT)
- ctype = sqltype_to_default_ctype(current_param->SQLType);
-
-#ifdef UNICODE_SUPPORT
- if (SQL_NTS == cbValue && SQL_C_WCHAR == ctype)
- cbValue = 2 * ucs2strlen((SQLWCHAR *) rgbValue);
-#endif /* UNICODE_SUPPORT */
- /* 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
- {
-#ifdef UNICODE_SUPPORT
- if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY || ctype == SQL_C_WCHAR)
-#else
- if (ctype == SQL_C_CHAR || ctype == SQL_C_BINARY)
-#endif /* UNICODE_SUPPORT */
- {
- 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
- {
- Int2 ctype = current_param->CType;
-
- if (ctype == SQL_C_DEFAULT)
- ctype = sqltype_to_default_ctype(current_param->SQLType);
- buffer = current_param->EXEC_buffer;
- if (old_pos = *current_param->EXEC_used, SQL_NTS == old_pos)
- {
-#ifdef UNICODE_SUPPORT
- if (SQL_C_WCHAR == ctype)
- old_pos = 2 * ucs2strlen((SQLWCHAR *) buffer);
- else
-#endif /* UNICODE_SUPPORT */
- old_pos = strlen(buffer);
- }
- if (SQL_NTS == cbValue)
- {
-#ifdef UNICODE_SUPPORT
- if (SQL_C_WCHAR == ctype)
- cbValue = 2 * ucs2strlen((SQLWCHAR *) rgbValue);
- else
-#endif /* UNICODE_SUPPORT */
- cbValue = strlen(rgbValue);
- }
- if (cbValue > 0)
- {
- *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;
-}