00001
00005
00006
00007 #include <iostream>
00008 #include <sstream>
00009 #include <string>
00010 #include <vector>
00011
00012 #include "TString.h"
00013
00014 #include "DatabaseInterface/DbiStatement.h"
00015 #include "DatabaseInterface/DbiTableMetaData.h"
00016 #include "LeakChecker/Lea.h"
00017 #include "MessageService/MsgService.h"
00018 #include "Util/UtilString.h"
00019
00020 ClassImp(DbiStatement)
00021
00022
00023
00024
00025
00026 CVSID("$Id: DbiStatement.cxx,v 1.37 2007/07/05 09:26:34 west Exp $");
00027
00028
00029
00030
00031
00032
00033
00034
00035 DbiStatement::DbiStatement(DbiConnection& conDb) :
00036 fConDb(conDb),
00037 fDbType(conDb.GetDbType())
00038 {
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 LEA_CTOR
00051
00052 MSG("Dbi", Msg::kVerbose) << "Creating DbiStatement" << endl;
00053 fConDb.ConnectStatement();
00054
00055 }
00056
00057
00058
00059 DbiStatement::~DbiStatement() {
00060
00061
00062
00063
00064 LEA_DTOR
00065 MSG("Dbi", Msg::kVerbose) << "Destroying DbiStatement" << endl;
00066
00067 fConDb.DisConnectStatement();
00068 }
00069
00070
00071
00072 TSQLStatement* DbiStatement::CreateProcessedStatement(const TString& sql ) {
00073
00074
00075
00076 TSQLStatement* stmt = fConDb.CreatePreparedStatement(sql.Data());
00077 if ( ! stmt ) {
00078 this->AppendExceptionLog(fConDb);
00079 return 0;
00080 }
00081 if ( stmt->Process() ) return stmt;
00082 this->AppendExceptionLog(stmt);
00083 delete stmt;
00084 stmt = 0;
00085 return 0;
00086
00087 }
00088
00089
00090
00091
00092 TSQLStatement* DbiStatement::ExecuteQuery( const TString& sql) {
00093
00094
00095
00096
00097
00098 this->ClearExceptionLog();
00099
00100 std::list<TString> sqlList(this->TranslateSQL(sql));
00101 std::list<TString>::const_iterator itr(sqlList.begin()), itrEnd(sqlList.end());
00102
00103 TSQLStatement* stmt = 0;
00104 while (itr != itrEnd) {
00105 const TString& sql = *itr++;
00106 MSG("Dbi",Msg::kSynopsis) << "SQL:" << fConDb.GetDbName() << ":" << sql << endl;
00107 delete stmt;
00108 stmt = this->CreateProcessedStatement(sql);
00109 if ( ! stmt ) return 0;
00110 }
00111
00112
00113 if ( stmt && ! stmt->StoreResult() ) {
00114 this->AppendExceptionLog(stmt);
00115 delete stmt;
00116 stmt = 0;
00117 }
00118
00119
00120
00121 if ( stmt ) {
00122 if ( ! fExceptionLog.IsEmpty() ) {
00123 delete stmt;
00124 stmt = 0;
00125 }
00126 }
00127 else if ( fExceptionLog.IsEmpty() ) {
00128 ostringstream oss;
00129 oss << "Unknown failure (no execption but no TSQLStatement either executing " << sql;
00130 fExceptionLog.AddEntry(oss.str().c_str());
00131 }
00132 return stmt;
00133
00134 }
00135
00136
00137
00138 Bool_t DbiStatement::ExecuteUpdate( const TString& sql) {
00139
00140
00141
00142
00143
00144
00145
00146 this->ClearExceptionLog();
00147
00148 std::list<TString> sqlList(this->TranslateSQL(sql));
00149 std::list<TString>::const_iterator itr(sqlList.begin()), itrEnd(sqlList.end());
00150
00151 while (itr != itrEnd) {
00152 const TString& sql = *itr++;
00153 MSG("Dbi",Msg::kSynopsis) << "SQL:" << fConDb.GetDbName() << ":" << sql << endl;
00154 bool ok = fConDb.GetServer()->Exec(sql.Data());
00155 if ( ! ok ) {
00156 fConDb.RecordException();
00157 this->AppendExceptionLog(fConDb);
00158 return false;
00159 }
00160 }
00161 return fExceptionLog.IsEmpty();
00162
00163 }
00164
00165
00166
00167 Bool_t DbiStatement::PrintExceptions(Int_t level) const {
00168
00169
00170
00171
00172
00173 const DbiExceptionLog& el(this->GetExceptionLog());
00174 if ( el.IsEmpty() ) return false;
00175 MSG("Dbi", level) << el;
00176 if ( level >= Msg::kWarning ) DbiExceptionLog::GetGELog().AddLog(el);
00177 return true;
00178
00179 }
00180
00181
00182
00183 std::list<TString> DbiStatement::TestTranslateSQL(const TString& sql, Dbi::DbTypes type) {
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 Dbi::DbTypes fDbTypeSave = fDbType;
00196 fDbType = type;
00197 std::list<TString> sqlTrans(this->TranslateSQL(sql));
00198 fDbType = fDbTypeSave;
00199 return sqlTrans;
00200
00201 }
00202
00203
00204
00205 std::list<TString> DbiStatement::TranslateSQL(const TString& sql) {
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 std::list<TString> sqlTransList;
00253
00254 if ( fDbType != Dbi::kOracle ) {
00255 sqlTransList.push_back(sql);
00256 return sqlTransList;
00257 }
00258
00259 Bool_t translated = false;
00260 Bool_t modified = false;
00261
00262 TString sqlTrans(sql);
00263 sqlTrans.ToUpper();
00264
00265
00266 sqlTransList.push_back("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD hh24:mi:ss'");
00267
00268
00269 if ( sqlTrans.Index("NOW()") != kNPOS ) {
00270 sqlTrans.ReplaceAll("NOW()","SYSDATE");
00271 modified = true;
00272 }
00273
00274
00275 if (sqlTrans == "SHOW TABLES" ) {
00276 sqlTrans = "SELECT TABLE_NAME FROM ALL_TABLES";
00277 sqlTransList.push_back(sqlTrans);
00278 translated = true;
00279 }
00280
00281 TString sqlIncant;
00282
00283
00284 Ssiz_t createTableIndex = sqlTrans.Index("CREATE TABLE",0,TString::kIgnoreCase );
00285 if ( ! translated && createTableIndex != kNPOS ) {
00286 DbiTableMetaData tmd;
00287 tmd.SetFromSql(sql.Data());
00288 std::vector<std::string> sql_list;
00289 UtilString::StringTok(sql_list,tmd.Sql(Dbi::kOracle),";");
00290 std::vector<std::string>::const_iterator itr(sql_list.begin()), itrEnd(sql_list.end());
00291 while ( itr != itrEnd ) {
00292 sqlTransList.push_back(*itr);
00293 ++itr;
00294 }
00295 translated = true;
00296 }
00297
00298
00299
00300 Ssiz_t dropTableIndex = sqlTrans.Index("DROP TABLE",0,TString::kIgnoreCase );
00301 if ( ! translated && dropTableIndex != kNPOS ) {
00302
00303 sqlTrans.ReplaceAll(" IF EXISTS ", " ");
00304
00305
00306 sqlTransList.push_back(sqlTrans);
00307
00308
00309 Ssiz_t startIndex = dropTableIndex + 10;
00310 while ( isspace(sqlTrans[startIndex]) ) ++startIndex;
00311 Ssiz_t endIndex = startIndex + 1;
00312 Ssiz_t endIndexMax = sqlTrans.Length();
00313 while ( endIndex < endIndexMax
00314 && (isalnum(sqlTrans[endIndex]) || sqlTrans[endIndex] == '_')
00315 ) ++endIndex;
00316 TString name(sqlTrans.Data()+startIndex,endIndex-startIndex);
00317 translated = true;
00318
00319
00320
00321 TString sqlIncant("DROP PUBLIC SYNONYM ");
00322 sqlIncant += name ;
00323 sqlTransList.push_back(sqlIncant);
00324 }
00325
00326
00327
00328 Ssiz_t whereStart = sqlTrans.Index("INSERT INTO",0,TString::kIgnoreCase );
00329 if ( whereStart == kNPOS ) whereStart = 0;
00330 else {
00331
00332
00333
00334
00335 Ssiz_t whereStartMax = sqlTrans.Length();
00336 whereStart = sqlTrans.Index("(",whereStart,TString::kIgnoreCase );
00337 if ( whereStart == kNPOS ) whereStart = whereStartMax;
00338 else ++whereStart;
00339 int level = 1;
00340 while ( whereStart < whereStartMax && level ) {
00341 char chr = sqlTrans[whereStart++];
00342 if ( chr == '(' ) ++level;
00343 if ( chr == ')' ) --level;
00344 }
00345 }
00346
00347 Ssiz_t whereIndex = sqlTrans.Index(" WHERE ",whereStart,TString::kIgnoreCase );
00348 if ( ! translated && whereIndex != kNPOS ) {
00349
00350
00351 ++whereIndex;
00352 Ssiz_t whereEnd = sqlTrans.Length();
00353 std::string whereDelim[] = { "GROUP BY", "HAVING", "ORDER BY", "LIMIT" };
00354 int numDelims = sizeof(whereDelim)/sizeof(string);
00355 for (int iDelim = 0; iDelim < numDelims; ++iDelim ) {
00356 const string& delimName = whereDelim[iDelim];
00357 Ssiz_t delimIndex = sqlTrans.Index(delimName.c_str(), delimName.size(), whereIndex + 5, TString::kIgnoreCase );
00358 if (delimIndex != kNPOS && delimIndex < whereEnd) whereEnd = delimIndex;
00359 }
00360
00361
00362
00363 TString whereClause(sql.Data()+whereIndex,whereEnd-whereIndex);
00364
00365 whereClause.ReplaceAll("\n"," ");
00366
00367 std::vector<std::string> tokens;
00368 UtilString::StringTok(tokens,whereClause.Data()," ");
00369 int numTokens = tokens.size();
00370 for (int ithToken = 1; ithToken < numTokens-1; ++ithToken ) {
00371 if ( tokens[ithToken] == "&" ) {
00372 string tmp("bitand(");
00373 tmp += tokens[ithToken-1] + "," + tokens[ithToken+1] + ") != 0";
00374 tokens[ithToken] = tmp;
00375 tokens[ithToken-1] = "";
00376 tokens[ithToken+1] = "";
00377 }
00378 }
00379
00380 sqlTrans = sql(0,whereIndex);
00381 for (int ithToken = 0; ithToken < numTokens; ++ithToken ) {
00382 sqlTrans += " ";
00383 sqlTrans += tokens[ithToken].c_str();
00384 }
00385 sqlTrans += " " + sql(whereEnd,999999);
00386 modified = true;
00387 }
00388
00389
00390 if ( ! translated && sqlTrans.Index("\\\'") != kNPOS ) {
00391
00392
00393 if ( not modified ) sqlTrans = sql;
00394 sqlTrans.ReplaceAll("\\\'","\'\'");
00395 modified = true;
00396 }
00397
00398 if ( modified && ! translated ) {
00399 sqlTransList.push_back(sqlTrans);
00400 translated = true;
00401 }
00402
00403 if ( translated ) {
00404 MSG("Dbi",Msg::kSynopsis) << "sql: " << sql << endl
00405 << "translates to " << sqlTransList.size()
00406 << " statements:- \n";
00407 std::list<TString>::const_iterator itr(sqlTransList.begin()), itrEnd(sqlTransList.end());
00408 while (itr != itrEnd) { MSG("Dbi",Msg::kSynopsis) << " " << *itr << endl; ++itr;}
00409 }
00410 else {
00411 sqlTransList.push_back(sql);
00412 }
00413
00414 return sqlTransList;
00415
00416 }
00417