Mercurial > hg > orthanc-databases
annotate Framework/Plugins/IndexBackend.cpp @ 65:aa2e27f77cc8
todo
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 21 Dec 2018 17:11:33 +0100 |
parents | d17b2631bb67 |
children | 714c5d2bee76 |
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 "IndexBackend.h" | |
23 | |
24 #include "../Common/BinaryStringValue.h" | |
25 #include "../Common/Integer64Value.h" | |
26 #include "../Common/Utf8StringValue.h" | |
27 #include "GlobalProperties.h" | |
28 | |
29 #include <Core/Logging.h> | |
30 #include <Core/OrthancException.h> | |
31 #include <OrthancServer/ServerEnumerations.h> | |
32 | |
33 | |
34 namespace OrthancDatabases | |
35 { | |
36 static std::string ConvertWildcardToLike(const std::string& query) | |
37 { | |
38 std::string s = query; | |
39 | |
40 for (size_t i = 0; i < s.size(); i++) | |
41 { | |
42 if (s[i] == '*') | |
43 { | |
44 s[i] = '%'; | |
45 } | |
46 else if (s[i] == '?') | |
47 { | |
48 s[i] = '_'; | |
49 } | |
50 } | |
51 | |
65 | 52 // TODO Escape underscores and percents |
53 | |
0 | 54 return s; |
55 } | |
56 | |
57 | |
58 int64_t IndexBackend::ReadInteger64(const DatabaseManager::CachedStatement& statement, | |
59 size_t field) | |
60 { | |
61 if (statement.IsDone()) | |
62 { | |
63 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | |
64 } | |
65 | |
66 const IValue& value = statement.GetResultField(field); | |
67 | |
68 switch (value.GetType()) | |
69 { | |
70 case ValueType_Integer64: | |
71 return dynamic_cast<const Integer64Value&>(value).GetValue(); | |
72 | |
73 default: | |
74 //LOG(ERROR) << value.Format(); | |
75 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
76 } | |
77 } | |
78 | |
79 | |
80 int32_t IndexBackend::ReadInteger32(const DatabaseManager::CachedStatement& statement, | |
81 size_t field) | |
82 { | |
83 if (statement.IsDone()) | |
84 { | |
85 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | |
86 } | |
87 | |
88 int64_t value = ReadInteger64(statement, field); | |
89 | |
90 if (value != static_cast<int64_t>(static_cast<int32_t>(value))) | |
91 { | |
92 LOG(ERROR) << "Integer overflow"; | |
93 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
94 } | |
95 else | |
96 { | |
97 return static_cast<int32_t>(value); | |
98 } | |
99 } | |
100 | |
101 | |
102 std::string IndexBackend::ReadString(const DatabaseManager::CachedStatement& statement, | |
103 size_t field) | |
104 { | |
105 const IValue& value = statement.GetResultField(field); | |
106 | |
107 switch (value.GetType()) | |
108 { | |
109 case ValueType_BinaryString: | |
110 return dynamic_cast<const BinaryStringValue&>(value).GetContent(); | |
111 | |
112 case ValueType_Utf8String: | |
113 return dynamic_cast<const Utf8StringValue&>(value).GetContent(); | |
114 | |
115 default: | |
116 //LOG(ERROR) << value.Format(); | |
117 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
118 } | |
119 } | |
120 | |
121 | |
122 template <typename T> | |
123 void IndexBackend::ReadListOfIntegers(std::list<T>& target, | |
124 DatabaseManager::CachedStatement& statement, | |
125 const Dictionary& args) | |
126 { | |
127 statement.Execute(args); | |
128 | |
129 target.clear(); | |
130 | |
131 if (!statement.IsDone()) | |
132 { | |
133 if (statement.GetResultFieldsCount() != 1) | |
134 { | |
135 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
136 } | |
137 | |
138 statement.SetResultFieldType(0, ValueType_Integer64); | |
139 | |
140 while (!statement.IsDone()) | |
141 { | |
142 target.push_back(static_cast<T>(ReadInteger64(statement, 0))); | |
143 statement.Next(); | |
144 } | |
145 } | |
146 } | |
147 | |
148 | |
149 void IndexBackend::ReadListOfStrings(std::list<std::string>& target, | |
150 DatabaseManager::CachedStatement& statement, | |
151 const Dictionary& args) | |
152 { | |
153 statement.Execute(args); | |
154 | |
155 target.clear(); | |
156 | |
157 if (!statement.IsDone()) | |
158 { | |
159 if (statement.GetResultFieldsCount() != 1) | |
160 { | |
161 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
162 } | |
163 | |
164 while (!statement.IsDone()) | |
165 { | |
166 target.push_back(ReadString(statement, 0)); | |
167 statement.Next(); | |
168 } | |
169 } | |
170 } | |
171 | |
172 | |
173 void IndexBackend::ReadChangesInternal(bool& done, | |
174 DatabaseManager::CachedStatement& statement, | |
175 const Dictionary& args, | |
176 uint32_t maxResults) | |
177 { | |
178 statement.Execute(args); | |
179 | |
180 uint32_t count = 0; | |
181 | |
182 while (count < maxResults && | |
183 !statement.IsDone()) | |
184 { | |
185 GetOutput().AnswerChange( | |
186 ReadInteger64(statement, 0), | |
187 ReadInteger32(statement, 1), | |
188 static_cast<OrthancPluginResourceType>(ReadInteger32(statement, 3)), | |
189 GetPublicId(ReadInteger64(statement, 2)), | |
190 ReadString(statement, 4)); | |
191 | |
192 statement.Next(); | |
193 count++; | |
194 } | |
195 | |
196 done = (count < maxResults || | |
197 statement.IsDone()); | |
198 } | |
199 | |
200 | |
201 void IndexBackend::ReadExportedResourcesInternal(bool& done, | |
202 DatabaseManager::CachedStatement& statement, | |
203 const Dictionary& args, | |
204 uint32_t maxResults) | |
205 { | |
206 statement.Execute(args); | |
207 | |
208 uint32_t count = 0; | |
209 | |
210 while (count < maxResults && | |
211 !statement.IsDone()) | |
212 { | |
213 int64_t seq = ReadInteger64(statement, 0); | |
214 OrthancPluginResourceType resourceType = | |
215 static_cast<OrthancPluginResourceType>(ReadInteger32(statement, 1)); | |
216 std::string publicId = ReadString(statement, 2); | |
217 | |
218 GetOutput().AnswerExportedResource(seq, | |
219 resourceType, | |
220 publicId, | |
221 ReadString(statement, 3), // modality | |
222 ReadString(statement, 8), // date | |
223 ReadString(statement, 4), // patient ID | |
224 ReadString(statement, 5), // study instance UID | |
225 ReadString(statement, 6), // series instance UID | |
226 ReadString(statement, 7)); // sop instance UID | |
227 | |
228 statement.Next(); | |
229 count++; | |
230 } | |
231 | |
232 done = (count < maxResults || | |
233 statement.IsDone()); | |
234 } | |
235 | |
236 | |
237 void IndexBackend::ClearDeletedFiles() | |
238 { | |
239 DatabaseManager::CachedStatement statement( | |
240 STATEMENT_FROM_HERE, manager_, | |
241 "DELETE FROM DeletedFiles"); | |
242 | |
243 statement.Execute(); | |
244 } | |
245 | |
246 | |
247 void IndexBackend::ClearDeletedResources() | |
248 { | |
249 DatabaseManager::CachedStatement statement( | |
250 STATEMENT_FROM_HERE, manager_, | |
251 "DELETE FROM DeletedResources"); | |
252 | |
253 statement.Execute(); | |
254 } | |
255 | |
256 | |
257 void IndexBackend::SignalDeletedFiles() | |
258 { | |
259 DatabaseManager::CachedStatement statement( | |
260 STATEMENT_FROM_HERE, manager_, | |
261 "SELECT * FROM DeletedFiles"); | |
262 | |
263 statement.SetReadOnly(true); | |
264 statement.Execute(); | |
265 | |
266 while (!statement.IsDone()) | |
267 { | |
268 std::string a = ReadString(statement, 0); | |
269 std::string b = ReadString(statement, 5); | |
270 std::string c = ReadString(statement, 6); | |
271 | |
272 GetOutput().SignalDeletedAttachment(a.c_str(), | |
273 ReadInteger32(statement, 1), | |
274 ReadInteger64(statement, 3), | |
275 b.c_str(), | |
276 ReadInteger32(statement, 4), | |
277 ReadInteger64(statement, 2), | |
278 c.c_str()); | |
279 | |
280 statement.Next(); | |
281 } | |
282 } | |
283 | |
284 | |
285 void IndexBackend::SignalDeletedResources() | |
286 { | |
287 DatabaseManager::CachedStatement statement( | |
288 STATEMENT_FROM_HERE, manager_, | |
289 "SELECT * FROM DeletedResources"); | |
290 | |
291 statement.SetReadOnly(true); | |
292 statement.Execute(); | |
293 | |
294 while (!statement.IsDone()) | |
295 { | |
296 GetOutput().SignalDeletedResource( | |
297 ReadString(statement, 1), | |
298 static_cast<OrthancPluginResourceType>(ReadInteger32(statement, 0))); | |
299 | |
300 statement.Next(); | |
301 } | |
302 } | |
303 | |
304 | |
305 IndexBackend::IndexBackend(IDatabaseFactory* factory) : | |
306 manager_(factory) | |
307 { | |
308 } | |
309 | |
310 | |
311 void IndexBackend::AddAttachment(int64_t id, | |
312 const OrthancPluginAttachment& attachment) | |
313 { | |
314 DatabaseManager::CachedStatement statement( | |
315 STATEMENT_FROM_HERE, manager_, | |
316 "INSERT INTO AttachedFiles VALUES(${id}, ${type}, ${uuid}, " | |
317 "${compressed}, ${uncompressed}, ${compression}, ${hash}, ${hash-compressed})"); | |
318 | |
319 statement.SetParameterType("id", ValueType_Integer64); | |
320 statement.SetParameterType("type", ValueType_Integer64); | |
321 statement.SetParameterType("uuid", ValueType_Utf8String); | |
322 statement.SetParameterType("compressed", ValueType_Integer64); | |
323 statement.SetParameterType("uncompressed", ValueType_Integer64); | |
324 statement.SetParameterType("compression", ValueType_Integer64); | |
325 statement.SetParameterType("hash", ValueType_Utf8String); | |
326 statement.SetParameterType("hash-compressed", ValueType_Utf8String); | |
327 | |
328 Dictionary args; | |
329 args.SetIntegerValue("id", id); | |
330 args.SetIntegerValue("type", attachment.contentType); | |
331 args.SetUtf8Value("uuid", attachment.uuid); | |
332 args.SetIntegerValue("compressed", attachment.compressedSize); | |
333 args.SetIntegerValue("uncompressed", attachment.uncompressedSize); | |
334 args.SetIntegerValue("compression", attachment.compressionType); | |
335 args.SetUtf8Value("hash", attachment.uncompressedHash); | |
336 args.SetUtf8Value("hash-compressed", attachment.compressedHash); | |
337 | |
338 statement.Execute(args); | |
339 } | |
340 | |
341 | |
342 void IndexBackend::AttachChild(int64_t parent, | |
343 int64_t child) | |
344 { | |
345 DatabaseManager::CachedStatement statement( | |
346 STATEMENT_FROM_HERE, manager_, | |
347 "UPDATE Resources SET parentId = ${parent} WHERE internalId = ${child}"); | |
348 | |
349 statement.SetParameterType("parent", ValueType_Integer64); | |
350 statement.SetParameterType("child", ValueType_Integer64); | |
351 | |
352 Dictionary args; | |
353 args.SetIntegerValue("parent", parent); | |
354 args.SetIntegerValue("child", child); | |
355 | |
356 statement.Execute(args); | |
357 } | |
358 | |
359 | |
360 void IndexBackend::ClearChanges() | |
361 { | |
362 DatabaseManager::CachedStatement statement( | |
363 STATEMENT_FROM_HERE, manager_, | |
364 "DELETE FROM Changes"); | |
365 | |
366 statement.Execute(); | |
367 } | |
368 | |
369 | |
370 void IndexBackend::ClearExportedResources() | |
371 { | |
372 DatabaseManager::CachedStatement statement( | |
373 STATEMENT_FROM_HERE, manager_, | |
374 "DELETE FROM ExportedResources"); | |
375 | |
376 statement.Execute(); | |
377 } | |
378 | |
379 | |
380 void IndexBackend::DeleteAttachment(int64_t id, | |
381 int32_t attachment) | |
382 { | |
383 ClearDeletedFiles(); | |
384 | |
385 { | |
386 DatabaseManager::CachedStatement statement( | |
387 STATEMENT_FROM_HERE, manager_, | |
388 "DELETE FROM AttachedFiles WHERE id=${id} AND fileType=${type}"); | |
389 | |
390 statement.SetParameterType("id", ValueType_Integer64); | |
391 statement.SetParameterType("type", ValueType_Integer64); | |
392 | |
393 Dictionary args; | |
394 args.SetIntegerValue("id", id); | |
395 args.SetIntegerValue("type", static_cast<int>(attachment)); | |
396 | |
397 statement.Execute(args); | |
398 } | |
399 | |
400 SignalDeletedFiles(); | |
401 } | |
402 | |
403 | |
404 void IndexBackend::DeleteMetadata(int64_t id, | |
405 int32_t metadataType) | |
406 { | |
407 DatabaseManager::CachedStatement statement( | |
408 STATEMENT_FROM_HERE, manager_, | |
409 "DELETE FROM Metadata WHERE id=${id} and type=${type}"); | |
410 | |
411 statement.SetParameterType("id", ValueType_Integer64); | |
412 statement.SetParameterType("type", ValueType_Integer64); | |
413 | |
414 Dictionary args; | |
415 args.SetIntegerValue("id", id); | |
416 args.SetIntegerValue("type", static_cast<int>(metadataType)); | |
417 | |
418 statement.Execute(args); | |
419 } | |
420 | |
421 | |
422 void IndexBackend::DeleteResource(int64_t id) | |
423 { | |
1
d17b2631bb67
starting StorageBackend
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
424 assert(manager_.GetDialect() != Dialect_MySQL); |
0 | 425 |
426 ClearDeletedFiles(); | |
427 ClearDeletedResources(); | |
428 | |
429 { | |
430 DatabaseManager::CachedStatement statement( | |
431 STATEMENT_FROM_HERE, GetManager(), | |
432 "DELETE FROM RemainingAncestor"); | |
433 | |
434 statement.Execute(); | |
435 } | |
436 | |
437 { | |
438 DatabaseManager::CachedStatement statement( | |
439 STATEMENT_FROM_HERE, GetManager(), | |
440 "DELETE FROM Resources WHERE internalId=${id}"); | |
441 | |
442 statement.SetParameterType("id", ValueType_Integer64); | |
443 | |
444 Dictionary args; | |
445 args.SetIntegerValue("id", id); | |
446 | |
447 statement.Execute(args); | |
448 } | |
449 | |
450 | |
451 { | |
452 DatabaseManager::CachedStatement statement( | |
453 STATEMENT_FROM_HERE, GetManager(), | |
454 "SELECT * FROM RemainingAncestor"); | |
455 | |
456 statement.Execute(); | |
457 | |
458 if (!statement.IsDone()) | |
459 { | |
460 GetOutput().SignalRemainingAncestor( | |
461 ReadString(statement, 1), | |
462 static_cast<OrthancPluginResourceType>(ReadInteger32(statement, 0))); | |
463 | |
464 // There is at most 1 remaining ancestor | |
465 assert((statement.Next(), statement.IsDone())); | |
466 } | |
467 } | |
468 | |
469 SignalDeletedFiles(); | |
470 SignalDeletedResources(); | |
471 } | |
472 | |
473 | |
474 void IndexBackend::GetAllInternalIds(std::list<int64_t>& target, | |
475 OrthancPluginResourceType resourceType) | |
476 { | |
477 DatabaseManager::CachedStatement statement( | |
478 STATEMENT_FROM_HERE, manager_, | |
479 "SELECT internalId FROM Resources WHERE resourceType=${type}"); | |
480 | |
481 statement.SetReadOnly(true); | |
482 statement.SetParameterType("type", ValueType_Integer64); | |
483 | |
484 Dictionary args; | |
485 args.SetIntegerValue("type", static_cast<int>(resourceType)); | |
486 | |
487 ReadListOfIntegers<int64_t>(target, statement, args); | |
488 } | |
489 | |
490 | |
491 void IndexBackend::GetAllPublicIds(std::list<std::string>& target, | |
492 OrthancPluginResourceType resourceType) | |
493 { | |
494 DatabaseManager::CachedStatement statement( | |
495 STATEMENT_FROM_HERE, manager_, | |
496 "SELECT publicId FROM Resources WHERE resourceType=${type}"); | |
497 | |
498 statement.SetReadOnly(true); | |
499 statement.SetParameterType("type", ValueType_Integer64); | |
500 | |
501 Dictionary args; | |
502 args.SetIntegerValue("type", static_cast<int>(resourceType)); | |
503 | |
504 ReadListOfStrings(target, statement, args); | |
505 } | |
506 | |
507 | |
508 void IndexBackend::GetAllPublicIds(std::list<std::string>& target, | |
509 OrthancPluginResourceType resourceType, | |
510 uint64_t since, | |
511 uint64_t limit) | |
512 { | |
513 DatabaseManager::CachedStatement statement( | |
514 STATEMENT_FROM_HERE, manager_, | |
515 "SELECT publicId FROM (SELECT publicId FROM Resources " | |
516 "WHERE resourceType=${type}) AS tmp " | |
517 "ORDER BY tmp.publicId LIMIT ${limit} OFFSET ${since}"); | |
518 | |
519 statement.SetReadOnly(true); | |
520 statement.SetParameterType("type", ValueType_Integer64); | |
521 statement.SetParameterType("limit", ValueType_Integer64); | |
522 statement.SetParameterType("since", ValueType_Integer64); | |
523 | |
524 Dictionary args; | |
525 args.SetIntegerValue("type", static_cast<int>(resourceType)); | |
526 args.SetIntegerValue("limit", limit); | |
527 args.SetIntegerValue("since", since); | |
528 | |
529 ReadListOfStrings(target, statement, args); | |
530 } | |
531 | |
532 | |
533 /* Use GetOutput().AnswerChange() */ | |
534 void IndexBackend::GetChanges(bool& done /*out*/, | |
535 int64_t since, | |
536 uint32_t maxResults) | |
537 { | |
538 DatabaseManager::CachedStatement statement( | |
539 STATEMENT_FROM_HERE, manager_, | |
540 "SELECT * FROM Changes WHERE seq>${since} ORDER BY seq LIMIT ${limit}"); | |
541 | |
542 statement.SetReadOnly(true); | |
543 statement.SetParameterType("limit", ValueType_Integer64); | |
544 statement.SetParameterType("since", ValueType_Integer64); | |
545 | |
546 Dictionary args; | |
547 args.SetIntegerValue("limit", maxResults + 1); | |
548 args.SetIntegerValue("since", since); | |
549 | |
550 ReadChangesInternal(done, statement, args, maxResults); | |
551 } | |
552 | |
553 | |
554 void IndexBackend::GetChildrenInternalId(std::list<int64_t>& target /*out*/, | |
555 int64_t id) | |
556 { | |
557 DatabaseManager::CachedStatement statement( | |
558 STATEMENT_FROM_HERE, manager_, | |
559 "SELECT a.internalId FROM Resources AS a, Resources AS b " | |
560 "WHERE a.parentId = b.internalId AND b.internalId = ${id}"); | |
561 | |
562 statement.SetReadOnly(true); | |
563 statement.SetParameterType("id", ValueType_Integer64); | |
564 | |
565 Dictionary args; | |
566 args.SetIntegerValue("id", id); | |
567 | |
568 ReadListOfIntegers<int64_t>(target, statement, args); | |
569 } | |
570 | |
571 | |
572 void IndexBackend::GetChildrenPublicId(std::list<std::string>& target /*out*/, | |
573 int64_t id) | |
574 { | |
575 DatabaseManager::CachedStatement statement( | |
576 STATEMENT_FROM_HERE, manager_, | |
577 "SELECT a.publicId FROM Resources AS a, Resources AS b " | |
578 "WHERE a.parentId = b.internalId AND b.internalId = ${id}"); | |
579 | |
580 statement.SetReadOnly(true); | |
581 statement.SetParameterType("id", ValueType_Integer64); | |
582 | |
583 Dictionary args; | |
584 args.SetIntegerValue("id", id); | |
585 | |
586 ReadListOfStrings(target, statement, args); | |
587 } | |
588 | |
589 | |
590 /* Use GetOutput().AnswerExportedResource() */ | |
591 void IndexBackend::GetExportedResources(bool& done /*out*/, | |
592 int64_t since, | |
593 uint32_t maxResults) | |
594 { | |
595 DatabaseManager::CachedStatement statement( | |
596 STATEMENT_FROM_HERE, manager_, | |
597 "SELECT * FROM ExportedResources WHERE seq>${since} ORDER BY seq LIMIT ${limit}"); | |
598 | |
599 statement.SetReadOnly(true); | |
600 statement.SetParameterType("limit", ValueType_Integer64); | |
601 statement.SetParameterType("since", ValueType_Integer64); | |
602 | |
603 Dictionary args; | |
604 args.SetIntegerValue("limit", maxResults + 1); | |
605 args.SetIntegerValue("since", since); | |
606 | |
607 ReadExportedResourcesInternal(done, statement, args, maxResults); | |
608 } | |
609 | |
610 | |
611 /* Use GetOutput().AnswerChange() */ | |
612 void IndexBackend::GetLastChange() | |
613 { | |
614 DatabaseManager::CachedStatement statement( | |
615 STATEMENT_FROM_HERE, manager_, | |
616 "SELECT * FROM Changes ORDER BY seq DESC LIMIT 1"); | |
617 | |
618 statement.SetReadOnly(true); | |
619 | |
620 Dictionary args; | |
621 | |
622 bool done; // Ignored | |
623 ReadChangesInternal(done, statement, args, 1); | |
624 } | |
625 | |
626 | |
627 /* Use GetOutput().AnswerExportedResource() */ | |
628 void IndexBackend::GetLastExportedResource() | |
629 { | |
630 DatabaseManager::CachedStatement statement( | |
631 STATEMENT_FROM_HERE, manager_, | |
632 "SELECT * FROM ExportedResources ORDER BY seq DESC LIMIT 1"); | |
633 | |
634 statement.SetReadOnly(true); | |
635 | |
636 Dictionary args; | |
637 | |
638 bool done; // Ignored | |
639 ReadExportedResourcesInternal(done, statement, args, 1); | |
640 } | |
641 | |
642 | |
643 /* Use GetOutput().AnswerDicomTag() */ | |
644 void IndexBackend::GetMainDicomTags(int64_t id) | |
645 { | |
646 DatabaseManager::CachedStatement statement( | |
647 STATEMENT_FROM_HERE, manager_, | |
648 "SELECT * FROM MainDicomTags WHERE id=${id}"); | |
649 | |
650 statement.SetReadOnly(true); | |
651 statement.SetParameterType("id", ValueType_Integer64); | |
652 | |
653 Dictionary args; | |
654 args.SetIntegerValue("id", id); | |
655 | |
656 statement.Execute(args); | |
657 | |
658 while (!statement.IsDone()) | |
659 { | |
660 GetOutput().AnswerDicomTag(static_cast<uint16_t>(ReadInteger64(statement, 1)), | |
661 static_cast<uint16_t>(ReadInteger64(statement, 2)), | |
662 ReadString(statement, 3)); | |
663 statement.Next(); | |
664 } | |
665 } | |
666 | |
667 | |
668 std::string IndexBackend::GetPublicId(int64_t resourceId) | |
669 { | |
670 DatabaseManager::CachedStatement statement( | |
671 STATEMENT_FROM_HERE, manager_, | |
672 "SELECT publicId FROM Resources WHERE internalId=${id}"); | |
673 | |
674 statement.SetReadOnly(true); | |
675 statement.SetParameterType("id", ValueType_Integer64); | |
676 | |
677 Dictionary args; | |
678 args.SetIntegerValue("id", resourceId); | |
679 | |
680 statement.Execute(args); | |
681 | |
682 if (statement.IsDone()) | |
683 { | |
684 throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource); | |
685 } | |
686 else | |
687 { | |
688 return ReadString(statement, 0); | |
689 } | |
690 } | |
691 | |
692 | |
693 uint64_t IndexBackend::GetResourceCount(OrthancPluginResourceType resourceType) | |
694 { | |
695 std::auto_ptr<DatabaseManager::CachedStatement> statement; | |
696 | |
1
d17b2631bb67
starting StorageBackend
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
697 switch (manager_.GetDialect()) |
0 | 698 { |
699 case Dialect_MySQL: | |
700 statement.reset(new DatabaseManager::CachedStatement( | |
701 STATEMENT_FROM_HERE, GetManager(), | |
702 "SELECT CAST(COUNT(*) AS UNSIGNED INT) FROM Resources WHERE resourceType=${type}")); | |
703 break; | |
704 | |
705 case Dialect_PostgreSQL: | |
706 statement.reset(new DatabaseManager::CachedStatement( | |
707 STATEMENT_FROM_HERE, GetManager(), | |
708 "SELECT CAST(COUNT(*) AS BIGINT) FROM Resources WHERE resourceType=${type}")); | |
709 break; | |
710 | |
711 case Dialect_SQLite: | |
712 statement.reset(new DatabaseManager::CachedStatement( | |
713 STATEMENT_FROM_HERE, GetManager(), | |
714 "SELECT COUNT(*) FROM Resources WHERE resourceType=${type}")); | |
715 break; | |
716 | |
717 default: | |
718 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
719 } | |
720 | |
721 statement->SetReadOnly(true); | |
722 statement->SetParameterType("type", ValueType_Integer64); | |
723 | |
724 Dictionary args; | |
725 args.SetIntegerValue("type", resourceType); | |
726 | |
727 statement->Execute(args); | |
728 | |
729 return static_cast<uint64_t>(ReadInteger64(*statement, 0)); | |
730 } | |
731 | |
732 | |
733 OrthancPluginResourceType IndexBackend::GetResourceType(int64_t resourceId) | |
734 { | |
735 DatabaseManager::CachedStatement statement( | |
736 STATEMENT_FROM_HERE, manager_, | |
737 "SELECT resourceType FROM Resources WHERE internalId=${id}"); | |
738 | |
739 statement.SetReadOnly(true); | |
740 statement.SetParameterType("id", ValueType_Integer64); | |
741 | |
742 Dictionary args; | |
743 args.SetIntegerValue("id", resourceId); | |
744 | |
745 statement.Execute(args); | |
746 | |
747 if (statement.IsDone()) | |
748 { | |
749 throw Orthanc::OrthancException(Orthanc::ErrorCode_UnknownResource); | |
750 } | |
751 else | |
752 { | |
753 return static_cast<OrthancPluginResourceType>(ReadInteger32(statement, 0)); | |
754 } | |
755 } | |
756 | |
757 | |
758 uint64_t IndexBackend::GetTotalCompressedSize() | |
759 { | |
760 std::auto_ptr<DatabaseManager::CachedStatement> statement; | |
761 | |
762 // NB: "COALESCE" is used to replace "NULL" by "0" if the number of rows is empty | |
763 | |
1
d17b2631bb67
starting StorageBackend
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
764 switch (manager_.GetDialect()) |
0 | 765 { |
766 case Dialect_MySQL: | |
767 statement.reset(new DatabaseManager::CachedStatement( | |
768 STATEMENT_FROM_HERE, GetManager(), | |
769 "SELECT CAST(COALESCE(SUM(compressedSize), 0) AS UNSIGNED INTEGER) FROM AttachedFiles")); | |
770 break; | |
771 | |
772 case Dialect_PostgreSQL: | |
773 statement.reset(new DatabaseManager::CachedStatement( | |
774 STATEMENT_FROM_HERE, GetManager(), | |
775 "SELECT CAST(COALESCE(SUM(compressedSize), 0) AS BIGINT) FROM AttachedFiles")); | |
776 break; | |
777 | |
778 case Dialect_SQLite: | |
779 statement.reset(new DatabaseManager::CachedStatement( | |
780 STATEMENT_FROM_HERE, GetManager(), | |
781 "SELECT COALESCE(SUM(compressedSize), 0) FROM AttachedFiles")); | |
782 break; | |
783 | |
784 default: | |
785 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
786 } | |
787 | |
788 statement->SetReadOnly(true); | |
789 statement->Execute(); | |
790 | |
791 return static_cast<uint64_t>(ReadInteger64(*statement, 0)); | |
792 } | |
793 | |
794 | |
795 uint64_t IndexBackend::GetTotalUncompressedSize() | |
796 { | |
797 std::auto_ptr<DatabaseManager::CachedStatement> statement; | |
798 | |
799 // NB: "COALESCE" is used to replace "NULL" by "0" if the number of rows is empty | |
800 | |
1
d17b2631bb67
starting StorageBackend
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
801 switch (manager_.GetDialect()) |
0 | 802 { |
803 case Dialect_MySQL: | |
804 statement.reset(new DatabaseManager::CachedStatement( | |
805 STATEMENT_FROM_HERE, GetManager(), | |
806 "SELECT CAST(COALESCE(SUM(uncompressedSize), 0) AS UNSIGNED INTEGER) FROM AttachedFiles")); | |
807 break; | |
808 | |
809 case Dialect_PostgreSQL: | |
810 statement.reset(new DatabaseManager::CachedStatement( | |
811 STATEMENT_FROM_HERE, GetManager(), | |
812 "SELECT CAST(COALESCE(SUM(uncompressedSize), 0) AS BIGINT) FROM AttachedFiles")); | |
813 break; | |
814 | |
815 case Dialect_SQLite: | |
816 statement.reset(new DatabaseManager::CachedStatement( | |
817 STATEMENT_FROM_HERE, GetManager(), | |
818 "SELECT COALESCE(SUM(uncompressedSize), 0) FROM AttachedFiles")); | |
819 break; | |
820 | |
821 default: | |
822 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
823 } | |
824 | |
825 statement->SetReadOnly(true); | |
826 statement->Execute(); | |
827 | |
828 return static_cast<uint64_t>(ReadInteger64(*statement, 0)); | |
829 } | |
830 | |
831 | |
832 bool IndexBackend::IsExistingResource(int64_t internalId) | |
833 { | |
834 DatabaseManager::CachedStatement statement( | |
835 STATEMENT_FROM_HERE, manager_, | |
836 "SELECT * FROM Resources WHERE internalId=${id}"); | |
837 | |
838 statement.SetReadOnly(true); | |
839 statement.SetParameterType("id", ValueType_Integer64); | |
840 | |
841 Dictionary args; | |
842 args.SetIntegerValue("id", internalId); | |
843 | |
844 statement.Execute(args); | |
845 | |
846 return !statement.IsDone(); | |
847 } | |
848 | |
849 | |
850 bool IndexBackend::IsProtectedPatient(int64_t internalId) | |
851 { | |
852 DatabaseManager::CachedStatement statement( | |
853 STATEMENT_FROM_HERE, manager_, | |
854 "SELECT * FROM PatientRecyclingOrder WHERE patientId = ${id}"); | |
855 | |
856 statement.SetReadOnly(true); | |
857 statement.SetParameterType("id", ValueType_Integer64); | |
858 | |
859 Dictionary args; | |
860 args.SetIntegerValue("id", internalId); | |
861 | |
862 statement.Execute(args); | |
863 | |
864 return statement.IsDone(); | |
865 } | |
866 | |
867 | |
868 void IndexBackend::ListAvailableMetadata(std::list<int32_t>& target /*out*/, | |
869 int64_t id) | |
870 { | |
871 DatabaseManager::CachedStatement statement( | |
872 STATEMENT_FROM_HERE, manager_, | |
873 "SELECT type FROM Metadata WHERE id=${id}"); | |
874 | |
875 statement.SetReadOnly(true); | |
876 statement.SetParameterType("id", ValueType_Integer64); | |
877 | |
878 Dictionary args; | |
879 args.SetIntegerValue("id", id); | |
880 | |
881 ReadListOfIntegers<int32_t>(target, statement, args); | |
882 } | |
883 | |
884 | |
885 void IndexBackend::ListAvailableAttachments(std::list<int32_t>& target /*out*/, | |
886 int64_t id) | |
887 { | |
888 DatabaseManager::CachedStatement statement( | |
889 STATEMENT_FROM_HERE, manager_, | |
890 "SELECT fileType FROM AttachedFiles WHERE id=${id}"); | |
891 | |
892 statement.SetReadOnly(true); | |
893 statement.SetParameterType("id", ValueType_Integer64); | |
894 | |
895 Dictionary args; | |
896 args.SetIntegerValue("id", id); | |
897 | |
898 ReadListOfIntegers<int32_t>(target, statement, args); | |
899 } | |
900 | |
901 | |
902 void IndexBackend::LogChange(const OrthancPluginChange& change) | |
903 { | |
904 int64_t id; | |
905 OrthancPluginResourceType type; | |
906 if (!LookupResource(id, type, change.publicId) || | |
907 type != change.resourceType) | |
908 { | |
909 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | |
910 } | |
911 | |
912 DatabaseManager::CachedStatement statement( | |
913 STATEMENT_FROM_HERE, manager_, | |
914 "INSERT INTO Changes VALUES(${}, ${changeType}, ${id}, ${resourceType}, ${date})"); | |
915 | |
916 statement.SetParameterType("changeType", ValueType_Integer64); | |
917 statement.SetParameterType("id", ValueType_Integer64); | |
918 statement.SetParameterType("resourceType", ValueType_Integer64); | |
919 statement.SetParameterType("date", ValueType_Utf8String); | |
920 | |
921 Dictionary args; | |
922 args.SetIntegerValue("changeType", change.changeType); | |
923 args.SetIntegerValue("id", id); | |
924 args.SetIntegerValue("resourceType", change.resourceType); | |
925 args.SetUtf8Value("date", change.date); | |
926 | |
927 statement.Execute(args); | |
928 } | |
929 | |
930 | |
931 void IndexBackend::LogExportedResource(const OrthancPluginExportedResource& resource) | |
932 { | |
933 DatabaseManager::CachedStatement statement( | |
934 STATEMENT_FROM_HERE, manager_, | |
935 "INSERT INTO ExportedResources VALUES(${}, ${type}, ${publicId}, " | |
936 "${modality}, ${patient}, ${study}, ${series}, ${instance}, ${date})"); | |
937 | |
938 statement.SetParameterType("type", ValueType_Integer64); | |
939 statement.SetParameterType("publicId", ValueType_Utf8String); | |
940 statement.SetParameterType("modality", ValueType_Utf8String); | |
941 statement.SetParameterType("patient", ValueType_Utf8String); | |
942 statement.SetParameterType("study", ValueType_Utf8String); | |
943 statement.SetParameterType("series", ValueType_Utf8String); | |
944 statement.SetParameterType("instance", ValueType_Utf8String); | |
945 statement.SetParameterType("date", ValueType_Utf8String); | |
946 | |
947 Dictionary args; | |
948 args.SetIntegerValue("type", resource.resourceType); | |
949 args.SetUtf8Value("publicId", resource.publicId); | |
950 args.SetUtf8Value("modality", resource.modality); | |
951 args.SetUtf8Value("patient", resource.patientId); | |
952 args.SetUtf8Value("study", resource.studyInstanceUid); | |
953 args.SetUtf8Value("series", resource.seriesInstanceUid); | |
954 args.SetUtf8Value("instance", resource.sopInstanceUid); | |
955 args.SetUtf8Value("date", resource.date); | |
956 | |
957 statement.Execute(args); | |
958 } | |
959 | |
960 | |
961 /* Use GetOutput().AnswerAttachment() */ | |
962 bool IndexBackend::LookupAttachment(int64_t id, | |
963 int32_t contentType) | |
964 { | |
965 DatabaseManager::CachedStatement statement( | |
966 STATEMENT_FROM_HERE, manager_, | |
967 "SELECT uuid, uncompressedSize, compressionType, compressedSize, " | |
968 "uncompressedHash, compressedHash FROM AttachedFiles WHERE id=${id} AND fileType=${type}"); | |
969 | |
970 statement.SetReadOnly(true); | |
971 statement.SetParameterType("id", ValueType_Integer64); | |
972 statement.SetParameterType("type", ValueType_Integer64); | |
973 | |
974 Dictionary args; | |
975 args.SetIntegerValue("id", id); | |
976 args.SetIntegerValue("type", static_cast<int>(contentType)); | |
977 | |
978 statement.Execute(args); | |
979 | |
980 if (statement.IsDone()) | |
981 { | |
982 return false; | |
983 } | |
984 else | |
985 { | |
986 GetOutput().AnswerAttachment(ReadString(statement, 0), | |
987 contentType, | |
988 ReadInteger64(statement, 1), | |
989 ReadString(statement, 4), | |
990 ReadInteger32(statement, 2), | |
991 ReadInteger64(statement, 3), | |
992 ReadString(statement, 5)); | |
993 return true; | |
994 } | |
995 } | |
996 | |
997 | |
998 bool IndexBackend::LookupGlobalProperty(std::string& target /*out*/, | |
999 int32_t property) | |
1000 { | |
1001 return ::OrthancDatabases::LookupGlobalProperty(target, manager_, static_cast<Orthanc::GlobalProperty>(property)); | |
1002 } | |
1003 | |
1004 | |
1005 void IndexBackend::LookupIdentifier(std::list<int64_t>& target /*out*/, | |
1006 OrthancPluginResourceType resourceType, | |
1007 uint16_t group, | |
1008 uint16_t element, | |
1009 OrthancPluginIdentifierConstraint constraint, | |
1010 const char* value) | |
1011 { | |
1012 std::auto_ptr<DatabaseManager::CachedStatement> statement; | |
1013 | |
1014 std::string header = | |
1015 "SELECT d.id FROM DicomIdentifiers AS d, Resources AS r WHERE " | |
1016 "d.id = r.internalId AND r.resourceType=${type} AND d.tagGroup=${group} " | |
1017 "AND d.tagElement=${element} AND "; | |
1018 | |
1019 switch (constraint) | |
1020 { | |
1021 case OrthancPluginIdentifierConstraint_Equal: | |
1022 header += "d.value = ${value}"; | |
1023 statement.reset(new DatabaseManager::CachedStatement( | |
1024 STATEMENT_FROM_HERE, manager_, header.c_str())); | |
1025 break; | |
1026 | |
1027 case OrthancPluginIdentifierConstraint_SmallerOrEqual: | |
1028 header += "d.value <= ${value}"; | |
1029 statement.reset(new DatabaseManager::CachedStatement( | |
1030 STATEMENT_FROM_HERE, manager_, header.c_str())); | |
1031 break; | |
1032 | |
1033 case OrthancPluginIdentifierConstraint_GreaterOrEqual: | |
1034 header += "d.value >= ${value}"; | |
1035 statement.reset(new DatabaseManager::CachedStatement( | |
1036 STATEMENT_FROM_HERE, manager_, header.c_str())); | |
1037 break; | |
1038 | |
1039 case OrthancPluginIdentifierConstraint_Wildcard: | |
1040 header += "d.value LIKE ${value}"; | |
1041 statement.reset(new DatabaseManager::CachedStatement( | |
1042 STATEMENT_FROM_HERE, manager_, header.c_str())); | |
1043 break; | |
1044 | |
1045 default: | |
1046 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | |
1047 } | |
1048 | |
1049 statement->SetReadOnly(true); | |
1050 statement->SetParameterType("type", ValueType_Integer64); | |
1051 statement->SetParameterType("group", ValueType_Integer64); | |
1052 statement->SetParameterType("element", ValueType_Integer64); | |
1053 statement->SetParameterType("value", ValueType_Utf8String); | |
1054 | |
1055 Dictionary args; | |
1056 args.SetIntegerValue("type", resourceType); | |
1057 args.SetIntegerValue("group", group); | |
1058 args.SetIntegerValue("element", element); | |
1059 | |
1060 if (constraint == OrthancPluginIdentifierConstraint_Wildcard) | |
1061 { | |
1062 args.SetUtf8Value("value", ConvertWildcardToLike(value)); | |
1063 } | |
1064 else | |
1065 { | |
1066 args.SetUtf8Value("value", value); | |
1067 } | |
1068 | |
1069 statement->Execute(args); | |
1070 | |
1071 target.clear(); | |
1072 while (!statement->IsDone()) | |
1073 { | |
1074 target.push_back(ReadInteger64(*statement, 0)); | |
1075 statement->Next(); | |
1076 } | |
1077 } | |
1078 | |
1079 | |
1080 void IndexBackend::LookupIdentifierRange(std::list<int64_t>& target /*out*/, | |
1081 OrthancPluginResourceType resourceType, | |
1082 uint16_t group, | |
1083 uint16_t element, | |
1084 const char* start, | |
1085 const char* end) | |
1086 { | |
1087 DatabaseManager::CachedStatement statement( | |
1088 STATEMENT_FROM_HERE, manager_, | |
1089 "SELECT d.id FROM DicomIdentifiers AS d, Resources AS r WHERE " | |
1090 "d.id = r.internalId AND r.resourceType=${type} AND d.tagGroup=${group} " | |
1091 "AND d.tagElement=${element} AND d.value>=${start} AND d.value<=${end}"); | |
1092 | |
1093 statement.SetReadOnly(true); | |
1094 statement.SetParameterType("type", ValueType_Integer64); | |
1095 statement.SetParameterType("group", ValueType_Integer64); | |
1096 statement.SetParameterType("element", ValueType_Integer64); | |
1097 statement.SetParameterType("start", ValueType_Utf8String); | |
1098 statement.SetParameterType("end", ValueType_Utf8String); | |
1099 | |
1100 Dictionary args; | |
1101 args.SetIntegerValue("type", resourceType); | |
1102 args.SetIntegerValue("group", group); | |
1103 args.SetIntegerValue("element", element); | |
1104 args.SetUtf8Value("start", start); | |
1105 args.SetUtf8Value("end", end); | |
1106 | |
1107 statement.Execute(args); | |
1108 | |
1109 target.clear(); | |
1110 while (!statement.IsDone()) | |
1111 { | |
1112 target.push_back(ReadInteger64(statement, 0)); | |
1113 statement.Next(); | |
1114 } | |
1115 } | |
1116 | |
1117 | |
1118 bool IndexBackend::LookupMetadata(std::string& target /*out*/, | |
1119 int64_t id, | |
1120 int32_t metadataType) | |
1121 { | |
1122 DatabaseManager::CachedStatement statement( | |
1123 STATEMENT_FROM_HERE, manager_, | |
1124 "SELECT value FROM Metadata WHERE id=${id} and type=${type}"); | |
1125 | |
1126 statement.SetReadOnly(true); | |
1127 statement.SetParameterType("id", ValueType_Integer64); | |
1128 statement.SetParameterType("type", ValueType_Integer64); | |
1129 | |
1130 Dictionary args; | |
1131 args.SetIntegerValue("id", id); | |
1132 args.SetIntegerValue("type", metadataType); | |
1133 | |
1134 statement.Execute(args); | |
1135 | |
1136 if (statement.IsDone()) | |
1137 { | |
1138 return false; | |
1139 } | |
1140 else | |
1141 { | |
1142 target = ReadString(statement, 0); | |
1143 return true; | |
1144 } | |
1145 } | |
1146 | |
1147 | |
1148 bool IndexBackend::LookupParent(int64_t& parentId /*out*/, | |
1149 int64_t resourceId) | |
1150 { | |
1151 DatabaseManager::CachedStatement statement( | |
1152 STATEMENT_FROM_HERE, manager_, | |
1153 "SELECT parentId FROM Resources WHERE internalId=${id}"); | |
1154 | |
1155 statement.SetReadOnly(true); | |
1156 statement.SetParameterType("id", ValueType_Integer64); | |
1157 | |
1158 Dictionary args; | |
1159 args.SetIntegerValue("id", resourceId); | |
1160 | |
1161 statement.Execute(args); | |
1162 | |
1163 if (statement.IsDone() || | |
1164 statement.GetResultField(0).GetType() == ValueType_Null) | |
1165 { | |
1166 return false; | |
1167 } | |
1168 else | |
1169 { | |
1170 parentId = ReadInteger64(statement, 0); | |
1171 return true; | |
1172 } | |
1173 } | |
1174 | |
1175 | |
1176 bool IndexBackend::LookupResource(int64_t& id /*out*/, | |
1177 OrthancPluginResourceType& type /*out*/, | |
1178 const char* publicId) | |
1179 { | |
1180 DatabaseManager::CachedStatement statement( | |
1181 STATEMENT_FROM_HERE, manager_, | |
1182 "SELECT internalId, resourceType FROM Resources WHERE publicId=${id}"); | |
1183 | |
1184 statement.SetReadOnly(true); | |
1185 statement.SetParameterType("id", ValueType_Utf8String); | |
1186 | |
1187 Dictionary args; | |
1188 args.SetUtf8Value("id", publicId); | |
1189 | |
1190 statement.Execute(args); | |
1191 | |
1192 if (statement.IsDone()) | |
1193 { | |
1194 return false; | |
1195 } | |
1196 else | |
1197 { | |
1198 id = ReadInteger64(statement, 0); | |
1199 type = static_cast<OrthancPluginResourceType>(ReadInteger32(statement, 1)); | |
1200 return true; | |
1201 } | |
1202 } | |
1203 | |
1204 | |
1205 bool IndexBackend::SelectPatientToRecycle(int64_t& internalId /*out*/) | |
1206 { | |
1207 DatabaseManager::CachedStatement statement( | |
1208 STATEMENT_FROM_HERE, manager_, | |
1209 "SELECT patientId FROM PatientRecyclingOrder ORDER BY seq ASC LIMIT 1"); | |
1210 | |
1211 statement.SetReadOnly(true); | |
1212 statement.Execute(); | |
1213 | |
1214 if (statement.IsDone()) | |
1215 { | |
1216 return false; | |
1217 } | |
1218 else | |
1219 { | |
1220 internalId = ReadInteger64(statement, 0); | |
1221 return true; | |
1222 } | |
1223 } | |
1224 | |
1225 | |
1226 bool IndexBackend::SelectPatientToRecycle(int64_t& internalId /*out*/, | |
1227 int64_t patientIdToAvoid) | |
1228 { | |
1229 DatabaseManager::CachedStatement statement( | |
1230 STATEMENT_FROM_HERE, manager_, | |
1231 "SELECT patientId FROM PatientRecyclingOrder " | |
1232 "WHERE patientId != ${id} ORDER BY seq ASC LIMIT 1"); | |
1233 | |
1234 statement.SetReadOnly(true); | |
1235 statement.SetParameterType("id", ValueType_Integer64); | |
1236 | |
1237 Dictionary args; | |
1238 args.SetIntegerValue("id", patientIdToAvoid); | |
1239 | |
1240 statement.Execute(args); | |
1241 | |
1242 if (statement.IsDone()) | |
1243 { | |
1244 return false; | |
1245 } | |
1246 else | |
1247 { | |
1248 internalId = ReadInteger64(statement, 0); | |
1249 return true; | |
1250 } | |
1251 } | |
1252 | |
1253 | |
1254 void IndexBackend::SetGlobalProperty(int32_t property, | |
1255 const char* value) | |
1256 { | |
1257 return ::OrthancDatabases::SetGlobalProperty(manager_, static_cast<Orthanc::GlobalProperty>(property), value); | |
1258 } | |
1259 | |
1260 | |
1261 static void ExecuteSetTag(DatabaseManager::CachedStatement& statement, | |
1262 int64_t id, | |
1263 uint16_t group, | |
1264 uint16_t element, | |
1265 const char* value) | |
1266 { | |
1267 statement.SetParameterType("id", ValueType_Integer64); | |
1268 statement.SetParameterType("group", ValueType_Integer64); | |
1269 statement.SetParameterType("element", ValueType_Integer64); | |
1270 statement.SetParameterType("value", ValueType_Utf8String); | |
1271 | |
1272 Dictionary args; | |
1273 args.SetIntegerValue("id", id); | |
1274 args.SetIntegerValue("group", group); | |
1275 args.SetIntegerValue("element", element); | |
1276 args.SetUtf8Value("value", value); | |
1277 | |
1278 statement.Execute(args); | |
1279 } | |
1280 | |
1281 | |
1282 void IndexBackend::SetMainDicomTag(int64_t id, | |
1283 uint16_t group, | |
1284 uint16_t element, | |
1285 const char* value) | |
1286 { | |
1287 DatabaseManager::CachedStatement statement( | |
1288 STATEMENT_FROM_HERE, manager_, | |
1289 "INSERT INTO MainDicomTags VALUES(${id}, ${group}, ${element}, ${value})"); | |
1290 | |
1291 ExecuteSetTag(statement, id, group, element, value); | |
1292 } | |
1293 | |
1294 | |
1295 void IndexBackend::SetIdentifierTag(int64_t id, | |
1296 uint16_t group, | |
1297 uint16_t element, | |
1298 const char* value) | |
1299 { | |
1300 DatabaseManager::CachedStatement statement( | |
1301 STATEMENT_FROM_HERE, manager_, | |
1302 "INSERT INTO DicomIdentifiers VALUES(${id}, ${group}, ${element}, ${value})"); | |
1303 | |
1304 ExecuteSetTag(statement, id, group, element, value); | |
1305 } | |
1306 | |
1307 | |
1308 void IndexBackend::SetMetadata(int64_t id, | |
1309 int32_t metadataType, | |
1310 const char* value) | |
1311 { | |
1
d17b2631bb67
starting StorageBackend
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
1312 if (manager_.GetDialect() == Dialect_SQLite) |
0 | 1313 { |
1314 DatabaseManager::CachedStatement statement( | |
1315 STATEMENT_FROM_HERE, manager_, | |
1316 "INSERT OR REPLACE INTO Metadata VALUES (${id}, ${type}, ${value})"); | |
1317 | |
1318 statement.SetParameterType("id", ValueType_Integer64); | |
1319 statement.SetParameterType("type", ValueType_Integer64); | |
1320 statement.SetParameterType("value", ValueType_Utf8String); | |
1321 | |
1322 Dictionary args; | |
1323 args.SetIntegerValue("id", id); | |
1324 args.SetIntegerValue("type", metadataType); | |
1325 args.SetUtf8Value("value", value); | |
1326 | |
1327 statement.Execute(args); | |
1328 } | |
1329 else | |
1330 { | |
1331 { | |
1332 DatabaseManager::CachedStatement statement( | |
1333 STATEMENT_FROM_HERE, manager_, | |
1334 "DELETE FROM Metadata WHERE id=${id} AND type=${type}"); | |
1335 | |
1336 statement.SetParameterType("id", ValueType_Integer64); | |
1337 statement.SetParameterType("type", ValueType_Integer64); | |
1338 | |
1339 Dictionary args; | |
1340 args.SetIntegerValue("id", id); | |
1341 args.SetIntegerValue("type", metadataType); | |
1342 | |
1343 statement.Execute(args); | |
1344 } | |
1345 | |
1346 { | |
1347 DatabaseManager::CachedStatement statement( | |
1348 STATEMENT_FROM_HERE, manager_, | |
1349 "INSERT INTO Metadata VALUES (${id}, ${type}, ${value})"); | |
1350 | |
1351 statement.SetParameterType("id", ValueType_Integer64); | |
1352 statement.SetParameterType("type", ValueType_Integer64); | |
1353 statement.SetParameterType("value", ValueType_Utf8String); | |
1354 | |
1355 Dictionary args; | |
1356 args.SetIntegerValue("id", id); | |
1357 args.SetIntegerValue("type", metadataType); | |
1358 args.SetUtf8Value("value", value); | |
1359 | |
1360 statement.Execute(args); | |
1361 } | |
1362 } | |
1363 } | |
1364 | |
1365 | |
1366 void IndexBackend::SetProtectedPatient(int64_t internalId, | |
1367 bool isProtected) | |
1368 { | |
1369 if (isProtected) | |
1370 { | |
1371 DatabaseManager::CachedStatement statement( | |
1372 STATEMENT_FROM_HERE, manager_, | |
1373 "DELETE FROM PatientRecyclingOrder WHERE patientId=${id}"); | |
1374 | |
1375 statement.SetParameterType("id", ValueType_Integer64); | |
1376 | |
1377 Dictionary args; | |
1378 args.SetIntegerValue("id", internalId); | |
1379 | |
1380 statement.Execute(args); | |
1381 } | |
1382 else if (IsProtectedPatient(internalId)) | |
1383 { | |
1384 DatabaseManager::CachedStatement statement( | |
1385 STATEMENT_FROM_HERE, manager_, | |
1386 "INSERT INTO PatientRecyclingOrder VALUES(${}, ${id})"); | |
1387 | |
1388 statement.SetParameterType("id", ValueType_Integer64); | |
1389 | |
1390 Dictionary args; | |
1391 args.SetIntegerValue("id", internalId); | |
1392 | |
1393 statement.Execute(args); | |
1394 } | |
1395 else | |
1396 { | |
1397 // Nothing to do: The patient is already unprotected | |
1398 } | |
1399 } | |
1400 | |
1401 | |
1402 uint32_t IndexBackend::GetDatabaseVersion() | |
1403 { | |
1404 std::string version = "unknown"; | |
1405 | |
1406 if (LookupGlobalProperty(version, Orthanc::GlobalProperty_DatabaseSchemaVersion)) | |
1407 { | |
1408 try | |
1409 { | |
1410 return boost::lexical_cast<unsigned int>(version); | |
1411 } | |
1412 catch (boost::bad_lexical_cast&) | |
1413 { | |
1414 } | |
1415 } | |
1416 | |
1417 LOG(ERROR) << "The database is corrupted. Drop it manually for Orthanc to recreate it"; | |
1418 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | |
1419 } | |
1420 | |
1421 | |
1422 /** | |
1423 * Upgrade the database to the specified version of the database | |
1424 * schema. The upgrade script is allowed to make calls to | |
1425 * OrthancPluginReconstructMainDicomTags(). | |
1426 **/ | |
1427 void IndexBackend::UpgradeDatabase(uint32_t targetVersion, | |
1428 OrthancPluginStorageArea* storageArea) | |
1429 { | |
1430 LOG(ERROR) << "Upgrading database is not implemented by this plugin"; | |
1431 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
1432 } | |
1433 | |
1434 | |
1435 void IndexBackend::ClearMainDicomTags(int64_t internalId) | |
1436 { | |
1437 { | |
1438 DatabaseManager::CachedStatement statement( | |
1439 STATEMENT_FROM_HERE, manager_, | |
1440 "DELETE FROM MainDicomTags WHERE id=${id}"); | |
1441 | |
1442 statement.SetParameterType("id", ValueType_Integer64); | |
1443 | |
1444 Dictionary args; | |
1445 args.SetIntegerValue("id", internalId); | |
1446 | |
1447 statement.Execute(args); | |
1448 } | |
1449 | |
1450 { | |
1451 DatabaseManager::CachedStatement statement( | |
1452 STATEMENT_FROM_HERE, manager_, | |
1453 "DELETE FROM DicomIdentifiers WHERE id=${id}"); | |
1454 | |
1455 statement.SetParameterType("id", ValueType_Integer64); | |
1456 | |
1457 Dictionary args; | |
1458 args.SetIntegerValue("id", internalId); | |
1459 | |
1460 statement.Execute(args); | |
1461 } | |
1462 } | |
1463 | |
1464 | |
1465 // For unit testing only! | |
1466 uint64_t IndexBackend::GetResourcesCount() | |
1467 { | |
1468 std::auto_ptr<DatabaseManager::CachedStatement> statement; | |
1469 | |
1
d17b2631bb67
starting StorageBackend
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
1470 switch (manager_.GetDialect()) |
0 | 1471 { |
1472 case Dialect_MySQL: | |
1473 statement.reset(new DatabaseManager::CachedStatement( | |
1474 STATEMENT_FROM_HERE, GetManager(), | |
1475 "SELECT CAST(COUNT(*) AS UNSIGNED INT) FROM Resources")); | |
1476 break; | |
1477 | |
1478 case Dialect_PostgreSQL: | |
1479 statement.reset(new DatabaseManager::CachedStatement( | |
1480 STATEMENT_FROM_HERE, GetManager(), | |
1481 "SELECT CAST(COUNT(*) AS BIGINT) FROM Resources")); | |
1482 break; | |
1483 | |
1484 case Dialect_SQLite: | |
1485 statement.reset(new DatabaseManager::CachedStatement( | |
1486 STATEMENT_FROM_HERE, GetManager(), | |
1487 "SELECT COUNT(*) FROM Resources")); | |
1488 break; | |
1489 | |
1490 default: | |
1491 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
1492 } | |
1493 | |
1494 statement->SetReadOnly(true); | |
1495 statement->Execute(); | |
1496 | |
1497 return static_cast<uint64_t>(ReadInteger64(*statement, 0)); | |
1498 } | |
1499 | |
1500 | |
1501 // For unit testing only! | |
1502 uint64_t IndexBackend::GetUnprotectedPatientsCount() | |
1503 { | |
1504 std::auto_ptr<DatabaseManager::CachedStatement> statement; | |
1505 | |
1
d17b2631bb67
starting StorageBackend
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
1506 switch (manager_.GetDialect()) |
0 | 1507 { |
1508 case Dialect_MySQL: | |
1509 statement.reset(new DatabaseManager::CachedStatement( | |
1510 STATEMENT_FROM_HERE, GetManager(), | |
1511 "SELECT CAST(COUNT(*) AS UNSIGNED INT) FROM PatientRecyclingOrder")); | |
1512 break; | |
1513 | |
1514 case Dialect_PostgreSQL: | |
1515 statement.reset(new DatabaseManager::CachedStatement( | |
1516 STATEMENT_FROM_HERE, GetManager(), | |
1517 "SELECT CAST(COUNT(*) AS BIGINT) FROM PatientRecyclingOrder")); | |
1518 break; | |
1519 | |
1520 case Dialect_SQLite: | |
1521 statement.reset(new DatabaseManager::CachedStatement( | |
1522 STATEMENT_FROM_HERE, GetManager(), | |
1523 "SELECT COUNT(*) FROM PatientRecyclingOrder")); | |
1524 break; | |
1525 | |
1526 default: | |
1527 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
1528 } | |
1529 | |
1530 statement->SetReadOnly(true); | |
1531 statement->Execute(); | |
1532 | |
1533 return static_cast<uint64_t>(ReadInteger64(*statement, 0)); | |
1534 } | |
1535 | |
1536 | |
1537 // For unit testing only! | |
1538 bool IndexBackend::GetParentPublicId(std::string& target, | |
1539 int64_t id) | |
1540 { | |
1541 DatabaseManager::CachedStatement statement( | |
1542 STATEMENT_FROM_HERE, GetManager(), | |
1543 "SELECT a.publicId FROM Resources AS a, Resources AS b " | |
1544 "WHERE a.internalId = b.parentId AND b.internalId = ${id}"); | |
1545 | |
1546 statement.SetReadOnly(true); | |
1547 statement.SetParameterType("id", ValueType_Integer64); | |
1548 | |
1549 Dictionary args; | |
1550 args.SetIntegerValue("id", id); | |
1551 | |
1552 statement.Execute(args); | |
1553 | |
1554 if (statement.IsDone()) | |
1555 { | |
1556 return false; | |
1557 } | |
1558 else | |
1559 { | |
1560 target = ReadString(statement, 0); | |
1561 return true; | |
1562 } | |
1563 } | |
1564 | |
1565 | |
1566 // For unit tests only! | |
1567 void IndexBackend::GetChildren(std::list<std::string>& childrenPublicIds, | |
1568 int64_t id) | |
1569 { | |
1570 DatabaseManager::CachedStatement statement( | |
1571 STATEMENT_FROM_HERE, GetManager(), | |
1572 "SELECT publicId FROM Resources WHERE parentId=${id}"); | |
1573 | |
1574 statement.SetReadOnly(true); | |
1575 statement.SetParameterType("id", ValueType_Integer64); | |
1576 | |
1577 Dictionary args; | |
1578 args.SetIntegerValue("id", id); | |
1579 | |
1580 ReadListOfStrings(childrenPublicIds, statement, args); | |
1581 } | |
1582 } |