From 7680f5197d2e4a2e0db3530a637a31d5183362a1 Mon Sep 17 00:00:00 2001 From: David Fahlander Date: Tue, 13 Jun 2023 00:43:57 +0200 Subject: [PATCH] Fix #1740 for Dexie 3x (#1742) * Repro of #1740 * Fixes #1740 --- src/classes/table/table.ts | 25 ++++++++++++++++-------- test/tests-whereclause.js | 40 +++++++++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/src/classes/table/table.ts b/src/classes/table/table.ts index 4ca180831..e4d37de6c 100644 --- a/src/classes/table/table.ts +++ b/src/classes/table/table.ts @@ -103,17 +103,26 @@ export class Table implements ITable { // Multiple criterias. // Let's try finding a compound index that matches all keyPaths in // arbritary order: - const compoundIndex = this.schema.indexes.concat(this.schema.primKey).filter(ix => - ix.compound && - keyPaths.every(keyPath => ix.keyPath.indexOf(keyPath) >= 0) && - (ix.keyPath as string[]).every(keyPath => keyPaths.indexOf(keyPath) >= 0))[0]; - - if (compoundIndex && this.db._maxKey !== maxString) + const compoundIndex = this.schema.indexes.concat(this.schema.primKey).filter(ix => { + if ( + ix.compound && + keyPaths.every(keyPath => ix.keyPath.indexOf(keyPath) >= 0)) { + for (let i=0; i a.keyPath.length - b.keyPath.length)[0]; + + if (compoundIndex && this.db._maxKey !== maxString) { // Cool! We found such compound index // and this browser supports compound indexes (maxKey !== maxString)! + const keyPathsInValidOrder = (compoundIndex.keyPath as string[]).slice(0, keyPaths.length); return this - .where(compoundIndex.name) - .equals((compoundIndex.keyPath as string[]).map(kp => indexOrCrit[kp])); + .where(keyPathsInValidOrder) + .equals(keyPathsInValidOrder.map(kp => indexOrCrit[kp])); + } if (!compoundIndex && debug) console.warn( `The query ${JSON.stringify(indexOrCrit)} on ${this.name} would benefit of a ` + diff --git a/test/tests-whereclause.js b/test/tests-whereclause.js index e9ea1b1be..a065299bd 100644 --- a/test/tests-whereclause.js +++ b/test/tests-whereclause.js @@ -5,13 +5,13 @@ import {resetDatabase, supports, spawnedTest, promisedTest} from './dexie-unitte const async = Dexie.async; var db = new Dexie("TestDBWhereClause"); -db.version(1).stores({ +db.version(2).stores({ folders: "++id,&path", files: "++id,filename,extension,[filename+extension],folderId", people: "[name+number],name,number", friends: "++id,name,age", chart: '[patno+row+col], patno', - chaps: "++id,[name+number]", + chaps: "++id,[name+number+age]", multiMulti: "id,*tags,*categories" }); @@ -753,7 +753,7 @@ asyncTest("startsWithAnyOfIgnoreCase()", function () { }).finally(start); }); -promisedTest("where({key: value})", async ()=>{ +promisedTest("where({key: value})", async () => { let readme = await db.files.where({filename: "README"}).first(); ok (readme, 'Should get a result for db.files.get({filename: "README"});'); equal (readme.extension, ".TXT", "Should get README.TXT"); @@ -782,6 +782,26 @@ promisedTest("where({key: value})", async ()=>{ }); }); +promisedTest("where({notIndexed: value}) should not return emtpy result", async () => { + await db.chaps.add({name: "Chaplin", number: 1, age: 134, notIndexed: 'foo'}); + try { + let chaplin = await db.chaps.where({name: "Chaplin", notIndexed: "foo"}).first(); + if (!chaplin) { + ok(false, "Got empty result when data exists matching the query. If we're not using an index we should not get an empty result but an error."); + } else { + ok(chaplin, + "Ok, so we got a result even though 'notIndexed' is not indexed at all. "+ + "This is not expected but ok if the result would be valid" + ); + equal(chaplin.name, "Chaplin", "Got the correct data Chaplin!"); + } + } catch (e) { + ok(true, `Got error: "${e}" because 'notIndexed' is not indexed at all. This is also ok.`); + } +}); + + + promisedTest("orderBy(['idx1','idx2'])", async () => { if (!supports("compound")) { ok(true, "Browser does not support compound indexes. Ignoring test."); @@ -818,21 +838,27 @@ promisedTest("Virtual Index", async () => { await db.chaps.bulkAdd([{ name: "David", - number: 2 + number: 2, + age: 29 },{ name: "David", - number: 3 + number: 3, + age: 39 },{ name: "David", - number: 1 + number: 1, + age: 49 },{ name: "Mambo", - number: 5 + number: 5, + age: 55 }]); // Verify that Dexie can use the [name+number] index to query name only: const davids = await db.chaps.where({name: "David"}).toArray(); equal(davids.length, 3, "There should be 3 Davids in the result"); + const mambosNumber5 = await db.chaps.where({name: "Mambo", number: 5}).toArray(); + equal(mambosNumber5.length, 1, "There should be 1 Mambo no 5 in the result"); // Verify that equalsIgnoreCase also works: const daves = await db.chaps.where('name').equalsIgnoreCase('david').toArray(); equal(JSON.stringify(daves.map(({name, number}) => ({name, number})), null, 2),