📄 execute.c
字号:
/* 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. * */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "psqlodbc.h"#include <stdio.h>#include <string.h>#ifndef WIN32#include "iodbc.h"#include "isqlext.h"#else#include <windows.h>#include <sqlext.h>#endif#include "connection.h"#include "statement.h"#include "qresult.h"#include "convert.h"#include "bind.h"#include "lobj.h"extern GLOBAL_VALUES globals;// Perform a Prepare on the SQL statementRETCODE SQL_API SQLPrepare(HSTMT hstmt, UCHAR FAR *szSqlStr, SDWORD cbSqlStr){static char *func = "SQLPrepare";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("**** SQLPrepare: STMT_PREMATURE, recycle\n"); SC_recycle_statement(self); /* recycle the statement, but do not remove parameter bindings */ break; case STMT_FINISHED: mylog("**** SQLPrepare: STMT_FINISHED, recycle\n"); SC_recycle_statement(self); /* recycle the statement, but do not remove parameter bindings */ break; case STMT_ALLOCATED: mylog("**** SQLPrepare: STMT_ALLOCATED, copy\n"); self->status = STMT_READY; break; case STMT_READY: mylog("**** SQLPrepare: STMT_READY, change SQL\n"); break; case STMT_EXECUTING: mylog("**** SQLPrepare: STMT_EXECUTING, error!\n"); self->errornumber = STMT_SEQUENCE_ERROR; self->errormsg = "SQLPrepare(): 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 readonly (only selects are allowed) if ( CC_is_readonly(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 SQLExecDirect( HSTMT hstmt, UCHAR FAR *szSqlStr, SDWORD cbSqlStr){StatementClass *stmt = (StatementClass *) hstmt;RETCODE result;static char *func = "SQLExecDirect"; 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; stmt->statement_type = statement_type(stmt->statement); // Check if connection is readonly (only selects are allowed) if ( CC_is_readonly(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 SQLExecute...\n", func); result = SQLExecute(hstmt); mylog("%s: returned %hd from SQLExecute\n", func, result); return result;}// Execute a prepared SQL statementRETCODE SQL_API SQLExecute( HSTMT hstmt){static char *func="SQLExecute";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) { 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; } /* 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++) { /* 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); return SC_execute(stmt);}// - - - - - - - - -RETCODE SQL_API SQLTransact( HENV henv, HDBC hdbc, UWORD fType){static char *func = "SQLTransact";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 ( SQLTransact(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 ="SQLTransact 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("SQLTransact: 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -