Mercurial > hg > orthanc-databases
annotate Framework/MySQL/MySQLDatabase.cpp @ 135:e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 08 May 2019 21:09:18 +0200 |
parents | 714c5d2bee76 |
children | 52b3859ee0b7 |
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 | |
67 | 5 * Copyright (C) 2017-2019 Osimis S.A., Belgium |
0 | 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" | |
23
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
27 #include "../Common/ImplicitTransaction.h" |
0 | 28 #include "../Common/Integer64Value.h" |
29 | |
30 #include <Core/Logging.h> | |
31 #include <Core/OrthancException.h> | |
32 #include <Core/Toolbox.h> | |
33 | |
6 | 34 #include <errmsg.h> |
0 | 35 #include <mysqld_error.h> |
36 | |
37 #include <memory> | |
135
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
38 #include <boost/thread.hpp> |
0 | 39 |
40 namespace OrthancDatabases | |
41 { | |
42 void MySQLDatabase::Close() | |
43 { | |
44 if (mysql_ != NULL) | |
45 { | |
46 LOG(INFO) << "Closing connection to MySQL database"; | |
47 mysql_close(mysql_); | |
48 mysql_ = NULL; | |
49 } | |
50 } | |
51 | |
52 | |
53 void MySQLDatabase::CheckErrorCode(int code) | |
54 { | |
55 if (code == 0) | |
56 { | |
57 return; | |
58 } | |
59 else | |
60 { | |
61 LogError(); | |
62 | |
63 unsigned int error = mysql_errno(mysql_); | |
64 if (error == CR_SERVER_GONE_ERROR || | |
65 error == CR_SERVER_LOST || | |
66 error == ER_QUERY_INTERRUPTED) | |
67 { | |
68 throw Orthanc::OrthancException(Orthanc::ErrorCode_DatabaseUnavailable); | |
69 } | |
70 else | |
71 { | |
72 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | |
73 } | |
74 } | |
75 } | |
76 | |
77 | |
78 MySQLDatabase::MySQLDatabase(const MySQLParameters& parameters) : | |
79 parameters_(parameters), | |
80 mysql_(NULL) | |
81 { | |
82 } | |
83 | |
84 | |
46
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
85 MySQLDatabase::~MySQLDatabase() |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
86 { |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
87 try |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
88 { |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
89 Close(); |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
90 } |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
91 catch (Orthanc::OrthancException&) |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
92 { |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
93 // Ignore possible exceptions due to connection loss |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
94 } |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
95 } |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
96 |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
97 |
0 | 98 void MySQLDatabase::LogError() |
99 { | |
100 if (mysql_ != NULL) | |
101 { | |
102 LOG(ERROR) << "MySQL error (" << mysql_errno(mysql_) | |
103 << "," << mysql_sqlstate(mysql_) | |
104 << "): " << mysql_error(mysql_); | |
105 } | |
106 } | |
107 | |
108 | |
109 MYSQL* MySQLDatabase::GetObject() | |
110 { | |
111 if (mysql_ == NULL) | |
112 { | |
113 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
114 } | |
115 else | |
116 { | |
117 return mysql_; | |
118 } | |
119 } | |
120 | |
121 | |
23
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
122 void MySQLDatabase::OpenInternal(const char* db) |
0 | 123 { |
124 if (mysql_ != NULL) | |
125 { | |
126 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
127 } | |
128 | |
129 mysql_ = mysql_init(NULL); | |
130 if (mysql_ == NULL) | |
131 { | |
132 LOG(ERROR) << "Cannot initialize the MySQL connector"; | |
133 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
134 } | |
46
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
135 |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
136 if (parameters_.GetUnixSocket().empty()) |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
137 { |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
138 // Fallback to TCP connection if no UNIX socket is provided |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
139 unsigned int protocol = MYSQL_PROTOCOL_TCP; |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
140 mysql_options(mysql_, MYSQL_OPT_PROTOCOL, (unsigned int *) &protocol); |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
24
diff
changeset
|
141 } |
0 | 142 |
143 const char* socket = (parameters_.GetUnixSocket().empty() ? NULL : | |
144 parameters_.GetUnixSocket().c_str()); | |
145 | |
146 if (mysql_real_connect(mysql_, | |
147 parameters_.GetHost().c_str(), | |
148 parameters_.GetUsername().c_str(), | |
149 parameters_.GetPassword().c_str(), db, | |
150 parameters_.GetPort(), socket, 0) == 0) | |
151 { | |
152 LogError(); | |
153 Close(); | |
154 throw Orthanc::OrthancException(Orthanc::ErrorCode_DatabaseUnavailable); | |
155 } | |
156 else | |
157 { | |
158 LOG(INFO) << "Successful connection to MySQL database"; | |
159 } | |
160 | |
161 if (mysql_set_character_set(mysql_, "utf8mb4") != 0) | |
162 { | |
163 LOG(ERROR) << "Cannot set the character set to UTF8"; | |
164 Close(); | |
165 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | |
166 } | |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
167 } |
0 | 168 |
23
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
169 |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
170 void MySQLDatabase::Open() |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
171 { |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
172 if (parameters_.GetDatabase().empty()) |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
173 { |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
174 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
175 } |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
176 else |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
177 { |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
178 OpenInternal(parameters_.GetDatabase().c_str()); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
179 } |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
180 } |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
181 |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
182 |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
183 void MySQLDatabase::ClearDatabase(const MySQLParameters& parameters) |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
184 { |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
185 MySQLDatabase db(parameters); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
186 db.OpenRoot(); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
187 |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
188 const std::string& database = parameters.GetDatabase(); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
189 |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
190 { |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
191 MySQLTransaction t(db); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
192 |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
193 if (!db.DoesDatabaseExist(t, database)) |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
194 { |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
195 LOG(ERROR) << "Inexistent database, please create it first: " << database; |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
196 throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
197 } |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
198 |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
199 db.Execute("DROP DATABASE " + database, false); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
200 db.Execute("CREATE DATABASE " + database, false); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
201 t.Commit(); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
202 } |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
203 } |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
204 |
0 | 205 |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
206 namespace |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
207 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
208 class ResultWrapper : public boost::noncopyable |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
209 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
210 private: |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
211 MYSQL_RES *result_; |
0 | 212 |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
213 public: |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
214 ResultWrapper(MySQLDatabase& mysql, |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
215 const std::string& sql) : |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
216 result_(NULL) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
217 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
218 if (mysql_real_query(mysql.GetObject(), sql.c_str(), sql.size())) |
0 | 219 { |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
220 mysql.LogError(); |
0 | 221 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); |
222 } | |
223 | |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
224 result_ = mysql_use_result(mysql.GetObject()); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
225 if (result_ == NULL) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
226 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
227 mysql.LogError(); |
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 } |
0 | 230 } |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
231 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
232 ~ResultWrapper() |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
233 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
234 if (result_ != NULL) |
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 mysql_free_result(result_); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
237 result_ = NULL; |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
238 } |
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 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
241 MYSQL_RES *GetObject() |
0 | 242 { |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
243 return result_; |
0 | 244 } |
16
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 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
247 |
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 bool MySQLDatabase::LookupGlobalStringVariable(std::string& value, |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
250 const std::string& variable) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
251 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
252 ResultWrapper result(*this, "SELECT @@global." + variable); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
253 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
254 MYSQL_ROW row = mysql_fetch_row(result.GetObject()); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
255 if (mysql_errno(mysql_) == 0 && |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
256 row && |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
257 row[0]) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
258 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
259 value = std::string(row[0]); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
260 return true; |
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 else |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
263 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
264 return false; |
0 | 265 } |
266 } | |
267 | |
268 | |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
269 bool MySQLDatabase::LookupGlobalIntegerVariable(int64_t& value, |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
270 const std::string& variable) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
271 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
272 std::string s; |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
273 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
274 if (LookupGlobalStringVariable(s, variable)) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
275 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
276 try |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
277 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
278 value = boost::lexical_cast<int64_t>(s); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
279 return true; |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
280 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
281 catch (boost::bad_lexical_cast&) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
282 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
283 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
284 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
285 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
286 else |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
287 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
288 return false; |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
289 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
290 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
291 |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
292 |
135
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
293 bool MySQLDatabase::RunAdvisoryLockStatement(const std::string& s) |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
294 { |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
295 Query query(s, false); |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
296 MySQLStatement statement(*this, query); |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
297 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
298 MySQLTransaction t(*this); |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
299 Dictionary args; |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
300 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
301 std::auto_ptr<IResult> result(t.Execute(statement, args)); |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
302 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
303 bool success = (!result->IsDone() && |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
304 result->GetField(0).GetType() == ValueType_Integer64 && |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
305 dynamic_cast<const Integer64Value&>(result->GetField(0)).GetValue() == 1); |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
306 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
307 t.Commit(); |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
308 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
309 return success; |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
310 } |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
311 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
312 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
313 bool MySQLDatabase::AcquireAdvisoryLock(int32_t lock) |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
314 { |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
315 return RunAdvisoryLockStatement("SELECT GET_LOCK('Lock" + |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
316 boost::lexical_cast<std::string>(lock) + "', 0);"); |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
317 } |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
318 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
319 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
320 bool MySQLDatabase::ReleaseAdvisoryLock(int32_t lock) |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
321 { |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
322 return RunAdvisoryLockStatement("SELECT RELEASE_LOCK('Lock" + |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
323 boost::lexical_cast<std::string>(lock) + "');"); |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
324 } |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
325 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
326 |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
327 void MySQLDatabase::AdvisoryLock(int32_t lock) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
328 { |
135
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
329 if (!AcquireAdvisoryLock(lock)) |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
330 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
331 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
|
332 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
333 } |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
334 } |
22
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 |
0 | 337 bool MySQLDatabase::DoesTableExist(MySQLTransaction& transaction, |
338 const std::string& name) | |
339 { | |
340 if (mysql_ == NULL) | |
341 { | |
342 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
343 } | |
344 | |
60
412e30336847
allowing dollars and underscores in MySQL database identifiers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
46
diff
changeset
|
345 if (!IsValidDatabaseIdentifier(name)) |
24
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
346 { |
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
347 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
348 } |
22
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
349 |
0 | 350 Query query("SELECT COUNT(*) FROM information_schema.TABLES WHERE " |
351 "(TABLE_SCHEMA = ${database}) AND (TABLE_NAME = ${table})", true); | |
352 query.SetType("database", ValueType_Utf8String); | |
353 query.SetType("table", ValueType_Utf8String); | |
354 | |
355 MySQLStatement statement(*this, query); | |
356 | |
357 Dictionary args; | |
358 args.SetUtf8Value("database", parameters_.GetDatabase()); | |
359 args.SetUtf8Value("table", name); | |
360 | |
361 std::auto_ptr<IResult> result(statement.Execute(transaction, args)); | |
362 return (!result->IsDone() && | |
363 result->GetFieldsCount() == 1 && | |
364 result->GetField(0).GetType() == ValueType_Integer64 && | |
365 dynamic_cast<const Integer64Value&>(result->GetField(0)).GetValue() == 1); | |
366 } | |
367 | |
368 | |
22
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
369 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
|
370 const std::string& name) |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
371 { |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
372 if (mysql_ == NULL) |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
373 { |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
374 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
|
375 } |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
376 |
60
412e30336847
allowing dollars and underscores in MySQL database identifiers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
46
diff
changeset
|
377 if (!IsValidDatabaseIdentifier(name)) |
24
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
378 { |
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
379 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
380 } |
22
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
381 |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
382 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
|
383 "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
|
384 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
|
385 |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
386 MySQLStatement statement(*this, query); |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
387 |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
388 Dictionary args; |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
389 args.SetUtf8Value("database", name); |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
390 |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
391 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
|
392 return (!result->IsDone() && |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
393 result->GetFieldsCount() == 1 && |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
394 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
|
395 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
|
396 } |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
397 |
1e9bad493475
prevent running unit tests on a non-existing db
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
16
diff
changeset
|
398 |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
399 void MySQLDatabase::Execute(const std::string& sql, |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
400 bool arobaseSeparator) |
0 | 401 { |
402 if (mysql_ == NULL) | |
403 { | |
404 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
405 } | |
406 | |
407 // This emulates the behavior of "CLIENT_MULTI_STATEMENTS" in | |
408 // "mysql_real_connect()", avoiding to implement a loop over | |
409 // "mysql_query()" | |
410 std::vector<std::string> commands; | |
411 Orthanc::Toolbox::TokenizeString(commands, sql, ';'); | |
412 | |
413 for (size_t i = 0; i < commands.size(); i++) | |
414 { | |
415 std::string s = Orthanc::Toolbox::StripSpaces(commands[i]); | |
416 | |
417 if (!s.empty()) | |
418 { | |
16
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
419 if (arobaseSeparator) |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
420 { |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
421 // Replace the escape character "@" by a semicolon |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
422 std::replace(s.begin(), s.end(), '@', ';'); |
9e419261f1c9
mysql storage area working
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
6
diff
changeset
|
423 } |
0 | 424 |
425 LOG(TRACE) << "MySQL: " << s; | |
426 CheckErrorCode(mysql_query(mysql_, s.c_str())); | |
427 } | |
428 } | |
429 } | |
430 | |
431 | |
432 IPrecompiledStatement* MySQLDatabase::Compile(const Query& query) | |
433 { | |
434 if (mysql_ == NULL) | |
435 { | |
436 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
437 } | |
438 | |
439 return new MySQLStatement(*this, query); | |
440 } | |
441 | |
442 | |
23
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
443 |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
444 namespace |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
445 { |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
446 class MySQLImplicitTransaction : public ImplicitTransaction |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
447 { |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
448 private: |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
449 MySQLDatabase& db_; |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
450 |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
451 protected: |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
452 virtual IResult* ExecuteInternal(IPrecompiledStatement& statement, |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
453 const Dictionary& parameters) |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
454 { |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
455 return dynamic_cast<MySQLStatement&>(statement).Execute(*this, parameters); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
456 } |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
457 |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
458 virtual void ExecuteWithoutResultInternal(IPrecompiledStatement& statement, |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
459 const Dictionary& parameters) |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
460 { |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
461 dynamic_cast<MySQLStatement&>(statement).ExecuteWithoutResult(*this, parameters); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
462 } |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
463 |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
464 public: |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
465 MySQLImplicitTransaction(MySQLDatabase& db) : |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
466 db_(db) |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
467 { |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
468 } |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
469 }; |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
470 } |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
471 |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
472 |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
473 ITransaction* MySQLDatabase::CreateTransaction(bool isImplicit) |
0 | 474 { |
475 if (mysql_ == NULL) | |
476 { | |
477 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
478 } | |
479 | |
23
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
480 if (isImplicit) |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
481 { |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
482 return new MySQLImplicitTransaction(*this); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
483 } |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
484 else |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
485 { |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
486 return new MySQLTransaction(*this); |
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
22
diff
changeset
|
487 } |
0 | 488 } |
489 | |
490 | |
491 void MySQLDatabase::GlobalFinalization() | |
492 { | |
493 mysql_library_end(); | |
494 } | |
24
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
495 |
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
496 |
60
412e30336847
allowing dollars and underscores in MySQL database identifiers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
46
diff
changeset
|
497 bool MySQLDatabase::IsValidDatabaseIdentifier(const std::string& s) |
24
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
498 { |
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
499 for (size_t i = 0; i < s.length(); i++) |
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
500 { |
60
412e30336847
allowing dollars and underscores in MySQL database identifiers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
46
diff
changeset
|
501 // https://dev.mysql.com/doc/refman/8.0/en/identifiers.html |
412e30336847
allowing dollars and underscores in MySQL database identifiers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
46
diff
changeset
|
502 if (!isalnum(s[i]) && |
412e30336847
allowing dollars and underscores in MySQL database identifiers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
46
diff
changeset
|
503 s[i] != '$' && |
412e30336847
allowing dollars and underscores in MySQL database identifiers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
46
diff
changeset
|
504 s[i] != '_') |
24
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
505 { |
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
506 return false; |
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
507 } |
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
508 } |
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
509 |
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
510 return true; |
17f849b2af34
sharing plugin initialization code
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
511 } |
135
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
512 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
513 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
514 MySQLDatabase::TransientAdvisoryLock:: |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
515 TransientAdvisoryLock(MySQLDatabase& database, |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
516 int32_t lock) : |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
517 database_(database), |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
518 lock_(lock) |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
519 { |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
520 bool locked = true; |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
521 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
522 for (unsigned int i = 0; i < 10; i++) |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
523 { |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
524 if (database_.AcquireAdvisoryLock(lock_)) |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
525 { |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
526 locked = false; |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
527 break; |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
528 } |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
529 else |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
530 { |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
531 boost::this_thread::sleep(boost::posix_time::milliseconds(500)); |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
532 } |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
533 } |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
534 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
535 if (locked) |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
536 { |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
537 LOG(ERROR) << "Cannot acquire a transient advisory lock"; |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
538 throw Orthanc::OrthancException(Orthanc::ErrorCode_Plugin); |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
539 } |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
540 } |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
541 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
542 |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
543 MySQLDatabase::TransientAdvisoryLock::~TransientAdvisoryLock() |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
544 { |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
545 database_.ReleaseAdvisoryLock(lock_); |
e26690365c25
MySQL: Added an advisory lock to avoid race conditions during database setup
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
67
diff
changeset
|
546 } |
0 | 547 } |