|
@@ -239,6 +239,40 @@ void test_vector_subdb_sentinel() {
|
|
|
"vector sub-db is stamped with its prefixed name");
|
|
"vector sub-db is stamped with its prefixed name");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// v2.4.4 Count is LMDB-first. Unfiltered it uses count(); filtered it uses
|
|
|
|
|
+// scan() with limit=0 and reads total_matched. Pin that contract: total_matched
|
|
|
|
|
+// is computed BEFORE pagination, so limit=0 must still report the true total
|
|
|
|
|
+// while returning no documents.
|
|
|
|
|
+void test_scan_limit_zero_reports_total() {
|
|
|
|
|
+ TmpEnv t("counting");
|
|
|
|
|
+ LmdbDocumentStore store(t.env);
|
|
|
|
|
+ for (int i = 0; i < 5; ++i) {
|
|
|
|
|
+ Document d;
|
|
|
|
|
+ d.id = "id" + std::to_string(i);
|
|
|
|
|
+ d.collection = "things";
|
|
|
|
|
+ d.set_data(nlohmann::json{{"kind", i < 3 ? "alpha" : "beta"}});
|
|
|
|
|
+ store.put("things", d.id, d);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ smartbotic::database::Query q;
|
|
|
|
|
+ q.limit = 0;
|
|
|
|
|
+ auto all = store.scan("things", q);
|
|
|
|
|
+ check(all.total_matched == 5, "limit=0 reports the full total");
|
|
|
|
|
+ check(all.documents.empty(), "limit=0 returns no documents");
|
|
|
|
|
+ check(store.count("things") == 5, "unfiltered count matches");
|
|
|
|
|
+
|
|
|
|
|
+ smartbotic::database::Query fq;
|
|
|
|
|
+ fq.limit = 0;
|
|
|
|
|
+ smartbotic::database::Filter f;
|
|
|
|
|
+ f.field = "kind";
|
|
|
|
|
+ f.op = smartbotic::database::FilterOp::EQ;
|
|
|
|
|
+ f.value = "alpha";
|
|
|
|
|
+ fq.filters.push_back(f);
|
|
|
|
|
+ auto filtered = store.scan("things", fq);
|
|
|
|
|
+ check(filtered.total_matched == 3,
|
|
|
|
|
+ "filtered limit=0 reports the matching total, not the collection size");
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
} // namespace
|
|
} // namespace
|
|
|
|
|
|
|
|
int main() {
|
|
int main() {
|
|
@@ -249,6 +283,7 @@ int main() {
|
|
|
test_identity_key_predicate();
|
|
test_identity_key_predicate();
|
|
|
test_sentinel_invisible_through_store();
|
|
test_sentinel_invisible_through_store();
|
|
|
test_vector_subdb_sentinel();
|
|
test_vector_subdb_sentinel();
|
|
|
|
|
+ test_scan_limit_zero_reports_total();
|
|
|
|
|
|
|
|
std::cout << "passed: " << g_pass << ", failed: " << g_fail << "\n";
|
|
std::cout << "passed: " << g_pass << ", failed: " << g_fail << "\n";
|
|
|
return g_fail == 0 ? 0 : 1;
|
|
return g_fail == 0 ? 0 : 1;
|