Skip to content

Commit 0cc98eb

Browse files
authored
CBL-7992: Error when creating a partial value index with compound expressions (#2478)
1 parent c580e2d commit 0cc98eb

2 files changed

Lines changed: 44 additions & 2 deletions

File tree

C/tests/c4QueryTest.cc

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,48 @@ N_WAY_TEST_CASE_METHOD(C4QueryTest, "C4Query partial value index", "[Query][C]")
317317
}
318318
}
319319

320+
N_WAY_TEST_CASE_METHOD(C4QueryTest, "C4Query partial value index with compound expressions", "[Query][C]") {
321+
C4Error err;
322+
auto defaultColl = getCollection(db, kC4DefaultCollectionSpec);
323+
324+
// First add some documents with specific fields to test
325+
{
326+
TransactionHelper t(db);
327+
createFleeceRev(db, "compound1"_sl, kRevID,
328+
R"({"locationID": "store1", "status": "active", "isPurged": false})"_sl);
329+
createFleeceRev(db, "compound2"_sl, kRevID,
330+
R"({"locationID": "store2", "status": "inactive", "isPurged": true})"_sl);
331+
createFleeceRev(db, "compound3"_sl, kRevID,
332+
R"({"locationID": "store1", "status": "active", "isPurged": true})"_sl);
333+
}
334+
335+
// Create a partial value index with compound expressions
336+
C4IndexOptions options{};
337+
options.where = R"(["=", [".isPurged"], false])";
338+
339+
// This is what was causing the bug - a value index with multiple expressions and a WHERE clause
340+
REQUIRE(c4coll_createIndex(defaultColl, C4STR("compound_idx"), c4str(R"([".locationID", ".status", ".isPurged"])"),
341+
kC4JSONQuery, kC4ValueIndex, &options, WITH_ERROR(&err)));
342+
343+
// Verify that the index works by running a query that would use it
344+
compileSelect("SELECT META().id FROM _ WHERE locationID = 'store1' AND status = 'active' AND isPurged = false",
345+
kC4N1QLQuery);
346+
REQUIRE(query);
347+
CHECK(run() == (vector<string>{"compound1"}));
348+
349+
// Create another index with N1QL syntax to verify that works too
350+
C4IndexOptions options2{};
351+
options2.where = "isPurged = true";
352+
REQUIRE(c4coll_createIndex(defaultColl, C4STR("compound_idx2"), c4str("locationID, status, isPurged"), kC4N1QLQuery,
353+
kC4ValueIndex, &options2, WITH_ERROR(&err)));
354+
355+
// Verify the second index works
356+
compileSelect("SELECT META().id FROM _ WHERE locationID = 'store1' AND status = 'active' AND isPurged = true",
357+
kC4N1QLQuery);
358+
REQUIRE(query);
359+
CHECK(run() == (vector<string>{"compound3"}));
360+
}
361+
320362
static bool lookForIndex(C4Database* db, slice name) {
321363
bool found = false;
322364
auto defaultColl = C4QueryTest::getCollection(db, kC4DefaultCollectionSpec);

LiteCore/Query/IndexSpec.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ namespace litecore {
8686
std::stringstream ss;
8787
if ( canPartialIndex() && !whereClause.empty() ) {
8888
hasWhere = true;
89-
ss << "SELECT ( " << expression.asString() << " ) FROM _ WHERE ( "
90-
<< whereClause.asString() << " )";
89+
ss << "SELECT " << expression.asString() << " FROM _ WHERE ( " << whereClause.asString()
90+
<< " )";
9191
result = n1ql::parse(ss.str(), &errPos);
9292
} else {
9393
result = n1ql::parse(expression.asString(), &errPos);

0 commit comments

Comments
 (0)