00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <ncbi_pch.hpp>
00033 #include <dbapi/driver/odbc/interfaces.hpp>
00034 #include <dbapi/driver/util/numeric_convert.hpp>
00035 #include <dbapi/error_codes.hpp>
00036
00037 #include <stdio.h>
00038
00039 #include "odbc_utils.hpp"
00040
00041
00042 #define NCBI_USE_ERRCODE_X Dbapi_Odbc_Cmds
00043
00044 BEGIN_NCBI_SCOPE
00045
00046
00047
00048
00049
00050
00051
00052 CODBC_RPCCmd::CODBC_RPCCmd(CODBC_Connection& conn,
00053 const string& proc_name) :
00054 CStatementBase(conn),
00055 impl::CBaseCmd(conn, proc_name),
00056 m_Res(0)
00057 {
00058 string extra_msg = "Procedure Name: " + proc_name;
00059 SetDbgInfo( extra_msg );
00060
00061 return;
00062 }
00063
00064
00065 CDBParams&
00066 CODBC_RPCCmd::GetBindParams(void)
00067 {
00068 if (m_InParams.get() == NULL) {
00069 m_InParams.reset(new impl::CRowInfo_SP_SQL_Server(
00070 GetQuery(),
00071 GetConnImpl(),
00072 GetBindParamsImpl()
00073 )
00074 );
00075 }
00076
00077 return *m_InParams;
00078 }
00079
00080
00081 bool CODBC_RPCCmd::Send()
00082 {
00083 Cancel();
00084
00085 SetHasFailed(false);
00086 m_HasStatus = false;
00087
00088
00089 string main_exec_query("declare @STpROCrETURNsTATUS int;\nexec @STpROCrETURNsTATUS=");
00090 main_exec_query += GetQuery();
00091 string param_result_query;
00092
00093 CMemPot bindGuard;
00094 string q_str;
00095
00096 if(GetBindParamsImpl().NofParams() > 0) {
00097 SQLLEN* indicator = (SQLLEN*)
00098 bindGuard.Alloc(GetBindParamsImpl().NofParams() * sizeof(SQLLEN));
00099
00100 if (!x_AssignParams(q_str, main_exec_query, param_result_query,
00101 bindGuard, indicator)) {
00102 ResetParams();
00103 SetHasFailed();
00104
00105 string err_message = "Cannot assign params." + GetDbgInfo();
00106 DATABASE_DRIVER_ERROR( err_message, 420003 );
00107 }
00108 }
00109
00110 if(NeedToRecompile()) main_exec_query += " with recompile";
00111
00112 q_str += main_exec_query + ";\nselect STpROCrETURNsTATUS=@STpROCrETURNsTATUS";
00113 if(!param_result_query.empty()) {
00114 q_str += ";\nselect " + param_result_query;
00115 }
00116
00117 switch(SQLExecDirect(GetHandle(), CODBCString(q_str, GetClientEncoding()), SQL_NTS)) {
00118 case SQL_SUCCESS:
00119 m_HasMoreResults = true;
00120 break;
00121
00122 case SQL_NO_DATA:
00123 m_HasMoreResults = true;
00124
00125 m_RowCount = 0;
00126 break;
00127
00128 case SQL_ERROR:
00129 ReportErrors();
00130 ResetParams();
00131 SetHasFailed();
00132 {
00133 string err_message = "SQLExecDirect failed." + GetDbgInfo();
00134 DATABASE_DRIVER_ERROR( err_message, 420001 );
00135 }
00136
00137 case SQL_SUCCESS_WITH_INFO:
00138 ReportErrors();
00139 m_HasMoreResults = true;
00140 break;
00141
00142 case SQL_STILL_EXECUTING:
00143 ReportErrors();
00144 ResetParams();
00145 SetHasFailed();
00146 {
00147 string err_message = "Some other query is executing on this connection." +
00148 GetDbgInfo();
00149 DATABASE_DRIVER_ERROR( err_message, 420002 );
00150 }
00151
00152 case SQL_INVALID_HANDLE:
00153 SetHasFailed();
00154 {
00155 string err_message = "The statement handler is invalid (memory corruption suspected)." +
00156 GetDbgInfo();
00157 DATABASE_DRIVER_ERROR( err_message, 420004 );
00158 }
00159
00160 default:
00161 ReportErrors();
00162 ResetParams();
00163 SetHasFailed();
00164 {
00165 string err_message = "Unexpected error." + GetDbgInfo();
00166 DATABASE_DRIVER_ERROR( err_message, 420005 );
00167 }
00168
00169 }
00170
00171 SetWasSent();
00172 return true;
00173 }
00174
00175
00176 bool CODBC_RPCCmd::Cancel()
00177 {
00178 if (WasSent()) {
00179 if (m_Res) {
00180 delete m_Res;
00181 m_Res = 0;
00182 }
00183
00184 SetWasSent(false);
00185
00186 if ( !Close() ) {
00187 return false;
00188 }
00189
00190 ResetParams();
00191
00192 }
00193
00194 return true;
00195 }
00196
00197
00198 CDB_Result* CODBC_RPCCmd::Result()
00199 {
00200 enum {eNameStrLen = 64};
00201
00202 if (m_Res) {
00203 delete m_Res;
00204 m_Res = 0;
00205 m_HasMoreResults = xCheck4MoreResults();
00206 }
00207
00208 if ( !WasSent() ) {
00209 string err_message = "A command has to be sent first." + GetDbgInfo();
00210 DATABASE_DRIVER_ERROR( err_message, 420010 );
00211 }
00212
00213 if(!m_HasMoreResults) {
00214 SetWasSent(false);
00215 return 0;
00216 }
00217
00218 SQLSMALLINT nof_cols = 0;
00219 odbc::TChar buffer[eNameStrLen];
00220
00221 while(m_HasMoreResults) {
00222 CheckSIE(SQLNumResultCols(GetHandle(), &nof_cols),
00223 "SQLNumResultCols failed", 420011);
00224
00225 if(nof_cols < 1) {
00226 SQLLEN rc;
00227
00228 CheckSIE(SQLRowCount(GetHandle(), &rc),
00229 "SQLRowCount failed", 420013);
00230
00231 m_RowCount = rc;
00232 m_HasMoreResults = xCheck4MoreResults();
00233 continue;
00234 }
00235
00236 if(nof_cols == 1) {
00237 SQLSMALLINT l;
00238
00239 CheckSIE(SQLColAttribute(GetHandle(),
00240 1,
00241 SQL_DESC_LABEL,
00242 buffer,
00243 sizeof(buffer),
00244 &l,
00245 0),
00246 "SQLColAttribute failed", 420015);
00247
00248 if(util::strcmp(buffer, _T("STpROCrETURNsTATUS")) == 0) {
00249 m_HasStatus = true;
00250 m_Res = new CODBC_StatusResult(*this);
00251 }
00252 }
00253 if(!m_Res) {
00254 if(m_HasStatus) {
00255 m_HasStatus = false;
00256 m_Res = new CODBC_ParamResult(*this, nof_cols);
00257 }
00258 else {
00259 m_Res = new CODBC_RowResult(*this, nof_cols, &m_RowCount);
00260 }
00261 }
00262 return Create_Result(*m_Res);
00263 }
00264
00265 SetWasSent(false);
00266 return 0;
00267 }
00268
00269
00270 bool CODBC_RPCCmd::HasMoreResults() const
00271 {
00272 return m_HasMoreResults;
00273 }
00274
00275
00276 int CODBC_RPCCmd::RowCount() const
00277 {
00278 return static_cast<int>(m_RowCount);
00279 }
00280
00281
00282 CODBC_RPCCmd::~CODBC_RPCCmd()
00283 {
00284 try {
00285 DetachInterface();
00286
00287 GetConnection().DropCmd(*this);
00288
00289 Cancel();
00290 }
00291 NCBI_CATCH_ALL_X( 5, NCBI_CURRENT_FUNCTION )
00292 }
00293
00294
00295 bool CODBC_RPCCmd::x_AssignParams(string& cmd, string& q_exec, string& q_select,
00296 CMemPot& bind_guard, SQLLEN* indicator)
00297 {
00298 char p_nm[16];
00299
00300 bool param_named = !GetBindParamsImpl().GetParamName(0).empty();
00301
00302 for (unsigned int n = 0; n < GetBindParamsImpl().NofParams(); n++) {
00303 if(GetBindParamsImpl().GetParamStatus(n) == 0) continue;
00304 const string& name = GetBindParamsImpl().GetParamName(n);
00305 CDB_Object& param = *GetBindParamsImpl().GetParam(n);
00306
00307 if (!x_BindParam_ODBC(param, bind_guard, indicator, n)) {
00308 return false;
00309 }
00310
00311 q_exec += n ? ',':' ';
00312
00313 const string type = Type2String(param);
00314 if(!param_named) {
00315 sprintf(p_nm, "@pR%d", n);
00316 q_exec += p_nm;
00317 cmd += "declare ";
00318 cmd += p_nm;
00319 cmd += ' ';
00320 cmd += type;
00321 cmd += ";select ";
00322 cmd += p_nm;
00323 cmd += " = ?;";
00324 }
00325 else {
00326 q_exec += name+'='+name;
00327 cmd += "declare " + name + ' ' + type + ";select " + name + " = ?;";
00328 }
00329
00330 if(param.IsNULL()) {
00331 indicator[n] = SQL_NULL_DATA;
00332 }
00333
00334 if ((GetBindParamsImpl().GetParamStatus(n) & impl::CDB_Params::fOutput) != 0) {
00335 q_exec += " output";
00336 const char* p_name = param_named? name.c_str() : p_nm;
00337 if(!q_select.empty()) q_select += ',';
00338 q_select.append(p_name+1);
00339 q_select += '=';
00340 q_select += p_name;
00341 }
00342 }
00343 return true;
00344 }
00345
00346 bool CODBC_RPCCmd::xCheck4MoreResults()
00347 {
00348
00349
00350
00351
00352
00353 switch(SQLMoreResults(GetHandle())) {
00354 case SQL_SUCCESS_WITH_INFO: ReportErrors();
00355 case SQL_SUCCESS: return true;
00356 case SQL_NO_DATA: return false;
00357 case SQL_ERROR:
00358 ReportErrors();
00359 {
00360 string err_message = "SQLMoreResults failed." + GetDbgInfo();
00361 DATABASE_DRIVER_ERROR( err_message, 420014 );
00362 }
00363 default:
00364 {
00365 string err_message = "SQLMoreResults failed (memory corruption suspected)." +
00366 GetDbgInfo();
00367 DATABASE_DRIVER_ERROR( err_message, 420015 );
00368 }
00369 }
00370 }
00371
00372 END_NCBI_SCOPE
00373
00374
00375
00376