Mercurial > hg > orthanc-databases
comparison Framework/Plugins/IndexBackend.cpp @ 70:e6c13ddd26d9 db-changes
all integration tests passing with LookupResources extension
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 03 Jan 2019 14:04:46 +0100 |
parents | 19764fc60ade |
children | a4e440e65c68 |
comparison
equal
deleted
inserted
replaced
69:19764fc60ade | 70:e6c13ddd26d9 |
---|---|
54 | 54 |
55 return s; | 55 return s; |
56 } | 56 } |
57 | 57 |
58 | 58 |
59 int64_t IndexBackend::ReadInteger64(const DatabaseManager::CachedStatement& statement, | 59 int64_t IndexBackend::ReadInteger64(const DatabaseManager::StatementBase& statement, |
60 size_t field) | 60 size_t field) |
61 { | 61 { |
62 if (statement.IsDone()) | 62 if (statement.IsDone()) |
63 { | 63 { |
64 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | 64 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); |
76 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | 76 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
77 } | 77 } |
78 } | 78 } |
79 | 79 |
80 | 80 |
81 int32_t IndexBackend::ReadInteger32(const DatabaseManager::CachedStatement& statement, | 81 int32_t IndexBackend::ReadInteger32(const DatabaseManager::StatementBase& statement, |
82 size_t field) | 82 size_t field) |
83 { | 83 { |
84 if (statement.IsDone()) | 84 if (statement.IsDone()) |
85 { | 85 { |
86 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); | 86 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database); |
98 return static_cast<int32_t>(value); | 98 return static_cast<int32_t>(value); |
99 } | 99 } |
100 } | 100 } |
101 | 101 |
102 | 102 |
103 std::string IndexBackend::ReadString(const DatabaseManager::CachedStatement& statement, | 103 std::string IndexBackend::ReadString(const DatabaseManager::StatementBase& statement, |
104 size_t field) | 104 size_t field) |
105 { | 105 { |
106 const IValue& value = statement.GetResultField(field); | 106 const IValue& value = statement.GetResultField(field); |
107 | 107 |
108 switch (value.GetType()) | 108 switch (value.GetType()) |
109 { | 109 { |
110 case ValueType_BinaryString: | 110 case ValueType_BinaryString: |
111 return dynamic_cast<const BinaryStringValue&>(value).GetContent(); | 111 return dynamic_cast<const BinaryStringValue&>(value).GetContent(); |
112 | 112 |
1584 | 1584 |
1585 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 | 1585 #if ORTHANC_PLUGINS_HAS_DATABASE_CONSTRAINT == 1 |
1586 class IndexBackend::LookupFormatter : public Orthanc::ISqlLookupFormatter | 1586 class IndexBackend::LookupFormatter : public Orthanc::ISqlLookupFormatter |
1587 { | 1587 { |
1588 private: | 1588 private: |
1589 Dialect dialect_; | 1589 Dialect dialect_; |
1590 | 1590 size_t count_; |
1591 Dictionary dictionary_; | |
1592 | |
1593 static std::string FormatParameter(size_t index) | |
1594 { | |
1595 return "p" + boost::lexical_cast<std::string>(index); | |
1596 } | |
1597 | |
1591 public: | 1598 public: |
1592 LookupFormatter(Dialect dialect) : | 1599 LookupFormatter(Dialect dialect) : |
1593 dialect_(dialect) | 1600 dialect_(dialect), |
1601 count_(0) | |
1594 { | 1602 { |
1595 } | 1603 } |
1596 | 1604 |
1597 virtual std::string GenerateParameter(const std::string& value) | 1605 virtual std::string GenerateParameter(const std::string& value) |
1606 { | |
1607 const std::string key = FormatParameter(count_); | |
1608 | |
1609 count_ ++; | |
1610 dictionary_.SetUtf8Value(key, value); | |
1611 | |
1612 return "${" + key + "}"; | |
1613 } | |
1614 | |
1615 virtual std::string FormatResourceType(Orthanc::ResourceType level) | |
1616 { | |
1617 return boost::lexical_cast<std::string>(Orthanc::Plugins::Convert(level)); | |
1618 } | |
1619 | |
1620 virtual std::string FormatWildcardEscape() | |
1598 { | 1621 { |
1599 switch (dialect_) | 1622 switch (dialect_) |
1600 { | 1623 { |
1624 case Dialect_SQLite: | |
1625 case Dialect_PostgreSQL: | |
1626 return "ESCAPE '\\'"; | |
1627 | |
1601 case Dialect_MySQL: | 1628 case Dialect_MySQL: |
1602 break; | 1629 return "ESCAPE '\\\\'"; |
1603 | |
1604 case Dialect_PostgreSQL: | |
1605 break; | |
1606 | |
1607 case Dialect_SQLite: | |
1608 break; | |
1609 | 1630 |
1610 default: | 1631 default: |
1611 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | 1632 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); |
1612 } | 1633 } |
1634 } | |
1635 | |
1636 void PrepareStatement(DatabaseManager::StandaloneStatement& statement) const | |
1637 { | |
1638 statement.SetReadOnly(true); | |
1639 | |
1640 for (size_t i = 0; i < count_; i++) | |
1641 { | |
1642 statement.SetParameterType(FormatParameter(i), ValueType_Utf8String); | |
1643 } | |
1644 } | |
1645 | |
1646 const Dictionary& GetDictionary() const | |
1647 { | |
1648 return dictionary_; | |
1613 } | 1649 } |
1614 }; | 1650 }; |
1615 #endif | 1651 #endif |
1616 | 1652 |
1617 | 1653 |
1620 void IndexBackend::LookupResources(const std::vector<Orthanc::DatabaseConstraint>& lookup, | 1656 void IndexBackend::LookupResources(const std::vector<Orthanc::DatabaseConstraint>& lookup, |
1621 OrthancPluginResourceType queryLevel, | 1657 OrthancPluginResourceType queryLevel, |
1622 uint32_t limit, | 1658 uint32_t limit, |
1623 bool requestSomeInstance) | 1659 bool requestSomeInstance) |
1624 { | 1660 { |
1661 LookupFormatter formatter(manager_.GetDialect()); | |
1662 | |
1625 std::string sql; | 1663 std::string sql; |
1626 | 1664 Orthanc::ISqlLookupFormatter::Apply(sql, formatter, lookup, |
1627 { | 1665 Orthanc::Plugins::Convert(queryLevel), limit); |
1628 LookupFormatter formatter(manager_.GetDialect()); | 1666 |
1629 Orthanc::ISqlLookupFormatter::Apply(sql, formatter, lookup, | 1667 if (requestSomeInstance) |
1630 Orthanc::Plugins::Convert(queryLevel), limit); | 1668 { |
1631 } | 1669 // Composite query to find some instance if requested |
1670 switch (queryLevel) | |
1671 { | |
1672 case OrthancPluginResourceType_Patient: | |
1673 sql = ("SELECT patients.publicId, MIN(instances.publicId) FROM (" + sql + ") patients " | |
1674 "INNER JOIN Resources studies ON studies.parentId = patients.internalId " | |
1675 "INNER JOIN Resources series ON series.parentId = studies.internalId " | |
1676 "INNER JOIN Resources instances ON instances.parentId = series.internalId " | |
1677 "GROUP BY patients.publicId"); | |
1678 break; | |
1679 | |
1680 case OrthancPluginResourceType_Study: | |
1681 sql = ("SELECT studies.publicId, MIN(instances.publicId) FROM (" + sql + ") studies " | |
1682 "INNER JOIN Resources series ON series.parentId = studies.internalId " | |
1683 "INNER JOIN Resources instances ON instances.parentId = series.internalId " | |
1684 "GROUP BY studies.publicId"); | |
1685 break; | |
1686 | |
1687 case OrthancPluginResourceType_Series: | |
1688 sql = ("SELECT series.publicId, MIN(instances.publicId) FROM (" + sql + ") series " | |
1689 "INNER JOIN Resources instances ON instances.parentId = series.internalId " | |
1690 "GROUP BY series.publicId"); | |
1691 break; | |
1692 | |
1693 case OrthancPluginResourceType_Instance: | |
1694 sql = ("SELECT instances.publicId, instances.publicId FROM (" + sql + ") instances"); | |
1695 break; | |
1696 | |
1697 default: | |
1698 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
1699 } | |
1700 } | |
1701 | |
1702 DatabaseManager::StandaloneStatement statement(GetManager(), sql); | |
1703 formatter.PrepareStatement(statement); | |
1704 | |
1705 statement.Execute(formatter.GetDictionary()); | |
1706 | |
1707 while (!statement.IsDone()) | |
1708 { | |
1709 if (requestSomeInstance) | |
1710 { | |
1711 GetOutput().AnswerMatchingResource(ReadString(statement, 0), ReadString(statement, 1)); | |
1712 } | |
1713 else | |
1714 { | |
1715 GetOutput().AnswerMatchingResource(ReadString(statement, 0)); | |
1716 } | |
1717 | |
1718 statement.Next(); | |
1719 } | |
1632 } | 1720 } |
1633 #endif | 1721 #endif |
1634 } | 1722 } |