EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FairDbConnection.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file FairDbConnection.cxx
1 
2 #include <cctype>
3 #include <cstdlib>
4 #include <list>
5 #include <sstream>
6 #include <string>
7 
8 #include "TList.h"
9 #include "string.h"
10 #include "TSystem.h"
11 
12 #include "FairDbConnection.h"
13 
15 
17  const string& url,
18  const string& user,
19  const string& password)
20  : fDbName(),
21  fUser(user),
22  fPassword(password),
23  fExistingTableList(),
24  fNumConnectedStatements(0),
25  fUrl(url.c_str()),
26  fUrlValidated(kFALSE),
27  fIsTemporary(kTRUE),
28  fDbType(FairDb::kUnknownDbType),
29  fServer(NULL),
30  fExceptionLog()
31 {
32 // Wrapper to a DB connection
33  cout << "-I- FairDbConnection : Creating a DB connection" << endl;
34 
35  if ( this->Open() ) {
36  cout << " -I- FairDbConnection: successfully opened connection to: "
37  << this->GetUrl() << endl;
38  fUrlValidated = kTRUE;
39 
40  // Initialise the list existing supported tables.
41  this->SetTableExists();
42  string productName(fServer->GetDBMS());
43 
44  // Get the c_strbase type
45  if( productName == "MySQL" ) { fDbType = FairDb::kMySQL; }
46  else if ( productName == "Oracle" ) { fDbType = FairDb::kOracle; }
47 
48  else {
49  cout<< "-E- FairDbConnection : Cannot determine DB type from name: "
50  << productName
51  << "\nWill assuming Oracle database " << endl;
52  fDbType = FairDb::kOracle;
53  }
54 
55  if ( fUrlValidated ) {
56  if ( ! fServer->HasStatement() ) {
57  cout << "-I- FairDbConnection : This client does not support prepared statements." << endl;
58  fUrlValidated = kFALSE;
59  }
60  string serverInfo(fServer->ServerInfo());
61  if ( fDbType == FairDb::kMySQL && serverInfo < "4.1" ) {
62  cout << "-I- FairDbConnection: this MySQL server (" << serverInfo
63  << ") does not support prepared statements." << endl;
64  fUrlValidated = kFALSE;
65  }
66  if ( fUrlValidated ) {
67  cout << "-I- FairDbConnection: this client, and MySQL server ("
68  << serverInfo
69  << ") does support prepared statements." << endl;
70  } else {
71 
72  cout<< "-I- FairDbConnection "<< endl;
73  cout<< "This version of MySQL does not support prepared statements.\n"
74  << "\n"
75  << "Please upgrade to MySQL (client and server) version 4.1 or greater \n"
76  << "\n"
77  << endl;
78  }
79 
80  }
81  if ( ! fUrlValidated ) {
82  cout << "-E- FairDbConnection : Aborting due to above errors" << endl;
83  exit(1);
84  }
85  }
86  fDbName = fUrl.GetFile();
87 }
88 
89 
91 {
92 
93  cout <<"-I- FairDBConnection::~FairDbConnection() : Droping Connection"
94  <<endl;
95  this->Close(kTRUE);
96 
97 }
98 
100 {
101 
102  if ( !this->IsClosed() ) { return kTRUE;}
103 
104  Int_t maxAttempt = fUrlValidated ? 100 : 20;
105  for (Int_t attempt = 1; attempt <= maxAttempt; ++attempt) {
106  // Main Connection call
107  fServer = TSQLServer::Connect(
108  fUrl.GetUrl(),
109  fUser.c_str(),
110  fPassword.c_str());
111  if ( ! fServer ) {
112  cout << "-E- Failing to open: " <<
113  fUrl.GetUrl() << " for user "
114  << fUser << " and password "
115  << fPassword << " (attempt "
116  << attempt << ")";
117 
118  if ( attempt == 1 ) {
119  cout <<"-I- FairDBConnection: Retrying ... " << endl;
120  }
121  gSystem->Sleep(attempt*1000);
122  } else {
123  fServer->EnableErrorOutput(false);
124  if ( attempt > 1 ) {
125  cout << "-I- FairDbConnection Connection opened on attempt "
126  << attempt << endl;
127  }
128  cout << "-I- Successfully opened connection to: "
129  << fUrl.GetUrl() << endl;
130 
131  // <DB> Check me about !!!
132  // ASCII database, populate it and make the connection permanent
133  // unless even ASCII DB connections are temporary.
134  return kTRUE;
135  }
136  }
137 
138  cout << " -E- FairDbConnection: Failed to open a connection to: "
139  << fUrl.GetUrl()
140  << " for user " << fUser << " and pwd " << fPassword << endl;
141 
142  return kFALSE;
143 }
144 
145 Bool_t FairDbConnection::Close(Bool_t force)
146 {
147 
148  if ( this->IsClosed() ) { return kTRUE; }
149 
150  if ( fNumConnectedStatements ) {
151  if ( ! force ) {
152  cout<< "-I- FairDbConnection Unable to close connection: "
153  << this->GetUrl()
154  << "; it still has "
155  << fNumConnectedStatements << "active statements. " << endl;
156  return kFALSE;
157  }
158  cout << "-I- FairDbConnection : closing connection: "
159  << this->GetUrl()
160  << "; even though it still has "
161  << fNumConnectedStatements << " active statements. " << endl;
162  }
163 
164  delete fServer;
165  fServer = NULL;
166  cout << "-I- FairDbConnection: closed connection: "
167  << this->GetUrl() << endl;
168  return kTRUE;
169 }
170 
172 {
173  if ( fIsTemporary && fNumConnectedStatements == 0 ) { this->Close(); }
174 }
175 
176 
177 //.....................................................................
178 
179 TSQLStatement* FairDbConnection::CreatePreparedStatement(const string& sql)
180 {
181 
182  TSQLStatement* stmt = 0;
183  if ( ! this->Open() ) { return stmt; }
184  stmt = fServer->Statement(sql.c_str());
185  if ( ! stmt ) {
186  cout<< "-E- FairDbConnection::CreatePreparedStatement "
187  << " no Statement created " << endl;
188  } else { stmt->EnableErrorOutput(kFALSE); }
189 
190  return stmt;
191 }
192 //.....................................................................
193 
195 {
196  if ( ! this->Open() ) { return 0; }
197  return fServer;
198 }
199 
200 const string& FairDbConnection::GetUrl() const
201 {
202  static string url;
203  url = const_cast<FairDbConnection*>(this)->fUrl.GetUrl();
204  return url;
205 
206 }
207 
208 void FairDbConnection::SetTableExists(const string& tableName)
209 {
210 
211 // Add name to list of existing tables
212 // (necessary when creating tables)
213 // Note: If tableName is null refresh list from the database.
214 
215  if ( tableName == "" ) {
216  TSQLStatement* stmt = CreatePreparedStatement("show tables");
217  if ( stmt ) {
218  if (stmt->Process()) {
219  stmt->StoreResult();
220  while (stmt->NextResultRow()) {
221  string tn(stmt->GetString(0));
222  this->SetTableExists(tn);
223  }
224  }
225  delete stmt;
226  stmt = 0;
227  }
228  } else {
229  if ( ! this->TableExists(tableName) ) {
230  fExistingTableList += ",'";
231  fExistingTableList += tableName;
232  fExistingTableList += "'";
233  }
234  }
235 }
236 
237 //.....................................................................
238 
239 Bool_t FairDbConnection::TableExists(const string& tableName) const
240 {
241 //
242 // Check to see table exists in connected database.
243 
244  string test("'");
245  test += tableName;
246  test += "'";
247  return fExistingTableList.find(test) != std::string::npos;
248 }
249 
250 
251 
252 
253 Bool_t FairDbConnection::PrintExceptionLog(Int_t level) const
254 {
255  return fExceptionLog.Size() != 0;
256 }
257 
259 {
261 }
262 
263 
264