Mercurial > hg > orthanc-databases
comparison Framework/Plugins/IndexBackend.cpp @ 533:2d3163d992fd find-refactoring
merged large-queries -> find-refactoring
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Fri, 06 Sep 2024 15:32:06 +0200 |
parents | 25cfcb752af6 |
children | 4ecf50a4521c |
comparison
equal
deleted
inserted
replaced
527:61338585e7f7 | 533:2d3163d992fd |
---|---|
115 void IndexBackend::ReadChangesInternal(IDatabaseBackendOutput& output, | 115 void IndexBackend::ReadChangesInternal(IDatabaseBackendOutput& output, |
116 bool& done, | 116 bool& done, |
117 DatabaseManager& manager, | 117 DatabaseManager& manager, |
118 DatabaseManager::CachedStatement& statement, | 118 DatabaseManager::CachedStatement& statement, |
119 const Dictionary& args, | 119 const Dictionary& args, |
120 uint32_t limit) | 120 uint32_t limit, |
121 { | 121 bool returnFirstResults) |
122 { | |
123 struct Change | |
124 { | |
125 int64_t seq_; | |
126 int32_t changeType_; | |
127 OrthancPluginResourceType resourceType_; | |
128 std::string publicId_; | |
129 std::string changeDate_; | |
130 | |
131 Change(int64_t seq, int32_t changeType, OrthancPluginResourceType resourceType, const std::string& publicId, const std::string& changeDate) | |
132 : seq_(seq), changeType_(changeType), resourceType_(resourceType), publicId_(publicId), changeDate_(changeDate) | |
133 { | |
134 } | |
135 }; | |
136 | |
122 statement.Execute(args); | 137 statement.Execute(args); |
123 | 138 |
124 uint32_t count = 0; | 139 std::list<Change> changes; |
125 | 140 while (!statement.IsDone()) |
126 while (count < limit && | 141 { |
127 !statement.IsDone()) | 142 changes.push_back(Change( |
128 { | |
129 output.AnswerChange( | |
130 statement.ReadInteger64(0), | 143 statement.ReadInteger64(0), |
131 statement.ReadInteger32(1), | 144 statement.ReadInteger32(1), |
132 static_cast<OrthancPluginResourceType>(statement.ReadInteger32(2)), | 145 static_cast<OrthancPluginResourceType>(statement.ReadInteger32(2)), |
133 statement.ReadString(3), | 146 statement.ReadString(3), |
134 statement.ReadString(4)); | 147 statement.ReadString(4) |
148 )); | |
135 | 149 |
136 statement.Next(); | 150 statement.Next(); |
137 count++; | 151 } |
138 } | 152 |
139 | 153 done = changes.size() <= limit; // 'done' means we have returned all requested changes |
140 done = (count < limit || | 154 |
141 statement.IsDone()); | 155 // if we have retrieved more changes than requested -> cleanup |
156 if (changes.size() > limit) | |
157 { | |
158 assert(changes.size() == limit+1); // the statement should only request 1 element more | |
159 | |
160 if (returnFirstResults) | |
161 { | |
162 changes.pop_back(); | |
163 } | |
164 else | |
165 { | |
166 changes.pop_front(); | |
167 } | |
168 } | |
169 | |
170 for (std::list<Change>::const_iterator it = changes.begin(); it != changes.end(); ++it) | |
171 { | |
172 output.AnswerChange(it->seq_, it->changeType_, it->resourceType_, it->publicId_, it->changeDate_); | |
173 } | |
142 } | 174 } |
143 | 175 |
144 | 176 |
145 void IndexBackend::ReadExportedResourcesInternal(IDatabaseBackendOutput& output, | 177 void IndexBackend::ReadExportedResourcesInternal(IDatabaseBackendOutput& output, |
146 bool& done, | 178 bool& done, |
552 args.SetIntegerValue("since", since); | 584 args.SetIntegerValue("since", since); |
553 | 585 |
554 ReadListOfStrings(target, statement, args); | 586 ReadListOfStrings(target, statement, args); |
555 } | 587 } |
556 | 588 |
557 | |
558 /* Use GetOutput().AnswerChange() */ | |
559 void IndexBackend::GetChanges(IDatabaseBackendOutput& output, | 589 void IndexBackend::GetChanges(IDatabaseBackendOutput& output, |
560 bool& done /*out*/, | 590 bool& done /*out*/, |
561 DatabaseManager& manager, | 591 DatabaseManager& manager, |
562 int64_t since, | 592 int64_t since, |
563 uint32_t limit) | 593 uint32_t limit) |
564 { | 594 { |
565 std::string suffix; | 595 #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 5) |
596 GetChangesExtended(output, done, manager, since, -1, _OrthancPluginChangeType_All, limit); | |
597 #else | |
598 GetChangesExtended(output, done, manager, since, -1, 65535, limit); | |
599 #endif | |
600 } | |
601 | |
602 /* Use GetOutput().AnswerChange() */ | |
603 void IndexBackend::GetChangesExtended(IDatabaseBackendOutput& output, | |
604 bool& done /*out*/, | |
605 DatabaseManager& manager, | |
606 int64_t since, | |
607 int64_t to, | |
608 int32_t changeType, | |
609 uint32_t limit) | |
610 { | |
611 std::string limitSuffix; | |
566 if (manager.GetDialect() == Dialect_MSSQL) | 612 if (manager.GetDialect() == Dialect_MSSQL) |
567 { | 613 { |
568 suffix = "OFFSET 0 ROWS FETCH FIRST ${limit} ROWS ONLY"; | 614 limitSuffix = "OFFSET 0 ROWS FETCH FIRST ${limit} ROWS ONLY"; |
569 } | 615 } |
570 else | 616 else |
571 { | 617 { |
572 suffix = "LIMIT ${limit}"; | 618 limitSuffix = "LIMIT ${limit}"; |
573 } | 619 } |
574 | 620 |
575 DatabaseManager::CachedStatement statement( | 621 std::vector<std::string> filters; |
576 STATEMENT_FROM_HERE, manager, | 622 bool hasSince = false; |
577 "SELECT Changes.seq, Changes.changeType, Changes.resourceType, Resources.publicId, " | 623 bool hasTo = false; |
578 "Changes.date FROM Changes INNER JOIN Resources " | 624 bool hasFilterType = false; |
579 "ON Changes.internalId = Resources.internalId WHERE seq>${since} ORDER BY seq " + suffix); | 625 |
580 | 626 if (since > 0) |
627 { | |
628 hasSince = true; | |
629 filters.push_back("seq>${since}"); | |
630 } | |
631 if (to != -1) | |
632 { | |
633 hasTo = true; | |
634 filters.push_back("seq<=${to}"); | |
635 } | |
636 if (changeType != _OrthancPluginChangeType_All) | |
637 { | |
638 hasFilterType = true; | |
639 filters.push_back("changeType=${changeType}"); | |
640 } | |
641 | |
642 std::string filtersString; | |
643 if (filters.size() > 0) | |
644 { | |
645 Orthanc::Toolbox::JoinStrings(filtersString, filters, " AND "); | |
646 filtersString = "WHERE " + filtersString; | |
647 } | |
648 | |
649 std::string sql; | |
650 bool returnFirstResults; | |
651 if (hasTo && !hasSince) | |
652 { | |
653 // in this case, we want the largest values but we want them ordered in ascending order | |
654 sql = "SELECT * FROM (SELECT Changes.seq, Changes.changeType, Changes.resourceType, Resources.publicId, Changes.date " | |
655 "FROM Changes INNER JOIN Resources " | |
656 "ON Changes.internalId = Resources.internalId " + filtersString + " ORDER BY seq DESC " + limitSuffix + | |
657 ") AS FilteredChanges ORDER BY seq ASC"; | |
658 | |
659 returnFirstResults = false; | |
660 } | |
661 else | |
662 { | |
663 // default query: we want the smallest values ordered in ascending order | |
664 sql = "SELECT Changes.seq, Changes.changeType, Changes.resourceType, Resources.publicId, " | |
665 "Changes.date FROM Changes INNER JOIN Resources " | |
666 "ON Changes.internalId = Resources.internalId " + filtersString + " ORDER BY seq ASC " + limitSuffix; | |
667 returnFirstResults = true; | |
668 } | |
669 | |
670 DatabaseManager::CachedStatement statement(STATEMENT_FROM_HERE_DYNAMIC(sql), manager, sql); | |
581 statement.SetReadOnly(true); | 671 statement.SetReadOnly(true); |
672 Dictionary args; | |
673 | |
582 statement.SetParameterType("limit", ValueType_Integer64); | 674 statement.SetParameterType("limit", ValueType_Integer64); |
583 statement.SetParameterType("since", ValueType_Integer64); | 675 args.SetIntegerValue("limit", limit + 1); // we take limit+1 because we use the +1 to know if "Done" must be set to true |
584 | 676 |
585 Dictionary args; | 677 if (hasSince) |
586 args.SetIntegerValue("limit", limit + 1); | 678 { |
587 args.SetIntegerValue("since", since); | 679 statement.SetParameterType("since", ValueType_Integer64); |
588 | 680 args.SetIntegerValue("since", since); |
589 ReadChangesInternal(output, done, manager, statement, args, limit); | 681 } |
682 | |
683 if (hasTo) | |
684 { | |
685 statement.SetParameterType("to", ValueType_Integer64); | |
686 args.SetIntegerValue("to", to); | |
687 } | |
688 | |
689 if (hasFilterType) | |
690 { | |
691 statement.SetParameterType("changeType", ValueType_Integer64); | |
692 args.SetIntegerValue("changeType", changeType); | |
693 } | |
694 | |
695 ReadChangesInternal(output, done, manager, statement, args, limit, returnFirstResults); | |
590 } | 696 } |
591 | 697 |
592 | 698 |
593 void IndexBackend::GetChildrenInternalId(std::list<int64_t>& target /*out*/, | 699 void IndexBackend::GetChildrenInternalId(std::list<int64_t>& target /*out*/, |
594 DatabaseManager& manager, | 700 DatabaseManager& manager, |
684 statement.SetReadOnly(true); | 790 statement.SetReadOnly(true); |
685 | 791 |
686 Dictionary args; | 792 Dictionary args; |
687 | 793 |
688 bool done; // Ignored | 794 bool done; // Ignored |
689 ReadChangesInternal(output, done, manager, statement, args, 1); | 795 ReadChangesInternal(output, done, manager, statement, args, 1, true); |
690 } | 796 } |
691 | 797 |
692 | 798 |
693 /* Use GetOutput().AnswerExportedResource() */ | 799 /* Use GetOutput().AnswerExportedResource() */ |
694 void IndexBackend::GetLastExportedResource(IDatabaseBackendOutput& output, | 800 void IndexBackend::GetLastExportedResource(IDatabaseBackendOutput& output, |