From 634508a3bc7de8233c90b937a92408c88f9e1d30 Mon Sep 17 00:00:00 2001
From: Ryan Bianchi <1435081+qedi-r@users.noreply.github.com>
Date: Sun, 22 Sep 2024 13:11:20 -0400
Subject: [PATCH] update sql regexp to default to empty string when field is
 null (#3480)

---
 .../platform/server/sqlite/index.electron.ts  |  2 +-
 .../platform/server/sqlite/index.web.test.ts  | 22 +++++++++++++++++++
 .../src/platform/server/sqlite/index.web.ts   |  2 +-
 upcoming-release-notes/3480.md                |  6 +++++
 4 files changed, 30 insertions(+), 2 deletions(-)
 create mode 100644 upcoming-release-notes/3480.md

diff --git a/packages/loot-core/src/platform/server/sqlite/index.electron.ts b/packages/loot-core/src/platform/server/sqlite/index.electron.ts
index 74c2b7dd1..2a479e4f9 100644
--- a/packages/loot-core/src/platform/server/sqlite/index.electron.ts
+++ b/packages/loot-core/src/platform/server/sqlite/index.electron.ts
@@ -99,7 +99,7 @@ export async function asyncTransaction(
 }
 
 function regexp(regex: string, text: string | null) {
-  return new RegExp(regex).test(text) ? 1 : 0;
+  return new RegExp(regex).test(text || '') ? 1 : 0;
 }
 
 export function openDatabase(pathOrBuffer: string | Buffer) {
diff --git a/packages/loot-core/src/platform/server/sqlite/index.web.test.ts b/packages/loot-core/src/platform/server/sqlite/index.web.test.ts
index 0d21e18d8..de8102cc9 100644
--- a/packages/loot-core/src/platform/server/sqlite/index.web.test.ts
+++ b/packages/loot-core/src/platform/server/sqlite/index.web.test.ts
@@ -16,6 +16,7 @@ beforeAll(() => {
 
 const initSQL = `
 CREATE TABLE numbers (id TEXT PRIMARY KEY, number INTEGER);
+CREATE TABLE textstrings (id TEXT PRIMARY KEY, string TEXT);
 `;
 
 describe('Web sqlite', () => {
@@ -85,4 +86,25 @@ describe('Web sqlite', () => {
     // @ts-expect-error Property 'number' does not exist on type 'unknown'
     expect(rows[2].number).toBe(6);
   });
+
+  it('should match regex on text fields', async () => {
+    const db = await openDatabase();
+    execQuery(db, initSQL);
+
+    runQuery(
+      db,
+      "INSERT INTO textstrings (id, string) VALUES ('id1', 'not empty string')",
+    );
+    runQuery(db, "INSERT INTO textstrings (id) VALUES ('id2')");
+
+    const rows = runQuery(
+      db,
+      'SELECT id FROM textstrings where REGEXP("n.", string)',
+      null,
+      true,
+    );
+    expect(rows.length).toBe(1);
+    // @ts-expect-error Property 'id' does not exist on type 'unknown'
+    expect(rows[0].id).toBe('id1');
+  });
 });
diff --git a/packages/loot-core/src/platform/server/sqlite/index.web.ts b/packages/loot-core/src/platform/server/sqlite/index.web.ts
index f8f91b7a4..64670e879 100644
--- a/packages/loot-core/src/platform/server/sqlite/index.web.ts
+++ b/packages/loot-core/src/platform/server/sqlite/index.web.ts
@@ -159,7 +159,7 @@ export async function asyncTransaction(db: Database, fn: () => Promise<void>) {
 }
 
 function regexp(regex: string, text: string) {
-  return new RegExp(regex).test(text) ? 1 : 0;
+  return new RegExp(regex).test(text || '') ? 1 : 0;
 }
 
 export async function openDatabase(pathOrBuffer?: string | Buffer) {
diff --git a/upcoming-release-notes/3480.md b/upcoming-release-notes/3480.md
new file mode 100644
index 000000000..212a45746
--- /dev/null
+++ b/upcoming-release-notes/3480.md
@@ -0,0 +1,6 @@
+---
+category: Bugfix
+authors: [qedi-r]
+---
+
+Fix 'matches' operator incorrectly matching empty strings.
-- 
GitLab