Mercurial > hg > orthanc-databases
annotate Framework/PostgreSQL/PostgreSQLStatement.cpp @ 518:e3102bad13a4
fix SDK 1.12.4 protobuf
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Thu, 06 Jun 2024 12:38:28 +0200 |
parents | 54d518dcd74a |
children | c49136b34891 |
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 | |
507
54d518dcd74a
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
460
diff
changeset
|
5 * Copyright (C) 2017-2023 Osimis S.A., Belgium |
54d518dcd74a
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
460
diff
changeset
|
6 * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium |
459
ecd0b719cff5
update year to 2024
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
389
diff
changeset
|
7 * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium |
0 | 8 * |
9 * This program is free software: you can redistribute it and/or | |
10 * modify it under the terms of the GNU Affero General Public License | |
11 * as published by the Free Software Foundation, either version 3 of | |
12 * the License, or (at your option) any later version. | |
13 * | |
14 * This program is distributed in the hope that it will be useful, but | |
15 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 * Affero General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU Affero General Public License | |
20 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 **/ | |
22 | |
23 | |
107
5765cc5fd268
reverted fix for OS X that breaks other targets
Sebastien Jodogne <s.jodogne@orthanc-labs.com>
parents:
105
diff
changeset
|
24 #include "PostgreSQLIncludes.h" // Must be the first |
105 | 25 #include "PostgreSQLStatement.h" |
0 | 26 |
27 #include "../Common/BinaryStringValue.h" | |
244
02cd7254c949
separating class InputFileValue from FileValue
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
237
diff
changeset
|
28 #include "../Common/InputFileValue.h" |
0 | 29 #include "../Common/Integer64Value.h" |
30 #include "../Common/NullValue.h" | |
31 #include "../Common/ResultBase.h" | |
32 #include "../Common/Utf8StringValue.h" | |
33 #include "PostgreSQLResult.h" | |
34 | |
157
275e14f57f1e
replacing deprecated std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
152
diff
changeset
|
35 #include <Compatibility.h> // For std::unique_ptr<> |
152 | 36 #include <Logging.h> |
37 #include <OrthancException.h> | |
38 #include <Toolbox.h> | |
39 #include <Endianness.h> | |
0 | 40 |
41 #include <cassert> | |
42 | |
43 | |
44 namespace OrthancDatabases | |
45 { | |
46 class PostgreSQLStatement::Inputs : public boost::noncopyable | |
47 { | |
48 private: | |
49 std::vector<char*> values_; | |
50 std::vector<int> sizes_; | |
51 | |
52 static char* Allocate(const void* source, int size) | |
53 { | |
54 if (size == 0) | |
55 { | |
56 return NULL; | |
57 } | |
58 else | |
59 { | |
60 char* ptr = reinterpret_cast<char*>(malloc(size)); | |
61 | |
62 if (source != NULL) | |
63 { | |
64 memcpy(ptr, source, size); | |
65 } | |
66 | |
67 return ptr; | |
68 } | |
69 } | |
70 | |
71 void Resize(size_t size) | |
72 { | |
73 // Shrinking of the vector | |
74 for (size_t i = size; i < values_.size(); i++) | |
75 { | |
76 if (values_[i] != NULL) | |
77 free(values_[i]); | |
78 } | |
79 | |
80 values_.resize(size, NULL); | |
81 sizes_.resize(size, 0); | |
82 } | |
83 | |
84 void EnlargeForIndex(size_t index) | |
85 { | |
86 if (index >= values_.size()) | |
87 { | |
88 // The vector is too small | |
89 Resize(index + 1); | |
90 } | |
91 } | |
92 | |
93 public: | |
94 Inputs() | |
95 { | |
96 } | |
97 | |
98 ~Inputs() | |
99 { | |
100 Resize(0); | |
101 } | |
102 | |
103 void SetItem(size_t pos, const void* source, int size) | |
104 { | |
105 EnlargeForIndex(pos); | |
106 | |
107 if (sizes_[pos] == size) | |
108 { | |
109 if (source && size != 0) | |
110 { | |
111 memcpy(values_[pos], source, size); | |
112 } | |
113 } | |
114 else | |
115 { | |
116 if (values_[pos] != NULL) | |
117 { | |
118 free(values_[pos]); | |
119 } | |
120 | |
121 values_[pos] = Allocate(source, size); | |
122 sizes_[pos] = size; | |
123 } | |
124 } | |
125 | |
126 void SetItem(size_t pos, int size) | |
127 { | |
128 SetItem(pos, NULL, size); | |
129 } | |
130 | |
131 void* GetItem(size_t pos) const | |
132 { | |
133 if (pos >= values_.size()) | |
134 { | |
135 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
136 } | |
137 | |
138 return values_[pos]; | |
139 } | |
140 | |
141 const std::vector<char*>& GetValues() const | |
142 { | |
143 return values_; | |
144 } | |
145 | |
146 const std::vector<int>& GetSizes() const | |
147 { | |
148 return sizes_; | |
149 } | |
150 }; | |
151 | |
152 | |
153 void PostgreSQLStatement::Prepare() | |
154 { | |
155 if (id_.size() > 0) | |
156 { | |
157 // Already prepared | |
158 return; | |
159 } | |
160 | |
161 for (size_t i = 0; i < oids_.size(); i++) | |
162 { | |
163 if (oids_[i] == 0) | |
164 { | |
165 // The type of an input parameter was not set | |
166 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
167 } | |
168 } | |
169 | |
170 id_ = Orthanc::Toolbox::GenerateUuid(); | |
171 | |
172 const unsigned int* tmp = oids_.size() ? &oids_[0] : NULL; | |
173 | |
174 PGresult* result = PQprepare(reinterpret_cast<PGconn*>(database_.pg_), | |
175 id_.c_str(), sql_.c_str(), oids_.size(), tmp); | |
176 | |
177 if (result == NULL) | |
178 { | |
179 id_.clear(); | |
180 database_.ThrowException(true); | |
181 } | |
182 | |
183 bool ok = (PQresultStatus(result) == PGRES_COMMAND_OK); | |
184 if (ok) | |
185 { | |
186 PQclear(result); | |
187 } | |
188 else | |
189 { | |
190 std::string message = PQresultErrorMessage(result); | |
191 PQclear(result); | |
192 id_.clear(); | |
193 LOG(ERROR) << "PostgreSQL error: " << message; | |
194 database_.ThrowException(false); | |
195 } | |
196 } | |
197 | |
198 | |
199 void PostgreSQLStatement::Unprepare() | |
200 { | |
201 if (id_.size() > 0) | |
202 { | |
203 // "Although there is no libpq function for deleting a | |
204 // prepared statement, the SQL DEALLOCATE statement can be | |
205 // used for that purpose." | |
237
35598014f140
refactoring to remove GlobalProperties.cpp
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
235
diff
changeset
|
206 database_.ExecuteMultiLines("DEALLOCATE \"" + id_ + "\""); |
0 | 207 } |
208 | |
209 id_.clear(); | |
210 } | |
211 | |
212 | |
213 void PostgreSQLStatement::DeclareInputInternal(unsigned int param, | |
214 unsigned int /*Oid*/ type) | |
215 { | |
216 Unprepare(); | |
217 | |
218 if (oids_.size() <= param) | |
219 { | |
220 oids_.resize(param + 1, 0); | |
221 binary_.resize(param + 1); | |
222 } | |
223 | |
224 oids_[param] = type; | |
225 binary_[param] = (type == TEXTOID || type == BYTEAOID || type == OIDOID) ? 0 : 1; | |
226 } | |
227 | |
228 | |
229 void PostgreSQLStatement::DeclareInputInteger(unsigned int param) | |
230 { | |
231 DeclareInputInternal(param, INT4OID); | |
232 } | |
233 | |
234 | |
235 void PostgreSQLStatement::DeclareInputInteger64(unsigned int param) | |
236 { | |
237 DeclareInputInternal(param, INT8OID); | |
238 } | |
239 | |
240 | |
241 void PostgreSQLStatement::DeclareInputString(unsigned int param) | |
242 { | |
243 DeclareInputInternal(param, TEXTOID); | |
244 } | |
245 | |
246 | |
247 void PostgreSQLStatement::DeclareInputBinary(unsigned int param) | |
248 { | |
249 DeclareInputInternal(param, BYTEAOID); | |
250 } | |
251 | |
252 | |
253 void PostgreSQLStatement::DeclareInputLargeObject(unsigned int param) | |
254 { | |
255 DeclareInputInternal(param, OIDOID); | |
256 } | |
257 | |
258 | |
259 void* /* PGresult* */ PostgreSQLStatement::Execute() | |
260 { | |
261 Prepare(); | |
262 | |
263 PGresult* result; | |
264 | |
265 if (oids_.size() == 0) | |
266 { | |
267 // No parameter | |
268 result = PQexecPrepared(reinterpret_cast<PGconn*>(database_.pg_), | |
269 id_.c_str(), 0, NULL, NULL, NULL, 1); | |
270 } | |
271 else | |
272 { | |
273 // At least 1 parameter | |
274 result = PQexecPrepared(reinterpret_cast<PGconn*>(database_.pg_), | |
275 id_.c_str(), | |
276 oids_.size(), | |
277 &inputs_->GetValues()[0], | |
278 &inputs_->GetSizes()[0], | |
279 &binary_[0], | |
280 1); | |
281 } | |
282 | |
234
d1b124d116c1
PostgreSQL index plugin handles retries for collisions between multiple writers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
283 if (PQtransactionStatus(reinterpret_cast<PGconn*>(database_.pg_)) == PQTRANS_INERROR) |
d1b124d116c1
PostgreSQL index plugin handles retries for collisions between multiple writers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
284 { |
d1b124d116c1
PostgreSQL index plugin handles retries for collisions between multiple writers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
285 if (result != NULL) |
d1b124d116c1
PostgreSQL index plugin handles retries for collisions between multiple writers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
286 { |
d1b124d116c1
PostgreSQL index plugin handles retries for collisions between multiple writers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
287 PQclear(result); |
d1b124d116c1
PostgreSQL index plugin handles retries for collisions between multiple writers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
288 } |
d1b124d116c1
PostgreSQL index plugin handles retries for collisions between multiple writers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
289 |
235
f2b32d31fc99
fix lsb build, fix backward compatibility with SDK <= 1.9.1
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
234
diff
changeset
|
290 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2) |
445
cec6a0cd399f
now logging DatabaseCannotSerialize as a warning only with the details (Orthanc will log it as an error after all retries)
Alain Mazy <am@osimis.io>
parents:
429
diff
changeset
|
291 std::string errorString(PQresultErrorMessage(result)); |
cec6a0cd399f
now logging DatabaseCannotSerialize as a warning only with the details (Orthanc will log it as an error after all retries)
Alain Mazy <am@osimis.io>
parents:
429
diff
changeset
|
292 throw Orthanc::OrthancException(Orthanc::ErrorCode_DatabaseCannotSerialize, errorString, false); // don't log here, it is handled at higher level |
235
f2b32d31fc99
fix lsb build, fix backward compatibility with SDK <= 1.9.1
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
234
diff
changeset
|
293 #else |
f2b32d31fc99
fix lsb build, fix backward compatibility with SDK <= 1.9.1
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
234
diff
changeset
|
294 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database, "Collision between multiple writers"); |
f2b32d31fc99
fix lsb build, fix backward compatibility with SDK <= 1.9.1
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
234
diff
changeset
|
295 #endif |
234
d1b124d116c1
PostgreSQL index plugin handles retries for collisions between multiple writers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
296 } |
d1b124d116c1
PostgreSQL index plugin handles retries for collisions between multiple writers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
214
diff
changeset
|
297 else if (result == NULL) |
0 | 298 { |
299 database_.ThrowException(true); | |
300 } | |
301 | |
302 return result; | |
303 } | |
304 | |
305 | |
306 PostgreSQLStatement::PostgreSQLStatement(PostgreSQLDatabase& database, | |
214
ab96698c73a3
removed useless information about read-only in ITransaction and IPrecompiledStatement
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
193
diff
changeset
|
307 const std::string& sql) : |
0 | 308 database_(database), |
309 sql_(sql), | |
310 inputs_(new Inputs), | |
311 formatter_(Dialect_PostgreSQL) | |
312 { | |
429
dbf811b1bb43
new configuration 'EnableVerboseLogs' to log SQL statements being executed
Alain Mazy <am@osimis.io>
parents:
389
diff
changeset
|
313 if (database.IsVerboseEnabled()) |
dbf811b1bb43
new configuration 'EnableVerboseLogs' to log SQL statements being executed
Alain Mazy <am@osimis.io>
parents:
389
diff
changeset
|
314 { |
dbf811b1bb43
new configuration 'EnableVerboseLogs' to log SQL statements being executed
Alain Mazy <am@osimis.io>
parents:
389
diff
changeset
|
315 LOG(TRACE) << "PostgreSQL: " << sql; |
dbf811b1bb43
new configuration 'EnableVerboseLogs' to log SQL statements being executed
Alain Mazy <am@osimis.io>
parents:
389
diff
changeset
|
316 } |
0 | 317 } |
318 | |
319 | |
320 PostgreSQLStatement::PostgreSQLStatement(PostgreSQLDatabase& database, | |
321 const Query& query) : | |
322 database_(database), | |
323 inputs_(new Inputs), | |
324 formatter_(Dialect_PostgreSQL) | |
325 { | |
326 query.Format(sql_, formatter_); | |
429
dbf811b1bb43
new configuration 'EnableVerboseLogs' to log SQL statements being executed
Alain Mazy <am@osimis.io>
parents:
389
diff
changeset
|
327 |
dbf811b1bb43
new configuration 'EnableVerboseLogs' to log SQL statements being executed
Alain Mazy <am@osimis.io>
parents:
389
diff
changeset
|
328 if (database.IsVerboseEnabled()) |
dbf811b1bb43
new configuration 'EnableVerboseLogs' to log SQL statements being executed
Alain Mazy <am@osimis.io>
parents:
389
diff
changeset
|
329 { |
dbf811b1bb43
new configuration 'EnableVerboseLogs' to log SQL statements being executed
Alain Mazy <am@osimis.io>
parents:
389
diff
changeset
|
330 LOG(TRACE) << "PostgreSQL: " << sql_; |
dbf811b1bb43
new configuration 'EnableVerboseLogs' to log SQL statements being executed
Alain Mazy <am@osimis.io>
parents:
389
diff
changeset
|
331 } |
0 | 332 |
333 for (size_t i = 0; i < formatter_.GetParametersCount(); i++) | |
334 { | |
335 switch (formatter_.GetParameterType(i)) | |
336 { | |
337 case ValueType_Integer64: | |
338 DeclareInputInteger64(i); | |
339 break; | |
340 | |
341 case ValueType_Utf8String: | |
342 DeclareInputString(i); | |
343 break; | |
344 | |
345 case ValueType_BinaryString: | |
346 DeclareInputBinary(i); | |
347 break; | |
348 | |
244
02cd7254c949
separating class InputFileValue from FileValue
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
237
diff
changeset
|
349 case ValueType_InputFile: |
0 | 350 DeclareInputLargeObject(i); |
351 break; | |
352 | |
353 case ValueType_Null: | |
354 default: | |
355 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
356 } | |
357 } | |
358 } | |
359 | |
360 | |
46
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
361 PostgreSQLStatement::~PostgreSQLStatement() |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
362 { |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
363 try |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
364 { |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
365 Unprepare(); |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
366 } |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
367 catch (Orthanc::OrthancException&) |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
368 { |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
369 // Ignore possible exceptions due to connection loss |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
370 } |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
371 } |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
372 |
6a574d810b98
Compatibility with MySQL 8.0
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
23
diff
changeset
|
373 |
0 | 374 void PostgreSQLStatement::Run() |
375 { | |
376 PGresult* result = reinterpret_cast<PGresult*>(Execute()); | |
377 assert(result != NULL); // An exception would have been thrown otherwise | |
378 | |
379 bool ok = (PQresultStatus(result) == PGRES_COMMAND_OK || | |
380 PQresultStatus(result) == PGRES_TUPLES_OK); | |
381 if (ok) | |
382 { | |
383 PQclear(result); | |
384 } | |
385 else | |
386 { | |
387 std::string error = PQresultErrorMessage(result); | |
388 PQclear(result); | |
389 LOG(ERROR) << "PostgreSQL error: " << error; | |
390 database_.ThrowException(false); | |
391 } | |
392 } | |
393 | |
394 | |
395 void PostgreSQLStatement::BindNull(unsigned int param) | |
396 { | |
397 if (param >= oids_.size()) | |
398 { | |
399 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
400 } | |
401 | |
402 inputs_->SetItem(param, 0); | |
403 } | |
404 | |
405 | |
406 void PostgreSQLStatement::BindInteger(unsigned int param, | |
407 int value) | |
408 { | |
409 if (param >= oids_.size()) | |
410 { | |
411 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
412 } | |
413 | |
414 if (oids_[param] != INT4OID) | |
415 { | |
416 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadParameterType); | |
417 } | |
418 | |
419 assert(sizeof(int32_t) == 4); | |
420 int32_t v = htobe32(static_cast<int32_t>(value)); | |
421 inputs_->SetItem(param, &v, sizeof(int32_t)); | |
422 } | |
423 | |
424 | |
425 void PostgreSQLStatement::BindInteger64(unsigned int param, | |
426 int64_t value) | |
427 { | |
428 if (param >= oids_.size()) | |
429 { | |
430 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
431 } | |
432 | |
433 if (oids_[param] != INT8OID) | |
434 { | |
435 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadParameterType); | |
436 } | |
437 | |
438 assert(sizeof(int64_t) == 8); | |
439 int64_t v = htobe64(value); | |
440 inputs_->SetItem(param, &v, sizeof(int64_t)); | |
441 } | |
442 | |
443 | |
444 void PostgreSQLStatement::BindString(unsigned int param, | |
445 const std::string& value) | |
446 { | |
447 if (param >= oids_.size()) | |
448 { | |
449 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
450 } | |
451 | |
452 if (oids_[param] != TEXTOID && oids_[param] != BYTEAOID) | |
453 { | |
454 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadParameterType); | |
455 } | |
456 | |
457 if (value.size() == 0) | |
458 { | |
459 inputs_->SetItem(param, "", 1 /* end-of-string character */); | |
460 } | |
461 else | |
462 { | |
463 inputs_->SetItem(param, value.c_str(), | |
464 value.size() + 1); // "+1" for end-of-string character | |
465 } | |
466 } | |
467 | |
468 | |
469 void PostgreSQLStatement::BindLargeObject(unsigned int param, | |
470 const PostgreSQLLargeObject& value) | |
471 { | |
472 if (param >= oids_.size()) | |
473 { | |
474 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
475 } | |
476 | |
477 if (oids_[param] != OIDOID) | |
478 { | |
479 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadParameterType); | |
480 } | |
481 | |
482 inputs_->SetItem(param, value.GetOid().c_str(), | |
483 value.GetOid().size() + 1); // "+1" for end-of-string character | |
484 } | |
485 | |
486 | |
487 class PostgreSQLStatement::ResultWrapper : public ResultBase | |
488 { | |
489 private: | |
157
275e14f57f1e
replacing deprecated std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
152
diff
changeset
|
490 std::unique_ptr<PostgreSQLResult> result_; |
0 | 491 |
492 protected: | |
493 virtual IValue* FetchField(size_t index) | |
494 { | |
495 return result_->GetValue(index); | |
496 } | |
497 | |
498 public: | |
186 | 499 explicit ResultWrapper(PostgreSQLStatement& statement) : |
0 | 500 result_(new PostgreSQLResult(statement)) |
501 { | |
502 SetFieldsCount(result_->GetColumnsCount()); | |
503 FetchFields(); | |
504 } | |
505 | |
506 virtual void Next() | |
507 { | |
508 result_->Next(); | |
509 FetchFields(); | |
510 } | |
511 | |
512 virtual bool IsDone() const | |
513 { | |
514 return result_->IsDone(); | |
515 } | |
516 }; | |
517 | |
518 | |
23
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
519 IResult* PostgreSQLStatement::Execute(ITransaction& transaction, |
0 | 520 const Dictionary& parameters) |
521 { | |
522 for (size_t i = 0; i < formatter_.GetParametersCount(); i++) | |
523 { | |
524 const std::string& name = formatter_.GetParameterName(i); | |
525 | |
526 switch (formatter_.GetParameterType(i)) | |
527 { | |
528 case ValueType_Integer64: | |
529 BindInteger64(i, dynamic_cast<const Integer64Value&>(parameters.GetValue(name)).GetValue()); | |
530 break; | |
531 | |
532 case ValueType_Null: | |
533 BindNull(i); | |
534 break; | |
535 | |
536 case ValueType_Utf8String: | |
537 BindString(i, dynamic_cast<const Utf8StringValue&> | |
538 (parameters.GetValue(name)).GetContent()); | |
539 break; | |
540 | |
541 case ValueType_BinaryString: | |
542 BindString(i, dynamic_cast<const BinaryStringValue&> | |
543 (parameters.GetValue(name)).GetContent()); | |
544 break; | |
545 | |
244
02cd7254c949
separating class InputFileValue from FileValue
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
237
diff
changeset
|
546 case ValueType_InputFile: |
0 | 547 { |
244
02cd7254c949
separating class InputFileValue from FileValue
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
237
diff
changeset
|
548 const InputFileValue& blob = |
02cd7254c949
separating class InputFileValue from FileValue
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
237
diff
changeset
|
549 dynamic_cast<const InputFileValue&>(parameters.GetValue(name)); |
0 | 550 |
551 PostgreSQLLargeObject largeObject(database_, blob.GetContent()); | |
552 BindLargeObject(i, largeObject); | |
553 break; | |
554 } | |
555 | |
556 default: | |
557 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
558 } | |
559 } | |
560 | |
561 return new ResultWrapper(*this); | |
562 } | |
563 | |
564 | |
23
b2ff1cd2907a
handling of implicit transactions in DatabaseManager
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
565 void PostgreSQLStatement::ExecuteWithoutResult(ITransaction& transaction, |
0 | 566 const Dictionary& parameters) |
567 { | |
157
275e14f57f1e
replacing deprecated std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
152
diff
changeset
|
568 std::unique_ptr<IResult> dummy(Execute(transaction, parameters)); |
0 | 569 } |
570 } |