Mercurial > hg > orthanc
diff OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp @ 5807:8279eaab0d1d attach-custom-data
merged default -> attach-custom-data
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Tue, 24 Sep 2024 11:39:52 +0200 |
parents | 9770d537880d 68fc5af30c03 |
children | 023a99146dd0 |
line wrap: on
line diff
--- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp Thu Sep 15 18:13:17 2022 +0200 +++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp Tue Sep 24 11:39:52 2024 +0200 @@ -2,8 +2,9 @@ * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium - * Copyright (C) 2017-2022 Osimis S.A., Belgium - * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium + * Copyright (C) 2017-2023 Osimis S.A., Belgium + * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium + * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -235,11 +236,11 @@ void GetChangesInternal(std::list<ServerIndexChange>& target, bool& done, SQLite::Statement& s, - uint32_t maxResults) + uint32_t limit) { target.clear(); - while (target.size() < maxResults && s.Step()) + while (target.size() < limit && s.Step()) { int64_t seq = s.ColumnInt64(0); ChangeType changeType = static_cast<ChangeType>(s.ColumnInt(1)); @@ -252,18 +253,18 @@ target.push_back(ServerIndexChange(seq, changeType, resourceType, publicId, date)); } - done = !(target.size() == maxResults && s.Step()); + done = !(target.size() == limit && s.Step()); } void GetExportedResourcesInternal(std::list<ExportedResource>& target, bool& done, SQLite::Statement& s, - uint32_t maxResults) + uint32_t limit) { target.clear(); - while (target.size() < maxResults && s.Step()) + while (target.size() < limit && s.Step()) { int64_t seq = s.ColumnInt64(0); ResourceType resourceType = static_cast<ResourceType>(s.ColumnInt(1)); @@ -282,7 +283,7 @@ target.push_back(resource); } - done = !(target.size() == maxResults && s.Step()); + done = !(target.size() == limit && s.Step()); } @@ -343,14 +344,16 @@ virtual void ApplyLookupResources(std::list<std::string>& resourcesId, std::list<std::string>* instancesId, - const std::vector<DatabaseConstraint>& lookup, + const DatabaseConstraints& lookup, ResourceType queryLevel, - size_t limit) ORTHANC_OVERRIDE + const std::set<std::string>& labels, + LabelsConstraint labelsConstraint, + uint32_t limit) ORTHANC_OVERRIDE { LookupFormatter formatter; std::string sql; - LookupFormatter::Apply(sql, formatter, lookup, queryLevel, limit); + LookupFormatter::Apply(sql, formatter, lookup, queryLevel, labels, labelsConstraint, limit); sql = "CREATE TEMPORARY TABLE Lookup AS " + sql; @@ -437,7 +440,7 @@ virtual int64_t CreateResource(const std::string& publicId, ResourceType type) ORTHANC_OVERRIDE { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Resources VALUES(NULL, ?, ?, NULL)"); + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Resources (internalId, resourceType, publicId, parentId) VALUES(NULL, ?, ?, NULL)"); s.BindInt(0, type); s.BindString(1, publicId); s.Run(); @@ -535,8 +538,8 @@ virtual void GetAllPublicIds(std::list<std::string>& target, ResourceType resourceType, - size_t since, - size_t limit) ORTHANC_OVERRIDE + int64_t since, + uint32_t limit) ORTHANC_OVERRIDE { if (limit == 0) { @@ -562,12 +565,12 @@ virtual void GetChanges(std::list<ServerIndexChange>& target /*out*/, bool& done /*out*/, int64_t since, - uint32_t maxResults) ORTHANC_OVERRIDE + uint32_t limit) ORTHANC_OVERRIDE { SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes WHERE seq>? ORDER BY seq LIMIT ?"); s.BindInt64(0, since); - s.BindInt(1, maxResults + 1); - GetChangesInternal(target, done, s, maxResults); + s.BindInt(1, limit + 1); + GetChangesInternal(target, done, s, limit); } @@ -614,13 +617,13 @@ virtual void GetExportedResources(std::list<ExportedResource>& target, bool& done, int64_t since, - uint32_t maxResults) ORTHANC_OVERRIDE + uint32_t limit) ORTHANC_OVERRIDE { SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT * FROM ExportedResources WHERE seq>? ORDER BY seq LIMIT ?"); s.BindInt64(0, since); - s.BindInt(1, maxResults + 1); - GetExportedResourcesInternal(target, done, s, maxResults); + s.BindInt(1, limit + 1); + GetExportedResourcesInternal(target, done, s, limit); } @@ -757,15 +760,6 @@ } - virtual bool IsExistingResource(int64_t internalId) ORTHANC_OVERRIDE - { - SQLite::Statement s(db_, SQLITE_FROM_HERE, - "SELECT * FROM Resources WHERE internalId=?"); - s.BindInt64(0, internalId); - return s.Step(); - } - - virtual bool IsProtectedPatient(int64_t internalId) ORTHANC_OVERRIDE { SQLite::Statement s(db_, SQLITE_FROM_HERE, @@ -791,14 +785,17 @@ } - virtual void LogChange(int64_t internalId, - const ServerIndexChange& change) ORTHANC_OVERRIDE + virtual void LogChange(ChangeType changeType, + ResourceType resourceType, + int64_t internalId, + const std::string& /* publicId - unused */, + const std::string& date) ORTHANC_OVERRIDE { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Changes VALUES(NULL, ?, ?, ?, ?)"); - s.BindInt(0, change.GetChangeType()); + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Changes (seq, changeType, internalId, resourceType, date) VALUES(NULL, ?, ?, ?, ?)"); + s.BindInt(0, changeType); s.BindInt64(1, internalId); - s.BindInt(2, change.GetResourceType()); - s.BindString(3, change.GetDate()); + s.BindInt(2, resourceType); + s.BindString(3, date); s.Run(); } @@ -806,7 +803,7 @@ virtual void LogExportedResource(const ExportedResource& resource) ORTHANC_OVERRIDE { SQLite::Statement s(db_, SQLITE_FROM_HERE, - "INSERT INTO ExportedResources VALUES(NULL, ?, ?, ?, ?, ?, ?, ?, ?)"); + "INSERT INTO ExportedResources (seq, resourceType, publicId, remoteModality, patientId, studyInstanceUid, seriesInstanceUid, sopInstanceUid, date) VALUES(NULL, ?, ?, ?, ?, ?, ?, ?, ?)"); s.BindInt(0, resource.GetResourceType()); s.BindString(1, resource.GetPublicId()); @@ -1001,7 +998,7 @@ // The "shared" info is not used by the SQLite database, as it // can only be used by one Orthanc server. - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT OR REPLACE INTO GlobalProperties VALUES(?, ?)"); + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT OR REPLACE INTO GlobalProperties (property, value) VALUES(?, ?)"); s.BindInt(0, property); s.BindString(1, value); s.Run(); @@ -1013,7 +1010,7 @@ const DicomTag& tag, const std::string& value) ORTHANC_OVERRIDE { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO DicomIdentifiers VALUES(?, ?, ?, ?)"); + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO DicomIdentifiers (id, tagGroup, tagElement, value) VALUES(?, ?, ?, ?)"); s.BindInt64(0, id); s.BindInt(1, tag.GetGroup()); s.BindInt(2, tag.GetElement()); @@ -1033,7 +1030,7 @@ } else if (IsProtectedPatient(internalId)) { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO PatientRecyclingOrder VALUES(NULL, ?)"); + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO PatientRecyclingOrder (seq, patientId) VALUES(NULL, ?)"); s.BindInt64(0, internalId); s.Run(); } @@ -1049,7 +1046,7 @@ const DicomTag& tag, const std::string& value) ORTHANC_OVERRIDE { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO MainDicomTags VALUES(?, ?, ?, ?)"); + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO MainDicomTags (id, tagGroup, tagElement, value) VALUES(?, ?, ?, ?)"); s.BindInt64(0, id); s.BindInt(1, tag.GetGroup()); s.BindInt(2, tag.GetElement()); @@ -1099,11 +1096,75 @@ { SQLite::Statement s(db_, SQLITE_FROM_HERE, - "INSERT INTO PatientRecyclingOrder VALUES(NULL, ?)"); + "INSERT INTO PatientRecyclingOrder (seq, patientId) VALUES(NULL, ?)"); s.BindInt64(0, patient); s.Run(); } } + + + virtual void AddLabel(int64_t resource, + const std::string& label) ORTHANC_OVERRIDE + { + if (label.empty()) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + else + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT OR IGNORE INTO Labels (id, label) VALUES(?, ?)"); + s.BindInt64(0, resource); + s.BindString(1, label); + s.Run(); + } + } + + + virtual void RemoveLabel(int64_t resource, + const std::string& label) ORTHANC_OVERRIDE + { + if (label.empty()) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + else + { + SQLite::Statement s(db_, SQLITE_FROM_HERE, "DELETE FROM Labels WHERE id=? AND label=?"); + s.BindInt64(0, resource); + s.BindString(1, label); + s.Run(); + } + } + + + virtual void ListLabels(std::set<std::string>& target, + int64_t resource) ORTHANC_OVERRIDE + { + target.clear(); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, + "SELECT label FROM Labels WHERE id=?"); + s.BindInt64(0, resource); + + while (s.Step()) + { + target.insert(s.ColumnString(0)); + } + } + + + virtual void ListAllLabels(std::set<std::string>& target) ORTHANC_OVERRIDE + { + target.clear(); + + SQLite::Statement s(db_, SQLITE_FROM_HERE, + "SELECT DISTINCT label FROM Labels"); + + while (s.Step()) + { + target.insert(s.ColumnString(0)); + } + } }; @@ -1298,6 +1359,9 @@ signalRemainingAncestor_(NULL), version_(0) { + // TODO: implement revisions in SQLite + dbCapabilities_.SetFlushToDisk(true); + dbCapabilities_.SetLabelsSupport(true); db_.Open(path); } @@ -1307,6 +1371,9 @@ signalRemainingAncestor_(NULL), version_(0) { + // TODO: implement revisions in SQLite + dbCapabilities_.SetFlushToDisk(true); + dbCapabilities_.SetLabelsSupport(true); db_.OpenInMemory(); } @@ -1384,20 +1451,29 @@ "Incompatible version of the Orthanc database: " + tmp); } - // New in Orthanc 1.5.1 - if (version_ >= 6) + if (version_ == 6) { - if (!transaction->LookupGlobalProperty(tmp, GlobalProperty_GetTotalSizeIsFast, true /* unused in SQLite */) - || tmp != "1") + // New in Orthanc 1.5.1 + if (!transaction->LookupGlobalProperty(tmp, GlobalProperty_GetTotalSizeIsFast, true /* unused in SQLite */) || + tmp != "1") { LOG(INFO) << "Installing the SQLite triggers to track the size of the attachments"; std::string query; ServerResources::GetFileResource(query, ServerResources::INSTALL_TRACK_ATTACHMENTS_SIZE); db_.Execute(query); } + + // New in Orthanc 1.12.0 + if (!db_.DoesTableExist("Labels")) + { + LOG(INFO) << "Installing the \"Labels\" table"; + std::string query; + ServerResources::GetFileResource(query, ServerResources::INSTALL_LABELS_TABLE); + db_.Execute(query); + } } - // New in Orthanc 1.12.0 + // New in Orthanc 1.12.5 if (version_ >= 6) { if (!transaction->LookupGlobalProperty(tmp, GlobalProperty_SQLiteHasCustomDataAndRevision, true /* unused in SQLite */) @@ -1528,7 +1604,7 @@ int64_t SQLiteDatabaseWrapper::UnitTestsTransaction::CreateResource(const std::string& publicId, ResourceType type) { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Resources VALUES(NULL, ?, ?, NULL)"); + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Resources (internalId, resourceType, publicId, parentId) VALUES(NULL, ?, ?, NULL)"); s.BindInt(0, type); s.BindString(1, publicId); s.Run(); @@ -1550,7 +1626,7 @@ const DicomTag& tag, const std::string& value) { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO DicomIdentifiers VALUES(?, ?, ?, ?)"); + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO DicomIdentifiers (id, tagGroup, tagElement, value) VALUES(?, ?, ?, ?)"); s.BindInt64(0, id); s.BindInt(1, tag.GetGroup()); s.BindInt(2, tag.GetElement()); @@ -1563,7 +1639,7 @@ const DicomTag& tag, const std::string& value) { - SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO MainDicomTags VALUES(?, ?, ?, ?)"); + SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO MainDicomTags (id, tagGroup, tagElement, value) VALUES(?, ?, ?, ?)"); s.BindInt64(0, id); s.BindInt(1, tag.GetGroup()); s.BindInt(2, tag.GetElement());