Skip to content

Commit

Permalink
Fixes actualbudget#3682 - Fix $ne filters incorrectly excluding null …
Browse files Browse the repository at this point in the history
…values (actualbudget#3686)

* allow matching null values when not equals query filter is set

* Also fix namedParameter queries with  filter

* improve tests

* release note

---------

Co-authored-by: Joel Rich <[email protected]>
  • Loading branch information
joel-rich and Joel Rich authored Nov 5, 2024
1 parent 19c6f85 commit c0f9073
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 3 deletions.
6 changes: 3 additions & 3 deletions packages/loot-core/src/server/aql/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -706,12 +706,12 @@ const compileOp = saveStack('op', (state, fieldRef, opData) => {
state.namedParameters = [].concat.apply([], orders);

return `CASE
WHEN ${left} IS NULL THEN ${right} IS NULL
ELSE ${left} != ${right}
WHEN ${left} IS NULL THEN ${right} IS NOT NULL
ELSE ${left} IS NOT ${right}
END`;
}

return `${left} != ${right}`;
return `(${left} != ${right} OR ${left} IS NULL)`;
}
case '$oneof': {
const [left, right] = valArray(state, [lhs, rhs], [null, 'array']);
Expand Down
44 changes: 44 additions & 0 deletions packages/loot-core/src/server/aql/exec.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ describe('runQuery', () => {
it('allows null as a parameter', async () => {
await db.insertCategoryGroup({ id: 'group', name: 'group' });
await db.insertCategory({ id: 'cat', name: 'cat', cat_group: 'group' });
await db.insertCategory({ id: 'cat2', name: 'cat2', cat_group: 'group' });
const transNoCat = await db.insertTransaction({
account: 'acct',
date: '2020-01-01',
Expand All @@ -179,6 +180,12 @@ describe('runQuery', () => {
amount: -5001,
category: 'cat',
});
const transCat2 = await db.insertTransaction({
account: 'acct',
date: '2020-01-02',
amount: -5001,
category: 'cat2',
});

const queryState = q('transactions')
.filter({ category: ':category' })
Expand All @@ -190,6 +197,43 @@ describe('runQuery', () => {

data = (await runQuery(queryState, { params: { category: 'cat' } })).data;
expect(data[0].id).toBe(transCat);

data = (
await runQuery(
q('transactions')
.filter({ category: { $ne: ':category' } })
.select('category')
.serialize(),

{ params: { category: 'cat2' } },
)
).data;
expect(data).toHaveLength(2);
expect(data).toEqual(
expect.arrayContaining([
expect.objectContaining({ id: transNoCat }),
expect.objectContaining({ id: transCat }),
expect.not.objectContaining({ id: transCat2 }),
]),
);

data = (
await runQuery(
q('transactions')
.filter({ category: { $ne: ':category' } })
.select('category')
.serialize(),
{ params: { category: null } },
)
).data;
expect(data).toHaveLength(2);
expect(data).toEqual(
expect.arrayContaining([
expect.not.objectContaining({ id: transNoCat }),
expect.objectContaining({ id: transCat }),
expect.objectContaining({ id: transCat2 }),
]),
);
});

it('parameters have the correct order', async () => {
Expand Down
6 changes: 6 additions & 0 deletions upcoming-release-notes/3686.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: Bugfix
authors: [joel-rich]
---

Fixes #3682 - Fix $ne filters incorrectly excluding null values

0 comments on commit c0f9073

Please sign in to comment.