Skip to content

Commit

Permalink
feat: add filted with null value SQLite
Browse files Browse the repository at this point in the history
  • Loading branch information
bao-sotatek committed May 7, 2024
1 parent 9d9c6a7 commit db48903
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 8 deletions.
20 changes: 20 additions & 0 deletions src/core/storage/ionicStorage/ionicStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@ const forEachMock = jest.fn().mockImplementation((fn: () => void) => {
}),
tags: { firstTag: "exists3", secondTag: "exists3" },
},

{
category: BasicRecord.type,
name: existingRecord.id,
value: JSON.stringify({
id: "test-0",
updatedAt: startTime,
content: {
test: "1",
},
}),
tags: { firstTag: null, secondTag: "exists3" },
},
];
items.forEach(fn);
});
Expand Down Expand Up @@ -284,4 +297,11 @@ describe("Ionic Storage Module: Basic Storage Service", () => {
expect(forEachMock).toBeCalled();
expect(result.length).toEqual(1);
});

test("should find an item with null query", async () => {
const tags = { firstTag: null };
const result = await storageService.findAllByQuery(tags, BasicRecord);
expect(forEachMock).toBeCalled();
expect(result.length).toEqual(1);
});
});
2 changes: 1 addition & 1 deletion src/core/storage/sqliteStorage/migrations/version-0.0.1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const DATA_V001 = {
id INTEGER PRIMARY KEY AUTOINCREMENT,
item_id TEXT NOT NULL,
name TEXT NOT NULL,
value TEXT NOT NULL,
value TEXT,
type TEXT NOT NULL,
FOREIGN KEY (item_id) REFERENCES items (id)
ON DELETE CASCADE ON UPDATE CASCADE
Expand Down
29 changes: 29 additions & 0 deletions src/core/storage/sqliteStorage/sqliteStorage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,33 @@ describe("Aries - Sqlite Storage Module: Storage Service", () => {
expect(condition).toEqual(expectedCondition);
expect(values).toMatchObject(expectdValues);
});

test("should generate exactly sql condition is null", () => {
const query = {
firstTag: null,
};
const expectedCondition =
"EXISTS (SELECT 1 FROM items_tags it WHERE i.id = it.item_id AND it.name = ? AND it.value is NULL)";
const expectdValues = ["firstTag"];
const { condition, values } = storageService.getQueryConditionSql(query);
expect(condition).toEqual(expectedCondition);
expect(values).toMatchObject(expectdValues);
});

test("should generate exactly sql insert tag is null", () => {
const query = {
firstTag: null,
};
const expectedCondition =
"INSERT INTO items_tags (item_id, name, value, type) VALUES (?,?,?,?)";
const expectdValues = ["id", "firstTag", null, "string"];
const [{ statement, values }] = storageService.getTagsInsertSql(
"id",
query
);
expect(statement).toEqual(expectedCondition);
expect(values).toMatchObject(expectdValues);
});
});

describe("Aries - Sqlite Storage Module: Util", () => {
Expand All @@ -345,11 +372,13 @@ describe("Aries - Sqlite Storage Module: Util", () => {
field2: true,
field3: false,
field4: "string",
field5: null,
};
expect(convertDbQuery(query)).toEqual({
field2: "1",
field3: "0",
field4: "string",
field5: null,
});
});
});
13 changes: 10 additions & 3 deletions src/core/storage/sqliteStorage/sqliteStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class SqliteStorage<T extends BaseRecord> implements StorageService<T> {
FROM items i WHERE category = ?`;
static readonly SCAN_TAGS_SQL_EQ =
"EXISTS (SELECT 1 FROM items_tags it WHERE i.id = it.item_id AND it.name = ? AND it.value = ?)";
static readonly SCAN_TAGS_SQL_IS_NULL =
"EXISTS (SELECT 1 FROM items_tags it WHERE i.id = it.item_id AND it.name = ? AND it.value is NULL)";
static readonly SCAN_TAGS_SQL_IN =
"EXISTS (SELECT 1 FROM items_tags it WHERE i.id = it.item_id AND it.name = ? AND it.value IN ";

Expand Down Expand Up @@ -223,7 +225,7 @@ class SqliteStorage<T extends BaseRecord> implements StorageService<T> {
await this.session!.executeSet(transactionStatements);
}

private getTagsInsertSql(itemId: string, tags: Record<string, unknown>) {
getTagsInsertSql(itemId: string, tags: Record<string, unknown>) {
const statements = [];
for (const key in tags) {
if (isNilOrEmptyString(tags[key])) continue;
Expand Down Expand Up @@ -288,8 +290,13 @@ class SqliteStorage<T extends BaseRecord> implements StorageService<T> {
);
values.push(queryKey, ...queryVal);
} else {
conditions.push(SqliteStorage.SCAN_TAGS_SQL_EQ);
values.push(queryKey, queryVal as string);
if (queryVal === null) {
conditions.push(SqliteStorage.SCAN_TAGS_SQL_IS_NULL);
values.push(queryKey);
} else {
conditions.push(SqliteStorage.SCAN_TAGS_SQL_EQ);
values.push(queryKey, queryVal as string);
}
}
}
return { condition: conditions.join(" AND "), values };
Expand Down
8 changes: 4 additions & 4 deletions src/core/storage/sqliteStorage/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ enum TagDataType {
BOOLEAN = "boolean",
}

function isNilOrEmptyString(value: unknown): boolean {
if (value == null || value === "") {
function isUndefinedOrEmptyString(value: unknown): boolean {
if (value === undefined || value === "") {
return true;
}
return false;
Expand All @@ -103,7 +103,7 @@ function isNilOrEmptyString(value: unknown): boolean {
function convertDbQuery(params: Query<BasicRecord>): Record<string, unknown> {
const result: Record<string, unknown> = {};
for (const [queryKey, queryVal] of Object.entries(params)) {
if (isNilOrEmptyString(queryVal)) continue;
if (isUndefinedOrEmptyString(queryVal)) continue;
if (typeof queryVal === "boolean") {
result[queryKey] = queryVal ? "1" : "0";
continue;
Expand All @@ -118,6 +118,6 @@ export {
versionCompare,
convertDbQuery,
resolveTagsFromDb,
isNilOrEmptyString,
isUndefinedOrEmptyString as isNilOrEmptyString,
TagDataType,
};

0 comments on commit db48903

Please sign in to comment.