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