@stamhoofd/sql 2.83.5 → 2.84.0
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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/src/QueryableModel.d.ts +1 -0
- package/dist/src/QueryableModel.d.ts.map +1 -1
- package/dist/src/QueryableModel.js +20 -2
- package/dist/src/QueryableModel.js.map +1 -1
- package/dist/src/SQL.d.ts +9 -16
- package/dist/src/SQL.d.ts.map +1 -1
- package/dist/src/SQL.js +16 -13
- package/dist/src/SQL.js.map +1 -1
- package/dist/src/SQLDelete.d.ts +2 -2
- package/dist/src/SQLDelete.d.ts.map +1 -1
- package/dist/src/SQLDelete.js +13 -3
- package/dist/src/SQLDelete.js.map +1 -1
- package/dist/src/SQLExpression.d.ts +3 -0
- package/dist/src/SQLExpression.d.ts.map +1 -1
- package/dist/src/SQLExpression.js.map +1 -1
- package/dist/src/SQLExpressions.d.ts +17 -6
- package/dist/src/SQLExpressions.d.ts.map +1 -1
- package/dist/src/SQLExpressions.js +20 -12
- package/dist/src/SQLExpressions.js.map +1 -1
- package/dist/src/SQLJoin.d.ts +3 -3
- package/dist/src/SQLJoin.d.ts.map +1 -1
- package/dist/src/SQLJoin.js +5 -1
- package/dist/src/SQLJoin.js.map +1 -1
- package/dist/src/SQLJsonExpressions.d.ts +22 -0
- package/dist/src/SQLJsonExpressions.d.ts.map +1 -1
- package/dist/src/SQLJsonExpressions.js +56 -4
- package/dist/src/SQLJsonExpressions.js.map +1 -1
- package/dist/src/SQLSelect.d.ts +10 -4
- package/dist/src/SQLSelect.d.ts.map +1 -1
- package/dist/src/SQLSelect.js +25 -11
- package/dist/src/SQLSelect.js.map +1 -1
- package/dist/src/SQLWhere.d.ts +29 -1
- package/dist/src/SQLWhere.d.ts.map +1 -1
- package/dist/src/SQLWhere.js +181 -12
- package/dist/src/SQLWhere.js.map +1 -1
- package/dist/src/filters/SQLFilter.d.ts +1 -0
- package/dist/src/filters/SQLFilter.d.ts.map +1 -1
- package/dist/src/filters/SQLFilter.js +8 -0
- package/dist/src/filters/SQLFilter.js.map +1 -1
- package/dist/src/filters/modern/SQLModernFilter.d.ts +73 -0
- package/dist/src/filters/modern/SQLModernFilter.d.ts.map +1 -0
- package/dist/src/filters/modern/SQLModernFilter.js +200 -0
- package/dist/src/filters/modern/SQLModernFilter.js.map +1 -0
- package/dist/src/filters/modern/compilers/contains.d.ts +4 -0
- package/dist/src/filters/modern/compilers/contains.d.ts.map +1 -0
- package/dist/src/filters/modern/compilers/contains.js +28 -0
- package/dist/src/filters/modern/compilers/contains.js.map +1 -0
- package/dist/src/filters/modern/compilers/equals.d.ts +4 -0
- package/dist/src/filters/modern/compilers/equals.d.ts.map +1 -0
- package/dist/src/filters/modern/compilers/equals.js +46 -0
- package/dist/src/filters/modern/compilers/equals.js.map +1 -0
- package/dist/src/filters/modern/compilers/greater.d.ts +4 -0
- package/dist/src/filters/modern/compilers/greater.d.ts.map +1 -0
- package/dist/src/filters/modern/compilers/greater.js +17 -0
- package/dist/src/filters/modern/compilers/greater.js.map +1 -0
- package/dist/src/filters/modern/compilers/in.d.ts +4 -0
- package/dist/src/filters/modern/compilers/in.d.ts.map +1 -0
- package/dist/src/filters/modern/compilers/in.js +50 -0
- package/dist/src/filters/modern/compilers/in.js.map +1 -0
- package/dist/src/filters/modern/compilers/index.d.ts +5 -0
- package/dist/src/filters/modern/compilers/index.d.ts.map +1 -0
- package/dist/src/filters/modern/compilers/index.js +8 -0
- package/dist/src/filters/modern/compilers/index.js.map +1 -0
- package/dist/src/filters/modern/compilers/less.d.ts +4 -0
- package/dist/src/filters/modern/compilers/less.d.ts.map +1 -0
- package/dist/src/filters/modern/compilers/less.js +17 -0
- package/dist/src/filters/modern/compilers/less.js.map +1 -0
- package/dist/src/filters/modern/helpers/isJSONColumn.d.ts +4 -0
- package/dist/src/filters/modern/helpers/isJSONColumn.d.ts.map +1 -0
- package/dist/src/filters/modern/helpers/isJSONColumn.js +16 -0
- package/dist/src/filters/modern/helpers/isJSONColumn.js.map +1 -0
- package/dist/src/filters/modern/helpers/normalizeCompareValue.d.ts +9 -0
- package/dist/src/filters/modern/helpers/normalizeCompareValue.d.ts.map +1 -0
- package/dist/src/filters/modern/helpers/normalizeCompareValue.js +82 -0
- package/dist/src/filters/modern/helpers/normalizeCompareValue.js.map +1 -0
- package/dist/tests/filters/$and.test.d.ts +2 -0
- package/dist/tests/filters/$and.test.d.ts.map +1 -0
- package/dist/tests/filters/$and.test.js +185 -0
- package/dist/tests/filters/$and.test.js.map +1 -0
- package/dist/tests/filters/$contains.test.d.ts +2 -0
- package/dist/tests/filters/$contains.test.d.ts.map +1 -0
- package/dist/tests/filters/$contains.test.js +701 -0
- package/dist/tests/filters/$contains.test.js.map +1 -0
- package/dist/tests/filters/$eq.test.d.ts +2 -0
- package/dist/tests/filters/$eq.test.d.ts.map +1 -0
- package/dist/tests/filters/$eq.test.js +986 -0
- package/dist/tests/filters/$eq.test.js.map +1 -0
- package/dist/tests/filters/$gt.test.d.ts +2 -0
- package/dist/tests/filters/$gt.test.d.ts.map +1 -0
- package/dist/tests/filters/$gt.test.js +463 -0
- package/dist/tests/filters/$gt.test.js.map +1 -0
- package/dist/tests/filters/$gte.test.d.ts +2 -0
- package/dist/tests/filters/$gte.test.d.ts.map +1 -0
- package/dist/tests/filters/$gte.test.js +433 -0
- package/dist/tests/filters/$gte.test.js.map +1 -0
- package/dist/tests/filters/$in.test.d.ts +2 -0
- package/dist/tests/filters/$in.test.d.ts.map +1 -0
- package/dist/tests/filters/$in.test.js +590 -0
- package/dist/tests/filters/$in.test.js.map +1 -0
- package/dist/tests/filters/$lt.test.d.ts +2 -0
- package/dist/tests/filters/$lt.test.d.ts.map +1 -0
- package/dist/tests/filters/$lt.test.js +433 -0
- package/dist/tests/filters/$lt.test.js.map +1 -0
- package/dist/tests/filters/$lte.test.d.ts +2 -0
- package/dist/tests/filters/$lte.test.d.ts.map +1 -0
- package/dist/tests/filters/$lte.test.js +472 -0
- package/dist/tests/filters/$lte.test.js.map +1 -0
- package/dist/tests/filters/$neq.test.d.ts +2 -0
- package/dist/tests/filters/$neq.test.d.ts.map +1 -0
- package/dist/tests/filters/$neq.test.js +32 -0
- package/dist/tests/filters/$neq.test.js.map +1 -0
- package/dist/tests/filters/$not.test.d.ts +2 -0
- package/dist/tests/filters/$not.test.d.ts.map +1 -0
- package/dist/tests/filters/$not.test.js +50 -0
- package/dist/tests/filters/$not.test.js.map +1 -0
- package/dist/tests/filters/$or.test.d.ts +2 -0
- package/dist/tests/filters/$or.test.d.ts.map +1 -0
- package/dist/tests/filters/$or.test.js +185 -0
- package/dist/tests/filters/$or.test.js.map +1 -0
- package/dist/tests/filters/dot-syntax.test.d.ts +2 -0
- package/dist/tests/filters/dot-syntax.test.d.ts.map +1 -0
- package/dist/tests/filters/dot-syntax.test.js +210 -0
- package/dist/tests/filters/dot-syntax.test.js.map +1 -0
- package/dist/tests/filters/exists.test.d.ts +2 -0
- package/dist/tests/filters/exists.test.d.ts.map +1 -0
- package/dist/tests/filters/exists.test.js +106 -0
- package/dist/tests/filters/exists.test.js.map +1 -0
- package/dist/tests/filters/joined-relations.test.d.ts +2 -0
- package/dist/tests/filters/joined-relations.test.d.ts.map +1 -0
- package/dist/tests/filters/joined-relations.test.js +167 -0
- package/dist/tests/filters/joined-relations.test.js.map +1 -0
- package/dist/tests/filters/special-cases.test.d.ts +2 -0
- package/dist/tests/filters/special-cases.test.d.ts.map +1 -0
- package/dist/tests/filters/special-cases.test.js +114 -0
- package/dist/tests/filters/special-cases.test.js.map +1 -0
- package/dist/tests/filters/wildcard.test.d.ts +2 -0
- package/dist/tests/filters/wildcard.test.d.ts.map +1 -0
- package/dist/tests/filters/wildcard.test.js +67 -0
- package/dist/tests/filters/wildcard.test.js.map +1 -0
- package/dist/tests/jest.global.setup.d.ts +3 -0
- package/dist/tests/jest.global.setup.d.ts.map +1 -0
- package/dist/tests/jest.global.setup.js +7 -0
- package/dist/tests/jest.global.setup.js.map +1 -0
- package/dist/tests/jest.setup.d.ts +2 -0
- package/dist/tests/jest.setup.d.ts.map +1 -0
- package/dist/tests/jest.setup.js +5 -0
- package/dist/tests/jest.setup.js.map +1 -0
- package/dist/tests/utils/index.d.ts +57 -0
- package/dist/tests/utils/index.d.ts.map +1 -0
- package/dist/tests/utils/index.js +206 -0
- package/dist/tests/utils/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -3
- package/src/QueryableModel.ts +22 -2
- package/src/SQL.ts +21 -30
- package/src/SQLDelete.ts +26 -15
- package/src/SQLExpression.ts +4 -0
- package/src/SQLExpressions.ts +23 -14
- package/src/SQLJoin.ts +8 -4
- package/src/SQLJsonExpressions.ts +65 -4
- package/src/SQLSelect.ts +31 -15
- package/src/SQLWhere.ts +208 -13
- package/src/filters/SQLFilter.ts +8 -0
- package/src/filters/modern/SQLModernFilter.ts +256 -0
- package/src/filters/modern/compilers/contains.ts +43 -0
- package/src/filters/modern/compilers/equals.ts +72 -0
- package/src/filters/modern/compilers/greater.ts +20 -0
- package/src/filters/modern/compilers/in.ts +62 -0
- package/src/filters/modern/compilers/index.ts +4 -0
- package/src/filters/modern/compilers/less.ts +19 -0
- package/src/filters/modern/helpers/isJSONColumn.ts +13 -0
- package/src/filters/modern/helpers/normalizeCompareValue.ts +95 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.testError = testError;
|
|
4
|
+
exports.test = test;
|
|
5
|
+
exports.testSelect = testSelect;
|
|
6
|
+
exports.testMultiple = testMultiple;
|
|
7
|
+
exports.testMultipleErrors = testMultipleErrors;
|
|
8
|
+
exports.doesQueryMatch = doesQueryMatch;
|
|
9
|
+
exports.createTableDefinition = createTableDefinition;
|
|
10
|
+
exports.testMatch = testMatch;
|
|
11
|
+
const simple_database_1 = require("@simonbackx/simple-database");
|
|
12
|
+
const test_utils_1 = require("@stamhoofd/test-utils");
|
|
13
|
+
const SQLModernFilter_1 = require("../../src/filters/modern/SQLModernFilter");
|
|
14
|
+
const SQL_1 = require("../../src/SQL");
|
|
15
|
+
const SQLWhere_1 = require("../../src/SQLWhere");
|
|
16
|
+
async function testError({ filter, filters, error }) {
|
|
17
|
+
await expect((0, SQLModernFilter_1.compileToModernSQLFilter)(filter, filters)).rejects.toThrow(error);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Only compares the WHERE clause of the query.
|
|
21
|
+
*/
|
|
22
|
+
async function test({ filter, filters, query }) {
|
|
23
|
+
const where = await (0, SQLModernFilter_1.compileToModernSQLFilter)(filter, filters);
|
|
24
|
+
if (where.isAlways === false) {
|
|
25
|
+
doesQueryMatch('', query);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (where.isAlways === true) {
|
|
29
|
+
doesQueryMatch('true', query);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const sql = where.getSQL({
|
|
33
|
+
defaultNamespace: 'default',
|
|
34
|
+
parentNamespace: 'parent',
|
|
35
|
+
});
|
|
36
|
+
doesQueryMatch(sql, query);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Use to also test joins. This will use `test_table` as the table name in your query.
|
|
40
|
+
*/
|
|
41
|
+
async function testSelect({ filter, filters, query }) {
|
|
42
|
+
const where = await (0, SQLModernFilter_1.compileToModernSQLFilter)(filter, filters);
|
|
43
|
+
if (where.isAlways === false) {
|
|
44
|
+
doesQueryMatch('', query);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const select = SQL_1.SQL.select().from('test_table').where(where);
|
|
48
|
+
let sql;
|
|
49
|
+
try {
|
|
50
|
+
sql = select.getSQL();
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
console.error('Error in testSelect:', e);
|
|
54
|
+
console.error('testSelect', select, where, (where instanceof SQLWhere_1.SQLWhereAnd ? where.children : where));
|
|
55
|
+
throw e;
|
|
56
|
+
}
|
|
57
|
+
doesQueryMatch(sql, query);
|
|
58
|
+
}
|
|
59
|
+
async function testMultiple({ testFilters, filters, query }) {
|
|
60
|
+
for (const filter of testFilters) {
|
|
61
|
+
await test({
|
|
62
|
+
filter,
|
|
63
|
+
filters,
|
|
64
|
+
query,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function testMultipleErrors({ testFilters, filters, error }) {
|
|
69
|
+
for (const filter of testFilters) {
|
|
70
|
+
await testError({
|
|
71
|
+
filter,
|
|
72
|
+
filters,
|
|
73
|
+
error,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function doesQueryMatch(query, withQuery) {
|
|
78
|
+
const str1 = typeof query === 'string' ? query : query.query;
|
|
79
|
+
const str2 = typeof withQuery === 'string' ? withQuery : withQuery.query;
|
|
80
|
+
const params1 = typeof query === 'string' ? [] : query.params;
|
|
81
|
+
const params2 = typeof withQuery === 'string' ? [] : withQuery.params;
|
|
82
|
+
expect(str1).toBe(str2);
|
|
83
|
+
expect(params1).toEqual(params2);
|
|
84
|
+
}
|
|
85
|
+
function createTableDefinition(tableName, definition) {
|
|
86
|
+
const columns = Object.entries(definition).map(([name, { type, nullable }]) => {
|
|
87
|
+
const stringType = type === 'varchar' ? 'VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci' : type;
|
|
88
|
+
return `\`${name}\` ${stringType}${nullable ? '' : ' NOT NULL'}`;
|
|
89
|
+
}).join(',\n');
|
|
90
|
+
return `CREATE TABLE \`${tableName}\` (\n${columns}\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;`;
|
|
91
|
+
}
|
|
92
|
+
let didAdd = false;
|
|
93
|
+
function closeDatabaseAfterTests() {
|
|
94
|
+
if (didAdd) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
didAdd = true;
|
|
98
|
+
test_utils_1.TestUtils.addAfterAll(async () => {
|
|
99
|
+
try {
|
|
100
|
+
await simple_database_1.Database.end();
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
console.error('Failed to close database connection after tests:', error);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Tests actual MySQL behaviour, for complex queries that depend on MySQL behaviour.
|
|
109
|
+
*
|
|
110
|
+
* Creates a table, inserts a row with provided data. Then runs a query with the provided filter and checks if the row matches the expected query.
|
|
111
|
+
*
|
|
112
|
+
* Snapshots the query.
|
|
113
|
+
*/
|
|
114
|
+
async function testMatch({ tableDefinition, rows, doMatch, doNotMatch, filters }) {
|
|
115
|
+
const tableName = 'test_table_' + Math.random().toString(36).substring(2, 15);
|
|
116
|
+
const createTableSQL = createTableDefinition(tableName, tableDefinition);
|
|
117
|
+
closeDatabaseAfterTests();
|
|
118
|
+
try {
|
|
119
|
+
await simple_database_1.Database.statement(createTableSQL);
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
console.error('Failed to create test table:', error);
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
// Insert test rows
|
|
126
|
+
for (const row of rows) {
|
|
127
|
+
const mappedValues = {};
|
|
128
|
+
for (const [key, value] of Object.entries(row)) {
|
|
129
|
+
if (value === null) {
|
|
130
|
+
mappedValues[key] = null;
|
|
131
|
+
}
|
|
132
|
+
else if (typeof value === 'object' && !(value instanceof Date)) {
|
|
133
|
+
mappedValues[key] = JSON.stringify(value);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
mappedValues[key] = value;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
await simple_database_1.Database.insert('INSERT INTO `' + tableName + '` SET ?', [mappedValues]);
|
|
141
|
+
}
|
|
142
|
+
catch (insertError) {
|
|
143
|
+
console.error('Failed to insert row:', insertError, row);
|
|
144
|
+
throw insertError;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Run queries
|
|
148
|
+
try {
|
|
149
|
+
for (const filter of doMatch ?? []) {
|
|
150
|
+
const where = await (0, SQLModernFilter_1.compileToModernSQLFilter)(filter, filters);
|
|
151
|
+
const select = SQL_1.SQL.select().from(tableName).where(where);
|
|
152
|
+
let results;
|
|
153
|
+
try {
|
|
154
|
+
results = await select.fetch();
|
|
155
|
+
}
|
|
156
|
+
catch (e) {
|
|
157
|
+
console.error('SQL error for filter:', filter, 'on table:', tableName, 'with where:', select.getSQL(), e);
|
|
158
|
+
throw e;
|
|
159
|
+
}
|
|
160
|
+
if (results.length !== rows.length) {
|
|
161
|
+
console.error('Unexpected results for filter:', filter, 'on table:', tableName, 'with where:', select.getSQL(), results);
|
|
162
|
+
}
|
|
163
|
+
expect(results).toHaveLength(rows.length);
|
|
164
|
+
const query = select.getSQL();
|
|
165
|
+
expect({
|
|
166
|
+
query: query.query.replaceAll('`' + tableName + '`', '`test_table`'),
|
|
167
|
+
params: query.params,
|
|
168
|
+
}).toMatchSnapshot('SQL Query for filter: ' + JSON.stringify(filter));
|
|
169
|
+
}
|
|
170
|
+
for (const filter of doNotMatch ?? []) {
|
|
171
|
+
const where = await (0, SQLModernFilter_1.compileToModernSQLFilter)(filter, filters);
|
|
172
|
+
const select = SQL_1.SQL.select().from(tableName).where(where);
|
|
173
|
+
let results;
|
|
174
|
+
try {
|
|
175
|
+
results = await select.fetch();
|
|
176
|
+
}
|
|
177
|
+
catch (e) {
|
|
178
|
+
console.error('SQL error for filter:', filter, 'on table:', tableName, 'with where:', select.getSQL(), e);
|
|
179
|
+
throw e;
|
|
180
|
+
}
|
|
181
|
+
if (results.length > 0) {
|
|
182
|
+
console.error('Unexpected results for filter:', filter, 'on table:', tableName, 'with where:', select.getSQL(), results);
|
|
183
|
+
}
|
|
184
|
+
expect(results).toHaveLength(0);
|
|
185
|
+
if (!select._where || !select._where.isAlwaysFalse) {
|
|
186
|
+
const query = select.getSQL();
|
|
187
|
+
expect({
|
|
188
|
+
query: query.query.replaceAll('`' + tableName + '`', '`test_table`'),
|
|
189
|
+
params: query.params,
|
|
190
|
+
}).toMatchSnapshot('SQL Query for not match filter: ' + JSON.stringify(filter));
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
expect('always false').toMatchSnapshot('SQL Query for not match filter: ' + JSON.stringify(filter));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
finally {
|
|
198
|
+
try {
|
|
199
|
+
await simple_database_1.Database.statement(`DROP TABLE IF EXISTS \`${tableName}\``);
|
|
200
|
+
}
|
|
201
|
+
catch (dropError) {
|
|
202
|
+
console.error('Failed to drop table after error:', dropError);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../tests/utils/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/queryablemodel.ts","../src/sql.ts","../src/sqldelete.ts","../src/sqlexpression.ts","../src/sqlexpressions.ts","../src/sqlinsert.ts","../src/sqljoin.ts","../src/sqljsonexpressions.ts","../src/sqlorderby.ts","../src/sqlselect.ts","../src/sqlupdate.ts","../src/sqlwhere.ts","../src/filters/sqlfilter.ts","../src/filters/sqlsorter.ts","../index.ts","../../../../environment.d.ts","../../../../jest-extended.d.ts","../../../stamhoofd.d.ts"],"version":"5.6.2"}
|
|
1
|
+
{"root":["../src/queryablemodel.ts","../src/sql.ts","../src/sqldelete.ts","../src/sqlexpression.ts","../src/sqlexpressions.ts","../src/sqlinsert.ts","../src/sqljoin.ts","../src/sqljsonexpressions.ts","../src/sqlorderby.ts","../src/sqlselect.ts","../src/sqlupdate.ts","../src/sqlwhere.ts","../src/filters/sqlfilter.ts","../src/filters/sqlsorter.ts","../src/filters/modern/sqlmodernfilter.ts","../src/filters/modern/compilers/contains.ts","../src/filters/modern/compilers/equals.ts","../src/filters/modern/compilers/greater.ts","../src/filters/modern/compilers/in.ts","../src/filters/modern/compilers/index.ts","../src/filters/modern/compilers/less.ts","../src/filters/modern/helpers/isjsoncolumn.ts","../src/filters/modern/helpers/normalizecomparevalue.ts","../tests/jest.global.setup.ts","../tests/jest.setup.ts","../tests/filters/$and.test.ts","../tests/filters/$contains.test.ts","../tests/filters/$eq.test.ts","../tests/filters/$gt.test.ts","../tests/filters/$gte.test.ts","../tests/filters/$in.test.ts","../tests/filters/$lt.test.ts","../tests/filters/$lte.test.ts","../tests/filters/$neq.test.ts","../tests/filters/$not.test.ts","../tests/filters/$or.test.ts","../tests/filters/dot-syntax.test.ts","../tests/filters/exists.test.ts","../tests/filters/joined-relations.test.ts","../tests/filters/special-cases.test.ts","../tests/filters/wildcard.test.ts","../tests/utils/index.ts","../index.ts","../../../../environment.d.ts","../../../../jest-extended.d.ts","../../../stamhoofd.d.ts"],"version":"5.6.2"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stamhoofd/sql",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.84.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"license": "UNLICENCED",
|
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
"dist"
|
|
11
11
|
],
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build": "tsc -b"
|
|
13
|
+
"build": "tsc -b",
|
|
14
|
+
"test": "jest"
|
|
14
15
|
},
|
|
15
16
|
"publishConfig": {
|
|
16
17
|
"access": "public"
|
|
17
18
|
},
|
|
18
|
-
"gitHead": "
|
|
19
|
+
"gitHead": "99cf8650892792358d7516bb83458642d886dee7"
|
|
19
20
|
}
|
package/src/QueryableModel.ts
CHANGED
|
@@ -41,9 +41,29 @@ export class QueryableModel extends Model {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
const me = await (this.static as typeof QueryableModel).select().where(this.static.primary.name, this.getPrimaryKey()).first(true);
|
|
44
|
+
this.copyFrom(me);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static async refreshAll<T extends typeof QueryableModel>(this: T, list: InstanceType<T>[]) {
|
|
48
|
+
// Cut up in batches of max 100
|
|
49
|
+
const batchSize = 100;
|
|
50
|
+
for (let i = 0; i < list.length; i += batchSize) {
|
|
51
|
+
const batch = list.slice(i, i + batchSize);
|
|
52
|
+
const ids = list.map(item => item.getPrimaryKey()).filter(id => id !== null);
|
|
53
|
+
if (ids.length === 0) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
44
56
|
|
|
45
|
-
|
|
46
|
-
|
|
57
|
+
const refreshed = await this.getByIDs(...ids);
|
|
58
|
+
|
|
59
|
+
for (const item of batch) {
|
|
60
|
+
const refreshedItem = refreshed.find(r => r.getPrimaryKey() === item.getPrimaryKey());
|
|
61
|
+
if (refreshedItem) {
|
|
62
|
+
for (const column of this.columns.values()) {
|
|
63
|
+
item[column.name] = refreshedItem[column.name];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
47
67
|
}
|
|
48
68
|
}
|
|
49
69
|
}
|
package/src/SQL.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { SQLResultNamespacedRow } from '@simonbackx/simple-database';
|
|
2
2
|
import { SQLDelete } from './SQLDelete';
|
|
3
|
-
import { isSQLExpression, SQLExpression } from './SQLExpression';
|
|
4
|
-
import { SQLAssignment, SQLColumnExpression, SQLColumnExpressionParams, SQLIf, SQLSafeValue, SQLScalar, SQLScalarValue, SQLTableExpression, SQLWildcardSelectExpression } from './SQLExpressions';
|
|
3
|
+
import { isSQLExpression, SQLExpression, SQLNamedExpression } from './SQLExpression';
|
|
4
|
+
import { SQLAssignment, SQLColumnExpression, SQLColumnExpressionParams, SQLIf, SQLParentNamespace, SQLSafeValue, SQLScalar, SQLScalarValue, SQLTableExpression, SQLWildcardSelectExpression } from './SQLExpressions';
|
|
5
5
|
import { SQLInsert } from './SQLInsert';
|
|
6
6
|
import { SQLJoin, SQLJoinType } from './SQLJoin';
|
|
7
|
-
import { SQLJsonExtract, SQLJsonLength, SQLJsonUnquote, SQLLpad } from './SQLJsonExpressions';
|
|
7
|
+
import { SQLJsonExtract, SQLJsonKeys, SQLJsonLength, SQLJsonUnquote, SQLLpad } from './SQLJsonExpressions';
|
|
8
8
|
import { parseTable, SQLSelect } from './SQLSelect';
|
|
9
9
|
import { SQLUpdate } from './SQLUpdate';
|
|
10
10
|
import { ParseWhereArguments, SQLEmptyWhere, SQLWhere } from './SQLWhere';
|
|
@@ -18,10 +18,18 @@ class StaticSQL {
|
|
|
18
18
|
return new SQLColumnExpression(...args);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
parentColumn(column: string): SQLColumnExpression {
|
|
22
|
+
return new SQLColumnExpression(SQLParentNamespace, column);
|
|
23
|
+
}
|
|
24
|
+
|
|
21
25
|
jsonValue(column: SQLExpression, path: string, asScalar = false): SQLJsonExtract {
|
|
22
26
|
return new SQLJsonExtract(column, asScalar ? new SQLScalar(path) : new SQLSafeValue(path));
|
|
23
27
|
}
|
|
24
28
|
|
|
29
|
+
jsonKeys(column: SQLExpression): SQLJsonKeys {
|
|
30
|
+
return new SQLJsonKeys(column);
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
lpad(column: SQLExpression, length: number, value: string): SQLLpad {
|
|
26
34
|
return new SQLLpad(column, new SQLSafeValue(length), new SQLSafeValue(value));
|
|
27
35
|
}
|
|
@@ -34,13 +42,8 @@ class StaticSQL {
|
|
|
34
42
|
return new SQLJsonLength(column, path ? new SQLSafeValue(path) : undefined);
|
|
35
43
|
}
|
|
36
44
|
|
|
37
|
-
table(
|
|
38
|
-
|
|
39
|
-
table(namespaceOrTable: string, table?: string): SQLTableExpression {
|
|
40
|
-
if (table === undefined) {
|
|
41
|
-
return new SQLTableExpression(namespaceOrTable);
|
|
42
|
-
}
|
|
43
|
-
return new SQLTableExpression(namespaceOrTable, table);
|
|
45
|
+
table(table: string, asNamespace?: string): SQLTableExpression {
|
|
46
|
+
return new SQLTableExpression(table, asNamespace);
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
select(...columns: (SQLExpression | string)[]): InstanceType<typeof SQLSelect<SQLResultNamespacedRow>> {
|
|
@@ -74,32 +77,20 @@ class StaticSQL {
|
|
|
74
77
|
return new SQLDelete();
|
|
75
78
|
}
|
|
76
79
|
|
|
77
|
-
leftJoin(
|
|
78
|
-
|
|
79
|
-
leftJoin(expression: SQLExpression): SQLJoin;
|
|
80
|
-
leftJoin(tableOrExpressiongOrNamespace: SQLExpression | string, table?: string): SQLJoin {
|
|
81
|
-
return new SQLJoin(SQLJoinType.Left, parseTable(tableOrExpressiongOrNamespace, table));
|
|
80
|
+
leftJoin(...args: Parameters<typeof parseTable>): SQLJoin {
|
|
81
|
+
return new SQLJoin(SQLJoinType.Left, parseTable(...args));
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
rightJoin(
|
|
85
|
-
|
|
86
|
-
rightJoin(expression: SQLExpression): SQLJoin;
|
|
87
|
-
rightJoin(tableOrExpressiongOrNamespace: SQLExpression | string, table?: string): SQLJoin {
|
|
88
|
-
return new SQLJoin(SQLJoinType.Right, parseTable(tableOrExpressiongOrNamespace, table));
|
|
84
|
+
rightJoin(...args: Parameters<typeof parseTable>): SQLJoin {
|
|
85
|
+
return new SQLJoin(SQLJoinType.Right, parseTable(...args));
|
|
89
86
|
}
|
|
90
87
|
|
|
91
|
-
innerJoin(
|
|
92
|
-
|
|
93
|
-
innerJoin(expression: SQLExpression): SQLJoin;
|
|
94
|
-
innerJoin(tableOrExpressiongOrNamespace: SQLExpression | string, table?: string): SQLJoin {
|
|
95
|
-
return new SQLJoin(SQLJoinType.Inner, parseTable(tableOrExpressiongOrNamespace, table));
|
|
88
|
+
innerJoin(...args: Parameters<typeof parseTable>): SQLJoin {
|
|
89
|
+
return new SQLJoin(SQLJoinType.Inner, parseTable(...args));
|
|
96
90
|
}
|
|
97
91
|
|
|
98
|
-
join(
|
|
99
|
-
|
|
100
|
-
join(expression: SQLExpression): SQLJoin;
|
|
101
|
-
join(tableOrExpressiongOrNamespace: SQLExpression | string, table?: string): SQLJoin {
|
|
102
|
-
return new SQLJoin(SQLJoinType.Inner, parseTable(tableOrExpressiongOrNamespace, table));
|
|
92
|
+
join(...args: Parameters<typeof parseTable>): SQLJoin {
|
|
93
|
+
return new SQLJoin(SQLJoinType.Inner, parseTable(...args));
|
|
103
94
|
}
|
|
104
95
|
|
|
105
96
|
if(...args: ConstructorParameters<typeof SQLIf>): SQLIf {
|
package/src/SQLDelete.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Database } from
|
|
2
|
-
import { SQLExpression, SQLExpressionOptions, SQLQuery, joinSQLQuery, normalizeSQLQuery } from
|
|
1
|
+
import { Database } from '@simonbackx/simple-database';
|
|
2
|
+
import { SQLExpression, SQLExpressionOptions, SQLQuery, joinSQLQuery, normalizeSQLQuery } from './SQLExpression';
|
|
3
3
|
import { SQLJoin } from './SQLJoin';
|
|
4
|
-
import { SQLWhere, Whereable } from
|
|
4
|
+
import { SQLWhere, Whereable } from './SQLWhere';
|
|
5
5
|
|
|
6
6
|
class EmptyClass {}
|
|
7
7
|
export class SQLDelete extends Whereable(EmptyClass) implements SQLExpression {
|
|
@@ -9,7 +9,7 @@ export class SQLDelete extends Whereable(EmptyClass) implements SQLExpression {
|
|
|
9
9
|
_joins: (InstanceType<typeof SQLJoin>)[] = [];
|
|
10
10
|
|
|
11
11
|
clone(): this {
|
|
12
|
-
const c = new SQLDelete()
|
|
12
|
+
const c = new SQLDelete();
|
|
13
13
|
Object.assign(c, this);
|
|
14
14
|
return c as any;
|
|
15
15
|
}
|
|
@@ -26,37 +26,48 @@ export class SQLDelete extends Whereable(EmptyClass) implements SQLExpression {
|
|
|
26
26
|
|
|
27
27
|
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
28
28
|
const query: SQLQuery[] = [
|
|
29
|
-
'DELETE'
|
|
30
|
-
]
|
|
29
|
+
'DELETE',
|
|
30
|
+
];
|
|
31
31
|
|
|
32
|
-
options = options ?? {}
|
|
32
|
+
options = options ?? {};
|
|
33
33
|
options.defaultNamespace = (this._from as any).namespace ?? (this._from as any).table ?? undefined;
|
|
34
34
|
|
|
35
35
|
query.push(
|
|
36
|
-
'FROM'
|
|
37
|
-
)
|
|
36
|
+
'FROM',
|
|
37
|
+
);
|
|
38
38
|
|
|
39
39
|
query.push(this._from.getSQL(options));
|
|
40
40
|
|
|
41
|
-
query.push(...this._joins.map(j => j.getSQL(options)))
|
|
41
|
+
query.push(...this._joins.map(j => j.getSQL(options)));
|
|
42
42
|
|
|
43
|
+
// Where
|
|
43
44
|
if (this._where) {
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
const always = this._where.isAlways;
|
|
46
|
+
if (always === false) {
|
|
47
|
+
throw new Error('Cannot use SQLDelete with a where that is not always true');
|
|
48
|
+
}
|
|
49
|
+
else if (always === null) {
|
|
50
|
+
query.push('WHERE');
|
|
51
|
+
query.push(this._where.getSQL(options));
|
|
52
|
+
}
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
return joinSQLQuery(query, ' ');
|
|
49
56
|
}
|
|
50
57
|
|
|
51
|
-
async delete(): Promise<{affectedRows: number}> {
|
|
52
|
-
|
|
58
|
+
async delete(): Promise<{ affectedRows: number }> {
|
|
59
|
+
if (this._where && this._where.isAlways === false) {
|
|
60
|
+
return { affectedRows: 0 };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const { query, params } = normalizeSQLQuery(this.getSQL());
|
|
53
64
|
|
|
54
65
|
console.log(query, params);
|
|
55
66
|
const [rows] = await Database.delete(query, params);
|
|
56
67
|
return rows;
|
|
57
68
|
}
|
|
58
69
|
|
|
59
|
-
async then(onFulfilled: (value: {affectedRows: number}) => any, onRejected: (reason: any) => any): Promise<any> {
|
|
70
|
+
async then(onFulfilled: (value: { affectedRows: number }) => any, onRejected: (reason: any) => any): Promise<any> {
|
|
60
71
|
return this.delete().then(onFulfilled, onRejected);
|
|
61
72
|
}
|
|
62
73
|
}
|
package/src/SQLExpression.ts
CHANGED
|
@@ -25,6 +25,10 @@ export interface SQLExpression {
|
|
|
25
25
|
getSQL(options?: SQLExpressionOptions): SQLQuery;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
export interface SQLNamedExpression extends SQLExpression {
|
|
29
|
+
getName(): string;
|
|
30
|
+
}
|
|
31
|
+
|
|
28
32
|
export function isSQLExpression(obj: unknown): obj is SQLExpression {
|
|
29
33
|
return typeof obj === 'object' && obj !== null && !!(obj as any).getSQL && typeof (obj as any).getSQL === 'function';
|
|
30
34
|
}
|
package/src/SQLExpressions.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Database } from '@simonbackx/simple-database';
|
|
2
|
-
import { joinSQLQuery, SQLExpression, SQLExpressionOptions, SQLQuery } from './SQLExpression';
|
|
2
|
+
import { joinSQLQuery, SQLExpression, SQLExpressionOptions, SQLNamedExpression, SQLQuery } from './SQLExpression';
|
|
3
3
|
import { ParseWhereArguments, SQLEmptyWhere } from './SQLWhere';
|
|
4
4
|
|
|
5
5
|
export type SQLScalarValue = string | number | boolean | Date;
|
|
@@ -269,7 +269,7 @@ export class SQLCast implements SQLExpression {
|
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
|
|
272
|
-
|
|
272
|
+
class SQLCastedJson implements SQLExpression {
|
|
273
273
|
value: null | true | false;
|
|
274
274
|
|
|
275
275
|
constructor(value: null | true | false) {
|
|
@@ -280,6 +280,9 @@ export class SQLJSONValue implements SQLExpression {
|
|
|
280
280
|
return "CAST('" + JSON.stringify(this.value) + "' AS JSON)";
|
|
281
281
|
}
|
|
282
282
|
}
|
|
283
|
+
export const SQLJSONNull = new SQLCastedJson(null);
|
|
284
|
+
export const SQLJSONTrue = new SQLCastedJson(true);
|
|
285
|
+
export const SQLJSONFalse = new SQLCastedJson(false);
|
|
283
286
|
|
|
284
287
|
export class SQLNull implements SQLExpression {
|
|
285
288
|
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
@@ -418,26 +421,32 @@ export class SQLColumnExpression implements SQLExpression {
|
|
|
418
421
|
}
|
|
419
422
|
}
|
|
420
423
|
|
|
421
|
-
export class SQLTableExpression implements
|
|
422
|
-
|
|
424
|
+
export class SQLTableExpression implements SQLNamedExpression {
|
|
425
|
+
/**
|
|
426
|
+
* By default the table name will be used as the namespace by MySQL.
|
|
427
|
+
*/
|
|
428
|
+
asNamespace?: string;
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* For now this is just a string, but thearetically it could be a subquery.
|
|
432
|
+
* We don't support that yet, as those queries are not optimized for performance.
|
|
433
|
+
*/
|
|
423
434
|
table: string;
|
|
424
435
|
|
|
425
|
-
constructor(
|
|
426
|
-
|
|
427
|
-
constructor(namespaceOrTable: string, table?: string) {
|
|
428
|
-
if (table === undefined) {
|
|
429
|
-
this.table = namespaceOrTable;
|
|
430
|
-
return;
|
|
431
|
-
}
|
|
432
|
-
this.namespace = namespaceOrTable;
|
|
436
|
+
constructor(table: string, asNamespace?: string) {
|
|
437
|
+
this.asNamespace = asNamespace;
|
|
433
438
|
this.table = table;
|
|
434
439
|
}
|
|
435
440
|
|
|
436
441
|
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
437
|
-
if (!this.
|
|
442
|
+
if (!this.asNamespace) {
|
|
438
443
|
return Database.escapeId(this.table);
|
|
439
444
|
}
|
|
440
|
-
return Database.escapeId(this.table) + ' ' + Database.escapeId(this.
|
|
445
|
+
return Database.escapeId(this.table) + ' ' + Database.escapeId(this.asNamespace);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
getName(): string {
|
|
449
|
+
return this.asNamespace ?? this.table;
|
|
441
450
|
}
|
|
442
451
|
}
|
|
443
452
|
|
package/src/SQLJoin.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SQLExpression, SQLExpressionOptions, SQLQuery, joinSQLQuery } from './SQLExpression';
|
|
1
|
+
import { SQLExpression, SQLExpressionOptions, SQLNamedExpression, SQLQuery, joinSQLQuery } from './SQLExpression';
|
|
2
2
|
import { Whereable } from './SQLWhere';
|
|
3
3
|
|
|
4
4
|
export enum SQLJoinType {
|
|
@@ -11,9 +11,9 @@ export enum SQLJoinType {
|
|
|
11
11
|
class EmptyClass {}
|
|
12
12
|
export class SQLJoin extends Whereable(EmptyClass) implements SQLExpression {
|
|
13
13
|
type = SQLJoinType.Left;
|
|
14
|
-
table:
|
|
14
|
+
table: SQLNamedExpression;
|
|
15
15
|
|
|
16
|
-
constructor(type: SQLJoinType, table:
|
|
16
|
+
constructor(type: SQLJoinType, table: SQLNamedExpression) {
|
|
17
17
|
super();
|
|
18
18
|
this.type = type;
|
|
19
19
|
this.table = table;
|
|
@@ -33,7 +33,11 @@ export class SQLJoin extends Whereable(EmptyClass) implements SQLExpression {
|
|
|
33
33
|
this.getJoinPrefix(),
|
|
34
34
|
this.table?.getSQL(options),
|
|
35
35
|
this._where ? 'ON' : undefined,
|
|
36
|
-
this._where?.getSQL(
|
|
36
|
+
this._where?.getSQL({
|
|
37
|
+
...options,
|
|
38
|
+
parentNamespace: options?.defaultNamespace,
|
|
39
|
+
defaultNamespace: this.table.getName(),
|
|
40
|
+
}),
|
|
37
41
|
], ' ');
|
|
38
42
|
}
|
|
39
43
|
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { SQLExpression, SQLExpressionOptions, SQLQuery, joinSQLQuery } from './SQLExpression';
|
|
2
|
-
import {
|
|
2
|
+
import { SQLJSONFalse, SQLJSONNull, SQLJSONTrue, SQLSafeValue, SQLScalar, SQLScalarValue } from './SQLExpressions';
|
|
3
3
|
import { SQLWhere } from './SQLWhere';
|
|
4
4
|
|
|
5
5
|
export function scalarToSQLJSONExpression(s: SQLScalarValue | null): SQLExpression {
|
|
6
6
|
if (s === null) {
|
|
7
|
-
return
|
|
7
|
+
return SQLJSONNull;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
if (s === true) {
|
|
11
|
-
return
|
|
11
|
+
return SQLJSONTrue;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
if (s === false) {
|
|
15
|
-
return
|
|
15
|
+
return SQLJSONFalse;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
return new SQLScalar(s);
|
|
@@ -34,6 +34,39 @@ export class SQLJsonUnquote implements SQLExpression {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
export type SQLJsonValueType = 'FLOAT' | 'DOUBLE' | 'DECIMAL' | 'SIGNED' | 'UNSIGNED' | 'DATE' | 'TIME' | 'DATETIME' | 'YEAR' | 'CHAR' | 'JSON';
|
|
38
|
+
|
|
39
|
+
export class SQLJsonValue implements SQLExpression {
|
|
40
|
+
target: SQLExpression;
|
|
41
|
+
path: SQLExpression;
|
|
42
|
+
type?: SQLJsonValueType;
|
|
43
|
+
|
|
44
|
+
constructor(target: SQLExpression, type?: SQLJsonValueType, path?: SQLExpression) {
|
|
45
|
+
this.target = target;
|
|
46
|
+
this.type = type;
|
|
47
|
+
|
|
48
|
+
if (!path && target instanceof SQLJsonExtract) {
|
|
49
|
+
// If the target is a SQLJsonExtract, we can use its path directly
|
|
50
|
+
this.target = target.target;
|
|
51
|
+
this.path = target.path;
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this.path = path ?? new SQLSafeValue('$');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
59
|
+
return joinSQLQuery([
|
|
60
|
+
'JSON_VALUE(',
|
|
61
|
+
this.target.getSQL(options),
|
|
62
|
+
',',
|
|
63
|
+
this.path.getSQL(options),
|
|
64
|
+
(this.type ? ' RETURNING ' + this.type + (this.type === 'CHAR' ? ' CHARACTER SET utf8mb4' : '') : ''),
|
|
65
|
+
' ERROR ON ERROR)',
|
|
66
|
+
]);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
37
70
|
/**
|
|
38
71
|
* Same as target->path, JSON_EXTRACT(target, path)
|
|
39
72
|
*/
|
|
@@ -55,6 +88,34 @@ export class SQLJsonExtract implements SQLExpression {
|
|
|
55
88
|
')',
|
|
56
89
|
]);
|
|
57
90
|
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* NOTE: this has to be combined with asScalar = true! Never let user input in a query without passing it as a parameter.
|
|
94
|
+
*
|
|
95
|
+
* E.g. SQL.jsonValue(SQL.column('settings'), `$.value.prices[*].bundleDiscounts.${SQLJsonExtract.escapePathComponent(key)}`, true) (note that last true!)
|
|
96
|
+
*/
|
|
97
|
+
static escapePathComponent(str: string) {
|
|
98
|
+
return '"' + str.replace(/(["\\])/g, '\\$1') + '"';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Same as target->path, JSON_EXTRACT(target, path)
|
|
104
|
+
*/
|
|
105
|
+
export class SQLJsonKeys implements SQLExpression {
|
|
106
|
+
target: SQLExpression;
|
|
107
|
+
|
|
108
|
+
constructor(target: SQLExpression) {
|
|
109
|
+
this.target = target;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
113
|
+
return joinSQLQuery([
|
|
114
|
+
'JSON_KEYS(',
|
|
115
|
+
this.target.getSQL(options),
|
|
116
|
+
')',
|
|
117
|
+
]);
|
|
118
|
+
}
|
|
58
119
|
}
|
|
59
120
|
|
|
60
121
|
export class SQLJsonLength implements SQLExpression {
|