Mercurial > hg > orthanc-databases
comparison Framework/Common/DatabaseManager.cpp @ 569:f18e46d7dbf8 attach-custom-data
merged find-refactoring -> attach-custom-data
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Tue, 24 Sep 2024 15:04:21 +0200 |
parents | 25cfcb752af6 |
children |
comparison
equal
deleted
inserted
replaced
368:82f73188b58d | 569:f18e46d7dbf8 |
---|---|
1 /** | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | 2 * Orthanc - A Lightweight, RESTful DICOM Store |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | 3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
4 * Department, University Hospital of Liege, Belgium | 4 * Department, University Hospital of Liege, Belgium |
5 * Copyright (C) 2017-2021 Osimis S.A., Belgium | 5 * Copyright (C) 2017-2023 Osimis S.A., Belgium |
6 * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium | |
7 * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium | |
6 * | 8 * |
7 * This program is free software: you can redistribute it and/or | 9 * This program is free software: you can redistribute it and/or |
8 * modify it under the terms of the GNU Affero General Public License | 10 * modify it under the terms of the GNU Affero General Public License |
9 * as published by the Free Software Foundation, either version 3 of | 11 * as published by the Free Software Foundation, either version 3 of |
10 * the License, or (at your option) any later version. | 12 * the License, or (at your option) any later version. |
75 Close(); | 77 Close(); |
76 } | 78 } |
77 } | 79 } |
78 | 80 |
79 | 81 |
80 IPrecompiledStatement* DatabaseManager::LookupCachedStatement(const StatementLocation& location) const | 82 IPrecompiledStatement* DatabaseManager::LookupCachedStatement(const StatementId& statementId) const |
81 { | 83 { |
82 CachedStatements::const_iterator found = cachedStatements_.find(location); | 84 CachedStatements::const_iterator found = cachedStatements_.find(statementId); |
83 | 85 |
84 if (found == cachedStatements_.end()) | 86 if (found == cachedStatements_.end()) |
85 { | 87 { |
86 return NULL; | 88 return NULL; |
87 } | 89 } |
91 return found->second; | 93 return found->second; |
92 } | 94 } |
93 } | 95 } |
94 | 96 |
95 | 97 |
96 IPrecompiledStatement& DatabaseManager::CacheStatement(const StatementLocation& location, | 98 IPrecompiledStatement& DatabaseManager::CacheStatement(const StatementId& statementId, |
97 const Query& query) | 99 const Query& query) |
98 { | 100 { |
99 LOG(TRACE) << "Caching statement from " << location.GetFile() << ":" << location.GetLine(); | 101 LOG(TRACE) << "Caching statement from " << statementId.GetFile() << ":" << statementId.GetLine() << "" << statementId.GetDynamicStatement(); |
100 | 102 |
101 std::unique_ptr<IPrecompiledStatement> statement(GetDatabase().Compile(query)); | 103 std::unique_ptr<IPrecompiledStatement> statement(GetDatabase().Compile(query)); |
102 | 104 |
103 IPrecompiledStatement* tmp = statement.get(); | 105 IPrecompiledStatement* tmp = statement.get(); |
104 if (tmp == NULL) | 106 if (tmp == NULL) |
105 { | 107 { |
106 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | 108 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
107 } | 109 } |
108 | 110 |
109 assert(cachedStatements_.find(location) == cachedStatements_.end()); | 111 assert(cachedStatements_.find(statementId) == cachedStatements_.end()); |
110 cachedStatements_[location] = statement.release(); | 112 cachedStatements_[statementId] = statement.release(); |
111 | 113 |
112 return *tmp; | 114 return *tmp; |
113 } | 115 } |
114 | 116 |
115 | 117 |
489 { | 491 { |
490 case ValueType_Integer64: | 492 case ValueType_Integer64: |
491 return dynamic_cast<const Integer64Value&>(value).GetValue(); | 493 return dynamic_cast<const Integer64Value&>(value).GetValue(); |
492 | 494 |
493 default: | 495 default: |
494 //LOG(ERROR) << value.Format(); | 496 // LOG(ERROR) << value.GetType(); |
495 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | 497 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "The returned field is not of the correct type (Integer64)"); |
496 } | 498 } |
497 } | 499 } |
498 } | 500 } |
499 | 501 |
500 | 502 |
508 { | 510 { |
509 int64_t value = ReadInteger64(field); | 511 int64_t value = ReadInteger64(field); |
510 | 512 |
511 if (value != static_cast<int64_t>(static_cast<int32_t>(value))) | 513 if (value != static_cast<int64_t>(static_cast<int32_t>(value))) |
512 { | 514 { |
513 LOG(ERROR) << "Integer overflow"; | 515 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Integer overflow"); |
514 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
515 } | 516 } |
516 else | 517 else |
517 { | 518 { |
518 return static_cast<int32_t>(value); | 519 return static_cast<int32_t>(value); |
519 } | 520 } |
520 } | 521 } |
521 } | 522 } |
522 | 523 |
523 | 524 bool DatabaseManager::StatementBase::IsNull(size_t field) const |
525 { | |
526 if (IsDone()) | |
527 { | |
528 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | |
529 } | |
530 else | |
531 { | |
532 return GetResultField(field).GetType() == ValueType_Null; | |
533 } | |
534 } | |
535 | |
524 std::string DatabaseManager::StatementBase::ReadString(size_t field) const | 536 std::string DatabaseManager::StatementBase::ReadString(size_t field) const |
525 { | 537 { |
526 const IValue& value = GetResultField(field); | 538 const IValue& value = GetResultField(field); |
527 | 539 |
528 switch (value.GetType()) | 540 switch (value.GetType()) |
532 | 544 |
533 case ValueType_Utf8String: | 545 case ValueType_Utf8String: |
534 return dynamic_cast<const Utf8StringValue&>(value).GetContent(); | 546 return dynamic_cast<const Utf8StringValue&>(value).GetContent(); |
535 | 547 |
536 default: | 548 default: |
537 //LOG(ERROR) << value.Format(); | 549 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "The returned field is not of the correct type (String)"); |
538 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | 550 } |
539 } | 551 } |
540 } | 552 |
541 | 553 std::string DatabaseManager::StatementBase::ReadStringOrNull(size_t field) const |
542 | 554 { |
543 DatabaseManager::CachedStatement::CachedStatement(const StatementLocation& location, | 555 if (IsNull(field)) |
556 { | |
557 return std::string(); | |
558 } | |
559 else | |
560 { | |
561 return ReadString(field); | |
562 } | |
563 } | |
564 | |
565 DatabaseManager::CachedStatement::CachedStatement(const StatementId& statementId, | |
544 DatabaseManager& manager, | 566 DatabaseManager& manager, |
545 const std::string& sql) : | 567 const std::string& sql) : |
546 StatementBase(manager), | 568 StatementBase(manager), |
547 location_(location) | 569 statementId_(statementId) |
548 { | 570 { |
549 statement_ = GetManager().LookupCachedStatement(location_); | 571 statement_ = GetManager().LookupCachedStatement(statementId_); |
550 | 572 |
551 if (statement_ == NULL) | 573 if (statement_ == NULL) |
552 { | 574 { |
553 SetQuery(new Query(sql)); | 575 SetQuery(new Query(sql)); |
554 } | 576 } |
555 else | 577 else |
556 { | 578 { |
557 LOG(TRACE) << "Reusing cached statement from " | 579 LOG(TRACE) << "Reusing cached statement from " |
558 << location_.GetFile() << ":" << location_.GetLine(); | 580 << statementId_.GetFile() << ":" << statementId_.GetLine() << " " << statementId_.GetDynamicStatement(); |
559 } | 581 } |
560 } | 582 } |
561 | 583 |
562 | 584 void DatabaseManager::CachedStatement::ExecuteInternal(const Dictionary& parameters, bool withResults) |
563 void DatabaseManager::CachedStatement::Execute(const Dictionary& parameters) | |
564 { | 585 { |
565 try | 586 try |
566 { | 587 { |
567 std::unique_ptr<Query> query(ReleaseQuery()); | 588 std::unique_ptr<Query> query(ReleaseQuery()); |
568 | 589 |
569 if (query.get() != NULL) | 590 if (query.get() != NULL) |
570 { | 591 { |
571 // Register the newly-created statement | 592 // Register the newly-created statement |
572 assert(statement_ == NULL); | 593 assert(statement_ == NULL); |
573 statement_ = &GetManager().CacheStatement(location_, *query); | 594 statement_ = &GetManager().CacheStatement(statementId_, *query); |
574 } | 595 } |
575 | 596 |
576 assert(statement_ != NULL); | 597 assert(statement_ != NULL); |
577 | 598 |
578 /* | 599 /* |
584 boost::lexical_cast<std::string>(location_.GetLine())); | 605 boost::lexical_cast<std::string>(location_.GetLine())); |
585 OrthancPlugins::MetricsTimer timer(name.c_str()); | 606 OrthancPlugins::MetricsTimer timer(name.c_str()); |
586 #endif | 607 #endif |
587 */ | 608 */ |
588 | 609 |
589 SetResult(GetTransaction().Execute(*statement_, parameters)); | 610 if (withResults) |
611 { | |
612 SetResult(GetTransaction().Execute(*statement_, parameters)); | |
613 } | |
614 else | |
615 { | |
616 GetTransaction().ExecuteWithoutResult(*statement_, parameters); | |
617 } | |
590 } | 618 } |
591 catch (Orthanc::OrthancException& e) | 619 catch (Orthanc::OrthancException& e) |
592 { | 620 { |
593 GetManager().CloseIfUnavailable(e.GetErrorCode()); | 621 GetManager().CloseIfUnavailable(e.GetErrorCode()); |
594 throw; | 622 throw; |
595 } | 623 } |
596 } | 624 } |
597 | 625 |
626 | |
627 void DatabaseManager::CachedStatement::Execute(const Dictionary& parameters) | |
628 { | |
629 ExecuteInternal(parameters, true); | |
630 } | |
631 | |
632 void DatabaseManager::CachedStatement::ExecuteWithoutResult(const Dictionary& parameters) | |
633 { | |
634 ExecuteInternal(parameters, false); | |
635 } | |
636 | |
598 | 637 |
599 DatabaseManager::StandaloneStatement::StandaloneStatement(DatabaseManager& manager, | 638 DatabaseManager::StandaloneStatement::StandaloneStatement(DatabaseManager& manager, |
600 const std::string& sql) : | 639 const std::string& sql) : |
601 StatementBase(manager) | 640 StatementBase(manager) |
602 { | 641 { |
611 statement_.reset(); | 650 statement_.reset(); |
612 } | 651 } |
613 | 652 |
614 | 653 |
615 void DatabaseManager::StandaloneStatement::Execute(const Dictionary& parameters) | 654 void DatabaseManager::StandaloneStatement::Execute(const Dictionary& parameters) |
655 { | |
656 ExecuteInternal(parameters, true); | |
657 } | |
658 | |
659 void DatabaseManager::StandaloneStatement::ExecuteWithoutResult(const Dictionary& parameters) | |
660 { | |
661 ExecuteInternal(parameters, false); | |
662 } | |
663 | |
664 void DatabaseManager::StandaloneStatement::ExecuteInternal(const Dictionary& parameters, bool withResults) | |
616 { | 665 { |
617 try | 666 try |
618 { | 667 { |
619 std::unique_ptr<Query> query(ReleaseQuery()); | 668 std::unique_ptr<Query> query(ReleaseQuery()); |
620 assert(query.get() != NULL); | 669 assert(query.get() != NULL); |
623 // is not destroyed, as the "IResult" can make calls to the | 672 // is not destroyed, as the "IResult" can make calls to the |
624 // statement (this is the case for SQLite and MySQL) - (*) | 673 // statement (this is the case for SQLite and MySQL) - (*) |
625 statement_.reset(GetManager().GetDatabase().Compile(*query)); | 674 statement_.reset(GetManager().GetDatabase().Compile(*query)); |
626 assert(statement_.get() != NULL); | 675 assert(statement_.get() != NULL); |
627 | 676 |
628 SetResult(GetTransaction().Execute(*statement_, parameters)); | 677 std::unique_ptr<IResult> result(GetTransaction().Execute(*statement_, parameters)); |
678 | |
679 if (withResults) | |
680 { | |
681 SetResult(result.release()); | |
682 } | |
629 } | 683 } |
630 catch (Orthanc::OrthancException& e) | 684 catch (Orthanc::OrthancException& e) |
631 { | 685 { |
632 GetManager().CloseIfUnavailable(e.GetErrorCode()); | 686 GetManager().CloseIfUnavailable(e.GetErrorCode()); |
633 throw; | 687 throw; |