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-2021 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 General Public License as 9 * published by the Free Software Foundation, either version 3 of the 10 * License, or (at your option) any later version. 11 * 12 * In addition, as a special exception, the copyright holders of this 13 * program give permission to link the code of its release with the 14 * OpenSSL project's "OpenSSL" library (or with modified versions of it 15 * that use the same license as the "OpenSSL" library), and distribute 16 * the linked executables. You must obey the GNU General Public License 17 * in all respects for all of the code used other than "OpenSSL". If you 18 * modify file(s) with this exception, you may extend this exception to 19 * your version of the file(s), but you are not obligated to do so. If 20 * you do not wish to do so, delete this exception statement from your 21 * version. If you delete this exception statement from all source files 22 * in the program, then also delete it here. 23 * 24 * This program is distributed in the hope that it will be useful, but 25 * WITHOUT ANY WARRANTY; without even the implied warranty of 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 27 * General Public License for more details. 28 * 29 * You should have received a copy of the GNU General Public License 30 * along with this program. If not, see <http://www.gnu.org/licenses/>. 31 **/ 32 33 34 #include "../../../Sources/PrecompiledHeadersServer.h" 35 #include "DatabaseWrapperBase.h" 36 37 #include <stdio.h> 38 #include <memory> 39 40 namespace Orthanc 41 { SetGlobalProperty(GlobalProperty property,const std::string & value)42 void DatabaseWrapperBase::SetGlobalProperty(GlobalProperty property, 43 const std::string& value) 44 { 45 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT OR REPLACE INTO GlobalProperties VALUES(?, ?)"); 46 s.BindInt(0, property); 47 s.BindString(1, value); 48 s.Run(); 49 } 50 LookupGlobalProperty(std::string & target,GlobalProperty property)51 bool DatabaseWrapperBase::LookupGlobalProperty(std::string& target, 52 GlobalProperty property) 53 { 54 SQLite::Statement s(db_, SQLITE_FROM_HERE, 55 "SELECT value FROM GlobalProperties WHERE property=?"); 56 s.BindInt(0, property); 57 58 if (!s.Step()) 59 { 60 return false; 61 } 62 else 63 { 64 target = s.ColumnString(0); 65 return true; 66 } 67 } 68 CreateResource(const std::string & publicId,ResourceType type)69 int64_t DatabaseWrapperBase::CreateResource(const std::string& publicId, 70 ResourceType type) 71 { 72 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Resources VALUES(NULL, ?, ?, NULL)"); 73 s.BindInt(0, type); 74 s.BindString(1, publicId); 75 s.Run(); 76 return db_.GetLastInsertRowId(); 77 } 78 LookupResource(int64_t & id,ResourceType & type,const std::string & publicId)79 bool DatabaseWrapperBase::LookupResource(int64_t& id, 80 ResourceType& type, 81 const std::string& publicId) 82 { 83 SQLite::Statement s(db_, SQLITE_FROM_HERE, 84 "SELECT internalId, resourceType FROM Resources WHERE publicId=?"); 85 s.BindString(0, publicId); 86 87 if (!s.Step()) 88 { 89 return false; 90 } 91 else 92 { 93 id = s.ColumnInt(0); 94 type = static_cast<ResourceType>(s.ColumnInt(1)); 95 96 // Check whether there is a single resource with this public id 97 assert(!s.Step()); 98 99 return true; 100 } 101 } 102 LookupParent(bool & found,int64_t & parentId,int64_t resourceId)103 ErrorCode DatabaseWrapperBase::LookupParent(bool& found, 104 int64_t& parentId, 105 int64_t resourceId) 106 { 107 SQLite::Statement s(db_, SQLITE_FROM_HERE, 108 "SELECT parentId FROM Resources WHERE internalId=?"); 109 s.BindInt64(0, resourceId); 110 111 if (!s.Step()) 112 { 113 return ErrorCode_UnknownResource; 114 } 115 116 if (s.ColumnIsNull(0)) 117 { 118 found = false; 119 } 120 else 121 { 122 found = true; 123 parentId = s.ColumnInt(0); 124 } 125 126 return ErrorCode_Success; 127 } 128 GetPublicId(std::string & result,int64_t resourceId)129 bool DatabaseWrapperBase::GetPublicId(std::string& result, 130 int64_t resourceId) 131 { 132 SQLite::Statement s(db_, SQLITE_FROM_HERE, 133 "SELECT publicId FROM Resources WHERE internalId=?"); 134 s.BindInt64(0, resourceId); 135 136 if (!s.Step()) 137 { 138 return false; 139 } 140 else 141 { 142 result = s.ColumnString(0); 143 return true; 144 } 145 } 146 147 GetResourceType(ResourceType & result,int64_t resourceId)148 ErrorCode DatabaseWrapperBase::GetResourceType(ResourceType& result, 149 int64_t resourceId) 150 { 151 SQLite::Statement s(db_, SQLITE_FROM_HERE, 152 "SELECT resourceType FROM Resources WHERE internalId=?"); 153 s.BindInt64(0, resourceId); 154 155 if (s.Step()) 156 { 157 result = static_cast<ResourceType>(s.ColumnInt(0)); 158 return ErrorCode_Success; 159 } 160 else 161 { 162 return ErrorCode_UnknownResource; 163 } 164 } 165 166 AttachChild(int64_t parent,int64_t child)167 void DatabaseWrapperBase::AttachChild(int64_t parent, 168 int64_t child) 169 { 170 SQLite::Statement s(db_, SQLITE_FROM_HERE, "UPDATE Resources SET parentId = ? WHERE internalId = ?"); 171 s.BindInt64(0, parent); 172 s.BindInt64(1, child); 173 s.Run(); 174 } 175 176 SetMetadata(int64_t id,MetadataType type,const std::string & value)177 void DatabaseWrapperBase::SetMetadata(int64_t id, 178 MetadataType type, 179 const std::string& value) 180 { 181 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT OR REPLACE INTO Metadata VALUES(?, ?, ?)"); 182 s.BindInt64(0, id); 183 s.BindInt(1, type); 184 s.BindString(2, value); 185 s.Run(); 186 } 187 DeleteMetadata(int64_t id,MetadataType type)188 void DatabaseWrapperBase::DeleteMetadata(int64_t id, 189 MetadataType type) 190 { 191 SQLite::Statement s(db_, SQLITE_FROM_HERE, "DELETE FROM Metadata WHERE id=? and type=?"); 192 s.BindInt64(0, id); 193 s.BindInt(1, type); 194 s.Run(); 195 } 196 LookupMetadata(std::string & target,int64_t id,MetadataType type)197 bool DatabaseWrapperBase::LookupMetadata(std::string& target, 198 int64_t id, 199 MetadataType type) 200 { 201 SQLite::Statement s(db_, SQLITE_FROM_HERE, 202 "SELECT value FROM Metadata WHERE id=? AND type=?"); 203 s.BindInt64(0, id); 204 s.BindInt(1, type); 205 206 if (!s.Step()) 207 { 208 return false; 209 } 210 else 211 { 212 target = s.ColumnString(0); 213 return true; 214 } 215 } 216 ListAvailableMetadata(std::list<MetadataType> & target,int64_t id)217 void DatabaseWrapperBase::ListAvailableMetadata(std::list<MetadataType>& target, 218 int64_t id) 219 { 220 target.clear(); 221 222 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT type FROM Metadata WHERE id=?"); 223 s.BindInt64(0, id); 224 225 while (s.Step()) 226 { 227 target.push_back(static_cast<MetadataType>(s.ColumnInt(0))); 228 } 229 } 230 231 AddAttachment(int64_t id,const FileInfo & attachment)232 void DatabaseWrapperBase::AddAttachment(int64_t id, 233 const FileInfo& attachment) 234 { 235 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO AttachedFiles VALUES(?, ?, ?, ?, ?, ?, ?, ?)"); 236 s.BindInt64(0, id); 237 s.BindInt(1, attachment.GetContentType()); 238 s.BindString(2, attachment.GetUuid()); 239 s.BindInt64(3, attachment.GetCompressedSize()); 240 s.BindInt64(4, attachment.GetUncompressedSize()); 241 s.BindInt(5, attachment.GetCompressionType()); 242 s.BindString(6, attachment.GetUncompressedMD5()); 243 s.BindString(7, attachment.GetCompressedMD5()); 244 s.Run(); 245 } 246 247 DeleteAttachment(int64_t id,FileContentType attachment)248 void DatabaseWrapperBase::DeleteAttachment(int64_t id, 249 FileContentType attachment) 250 { 251 SQLite::Statement s(db_, SQLITE_FROM_HERE, "DELETE FROM AttachedFiles WHERE id=? AND fileType=?"); 252 s.BindInt64(0, id); 253 s.BindInt(1, attachment); 254 s.Run(); 255 } 256 257 258 ListAvailableAttachments(std::list<FileContentType> & target,int64_t id)259 void DatabaseWrapperBase::ListAvailableAttachments(std::list<FileContentType>& target, 260 int64_t id) 261 { 262 target.clear(); 263 264 SQLite::Statement s(db_, SQLITE_FROM_HERE, 265 "SELECT fileType FROM AttachedFiles WHERE id=?"); 266 s.BindInt64(0, id); 267 268 while (s.Step()) 269 { 270 target.push_back(static_cast<FileContentType>(s.ColumnInt(0))); 271 } 272 } 273 LookupAttachment(FileInfo & attachment,int64_t id,FileContentType contentType)274 bool DatabaseWrapperBase::LookupAttachment(FileInfo& attachment, 275 int64_t id, 276 FileContentType contentType) 277 { 278 SQLite::Statement s(db_, SQLITE_FROM_HERE, 279 "SELECT uuid, uncompressedSize, compressionType, compressedSize, uncompressedMD5, compressedMD5 FROM AttachedFiles WHERE id=? AND fileType=?"); 280 s.BindInt64(0, id); 281 s.BindInt(1, contentType); 282 283 if (!s.Step()) 284 { 285 return false; 286 } 287 else 288 { 289 attachment = FileInfo(s.ColumnString(0), 290 contentType, 291 s.ColumnInt64(1), 292 s.ColumnString(4), 293 static_cast<CompressionType>(s.ColumnInt(2)), 294 s.ColumnInt64(3), 295 s.ColumnString(5)); 296 return true; 297 } 298 } 299 300 ClearMainDicomTags(int64_t id)301 void DatabaseWrapperBase::ClearMainDicomTags(int64_t id) 302 { 303 { 304 SQLite::Statement s(db_, SQLITE_FROM_HERE, "DELETE FROM DicomIdentifiers WHERE id=?"); 305 s.BindInt64(0, id); 306 s.Run(); 307 } 308 309 { 310 SQLite::Statement s(db_, SQLITE_FROM_HERE, "DELETE FROM MainDicomTags WHERE id=?"); 311 s.BindInt64(0, id); 312 s.Run(); 313 } 314 } 315 316 SetMainDicomTag(int64_t id,const DicomTag & tag,const std::string & value)317 void DatabaseWrapperBase::SetMainDicomTag(int64_t id, 318 const DicomTag& tag, 319 const std::string& value) 320 { 321 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO MainDicomTags VALUES(?, ?, ?, ?)"); 322 s.BindInt64(0, id); 323 s.BindInt(1, tag.GetGroup()); 324 s.BindInt(2, tag.GetElement()); 325 s.BindString(3, value); 326 s.Run(); 327 } 328 329 SetIdentifierTag(int64_t id,const DicomTag & tag,const std::string & value)330 void DatabaseWrapperBase::SetIdentifierTag(int64_t id, 331 const DicomTag& tag, 332 const std::string& value) 333 { 334 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO DicomIdentifiers VALUES(?, ?, ?, ?)"); 335 s.BindInt64(0, id); 336 s.BindInt(1, tag.GetGroup()); 337 s.BindInt(2, tag.GetElement()); 338 s.BindString(3, value); 339 s.Run(); 340 } 341 342 GetMainDicomTags(DicomMap & map,int64_t id)343 void DatabaseWrapperBase::GetMainDicomTags(DicomMap& map, 344 int64_t id) 345 { 346 map.Clear(); 347 348 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT * FROM MainDicomTags WHERE id=?"); 349 s.BindInt64(0, id); 350 while (s.Step()) 351 { 352 map.SetValue(s.ColumnInt(1), 353 s.ColumnInt(2), 354 s.ColumnString(3), false); 355 } 356 } 357 358 359 GetChildrenPublicId(std::list<std::string> & target,int64_t id)360 void DatabaseWrapperBase::GetChildrenPublicId(std::list<std::string>& target, 361 int64_t id) 362 { 363 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT a.publicId FROM Resources AS a, Resources AS b " 364 "WHERE a.parentId = b.internalId AND b.internalId = ?"); 365 s.BindInt64(0, id); 366 367 target.clear(); 368 369 while (s.Step()) 370 { 371 target.push_back(s.ColumnString(0)); 372 } 373 } 374 375 GetChildrenInternalId(std::list<int64_t> & target,int64_t id)376 void DatabaseWrapperBase::GetChildrenInternalId(std::list<int64_t>& target, 377 int64_t id) 378 { 379 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT a.internalId FROM Resources AS a, Resources AS b " 380 "WHERE a.parentId = b.internalId AND b.internalId = ?"); 381 s.BindInt64(0, id); 382 383 target.clear(); 384 385 while (s.Step()) 386 { 387 target.push_back(s.ColumnInt64(0)); 388 } 389 } 390 391 LogChange(int64_t internalId,const ServerIndexChange & change)392 void DatabaseWrapperBase::LogChange(int64_t internalId, 393 const ServerIndexChange& change) 394 { 395 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Changes VALUES(NULL, ?, ?, ?, ?)"); 396 s.BindInt(0, change.GetChangeType()); 397 s.BindInt64(1, internalId); 398 s.BindInt(2, change.GetResourceType()); 399 s.BindString(3, change.GetDate()); 400 s.Run(); 401 } 402 403 GetChangesInternal(std::list<ServerIndexChange> & target,bool & done,SQLite::Statement & s,uint32_t maxResults)404 ErrorCode DatabaseWrapperBase::GetChangesInternal(std::list<ServerIndexChange>& target, 405 bool& done, 406 SQLite::Statement& s, 407 uint32_t maxResults) 408 { 409 target.clear(); 410 411 while (target.size() < maxResults && s.Step()) 412 { 413 int64_t seq = s.ColumnInt64(0); 414 ChangeType changeType = static_cast<ChangeType>(s.ColumnInt(1)); 415 ResourceType resourceType = static_cast<ResourceType>(s.ColumnInt(3)); 416 const std::string& date = s.ColumnString(4); 417 418 int64_t internalId = s.ColumnInt64(2); 419 std::string publicId; 420 if (!GetPublicId(publicId, internalId)) 421 { 422 return ErrorCode_UnknownResource; 423 } 424 425 target.push_back(ServerIndexChange(seq, changeType, resourceType, publicId, date)); 426 } 427 428 done = !(target.size() == maxResults && s.Step()); 429 return ErrorCode_Success; 430 } 431 432 GetChanges(std::list<ServerIndexChange> & target,bool & done,int64_t since,uint32_t maxResults)433 ErrorCode DatabaseWrapperBase::GetChanges(std::list<ServerIndexChange>& target, 434 bool& done, 435 int64_t since, 436 uint32_t maxResults) 437 { 438 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes WHERE seq>? ORDER BY seq LIMIT ?"); 439 s.BindInt64(0, since); 440 s.BindInt(1, maxResults + 1); 441 return GetChangesInternal(target, done, s, maxResults); 442 } 443 GetLastChange(std::list<ServerIndexChange> & target)444 ErrorCode DatabaseWrapperBase::GetLastChange(std::list<ServerIndexChange>& target) 445 { 446 bool done; // Ignored 447 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes ORDER BY seq DESC LIMIT 1"); 448 return GetChangesInternal(target, done, s, 1); 449 } 450 451 LogExportedResource(const ExportedResource & resource)452 void DatabaseWrapperBase::LogExportedResource(const ExportedResource& resource) 453 { 454 SQLite::Statement s(db_, SQLITE_FROM_HERE, 455 "INSERT INTO ExportedResources VALUES(NULL, ?, ?, ?, ?, ?, ?, ?, ?)"); 456 457 s.BindInt(0, resource.GetResourceType()); 458 s.BindString(1, resource.GetPublicId()); 459 s.BindString(2, resource.GetModality()); 460 s.BindString(3, resource.GetPatientId()); 461 s.BindString(4, resource.GetStudyInstanceUid()); 462 s.BindString(5, resource.GetSeriesInstanceUid()); 463 s.BindString(6, resource.GetSopInstanceUid()); 464 s.BindString(7, resource.GetDate()); 465 s.Run(); 466 } 467 468 GetExportedResourcesInternal(std::list<ExportedResource> & target,bool & done,SQLite::Statement & s,uint32_t maxResults)469 void DatabaseWrapperBase::GetExportedResourcesInternal(std::list<ExportedResource>& target, 470 bool& done, 471 SQLite::Statement& s, 472 uint32_t maxResults) 473 { 474 target.clear(); 475 476 while (target.size() < maxResults && s.Step()) 477 { 478 int64_t seq = s.ColumnInt64(0); 479 ResourceType resourceType = static_cast<ResourceType>(s.ColumnInt(1)); 480 std::string publicId = s.ColumnString(2); 481 482 ExportedResource resource(seq, 483 resourceType, 484 publicId, 485 s.ColumnString(3), // modality 486 s.ColumnString(8), // date 487 s.ColumnString(4), // patient ID 488 s.ColumnString(5), // study instance UID 489 s.ColumnString(6), // series instance UID 490 s.ColumnString(7)); // sop instance UID 491 492 target.push_back(resource); 493 } 494 495 done = !(target.size() == maxResults && s.Step()); 496 } 497 498 GetExportedResources(std::list<ExportedResource> & target,bool & done,int64_t since,uint32_t maxResults)499 void DatabaseWrapperBase::GetExportedResources(std::list<ExportedResource>& target, 500 bool& done, 501 int64_t since, 502 uint32_t maxResults) 503 { 504 SQLite::Statement s(db_, SQLITE_FROM_HERE, 505 "SELECT * FROM ExportedResources WHERE seq>? ORDER BY seq LIMIT ?"); 506 s.BindInt64(0, since); 507 s.BindInt(1, maxResults + 1); 508 GetExportedResourcesInternal(target, done, s, maxResults); 509 } 510 511 GetLastExportedResource(std::list<ExportedResource> & target)512 void DatabaseWrapperBase::GetLastExportedResource(std::list<ExportedResource>& target) 513 { 514 bool done; // Ignored 515 SQLite::Statement s(db_, SQLITE_FROM_HERE, 516 "SELECT * FROM ExportedResources ORDER BY seq DESC LIMIT 1"); 517 GetExportedResourcesInternal(target, done, s, 1); 518 } 519 520 521 GetTotalCompressedSize()522 uint64_t DatabaseWrapperBase::GetTotalCompressedSize() 523 { 524 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT SUM(compressedSize) FROM AttachedFiles"); 525 s.Run(); 526 return static_cast<uint64_t>(s.ColumnInt64(0)); 527 } 528 529 GetTotalUncompressedSize()530 uint64_t DatabaseWrapperBase::GetTotalUncompressedSize() 531 { 532 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT SUM(uncompressedSize) FROM AttachedFiles"); 533 s.Run(); 534 return static_cast<uint64_t>(s.ColumnInt64(0)); 535 } 536 GetAllInternalIds(std::list<int64_t> & target,ResourceType resourceType)537 void DatabaseWrapperBase::GetAllInternalIds(std::list<int64_t>& target, 538 ResourceType resourceType) 539 { 540 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT internalId FROM Resources WHERE resourceType=?"); 541 s.BindInt(0, resourceType); 542 543 target.clear(); 544 while (s.Step()) 545 { 546 target.push_back(s.ColumnInt64(0)); 547 } 548 } 549 550 GetAllPublicIds(std::list<std::string> & target,ResourceType resourceType)551 void DatabaseWrapperBase::GetAllPublicIds(std::list<std::string>& target, 552 ResourceType resourceType) 553 { 554 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT publicId FROM Resources WHERE resourceType=?"); 555 s.BindInt(0, resourceType); 556 557 target.clear(); 558 while (s.Step()) 559 { 560 target.push_back(s.ColumnString(0)); 561 } 562 } 563 GetAllPublicIds(std::list<std::string> & target,ResourceType resourceType,size_t since,size_t limit)564 void DatabaseWrapperBase::GetAllPublicIds(std::list<std::string>& target, 565 ResourceType resourceType, 566 size_t since, 567 size_t limit) 568 { 569 if (limit == 0) 570 { 571 target.clear(); 572 return; 573 } 574 575 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT publicId FROM Resources WHERE resourceType=? LIMIT ? OFFSET ?"); 576 s.BindInt(0, resourceType); 577 s.BindInt64(1, limit); 578 s.BindInt64(2, since); 579 580 target.clear(); 581 while (s.Step()) 582 { 583 target.push_back(s.ColumnString(0)); 584 } 585 } 586 587 GetResourceCount(ResourceType resourceType)588 uint64_t DatabaseWrapperBase::GetResourceCount(ResourceType resourceType) 589 { 590 SQLite::Statement s(db_, SQLITE_FROM_HERE, 591 "SELECT COUNT(*) FROM Resources WHERE resourceType=?"); 592 s.BindInt(0, resourceType); 593 594 if (!s.Step()) 595 { 596 return 0; 597 } 598 else 599 { 600 int64_t c = s.ColumnInt(0); 601 assert(!s.Step()); 602 return c; 603 } 604 } 605 606 SelectPatientToRecycle(int64_t & internalId)607 bool DatabaseWrapperBase::SelectPatientToRecycle(int64_t& internalId) 608 { 609 SQLite::Statement s(db_, SQLITE_FROM_HERE, 610 "SELECT patientId FROM PatientRecyclingOrder ORDER BY seq ASC LIMIT 1"); 611 612 if (!s.Step()) 613 { 614 // No patient remaining or all the patients are protected 615 return false; 616 } 617 else 618 { 619 internalId = s.ColumnInt(0); 620 return true; 621 } 622 } 623 SelectPatientToRecycle(int64_t & internalId,int64_t patientIdToAvoid)624 bool DatabaseWrapperBase::SelectPatientToRecycle(int64_t& internalId, 625 int64_t patientIdToAvoid) 626 { 627 SQLite::Statement s(db_, SQLITE_FROM_HERE, 628 "SELECT patientId FROM PatientRecyclingOrder " 629 "WHERE patientId != ? ORDER BY seq ASC LIMIT 1"); 630 s.BindInt64(0, patientIdToAvoid); 631 632 if (!s.Step()) 633 { 634 // No patient remaining or all the patients are protected 635 return false; 636 } 637 else 638 { 639 internalId = s.ColumnInt(0); 640 return true; 641 } 642 } 643 IsProtectedPatient(int64_t internalId)644 bool DatabaseWrapperBase::IsProtectedPatient(int64_t internalId) 645 { 646 SQLite::Statement s(db_, SQLITE_FROM_HERE, 647 "SELECT * FROM PatientRecyclingOrder WHERE patientId = ?"); 648 s.BindInt64(0, internalId); 649 return !s.Step(); 650 } 651 SetProtectedPatient(int64_t internalId,bool isProtected)652 void DatabaseWrapperBase::SetProtectedPatient(int64_t internalId, 653 bool isProtected) 654 { 655 if (isProtected) 656 { 657 SQLite::Statement s(db_, SQLITE_FROM_HERE, "DELETE FROM PatientRecyclingOrder WHERE patientId=?"); 658 s.BindInt64(0, internalId); 659 s.Run(); 660 } 661 else if (IsProtectedPatient(internalId)) 662 { 663 SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO PatientRecyclingOrder VALUES(NULL, ?)"); 664 s.BindInt64(0, internalId); 665 s.Run(); 666 } 667 else 668 { 669 // Nothing to do: The patient is already unprotected 670 } 671 } 672 673 674 IsExistingResource(int64_t internalId)675 bool DatabaseWrapperBase::IsExistingResource(int64_t internalId) 676 { 677 SQLite::Statement s(db_, SQLITE_FROM_HERE, 678 "SELECT * FROM Resources WHERE internalId=?"); 679 s.BindInt64(0, internalId); 680 return s.Step(); 681 } 682 683 684 LookupIdentifier(std::list<int64_t> & target,ResourceType level,const DicomTag & tag,IdentifierConstraintType type,const std::string & value)685 void DatabaseWrapperBase::LookupIdentifier(std::list<int64_t>& target, 686 ResourceType level, 687 const DicomTag& tag, 688 IdentifierConstraintType type, 689 const std::string& value) 690 { 691 static const char* COMMON = ("SELECT d.id FROM DicomIdentifiers AS d, Resources AS r WHERE " 692 "d.id = r.internalId AND r.resourceType=? AND " 693 "d.tagGroup=? AND d.tagElement=? AND "); 694 695 std::auto_ptr<SQLite::Statement> s; 696 697 switch (type) 698 { 699 case IdentifierConstraintType_GreaterOrEqual: 700 s.reset(new SQLite::Statement(db_, std::string(COMMON) + "d.value>=?")); 701 break; 702 703 case IdentifierConstraintType_SmallerOrEqual: 704 s.reset(new SQLite::Statement(db_, std::string(COMMON) + "d.value<=?")); 705 break; 706 707 case IdentifierConstraintType_Wildcard: 708 s.reset(new SQLite::Statement(db_, std::string(COMMON) + "d.value GLOB ?")); 709 break; 710 711 case IdentifierConstraintType_Equal: 712 default: 713 s.reset(new SQLite::Statement(db_, std::string(COMMON) + "d.value=?")); 714 break; 715 } 716 717 assert(s.get() != NULL); 718 719 s->BindInt(0, level); 720 s->BindInt(1, tag.GetGroup()); 721 s->BindInt(2, tag.GetElement()); 722 s->BindString(3, value); 723 724 target.clear(); 725 726 while (s->Step()) 727 { 728 target.push_back(s->ColumnInt64(0)); 729 } 730 } 731 732 LookupIdentifierRange(std::list<int64_t> & target,ResourceType level,const DicomTag & tag,const std::string & start,const std::string & end)733 void DatabaseWrapperBase::LookupIdentifierRange(std::list<int64_t>& target, 734 ResourceType level, 735 const DicomTag& tag, 736 const std::string& start, 737 const std::string& end) 738 { 739 SQLite::Statement statement(db_, SQLITE_FROM_HERE, 740 "SELECT d.id FROM DicomIdentifiers AS d, Resources AS r WHERE " 741 "d.id = r.internalId AND r.resourceType=? AND " 742 "d.tagGroup=? AND d.tagElement=? AND d.value>=? AND d.value<=?"); 743 744 statement.BindInt(0, level); 745 statement.BindInt(1, tag.GetGroup()); 746 statement.BindInt(2, tag.GetElement()); 747 statement.BindString(3, start); 748 statement.BindString(4, end); 749 750 target.clear(); 751 752 while (statement.Step()) 753 { 754 target.push_back(statement.ColumnInt64(0)); 755 } 756 } 757 } 758