# HG changeset patch # User Sebastien Jodogne # Date 1545214719 -3600 # Node ID 25afa7b8cb51969b922b412f96f342407a487ff6 # Parent ea653ec47f31de004331ee2af242607feadb19ac SQLiteDatabaseWrapper::ApplyLookupResources() diff -r ea653ec47f31 -r 25afa7b8cb51 OrthancServer/SQLiteDatabaseWrapper.cpp --- a/OrthancServer/SQLiteDatabaseWrapper.cpp Tue Dec 18 18:56:55 2018 +0100 +++ b/OrthancServer/SQLiteDatabaseWrapper.cpp Wed Dec 19 11:18:39 2018 +0100 @@ -1206,6 +1206,28 @@ } + static std::string FormatLevel(ResourceType level) + { + switch (level) + { + case ResourceType_Patient: + return "patients"; + + case ResourceType_Study: + return "studies"; + + case ResourceType_Series: + return "series"; + + case ResourceType_Instance: + return "instances"; + + default: + throw OrthancException(ErrorCode_InternalError); + } + } + + static void FormatJoin(std::string& target, const DatabaseConstraint& constraint, size_t index) @@ -1230,31 +1252,8 @@ target += "MainDicomTags "; } - target += tag + " ON " + tag + ".id = "; - - switch (constraint.GetLevel()) - { - case ResourceType_Patient: - target += "patient"; - break; - - case ResourceType_Study: - target += "study"; - break; - - case ResourceType_Series: - target += "series"; - break; - - case ResourceType_Instance: - target += "instance"; - break; - - default: - throw OrthancException(ErrorCode_InternalError); - } - - target += (".internalId AND " + tag + ".tagGroup = " + + target += (tag + " ON " + tag + ".id = " + FormatLevel(constraint.GetLevel()) + + ".internalId AND " + tag + ".tagGroup = " + boost::lexical_cast(constraint.GetTag().GetGroup()) + " AND " + tag + ".tagElement = " + boost::lexical_cast(constraint.GetTag().GetElement())); @@ -1391,7 +1390,7 @@ } default: - // Don't modify "parameters"! + // Don't modify "parameters" in this case! return false; } @@ -1406,23 +1405,94 @@ return true; } - - - void SQLiteDatabaseWrapper::ApplyLookupPatients(std::vector& patientsId, - std::vector& instancesId, - const std::vector& lookup, - size_t limit) + + + static void PrepareLookup(SQLite::Connection& db) + { + SQLite::Statement s(db, SQLITE_FROM_HERE, "DROP TABLE IF EXISTS Lookup"); + s.Run(); + } + + + static void AnswerLookup(std::vector& resourcesId, + std::vector& instancesId, + SQLite::Connection& db, + ResourceType level) { - printf("ICI 1\n"); + resourcesId.clear(); + instancesId.clear(); + + std::auto_ptr statement; + + switch (level) + { + case ResourceType_Patient: + { + statement.reset( + new SQLite::Statement( + db, SQLITE_FROM_HERE, + "SELECT patients.publicId, instances.publicID FROM Lookup AS patients " + "INNER JOIN Resources studies ON patients.internalId=studies.parentId " + "INNER JOIN Resources series ON studies.internalId=series.parentId " + "INNER JOIN Resources instances ON series.internalId=instances.parentId " + "GROUP BY patients.publicId")); + + break; + } - { - SQLite::Statement s(db_, "DROP TABLE IF EXISTS Lookup"); - s.Run(); + case ResourceType_Study: + { + statement.reset( + new SQLite::Statement( + db, SQLITE_FROM_HERE, + "SELECT studies.publicId, instances.publicID FROM Lookup AS studies " + "INNER JOIN Resources series ON studies.internalId=series.parentId " + "INNER JOIN Resources instances ON series.internalId=instances.parentId " + "GROUP BY studies.publicId")); + + break; + } + + case ResourceType_Series: + { + statement.reset( + new SQLite::Statement( + db, SQLITE_FROM_HERE, + "SELECT series.publicId, instances.publicID FROM Lookup AS series " + "INNER JOIN Resources instances ON series.internalId=instances.parentId " + "GROUP BY series.publicId")); + + break; + } + + case ResourceType_Instance: + { + statement.reset( + new SQLite::Statement( + db, SQLITE_FROM_HERE, "SELECT publicId, publicId FROM Lookup")); + + break; + } + + default: + throw OrthancException(ErrorCode_InternalError); } - - std::string joins, comparisons; - std::vector parameters; + assert(statement.get() != NULL); + + while (statement->Step()) + { + resourcesId.push_back(statement->ColumnString(0)); + instancesId.push_back(statement->ColumnString(1)); + } + } + + + static void FormatConstraints(std::string& joins, + std::string& comparisons, + std::vector& parameters, + const std::vector& lookup) + { size_t count = 0; for (size_t i = 0; i < lookup.size(); i++) @@ -1440,11 +1510,25 @@ count ++; } } + } + + + + void SQLiteDatabaseWrapper::ApplyLookupPatients(std::vector& patientsId, + std::vector& instancesId, + const std::vector& lookup, + size_t limit) + { + PrepareLookup(db_); + + std::string joins, comparisons; + std::vector parameters; + FormatConstraints(joins, comparisons, parameters, lookup); { std::string sql = ("CREATE TEMPORARY TABLE Lookup AS " - "SELECT patient.publicId, patient.internalId FROM Resources AS patient" + - joins + " WHERE patient.resourceType = " + + "SELECT patients.publicId, patients.internalId FROM Resources AS patients" + + joins + " WHERE patients.resourceType = " + boost::lexical_cast(ResourceType_Patient) + comparisons); if (limit != 0) @@ -1458,6 +1542,88 @@ for (size_t i = 0; i < parameters.size(); i++) { + s.BindString(i, parameters[i]); + } + + s.Run(); + } + + AnswerLookup(patientsId, instancesId, db_, ResourceType_Patient); + } + + + void SQLiteDatabaseWrapper::ApplyLookupResources(std::vector& resourcesId, + std::vector& instancesId, + const std::vector& lookup, + ResourceType queryLevel, + size_t limit) + { + assert(ResourceType_Patient < ResourceType_Study && + ResourceType_Study < ResourceType_Series && + ResourceType_Series < ResourceType_Instance); + + ResourceType upperLevel = queryLevel; + ResourceType lowerLevel = queryLevel; + + for (size_t i = 0; i < lookup.size(); i++) + { + ResourceType level = lookup[i].GetLevel(); + + if (level < upperLevel) + { + upperLevel = level; + } + + if (level > lowerLevel) + { + lowerLevel = level; + } + } + + printf("ICI 2: [%s] -> [%s]\n", EnumerationToString(upperLevel), EnumerationToString(lowerLevel)); + + PrepareLookup(db_); + + std::string joins, comparisons; + std::vector parameters; + FormatConstraints(joins, comparisons, parameters, lookup); + + { + std::string sql = ("CREATE TEMPORARY TABLE Lookup AS SELECT " + + FormatLevel(queryLevel) + ".publicId, " + + FormatLevel(queryLevel) + ".internalId" + + " FROM Resources AS " + FormatLevel(queryLevel)); + + for (int level = queryLevel - 1; level >= upperLevel; level--) + { + sql += (" INNER JOIN Resources " + + FormatLevel(static_cast(level)) + " ON " + + FormatLevel(static_cast(level)) + ".internalId=" + + FormatLevel(static_cast(level + 1)) + ".parentId"); + } + + for (int level = queryLevel + 1; level <= lowerLevel; level++) + { + sql += (" INNER JOIN Resources " + + FormatLevel(static_cast(level - 1)) + " ON " + + FormatLevel(static_cast(level - 1)) + ".internalId=" + + FormatLevel(static_cast(level)) + ".parentId"); + } + + sql += (joins + " WHERE " + FormatLevel(queryLevel) + ".resourceType = " + + boost::lexical_cast(queryLevel) + comparisons); + + if (limit != 0) + { + sql += " LIMIT " + boost::lexical_cast(limit); + } + + printf("[%s]\n", sql.c_str()); + + SQLite::Statement s(db_, sql); + + for (size_t i = 0; i < parameters.size(); i++) + { printf(" %lu = '%s'\n", i, parameters[i].c_str()); s.BindString(i, parameters[i]); } @@ -1465,52 +1631,6 @@ s.Run(); } - { - SQLite::Statement s - (db_, "SELECT patient.publicId, instances.publicID FROM Lookup AS patient " - "INNER JOIN Resources studies ON patient.internalId=studies.parentId " - "INNER JOIN Resources series ON studies.internalId=series.parentId " - "INNER JOIN Resources instances ON series.internalId=instances.parentId " - "GROUP BY patient.publicId"); - - patientsId.clear(); - - while (s.Step()) - { - const std::string patient = s.ColumnString(0); - const std::string instance = s.ColumnString(1); - patientsId.push_back(patient); - instancesId.push_back(instance); - printf("** [%s] [%s]\n", patient.c_str(), instance.c_str()); - } - } - } - - - void SQLiteDatabaseWrapper::ApplyLookupResources(std::vector& resourcesId, - std::vector& instancesId, - const std::vector& lookup, - ResourceType queryLevel, - size_t limit) - { - ResourceType upperLevel = queryLevel; - ResourceType lowerLevel = queryLevel; - - for (size_t i = 0; i < lookup.size(); i++) - { - if (!IsResourceLevelAboveOrEqual(upperLevel, lookup[i].GetLevel())) - { - upperLevel = lookup[i].GetLevel(); - } - - if (!IsResourceLevelAboveOrEqual(lookup[i].GetLevel(), lowerLevel)) - { - lowerLevel = lookup[i].GetLevel(); - } - } - - printf("ICI 2: [%s] -> [%s]\n", EnumerationToString(upperLevel), EnumerationToString(lowerLevel)); - - throw OrthancException(ErrorCode_NotImplemented); + AnswerLookup(resourcesId, instancesId, db_, queryLevel); } } diff -r ea653ec47f31 -r 25afa7b8cb51 OrthancServer/ServerIndex.cpp --- a/OrthancServer/ServerIndex.cpp Tue Dec 18 18:56:55 2018 +0100 +++ b/OrthancServer/ServerIndex.cpp Wed Dec 19 11:18:39 2018 +0100 @@ -2574,7 +2574,7 @@ DicomTagType tagType; mainDicomTagsRegistry_->LookupTag(tagLevel, tagType, constraint.GetTag()); - if (IsResourceLevelAboveOrEqual(tagLevel, queryLevel) && + if (//IsResourceLevelAboveOrEqual(tagLevel, queryLevel) && (tagType == DicomTagType_Identifier || tagType == DicomTagType_Main)) {