diff --git a/src/tests/simple-queries.spec.ts b/src/tests/simple-queries.spec.ts index 7a96a20..ed7db64 100644 --- a/src/tests/simple-queries.spec.ts +++ b/src/tests/simple-queries.spec.ts @@ -502,5 +502,16 @@ describe('Simple queries', () => { members VARCHAR[] );`); expectQueryError(() => none(`INSERT INTO example (members) VALUES (ARRAY[])`), /cannot determine type of empty array/); - }) + }); + + it('should select row with null value condition for indexed column', async () => { + none(` + CREATE TABLE "tableA" ("id" SERIAL NOT NULL, "reference" INTEGER); + CREATE INDEX "IDX_1" ON "tableA" ("reference"); + INSERT INTO "tableA"(id, reference) values (1, null); + `); + // it is important that EqFilter hasItem gets called, so two same conditions are applied to fall both into best and sorted conditions + const got = many(`SELECT "tableA"."id" FROM "tableA" WHERE ("tableA"."id" IN (1, 2) AND "tableA"."reference" IS NULL) AND ("tableA"."id" IN (1, 2) AND "tableA"."reference" IS NULL)`); + expect(got).toHaveLength(1); + }); }); diff --git a/src/transforms/eq-filter.ts b/src/transforms/eq-filter.ts index 8cb1290..e9e9fda 100644 --- a/src/transforms/eq-filter.ts +++ b/src/transforms/eq-filter.ts @@ -28,7 +28,12 @@ export class EqFilter extends FilterBase { } hasItem(item: Row, t: _Transaction) { + const isEq = this.op === 'eq'; const val = this.onValue.get(item, t); + + if (this.matchNull && nullIsh(val)) { + return isEq; + } if (nullIsh(val)) { return false; } @@ -36,7 +41,7 @@ export class EqFilter extends FilterBase { if (nullIsh(eq)) { return false; } - return this.op === 'eq' ? !!eq : !eq; + return isEq ? !!eq : !eq; } constructor(private onValue: IValue