Skip to content

Commit

Permalink
Fix #1740 for Dexie 3x (#1742)
Browse files Browse the repository at this point in the history
* Repro of #1740
* Fixes #1740
  • Loading branch information
dfahlander authored Jun 12, 2023
1 parent 9dee484 commit 7680f51
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 15 deletions.
25 changes: 17 additions & 8 deletions src/classes/table/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,17 +103,26 @@ export class Table implements ITable<any, IndexableType> {
// 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<keyPaths.length; ++i) {
if (keyPaths.indexOf(ix.keyPath[i]) === -1) return false;
}
return true;
}
return false;
}).sort((a,b) => 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 ` +
Expand Down
40 changes: 33 additions & 7 deletions test/tests-whereclause.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"
});

Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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.");
Expand Down Expand Up @@ -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),
Expand Down

0 comments on commit 7680f51

Please sign in to comment.