Mercurial > hg > orthanc-databases
annotate Framework/MySQL/MySQLDatabase.cpp @ 22:1e9bad493475
prevent running unit tests on a non-existing db
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 11 Jul 2018 14:39:59 +0200 |
parents | 9e419261f1c9 |
children | b2ff1cd2907a |
rev | line source |
---|---|
0 | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2018 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
21 | |
22 #include "MySQLDatabase.h" | |
23 | |
24 #include "MySQLResult.h" | |
25 #include "MySQLStatement.h" | |
26 #include "MySQLTransaction.h" | |
27 #include "../Common/Integer64Value.h" | |
28 | |
29 #include <Core/Logging.h> | |
30 #include <Core/OrthancException.h> | |
31 #include <Core/Toolbox.h> | |
32 | |
6 | 33 #include <errmsg.h> |
0 | 34 #include <mysqld_error.h> |
35 | |
36 #include <memory> | |
37 | |
38 namespace OrthancDatabases | |
39 { | |
40 void MySQLDatabase::Close() | |
41 { | |
42 if (mysql_ != NULL) | |
43 { | |
44 LOG(INFO) << "Closing connection to MySQL database"; | |
45 mysql_close(mysql_); | |
46 mysql_ = NULL; | |
47 } | |
48 } | |
49 | |
50 | |
51 void MySQLDatabase::CheckErrorCode(int code) | |
52 { | |
53 if (code == 0) | |
54 { | |
55 return; | |
56 } | |
57 else | |
58 { | |
59 LogError(); | |
60 | |
61 unsigned int error = mysql_errno(mysql_); | |
62 if (error == CR_SERVER_GONE_ERROR || | |
63 error == CR_SERVER_LOST || | |
64 error == ER_QUERY_INTERRUPTED) | |
65 { | |
66 throw Orthanc::OrthancException(Orthanc::ErrorCode_DatabaseUnavailable); | |
67 } | |
68 else | |
69 { | |
70 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | |
71 } | |
72 } | |
73 } | |
74 | |
75 | |
76 MySQLDatabase::MySQLDatabase(const MySQLParameters& parameters) : | |
77 parameters_(parameters), | |
78 mysql_(NULL) | |
79 { | |
80 } | |
81 | |
82 | |
83 void MySQLDatabase::LogError() | |
84 { | |
85 if (mysql_ != NULL) | |
86 { | |
87 LOG(ERROR) << "MySQL error (" << mysql_errno(mysql_) | |
88 << "," << mysql_sqlstate(mysql_) | |
89 << "): " << mysql_error(mysql_); | |
90 } | |
91 } | |
92 | |
93 | |
94 MYSQL* MySQLDatabase::GetObject() | |
95 { | |
96 if (mysql_ == NULL) | |
97 { | |
98 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
99 } | |
100 else | |
101 { | |
102 return mysql_; | |
103 } | |
104 } | |
105 | |
106 | |
107 void MySQLDatabase::Open() | |
108 { | |
109 if (mysql_ != NULL) | |
110 { | |
111 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
112 } | |
113 | |
114 mysql_ = mysql_init(NULL); | |
115 if (mysql_ == NULL) | |
116 { | |
117 LOG(ERROR) << "Cannot initialize the MySQL connector"; | |
118 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
119 } | |
120 | |
121 const char* db = (parameters_.GetDatabase().empty() ? NULL : | |
122 parameters_.GetDatabase().c_str()); | |
123 | |
124 const char* socket = (parameters_.GetUnixSocket().empty() ? NULL : | |
125 parameters_.GetUnixSocket().c_str()); | |
126 | |
127 if (mysql_real_connect(mysql_, | |
128 parameters_.GetHost().c_str(), | |
129 parameters_.GetUsername().c_str(), | |
130 parameters_.GetPassword().c_str(), db, | |
131 parameters_.GetPort(), socket, 0) == 0) | |
132 { | |
133 LogError(); | |
134 Close(); | |
135 throw Orthanc::OrthancException(Orthanc::ErrorCode_DatabaseUnavailable); | |
136 } | |
137 else | |
138 { | |
139 LOG(INFO) << "Successful connection to MySQL database"; | |
140 } | |
141 | |
142 if (mysql_set_character_set(mysql_, "utf8mb4") != 0) | |
143 { | |
144 LOG(ERROR) << "Cannot set the character set to UTF8"; | |
145 Close(); | |
146 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | |
147 } | |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
148 } |
0 | 149 |
150 | |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
151 namespace |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
152 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
153 class ResultWrapper : public boost::noncopyable |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
154 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
155 private: |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
156 MYSQL_RES *result_; |
0 | 157 |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
158 public: |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
159 ResultWrapper(MySQLDatabase& mysql, |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
160 const std::string& sql) : |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
161 result_(NULL) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
162 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
163 if (mysql_real_query(mysql.GetObject(), sql.c_str(), sql.size())) |
0 | 164 { |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
165 mysql.LogError(); |
0 | 166 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); |
167 } | |
168 | |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
169 result_ = mysql_use_result(mysql.GetObject()); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
170 if (result_ == NULL) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
171 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
172 mysql.LogError(); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
173 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
174 } |
0 | 175 } |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
176 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
177 ~ResultWrapper() |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
178 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
179 if (result_ != NULL) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
180 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
181 mysql_free_result(result_); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
182 result_ = NULL; |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
183 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
184 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
185 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
186 MYSQL_RES *GetObject() |
0 | 187 { |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
188 return result_; |
0 | 189 } |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
190 }; |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
191 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
192 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
193 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
194 bool MySQLDatabase::LookupGlobalStringVariable(std::string& value, |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
195 const std::string& variable) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
196 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
197 ResultWrapper result(*this, "SELECT @@global." + variable); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
198 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
199 MYSQL_ROW row = mysql_fetch_row(result.GetObject()); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
200 if (mysql_errno(mysql_) == 0 && |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
201 row && |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
202 row[0]) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
203 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
204 value = std::string(row[0]); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
205 return true; |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
206 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
207 else |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
208 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
209 return false; |
0 | 210 } |
211 } | |
212 | |
213 | |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
214 bool MySQLDatabase::LookupGlobalIntegerVariable(int64_t& value, |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
215 const std::string& variable) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
216 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
217 std::string s; |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
218 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
219 if (LookupGlobalStringVariable(s, variable)) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
220 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
221 try |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
222 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
223 value = boost::lexical_cast<int64_t>(s); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
224 return true; |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
225 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
226 catch (boost::bad_lexical_cast&) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
227 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
228 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
229 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
230 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
231 else |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
232 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
233 return false; |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
234 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
235 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
236 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
237 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
238 void MySQLDatabase::AdvisoryLock(int32_t lock) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
239 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
240 try |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
241 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
242 Query query("SELECT GET_LOCK('Lock" + |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
243 boost::lexical_cast<std::string>(lock) + "', 0);", false); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
244 MySQLStatement statement(*this, query); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
245 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
246 MySQLTransaction t(*this); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
247 Dictionary args; |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
248 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
249 std::auto_ptr<IResult> result(t.Execute(statement, args)); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
250 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
251 if (result->IsDone() || |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
252 result->GetField(0).GetType() != ValueType_Integer64 || |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
253 dynamic_cast<const Integer64Value&>(result->GetField(0)).GetValue() != 1) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
254 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
255 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
256 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
257 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
258 t.Commit(); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
259 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
260 catch (Orthanc::OrthancException&) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
261 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
262 LOG(ERROR) << "The MySQL database is locked by another instance of Orthanc"; |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
263 Close(); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
264 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
265 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
266 } |
22
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
267 |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
268 |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
269 static void CheckAlphanumericString(const std::string& name) |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
270 { |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
271 for (size_t i = 0; i < name.length(); i++) |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
272 { |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
273 if (!isalnum(name[i])) |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
274 { |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
275 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
276 } |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
277 } |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
278 } |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
279 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
280 |
0 | 281 bool MySQLDatabase::DoesTableExist(MySQLTransaction& transaction, |
282 const std::string& name) | |
283 { | |
284 if (mysql_ == NULL) | |
285 { | |
286 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
287 } | |
288 | |
22
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
289 CheckAlphanumericString(name); |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
290 |
0 | 291 Query query("SELECT COUNT(*) FROM information_schema.TABLES WHERE " |
292 "(TABLE_SCHEMA = ${database}) AND (TABLE_NAME = ${table})", true); | |
293 query.SetType("database", ValueType_Utf8String); | |
294 query.SetType("table", ValueType_Utf8String); | |
295 | |
296 MySQLStatement statement(*this, query); | |
297 | |
298 Dictionary args; | |
299 args.SetUtf8Value("database", parameters_.GetDatabase()); | |
300 args.SetUtf8Value("table", name); | |
301 | |
302 std::auto_ptr<IResult> result(statement.Execute(transaction, args)); | |
303 return (!result->IsDone() && | |
304 result->GetFieldsCount() == 1 && | |
305 result->GetField(0).GetType() == ValueType_Integer64 && | |
306 dynamic_cast<const Integer64Value&>(result->GetField(0)).GetValue() == 1); | |
307 } | |
308 | |
309 | |
22
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
310 bool MySQLDatabase::DoesDatabaseExist(MySQLTransaction& transaction, |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
311 const std::string& name) |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
312 { |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
313 if (mysql_ == NULL) |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
314 { |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
315 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
316 } |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
317 |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
318 CheckAlphanumericString(name); |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
319 |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
320 Query query("SELECT COUNT(*) FROM information_schema.SCHEMATA " |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
321 "WHERE SCHEMA_NAME = ${database}", true); |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
322 query.SetType("database", ValueType_Utf8String); |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
323 |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
324 MySQLStatement statement(*this, query); |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
325 |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
326 Dictionary args; |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
327 args.SetUtf8Value("database", name); |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
328 |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
329 std::auto_ptr<IResult> result(statement.Execute(transaction, args)); |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
330 return (!result->IsDone() && |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
331 result->GetFieldsCount() == 1 && |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
332 result->GetField(0).GetType() == ValueType_Integer64 && |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
333 dynamic_cast<const Integer64Value&>(result->GetField(0)).GetValue() == 1); |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
334 } |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
335 |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
336 |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
337 void MySQLDatabase::Execute(const std::string& sql, |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
338 bool arobaseSeparator) |
0 | 339 { |
340 if (mysql_ == NULL) | |
341 { | |
342 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
343 } | |
344 | |
345 // This emulates the behavior of "CLIENT_MULTI_STATEMENTS" in | |
346 // "mysql_real_connect()", avoiding to implement a loop over | |
347 // "mysql_query()" | |
348 std::vector<std::string> commands; | |
349 Orthanc::Toolbox::TokenizeString(commands, sql, ';'); | |
350 | |
351 for (size_t i = 0; i < commands.size(); i++) | |
352 { | |
353 std::string s = Orthanc::Toolbox::StripSpaces(commands[i]); | |
354 | |
355 if (!s.empty()) | |
356 { | |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
357 if (arobaseSeparator) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
358 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
359 // Replace the escape character "@" by a semicolon |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
360 std::replace(s.begin(), s.end(), '@', ';'); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
361 } |
0 | 362 |
363 LOG(TRACE) << "MySQL: " << s; | |
364 CheckErrorCode(mysql_query(mysql_, s.c_str())); | |
365 } | |
366 } | |
367 } | |
368 | |
369 | |
370 IPrecompiledStatement* MySQLDatabase::Compile(const Query& query) | |
371 { | |
372 if (mysql_ == NULL) | |
373 { | |
374 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
375 } | |
376 | |
377 return new MySQLStatement(*this, query); | |
378 } | |
379 | |
380 | |
381 ITransaction* MySQLDatabase::CreateTransaction() | |
382 { | |
383 if (mysql_ == NULL) | |
384 { | |
385 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
386 } | |
387 | |
388 return new MySQLTransaction(*this); | |
389 } | |
390 | |
391 | |
392 void MySQLDatabase::GlobalFinalization() | |
393 { | |
394 mysql_library_end(); | |
395 } | |
396 } |