@wxn0brp/db-string-query 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/build.yml +18 -0
- package/CHANGELOG.md +31 -0
- package/bun.lock +115 -0
- package/dist/sql/where.js +51 -17
- package/dist/test/js.test.d.ts +1 -0
- package/dist/test/js.test.js +85 -0
- package/dist/test/sql/delete.test.d.ts +1 -0
- package/dist/test/sql/delete.test.js +79 -0
- package/dist/test/sql/insert.test.d.ts +1 -0
- package/dist/test/sql/insert.test.js +79 -0
- package/dist/test/sql/select.test.d.ts +1 -0
- package/dist/test/sql/select.test.js +59 -0
- package/dist/test/sql/update.test.d.ts +1 -0
- package/dist/test/sql/update.test.js +71 -0
- package/package.json +37 -40
- package/src/sql/where.ts +50 -17
- package/src/test/js.test.ts +103 -0
- package/src/test/sql/delete.test.ts +95 -0
- package/src/test/sql/insert.test.ts +95 -0
- package/src/test/sql/select.test.ts +71 -0
- package/src/test/sql/update.test.ts +85 -0
- package/suglite.json +2 -2
- package/typedocs-generated/.nojekyll +1 -0
- package/typedocs-generated/assets/hierarchy.js +1 -0
- package/typedocs-generated/assets/highlight.css +78 -0
- package/typedocs-generated/assets/icons.js +18 -0
- package/typedocs-generated/assets/icons.svg +1 -0
- package/typedocs-generated/assets/main.js +60 -0
- package/typedocs-generated/assets/navigation.js +1 -0
- package/typedocs-generated/assets/search.js +1 -0
- package/typedocs-generated/assets/style.css +1633 -0
- package/typedocs-generated/classes/js.default.html +3 -0
- package/typedocs-generated/classes/sql_index.default.html +3 -0
- package/typedocs-generated/functions/sql_handle.handleCreate.html +1 -0
- package/typedocs-generated/functions/sql_handle.handleDelete.html +1 -0
- package/typedocs-generated/functions/sql_handle.handleDrop.html +1 -0
- package/typedocs-generated/functions/sql_handle.handleExists.html +1 -0
- package/typedocs-generated/functions/sql_handle.handleGet.html +1 -0
- package/typedocs-generated/functions/sql_handle.handleInsert.html +1 -0
- package/typedocs-generated/functions/sql_handle.handleSelect.html +1 -0
- package/typedocs-generated/functions/sql_handle.handleUpdate.html +1 -0
- package/typedocs-generated/functions/sql_handle.parseSelectClause.html +1 -0
- package/typedocs-generated/functions/sql_utils.parseReturn.html +1 -0
- package/typedocs-generated/functions/sql_utils.parseSet.html +1 -0
- package/typedocs-generated/functions/sql_where.parseWhere.html +1 -0
- package/typedocs-generated/hierarchy.html +1 -0
- package/typedocs-generated/index.html +35 -0
- package/typedocs-generated/interfaces/types.ValtheraParser.html +2 -0
- package/typedocs-generated/interfaces/types.ValtheraQuery.html +3 -0
- package/typedocs-generated/media/LICENSE +21 -0
- package/typedocs-generated/modules/.html +1 -0
- package/typedocs-generated/modules/index.html +1 -0
- package/typedocs-generated/modules/js.html +1 -0
- package/typedocs-generated/modules/sql_handle.html +1 -0
- package/typedocs-generated/modules/sql_index.html +1 -0
- package/typedocs-generated/modules/sql_utils.html +1 -0
- package/typedocs-generated/modules/sql_where.html +1 -0
- package/typedocs-generated/modules/test_js.test.html +1 -0
- package/typedocs-generated/modules/test_sql_delete.test.html +1 -0
- package/typedocs-generated/modules/test_sql_insert.test.html +1 -0
- package/typedocs-generated/modules/test_sql_select.test.html +1 -0
- package/typedocs-generated/modules/test_sql_update.test.html +1 -0
- package/typedocs-generated/modules/types.html +1 -0
- package/typedocs-generated/modules.html +1 -0
- package/typedocs-generated/variables/.ValtheraDbParsers.html +1 -0
- package/typedocs-generated/variables/.ValtheraDbRelations.html +1 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { ValtheraDbParsers } from "../../index.js";
|
|
3
|
+
const sqlParser = new ValtheraDbParsers.sql();
|
|
4
|
+
describe("SQL Parser - SELECT", () => {
|
|
5
|
+
test("should parse a simple SELECT query", () => {
|
|
6
|
+
const query = "SELECT * FROM users WHERE id = 1";
|
|
7
|
+
const parsedQuery = sqlParser.parse(query);
|
|
8
|
+
expect(parsedQuery).toBeDefined();
|
|
9
|
+
expect(parsedQuery.method).toBe("find");
|
|
10
|
+
expect(parsedQuery.args).toHaveLength(4);
|
|
11
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
12
|
+
expect(parsedQuery.args[1]).toEqual({ id: 1 }); // where clause
|
|
13
|
+
});
|
|
14
|
+
test("should parse a SELECT query with specific columns", () => {
|
|
15
|
+
const query = "SELECT name, email FROM users WHERE active = 1";
|
|
16
|
+
const parsedQuery = sqlParser.parse(query);
|
|
17
|
+
expect(parsedQuery).toBeDefined();
|
|
18
|
+
expect(parsedQuery.method).toBe("find");
|
|
19
|
+
expect(parsedQuery.args).toHaveLength(4);
|
|
20
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
21
|
+
expect(parsedQuery.args[1]).toEqual({ active: 1 }); // where clause
|
|
22
|
+
expect(parsedQuery.args[3]).toEqual({ select: ["name", "email"] }); // select options
|
|
23
|
+
});
|
|
24
|
+
test("should parse a SELECT query without WHERE clause", () => {
|
|
25
|
+
const query = "SELECT * FROM users";
|
|
26
|
+
const parsedQuery = sqlParser.parse(query);
|
|
27
|
+
expect(parsedQuery).toBeDefined();
|
|
28
|
+
expect(parsedQuery.method).toBe("find");
|
|
29
|
+
expect(parsedQuery.args).toHaveLength(4);
|
|
30
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
31
|
+
expect(parsedQuery.args[1]).toEqual({}); // empty where clause
|
|
32
|
+
});
|
|
33
|
+
test("should parse a SELECT query with EXCLUDE clause", () => {
|
|
34
|
+
const query = "SELECT * EXCLUDE password, createdAt FROM users WHERE active = 1";
|
|
35
|
+
const parsedQuery = sqlParser.parse(query);
|
|
36
|
+
expect(parsedQuery).toBeDefined();
|
|
37
|
+
expect(parsedQuery.method).toBe("find");
|
|
38
|
+
expect(parsedQuery.args).toHaveLength(4);
|
|
39
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
40
|
+
expect(parsedQuery.args[1]).toEqual({ active: 1 }); // where clause
|
|
41
|
+
expect(parsedQuery.args[3]).toEqual({ exclude: ["password", "createdAt"] }); // exclude options
|
|
42
|
+
});
|
|
43
|
+
test("should parse a SELECT query with complex WHERE conditions", () => {
|
|
44
|
+
const query = "SELECT * FROM users WHERE age > 18 AND status = 'active'";
|
|
45
|
+
const parsedQuery = sqlParser.parse(query);
|
|
46
|
+
expect(parsedQuery).toBeDefined();
|
|
47
|
+
expect(parsedQuery.method).toBe("find");
|
|
48
|
+
expect(parsedQuery.args).toHaveLength(4);
|
|
49
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
50
|
+
expect(parsedQuery.args[1]).toEqual({ $gt: { age: 18 }, status: "active" }); // where clause
|
|
51
|
+
});
|
|
52
|
+
test("should throw error for invalid SELECT syntax", () => {
|
|
53
|
+
const query = "SELECT FROM users";
|
|
54
|
+
expect(() => {
|
|
55
|
+
sqlParser.parse(query);
|
|
56
|
+
}).toThrow();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VsZWN0LnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdGVzdC9zcWwvc2VsZWN0LnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ2xELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLE9BQU8sQ0FBQztBQUUxQyxNQUFNLFNBQVMsR0FBRyxJQUFJLGlCQUFpQixDQUFDLEdBQUcsRUFBRSxDQUFDO0FBRTlDLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxHQUFHLEVBQUU7SUFDakMsSUFBSSxDQUFDLG9DQUFvQyxFQUFFLEdBQUcsRUFBRTtRQUM1QyxNQUFNLEtBQUssR0FBRyxrQ0FBa0MsQ0FBQztRQUNqRCxNQUFNLFdBQVcsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRTNDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNsQyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN4QyxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN6QyxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLGtCQUFrQjtRQUM3RCxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsZUFBZTtJQUNuRSxDQUFDLENBQUMsQ0FBQztJQUVILElBQUksQ0FBQyxtREFBbUQsRUFBRSxHQUFHLEVBQUU7UUFDM0QsTUFBTSxL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
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { ValtheraDbParsers } from "../../index.js";
|
|
3
|
+
const sqlParser = new ValtheraDbParsers.sql();
|
|
4
|
+
describe("SQL Parser - UPDATE", () => {
|
|
5
|
+
test("should parse a simple UPDATE query", () => {
|
|
6
|
+
const query = "UPDATE users SET name = 'John' WHERE id = 1";
|
|
7
|
+
const parsedQuery = sqlParser.parse(query);
|
|
8
|
+
expect(parsedQuery).toBeDefined();
|
|
9
|
+
expect(parsedQuery.method).toBe("update"); // UPDATE maps to "update" method
|
|
10
|
+
expect(parsedQuery.args).toHaveLength(3);
|
|
11
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
12
|
+
expect(parsedQuery.args[1]).toEqual({ id: 1 }); // where clause
|
|
13
|
+
expect(parsedQuery.args[2]).toEqual({ name: "John" }); // set clause
|
|
14
|
+
});
|
|
15
|
+
test("should parse UPDATE with multiple SET fields", () => {
|
|
16
|
+
const query = "UPDATE users SET name = 'Jane', email = 'jane@example.com' WHERE id = 2";
|
|
17
|
+
const parsedQuery = sqlParser.parse(query);
|
|
18
|
+
expect(parsedQuery).toBeDefined();
|
|
19
|
+
expect(parsedQuery.method).toBe("update");
|
|
20
|
+
expect(parsedQuery.args).toHaveLength(3);
|
|
21
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
22
|
+
expect(parsedQuery.args[1]).toEqual({ id: 2 }); // where clause
|
|
23
|
+
expect(parsedQuery.args[2]).toEqual({ name: "Jane", email: "jane@example.com" }); // set clause
|
|
24
|
+
});
|
|
25
|
+
test("should parse UPDATE with numeric values", () => {
|
|
26
|
+
const query = "UPDATE products SET price = 29.99, stock = 100 WHERE id = 1";
|
|
27
|
+
const parsedQuery = sqlParser.parse(query);
|
|
28
|
+
expect(parsedQuery).toBeDefined();
|
|
29
|
+
expect(parsedQuery.method).toBe("update");
|
|
30
|
+
expect(parsedQuery.args).toHaveLength(3);
|
|
31
|
+
expect(parsedQuery.args[0]).toBe("products"); // collection name
|
|
32
|
+
expect(parsedQuery.args[1]).toEqual({ id: 1 }); // where clause
|
|
33
|
+
expect(parsedQuery.args[2]).toEqual({ price: 29.99, stock: 100 }); // set clause
|
|
34
|
+
});
|
|
35
|
+
test("should parse UPDATE with string values containing spaces", () => {
|
|
36
|
+
const query = "UPDATE posts SET title = 'Hello World Post', content = 'This is the content' WHERE id = 1";
|
|
37
|
+
const parsedQuery = sqlParser.parse(query);
|
|
38
|
+
expect(parsedQuery).toBeDefined();
|
|
39
|
+
expect(parsedQuery.method).toBe("update");
|
|
40
|
+
expect(parsedQuery.args).toHaveLength(3);
|
|
41
|
+
expect(parsedQuery.args[0]).toBe("posts"); // collection name
|
|
42
|
+
expect(parsedQuery.args[1]).toEqual({ id: 1 }); // where clause
|
|
43
|
+
expect(parsedQuery.args[2]).toEqual({
|
|
44
|
+
title: "Hello World Post",
|
|
45
|
+
content: "This is the content"
|
|
46
|
+
}); // set clause
|
|
47
|
+
});
|
|
48
|
+
test("should throw error for invalid UPDATE syntax", () => {
|
|
49
|
+
const query = "UPDATE users name = 'John' WHERE id = 1"; // missing SET keyword
|
|
50
|
+
expect(() => {
|
|
51
|
+
sqlParser.parse(query);
|
|
52
|
+
}).toThrow("Invalid UPDATE syntax");
|
|
53
|
+
});
|
|
54
|
+
test("should handle UPDATE with complex WHERE conditions", () => {
|
|
55
|
+
const query = "UPDATE users SET status = 'inactive' WHERE age > 65 AND active = 1";
|
|
56
|
+
const parsedQuery = sqlParser.parse(query);
|
|
57
|
+
expect(parsedQuery).toBeDefined();
|
|
58
|
+
expect(parsedQuery.method).toBe("update");
|
|
59
|
+
expect(parsedQuery.args).toHaveLength(3);
|
|
60
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
61
|
+
expect(parsedQuery.args[1]).toEqual({ $gt: { age: 65 }, active: 1 }); // where clause
|
|
62
|
+
expect(parsedQuery.args[2]).toEqual({ status: "inactive" }); // set clause
|
|
63
|
+
});
|
|
64
|
+
test("should throw error when there is no WHERE clause", () => {
|
|
65
|
+
const query = "UPDATE users SET name = 'John'"; // missing WHERE
|
|
66
|
+
expect(() => {
|
|
67
|
+
sqlParser.parse(query);
|
|
68
|
+
}).toThrow("Invalid UPDATE syntax");
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBkYXRlLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdGVzdC9zcWwvdXBkYXRlLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ2xELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLE9BQU8sQ0FBQztBQUUxQyxNQUFNLFNBQVMsR0FBRyxJQUFJLGlCQUFpQixDQUFDLEdBQUcsRUFBRSxDQUFDO0FBRTlDLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxHQUFHLEVBQUU7SUFDakMsSUFBSSxDQUFDLG9DQUFvQyxFQUFFLEdBQUcsRUFBRTtRQUM1QyxNQUFNLEtBQUssR0FBRyw2Q0FBNkMsQ0FBQztRQUM1RCxNQUFNLFdBQVcsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRTNDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUNsQyxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLGlDQUFpQztRQUM1RSxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN6QyxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLGtCQUFrQjtRQUM3RCxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsZUFBZTtRQUMvRCxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9B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
|
package/package.json
CHANGED
|
@@ -1,44 +1,41 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
2
|
+
"name": "@wxn0brp/db-string-query",
|
|
3
|
+
"version": "0.0.8",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/wxn0brP/ValtheraDB-string-query.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/wxn0brP/ValtheraDB-string-query",
|
|
11
|
+
"author": "wxn0brP",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/bun": "^1.3.2",
|
|
16
|
+
"@types/node": "*",
|
|
17
|
+
"json5": "^2.2.3",
|
|
18
|
+
"tsc-alias": "*",
|
|
19
|
+
"typescript": "*"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"json5": "^2.2.3"
|
|
23
|
+
},
|
|
24
|
+
"peerDependenciesMeta": {
|
|
25
|
+
"json5": {
|
|
26
|
+
"optional": true
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"default": "./dist/index.js",
|
|
33
|
+
"import": "./dist/index.js"
|
|
31
34
|
},
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"import": "./dist/index.js"
|
|
37
|
-
},
|
|
38
|
-
"./*": {
|
|
39
|
-
"types": "./dist/*.d.ts",
|
|
40
|
-
"default": "./dist/*.js",
|
|
41
|
-
"import": "./dist/*.js"
|
|
42
|
-
}
|
|
35
|
+
"./*": {
|
|
36
|
+
"types": "./dist/*.d.ts",
|
|
37
|
+
"default": "./dist/*.js",
|
|
38
|
+
"import": "./dist/*.js"
|
|
43
39
|
}
|
|
40
|
+
}
|
|
44
41
|
}
|
package/src/sql/where.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
type QueryObject = Record<string, any>;
|
|
2
2
|
|
|
3
3
|
const operators: Record<string, string> = {
|
|
4
|
-
"=":
|
|
4
|
+
"=": null,
|
|
5
5
|
"<": "$lt",
|
|
6
6
|
">": "$gt",
|
|
7
7
|
"<=": "$lte",
|
|
@@ -11,6 +11,27 @@ const operators: Record<string, string> = {
|
|
|
11
11
|
"NOT IN": "$nin"
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
+
function mergeQueries(target: QueryObject, source: QueryObject) {
|
|
15
|
+
for (const key in source) {
|
|
16
|
+
if (key.startsWith('$')) {
|
|
17
|
+
// If the key is an operator, simply add it
|
|
18
|
+
target[key] = source[key];
|
|
19
|
+
} else {
|
|
20
|
+
// If the key is a field, check if there is not already an operator in the target
|
|
21
|
+
if (target[key] !== undefined) {
|
|
22
|
+
// If target[key] is an object with an operator, merge the objects
|
|
23
|
+
if (typeof target[key] === 'object' && !Array.isArray(target[key])) {
|
|
24
|
+
Object.assign(target[key], source[key]);
|
|
25
|
+
} else {
|
|
26
|
+
target[key] = source[key];
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
target[key] = source[key];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
14
35
|
export function parseWhere(where: string): QueryObject {
|
|
15
36
|
if (!where) return {};
|
|
16
37
|
const trimmed = where.trim();
|
|
@@ -47,7 +68,7 @@ export function parseWhere(where: string): QueryObject {
|
|
|
47
68
|
if (frames.length === 0) {
|
|
48
69
|
throw new Error("Unmatched closing parenthesis");
|
|
49
70
|
}
|
|
50
|
-
const parentFrame = frames.pop()
|
|
71
|
+
const parentFrame = frames.pop()!;
|
|
51
72
|
const parentCurrent = parentFrame.current;
|
|
52
73
|
const parentOperatorStack = parentFrame.operatorStack;
|
|
53
74
|
const parentStack = parentFrame.stack;
|
|
@@ -59,15 +80,21 @@ export function parseWhere(where: string): QueryObject {
|
|
|
59
80
|
parentStack.push(parentCurrent);
|
|
60
81
|
current = groupedQuery;
|
|
61
82
|
} else if (op === "AND") {
|
|
62
|
-
|
|
83
|
+
const newCurrent: QueryObject = {};
|
|
84
|
+
mergeQueries(newCurrent, parentCurrent);
|
|
85
|
+
mergeQueries(newCurrent, groupedQuery);
|
|
86
|
+
current = newCurrent;
|
|
63
87
|
}
|
|
64
88
|
} else {
|
|
65
|
-
|
|
89
|
+
const newCurrent: QueryObject = {};
|
|
90
|
+
mergeQueries(newCurrent, parentCurrent);
|
|
91
|
+
mergeQueries(newCurrent, groupedQuery);
|
|
92
|
+
current = newCurrent;
|
|
66
93
|
}
|
|
67
94
|
|
|
68
95
|
// Restore parent's stack and operator stack
|
|
69
96
|
operatorStack = parentFrame.operatorStack;
|
|
70
|
-
stack =
|
|
97
|
+
stack = parentFrame.stack;
|
|
71
98
|
} else if (token.toUpperCase() === "AND" || token.toUpperCase() === "OR") {
|
|
72
99
|
operatorStack.push(token.toUpperCase());
|
|
73
100
|
} else {
|
|
@@ -82,11 +109,11 @@ export function parseWhere(where: string): QueryObject {
|
|
|
82
109
|
}
|
|
83
110
|
|
|
84
111
|
let key = token;
|
|
85
|
-
let
|
|
112
|
+
let opToken = tokens[++i]?.trim();
|
|
86
113
|
let value: any = tokens[++i]?.trim();
|
|
87
114
|
|
|
88
|
-
if (!key || !
|
|
89
|
-
throw new Error(`Invalid condition near '${key} ${
|
|
115
|
+
if (!key || !opToken || value === undefined) {
|
|
116
|
+
throw new Error(`Invalid condition near '${key} ${opToken} ${value}'`);
|
|
90
117
|
}
|
|
91
118
|
|
|
92
119
|
// Handle quoted values
|
|
@@ -100,9 +127,9 @@ export function parseWhere(where: string): QueryObject {
|
|
|
100
127
|
}
|
|
101
128
|
|
|
102
129
|
// Handle IN and NOT IN operations
|
|
103
|
-
if (
|
|
130
|
+
if (opToken.toUpperCase() === "IN" || opToken.toUpperCase() === "NOT IN") {
|
|
104
131
|
if (!value.startsWith("(") || !value.endsWith(")")) {
|
|
105
|
-
throw new Error(`Invalid syntax for '${
|
|
132
|
+
throw new Error(`Invalid syntax for '${opToken}' near '${value}'`);
|
|
106
133
|
}
|
|
107
134
|
value = value.slice(1, -1).split(",").map((v: string) => {
|
|
108
135
|
v = v.trim();
|
|
@@ -113,16 +140,22 @@ export function parseWhere(where: string): QueryObject {
|
|
|
113
140
|
});
|
|
114
141
|
}
|
|
115
142
|
|
|
116
|
-
// Map the operator to
|
|
117
|
-
const mappedOp = operators[
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
143
|
+
// Map the operator to the query operators
|
|
144
|
+
const mappedOp = operators[opToken.toUpperCase()];
|
|
145
|
+
|
|
146
|
+
if (mappedOp !== undefined) {
|
|
147
|
+
if (mappedOp === null) {
|
|
148
|
+
// "=" operator - direct assignment
|
|
149
|
+
current[key] = value;
|
|
121
150
|
} else {
|
|
122
|
-
|
|
123
|
-
(current[
|
|
151
|
+
// Other operators - they go to the root level
|
|
152
|
+
if (!current[mappedOp]) {
|
|
153
|
+
current[mappedOp] = {};
|
|
154
|
+
}
|
|
155
|
+
(current[mappedOp] as Record<string, any>)[key] = value;
|
|
124
156
|
}
|
|
125
157
|
} else {
|
|
158
|
+
// If operator not found, default to direct assignment
|
|
126
159
|
current[key] = value;
|
|
127
160
|
}
|
|
128
161
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { ValtheraDbParsers } from "..";
|
|
3
|
+
|
|
4
|
+
const jsParser = new ValtheraDbParsers.js();
|
|
5
|
+
|
|
6
|
+
describe("JS-like Parser", () => {
|
|
7
|
+
test("should parse a simple method call with arguments", () => {
|
|
8
|
+
const query = "myMethod(1, 'hello')";
|
|
9
|
+
const parsedQuery = jsParser.parse(query);
|
|
10
|
+
|
|
11
|
+
expect(parsedQuery).toBeDefined();
|
|
12
|
+
expect(parsedQuery.method).toBe("myMethod");
|
|
13
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
14
|
+
expect(parsedQuery.args[0]).toBe(1);
|
|
15
|
+
expect(parsedQuery.args[1]).toBe("hello");
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("should parse method call with object argument", () => {
|
|
19
|
+
const query = `find({ id: 1, name: "John" })`;
|
|
20
|
+
const parsedQuery = jsParser.parse(query);
|
|
21
|
+
|
|
22
|
+
expect(parsedQuery).toBeDefined();
|
|
23
|
+
expect(parsedQuery.method).toBe("find");
|
|
24
|
+
expect(parsedQuery.args).toHaveLength(1);
|
|
25
|
+
expect(parsedQuery.args[0]).toEqual({ id: 1, name: "John" });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("should parse method call with array argument", () => {
|
|
29
|
+
const query = `myMethod([1, 2, 3])`;
|
|
30
|
+
const parsedQuery = jsParser.parse(query);
|
|
31
|
+
|
|
32
|
+
expect(parsedQuery).toBeDefined();
|
|
33
|
+
expect(parsedQuery.method).toBe("myMethod");
|
|
34
|
+
expect(parsedQuery.args).toHaveLength(1);
|
|
35
|
+
expect(parsedQuery.args[0]).toEqual([1, 2, 3]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("should parse method call with nested objects and arrays", () => {
|
|
39
|
+
const query = `complexMethod({ users: [{ id: 1, active: true }], settings: { theme: "dark" } })`;
|
|
40
|
+
const parsedQuery = jsParser.parse(query);
|
|
41
|
+
|
|
42
|
+
expect(parsedQuery).toBeDefined();
|
|
43
|
+
expect(parsedQuery.method).toBe("complexMethod");
|
|
44
|
+
expect(parsedQuery.args).toHaveLength(1);
|
|
45
|
+
expect(parsedQuery.args[0]).toEqual({
|
|
46
|
+
users: [{ id: 1, active: true }],
|
|
47
|
+
settings: { theme: "dark" }
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("should parse method call with mixed argument types", () => {
|
|
52
|
+
const query = `mixedArgs(42, "text", true, null, [1, "two", false])`;
|
|
53
|
+
const parsedQuery = jsParser.parse(query);
|
|
54
|
+
|
|
55
|
+
expect(parsedQuery).toBeDefined();
|
|
56
|
+
expect(parsedQuery.method).toBe("mixedArgs");
|
|
57
|
+
expect(parsedQuery.args).toHaveLength(5);
|
|
58
|
+
expect(parsedQuery.args[0]).toBe(42);
|
|
59
|
+
expect(parsedQuery.args[1]).toBe("text");
|
|
60
|
+
expect(parsedQuery.args[2]).toBe(true);
|
|
61
|
+
expect(parsedQuery.args[3]).toBeNull();
|
|
62
|
+
expect(parsedQuery.args[4]).toEqual([1, "two", false]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("should handle string arguments with quotes", () => {
|
|
66
|
+
const query = `stringMethod("double quotes", 'single quotes')`;
|
|
67
|
+
const parsedQuery = jsParser.parse(query);
|
|
68
|
+
|
|
69
|
+
expect(parsedQuery).toBeDefined();
|
|
70
|
+
expect(parsedQuery.method).toBe("stringMethod");
|
|
71
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
72
|
+
expect(parsedQuery.args[0]).toBe("double quotes");
|
|
73
|
+
expect(parsedQuery.args[1]).toBe("single quotes");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("should throw error for invalid query syntax", () => {
|
|
77
|
+
const query = "invalidQuery";
|
|
78
|
+
|
|
79
|
+
expect(() => {
|
|
80
|
+
jsParser.parse(query);
|
|
81
|
+
}).toThrow("Invalid query");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("should throw error for malformed arguments", () => {
|
|
85
|
+
const query = "method({unclosed: object";
|
|
86
|
+
|
|
87
|
+
expect(() => {
|
|
88
|
+
jsParser.parse(query);
|
|
89
|
+
}).toThrow();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test("should parse floating point numbers correctly", () => {
|
|
93
|
+
const query = `numberMethod(3.14, -2.5, 0.001)`;
|
|
94
|
+
const parsedQuery = jsParser.parse(query);
|
|
95
|
+
|
|
96
|
+
expect(parsedQuery).toBeDefined();
|
|
97
|
+
expect(parsedQuery.method).toBe("numberMethod");
|
|
98
|
+
expect(parsedQuery.args).toHaveLength(3);
|
|
99
|
+
expect(parsedQuery.args[0]).toBe(3.14);
|
|
100
|
+
expect(parsedQuery.args[1]).toBe(-2.5);
|
|
101
|
+
expect(parsedQuery.args[2]).toBe(0.001);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { ValtheraDbParsers } from "../..";
|
|
3
|
+
|
|
4
|
+
const sqlParser = new ValtheraDbParsers.sql();
|
|
5
|
+
|
|
6
|
+
describe("SQL Parser - DELETE", () => {
|
|
7
|
+
test("should parse a simple DELETE query", () => {
|
|
8
|
+
const query = "DELETE FROM users WHERE id = 1";
|
|
9
|
+
const parsedQuery = sqlParser.parse(query);
|
|
10
|
+
|
|
11
|
+
expect(parsedQuery).toBeDefined();
|
|
12
|
+
expect(parsedQuery.method).toBe("remove"); // DELETE maps to "remove" method
|
|
13
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
14
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
15
|
+
expect(parsedQuery.args[1]).toEqual({ id: 1 }); // where clause
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("should parse DELETE query without WHERE clause", () => {
|
|
19
|
+
const query = "DELETE FROM users";
|
|
20
|
+
const parsedQuery = sqlParser.parse(query);
|
|
21
|
+
|
|
22
|
+
expect(parsedQuery).toBeDefined();
|
|
23
|
+
expect(parsedQuery.method).toBe("remove");
|
|
24
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
25
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
26
|
+
expect(parsedQuery.args[1]).toEqual({}); // empty where clause
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("should parse DELETE with complex WHERE conditions", () => {
|
|
30
|
+
const query = "DELETE FROM users WHERE age > 65 AND status = 'inactive'";
|
|
31
|
+
const parsedQuery = sqlParser.parse(query);
|
|
32
|
+
|
|
33
|
+
expect(parsedQuery).toBeDefined();
|
|
34
|
+
expect(parsedQuery.method).toBe("remove");
|
|
35
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
36
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
37
|
+
expect(parsedQuery.args[1]).toEqual({ $gt: { age: 65 }, status: "inactive" }); // where clause
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("should parse DELETE with string values", () => {
|
|
41
|
+
const query = "DELETE FROM posts WHERE title = 'Unwanted Post'";
|
|
42
|
+
const parsedQuery = sqlParser.parse(query);
|
|
43
|
+
|
|
44
|
+
expect(parsedQuery).toBeDefined();
|
|
45
|
+
expect(parsedQuery.method).toBe("remove");
|
|
46
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
47
|
+
expect(parsedQuery.args[0]).toBe("posts"); // collection name
|
|
48
|
+
expect(parsedQuery.args[1]).toEqual({ title: "Unwanted Post" }); // where clause
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("should parse DELETE with numeric values", () => {
|
|
52
|
+
const query = "DELETE FROM products WHERE price = 0";
|
|
53
|
+
const parsedQuery = sqlParser.parse(query);
|
|
54
|
+
|
|
55
|
+
expect(parsedQuery).toBeDefined();
|
|
56
|
+
expect(parsedQuery.method).toBe("remove");
|
|
57
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
58
|
+
expect(parsedQuery.args[0]).toBe("products"); // collection name
|
|
59
|
+
expect(parsedQuery.args[1]).toEqual({ price: 0 }); // where clause
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("should throw error for invalid DELETE syntax", () => {
|
|
63
|
+
const query = "DELETE users WHERE id = 1"; // missing FROM keyword
|
|
64
|
+
|
|
65
|
+
expect(() => {
|
|
66
|
+
sqlParser.parse(query);
|
|
67
|
+
}).toThrow("Invalid DELETE syntax");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("should parse DELETE with quoted string values", () => {
|
|
71
|
+
const query = "DELETE FROM users WHERE name = 'John Doe'";
|
|
72
|
+
const parsedQuery = sqlParser.parse(query);
|
|
73
|
+
|
|
74
|
+
expect(parsedQuery).toBeDefined();
|
|
75
|
+
expect(parsedQuery.method).toBe("remove");
|
|
76
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
77
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
78
|
+
expect(parsedQuery.args[1]).toEqual({ name: "John Doe" }); // where clause
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("should handle DELETE with multiple condition types", () => {
|
|
82
|
+
const query = "DELETE FROM orders WHERE total > 1000 AND status = 'cancelled' AND user_id != 5";
|
|
83
|
+
const parsedQuery = sqlParser.parse(query);
|
|
84
|
+
|
|
85
|
+
expect(parsedQuery).toBeDefined();
|
|
86
|
+
expect(parsedQuery.method).toBe("remove");
|
|
87
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
88
|
+
expect(parsedQuery.args[0]).toBe("orders"); // collection name
|
|
89
|
+
expect(parsedQuery.args[1]).toEqual({
|
|
90
|
+
$gt: { total: 1000 },
|
|
91
|
+
status: "cancelled",
|
|
92
|
+
$not: { user_id: 5 }
|
|
93
|
+
}); // where clause with multiple operators
|
|
94
|
+
});
|
|
95
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { ValtheraDbParsers } from "../..";
|
|
3
|
+
|
|
4
|
+
const sqlParser = new ValtheraDbParsers.sql();
|
|
5
|
+
|
|
6
|
+
describe("SQL Parser - INSERT", () => {
|
|
7
|
+
test("should parse a simple INSERT query", () => {
|
|
8
|
+
const query = "INSERT INTO users (name, email) VALUES ('John', 'john@example.com')";
|
|
9
|
+
const parsedQuery = sqlParser.parse(query);
|
|
10
|
+
|
|
11
|
+
expect(parsedQuery).toBeDefined();
|
|
12
|
+
expect(parsedQuery.method).toBe("add"); // INSERT maps to "add" method
|
|
13
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
14
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
15
|
+
expect(parsedQuery.args[1]).toEqual({ name: "John", email: "john@example.com" }); // data
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("should parse INSERT with numeric values", () => {
|
|
19
|
+
const query = "INSERT INTO products (id, name, price) VALUES (1, 'Laptop', 999.99)";
|
|
20
|
+
const parsedQuery = sqlParser.parse(query);
|
|
21
|
+
|
|
22
|
+
expect(parsedQuery).toBeDefined();
|
|
23
|
+
expect(parsedQuery.method).toBe("add");
|
|
24
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
25
|
+
expect(parsedQuery.args[0]).toBe("products"); // collection name
|
|
26
|
+
expect(parsedQuery.args[1]).toEqual({ id: 1, name: "Laptop", price: 999.99 }); // data with numeric values
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("should parse INSERT with mixed data types", () => {
|
|
30
|
+
const query = "INSERT INTO users (id, name, active, score) VALUES (1, 'Jane', true, 95.5)";
|
|
31
|
+
const parsedQuery = sqlParser.parse(query);
|
|
32
|
+
|
|
33
|
+
expect(parsedQuery).toBeDefined();
|
|
34
|
+
expect(parsedQuery.method).toBe("add");
|
|
35
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
36
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
37
|
+
expect(parsedQuery.args[1]).toEqual({ id: 1, name: "Jane", active: "true", score: 95.5 });
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("should handle INSERT with quoted values containing commas", () => {
|
|
41
|
+
const query = `INSERT INTO posts (title, content) VALUES ('Hello, World!', 'This is a post, with commas.')`;
|
|
42
|
+
const parsedQuery = sqlParser.parse(query);
|
|
43
|
+
|
|
44
|
+
expect(parsedQuery).toBeDefined();
|
|
45
|
+
expect(parsedQuery.method).toBe("add");
|
|
46
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
47
|
+
expect(parsedQuery.args[0]).toBe("posts"); // collection name
|
|
48
|
+
expect(parsedQuery.args[1]).toEqual({
|
|
49
|
+
title: "Hello, World!",
|
|
50
|
+
content: "This is a post, with commas."
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("should throw error for mismatched columns and values", () => {
|
|
55
|
+
const query = "INSERT INTO users (name, email) VALUES ('John')"; // missing value
|
|
56
|
+
|
|
57
|
+
expect(() => {
|
|
58
|
+
sqlParser.parse(query);
|
|
59
|
+
}).toThrow("Number of columns and values does not match");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("should throw error for invalid INSERT syntax", () => {
|
|
63
|
+
const query = "INSERT users (name) VALUES ('John')"; // missing INTO
|
|
64
|
+
|
|
65
|
+
expect(() => {
|
|
66
|
+
sqlParser.parse(query);
|
|
67
|
+
}).toThrow("Invalid INSERT syntax");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("should handle INSERT with double quotes", () => {
|
|
71
|
+
const query = 'INSERT INTO users (name, email) VALUES ("Jane", "jane@example.com")';
|
|
72
|
+
const parsedQuery = sqlParser.parse(query);
|
|
73
|
+
|
|
74
|
+
expect(parsedQuery).toBeDefined();
|
|
75
|
+
expect(parsedQuery.method).toBe("add");
|
|
76
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
77
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
78
|
+
expect(parsedQuery.args[1]).toEqual({ name: "Jane", email: "jane@example.com" });
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("should handle INSERT with mixed quote types", () => {
|
|
82
|
+
const query = `INSERT INTO users (name, email, description) VALUES ("Jane", 'jane@example.com', "User, with 'special' chars")`;
|
|
83
|
+
const parsedQuery = sqlParser.parse(query);
|
|
84
|
+
|
|
85
|
+
expect(parsedQuery).toBeDefined();
|
|
86
|
+
expect(parsedQuery.method).toBe("add");
|
|
87
|
+
expect(parsedQuery.args).toHaveLength(2);
|
|
88
|
+
expect(parsedQuery.args[0]).toBe("users"); // collection name
|
|
89
|
+
expect(parsedQuery.args[1]).toEqual({
|
|
90
|
+
name: "Jane",
|
|
91
|
+
email: "jane@example.com",
|
|
92
|
+
description: "User, with 'special' chars"
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
});
|