Mercurial > hg > orthanc
comparison OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp @ 5553:28cc06e4859a large-queries
Added ExtendedApiV1: /changes
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Thu, 11 Apr 2024 19:02:20 +0200 |
parents | 0d0f8788884a |
children | 3765085693e5 |
comparison
equal
deleted
inserted
replaced
5549:dcbf0c776945 | 5553:28cc06e4859a |
---|---|
231 | 231 |
232 | 232 |
233 void GetChangesInternal(std::list<ServerIndexChange>& target, | 233 void GetChangesInternal(std::list<ServerIndexChange>& target, |
234 bool& done, | 234 bool& done, |
235 SQLite::Statement& s, | 235 SQLite::Statement& s, |
236 uint32_t limit) | 236 uint32_t limit, |
237 bool returnFirstResults) // the statement usually returns limit+1 results while we only need the limit results -> we need to know which ones to return, the firsts or the lasts | |
237 { | 238 { |
238 target.clear(); | 239 target.clear(); |
239 | 240 |
240 while (target.size() < limit && s.Step()) | 241 while (s.Step()) |
241 { | 242 { |
242 int64_t seq = s.ColumnInt64(0); | 243 int64_t seq = s.ColumnInt64(0); |
243 ChangeType changeType = static_cast<ChangeType>(s.ColumnInt(1)); | 244 ChangeType changeType = static_cast<ChangeType>(s.ColumnInt(1)); |
244 ResourceType resourceType = static_cast<ResourceType>(s.ColumnInt(3)); | 245 ResourceType resourceType = static_cast<ResourceType>(s.ColumnInt(3)); |
245 const std::string& date = s.ColumnString(4); | 246 const std::string& date = s.ColumnString(4); |
248 std::string publicId = GetPublicId(internalId); | 249 std::string publicId = GetPublicId(internalId); |
249 | 250 |
250 target.push_back(ServerIndexChange(seq, changeType, resourceType, publicId, date)); | 251 target.push_back(ServerIndexChange(seq, changeType, resourceType, publicId, date)); |
251 } | 252 } |
252 | 253 |
253 done = !(target.size() == limit && s.Step()); | 254 done = target.size() <= limit; // 'done' means "there are no more other changes of this type in that direction (depending on since/to)" |
255 | |
256 // if we have retrieved more changes than requested -> cleanup | |
257 if (target.size() > limit) | |
258 { | |
259 assert(target.size() == limit+1); // the statement should only request 1 element more | |
260 | |
261 if (returnFirstResults) | |
262 { | |
263 target.pop_back(); | |
264 } | |
265 else | |
266 { | |
267 target.pop_front(); | |
268 } | |
269 } | |
254 } | 270 } |
255 | 271 |
256 | 272 |
257 void GetExportedResourcesInternal(std::list<ExportedResource>& target, | 273 void GetExportedResourcesInternal(std::list<ExportedResource>& target, |
258 bool& done, | 274 bool& done, |
538 virtual void GetChanges(std::list<ServerIndexChange>& target /*out*/, | 554 virtual void GetChanges(std::list<ServerIndexChange>& target /*out*/, |
539 bool& done /*out*/, | 555 bool& done /*out*/, |
540 int64_t since, | 556 int64_t since, |
541 uint32_t limit) ORTHANC_OVERRIDE | 557 uint32_t limit) ORTHANC_OVERRIDE |
542 { | 558 { |
543 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes WHERE seq>? ORDER BY seq LIMIT ?"); | 559 GetChanges2(target, done, since, -1, limit, ChangeType_INTERNAL_All); |
544 s.BindInt64(0, since); | 560 } |
545 s.BindInt(1, limit + 1); | 561 |
546 GetChangesInternal(target, done, s, limit); | 562 virtual void GetChanges2(std::list<ServerIndexChange>& target /*out*/, |
563 bool& done /*out*/, | |
564 int64_t since, | |
565 int64_t to, | |
566 uint32_t limit, | |
567 ChangeType filterType) ORTHANC_OVERRIDE | |
568 { | |
569 std::vector<std::string> filters; | |
570 bool hasSince = false; | |
571 bool hasTo = false; | |
572 bool hasFilterType = false; | |
573 | |
574 if (since > 0) | |
575 { | |
576 hasSince = true; | |
577 filters.push_back("seq>?"); | |
578 } | |
579 if (to != -1) | |
580 { | |
581 hasTo = true; | |
582 filters.push_back("seq<=?"); | |
583 } | |
584 if (filterType != ChangeType_INTERNAL_All) | |
585 { | |
586 hasFilterType = true; | |
587 filters.push_back("changeType=?"); | |
588 } | |
589 | |
590 std::string filtersString; | |
591 if (filters.size() > 0) | |
592 { | |
593 Toolbox::JoinStrings(filtersString, filters, " AND "); | |
594 filtersString = "WHERE " + filtersString; | |
595 } | |
596 | |
597 std::string sql; | |
598 bool returnFirstResults; | |
599 if (hasTo && !hasSince) | |
600 { | |
601 // in this case, we want the largest values in the LIMIT clause but we want them ordered in ascending order | |
602 sql = "SELECT * FROM (SELECT * FROM Changes " + filtersString + " ORDER BY seq DESC LIMIT ?) ORDER BY seq ASC"; | |
603 returnFirstResults = false; | |
604 } | |
605 else | |
606 { | |
607 // default query: we want the smallest values ordered in ascending order | |
608 sql = "SELECT * FROM Changes " + filtersString + " ORDER BY seq ASC LIMIT ?"; | |
609 returnFirstResults = true; | |
610 } | |
611 | |
612 SQLite::Statement s(db_, SQLITE_FROM_HERE_DYNAMIC(sql), sql); | |
613 | |
614 int paramCounter = 0; | |
615 if (hasSince) | |
616 { | |
617 s.BindInt64(paramCounter++, since); | |
618 } | |
619 if (hasTo) | |
620 { | |
621 s.BindInt64(paramCounter++, to); | |
622 } | |
623 if (hasFilterType) | |
624 { | |
625 s.BindInt(paramCounter++, filterType); | |
626 } | |
627 s.BindInt(paramCounter++, limit + 1); // we take limit+1 because we use the +1 to know if "Done" must be set to true | |
628 GetChangesInternal(target, done, s, limit, returnFirstResults); | |
547 } | 629 } |
548 | 630 |
549 | 631 |
550 virtual void GetChildrenMetadata(std::list<std::string>& target, | 632 virtual void GetChildrenMetadata(std::list<std::string>& target, |
551 int64_t resourceId, | 633 int64_t resourceId, |
602 | 684 |
603 virtual void GetLastChange(std::list<ServerIndexChange>& target /*out*/) ORTHANC_OVERRIDE | 685 virtual void GetLastChange(std::list<ServerIndexChange>& target /*out*/) ORTHANC_OVERRIDE |
604 { | 686 { |
605 bool done; // Ignored | 687 bool done; // Ignored |
606 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes ORDER BY seq DESC LIMIT 1"); | 688 SQLite::Statement s(db_, SQLITE_FROM_HERE, "SELECT * FROM Changes ORDER BY seq DESC LIMIT 1"); |
607 GetChangesInternal(target, done, s, 1); | 689 GetChangesInternal(target, done, s, 1, true); |
608 } | 690 } |
609 | 691 |
610 | 692 |
611 int64_t GetLastChangeIndex() ORTHANC_OVERRIDE | 693 int64_t GetLastChangeIndex() ORTHANC_OVERRIDE |
612 { | 694 { |
1325 version_(0) | 1407 version_(0) |
1326 { | 1408 { |
1327 // TODO: implement revisions in SQLite | 1409 // TODO: implement revisions in SQLite |
1328 dbCapabilities_.SetFlushToDisk(true); | 1410 dbCapabilities_.SetFlushToDisk(true); |
1329 dbCapabilities_.SetLabelsSupport(true); | 1411 dbCapabilities_.SetLabelsSupport(true); |
1412 dbCapabilities_.SetHasExtendedApiV1(true); | |
1330 db_.Open(path); | 1413 db_.Open(path); |
1331 } | 1414 } |
1332 | 1415 |
1333 | 1416 |
1334 SQLiteDatabaseWrapper::SQLiteDatabaseWrapper() : | 1417 SQLiteDatabaseWrapper::SQLiteDatabaseWrapper() : |
1337 version_(0) | 1420 version_(0) |
1338 { | 1421 { |
1339 // TODO: implement revisions in SQLite | 1422 // TODO: implement revisions in SQLite |
1340 dbCapabilities_.SetFlushToDisk(true); | 1423 dbCapabilities_.SetFlushToDisk(true); |
1341 dbCapabilities_.SetLabelsSupport(true); | 1424 dbCapabilities_.SetLabelsSupport(true); |
1425 dbCapabilities_.SetHasExtendedApiV1(true); | |
1342 db_.OpenInMemory(); | 1426 db_.OpenInMemory(); |
1343 } | 1427 } |
1344 | 1428 |
1345 SQLiteDatabaseWrapper::~SQLiteDatabaseWrapper() | 1429 SQLiteDatabaseWrapper::~SQLiteDatabaseWrapper() |
1346 { | 1430 { |