@stamhoofd/sql 2.10.2 → 2.16.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.
Files changed (51) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/src/SQL.d.ts +16 -43
  6. package/dist/src/SQL.d.ts.map +1 -1
  7. package/dist/src/SQL.js +10 -10
  8. package/dist/src/SQL.js.map +1 -1
  9. package/dist/src/SQLDelete.d.ts +15 -15
  10. package/dist/src/SQLDelete.d.ts.map +1 -1
  11. package/dist/src/SQLDelete.js +9 -10
  12. package/dist/src/SQLDelete.js.map +1 -1
  13. package/dist/src/SQLExpression.js +4 -5
  14. package/dist/src/SQLExpression.js.map +1 -1
  15. package/dist/src/SQLExpressions.d.ts +6 -0
  16. package/dist/src/SQLExpressions.d.ts.map +1 -1
  17. package/dist/src/SQLExpressions.js +41 -8
  18. package/dist/src/SQLExpressions.js.map +1 -1
  19. package/dist/src/SQLJoin.d.ts +16 -14
  20. package/dist/src/SQLJoin.d.ts.map +1 -1
  21. package/dist/src/SQLJoin.js +10 -9
  22. package/dist/src/SQLJoin.js.map +1 -1
  23. package/dist/src/SQLJsonExpressions.js +14 -0
  24. package/dist/src/SQLJsonExpressions.js.map +1 -1
  25. package/dist/src/SQLOrderBy.d.ts +5 -8
  26. package/dist/src/SQLOrderBy.d.ts.map +1 -1
  27. package/dist/src/SQLOrderBy.js +11 -9
  28. package/dist/src/SQLOrderBy.js.map +1 -1
  29. package/dist/src/SQLSelect.d.ts +32 -29
  30. package/dist/src/SQLSelect.d.ts.map +1 -1
  31. package/dist/src/SQLSelect.js +41 -20
  32. package/dist/src/SQLSelect.js.map +1 -1
  33. package/dist/src/SQLWhere.d.ts +11 -14
  34. package/dist/src/SQLWhere.d.ts.map +1 -1
  35. package/dist/src/SQLWhere.js +46 -28
  36. package/dist/src/SQLWhere.js.map +1 -1
  37. package/dist/src/filters/SQLFilter.d.ts +9 -2
  38. package/dist/src/filters/SQLFilter.d.ts.map +1 -1
  39. package/dist/src/filters/SQLFilter.js +34 -21
  40. package/dist/src/filters/SQLFilter.js.map +1 -1
  41. package/dist/src/filters/SQLSorter.js +1 -2
  42. package/dist/src/filters/SQLSorter.js.map +1 -1
  43. package/package.json +2 -2
  44. package/src/SQL.ts +25 -12
  45. package/src/SQLDelete.ts +3 -8
  46. package/src/SQLExpressions.ts +20 -0
  47. package/src/SQLJoin.ts +4 -5
  48. package/src/SQLOrderBy.ts +14 -12
  49. package/src/SQLSelect.ts +47 -24
  50. package/src/SQLWhere.ts +46 -33
  51. package/src/filters/SQLFilter.ts +42 -15
package/src/SQLWhere.ts CHANGED
@@ -1,22 +1,27 @@
1
1
  import { SQLExpression, SQLExpressionOptions, SQLQuery, joinSQLQuery, normalizeSQLQuery } from "./SQLExpression";
2
- import { SQLArray, SQLDynamicExpression, SQLNull, readDynamicSQLExpression } from "./SQLExpressions";
2
+ import { SQLArray, SQLColumnExpression, SQLDynamicExpression, SQLNull, readDynamicSQLExpression } from "./SQLExpressions";
3
3
 
4
- type GConstructor<T = {}> = new (...args: any[]) => T;
5
- type Whereable = GConstructor<{ _where: SQLWhere|null }>;
4
+ type Constructor<T = {}> = new (...args: any[]) => T;
6
5
 
7
6
  export type ParseWhereArguments = [
8
7
  where: SQLWhere
9
8
  ] | [
10
- whereOrColumn: SQLExpression,
9
+ whereOrColumn: SQLExpression|string,
11
10
  sign: SQLWhereSign,
12
11
  value: SQLDynamicExpression
13
12
  ] | [
14
- whereOrColumn: SQLExpression,
13
+ whereOrColumn: SQLExpression|string,
15
14
  value: SQLDynamicExpression
16
15
  ]
17
16
 
18
- export function addWhereHelpers<TBase extends Whereable>(Base: TBase) {
17
+ function assertWhereable(o: any): any {
18
+ return o;
19
+ }
20
+
21
+ export function Whereable<Sup extends Constructor<{}>>(Base: Sup) {
19
22
  return class extends Base {
23
+ _where: SQLWhere|null = null
24
+
20
25
  parseWhere(...[whereOrColumn, signOrValue, value]: ParseWhereArguments): SQLWhere {
21
26
  if (signOrValue === undefined) {
22
27
  return whereOrColumn as SQLWhere;
@@ -24,63 +29,71 @@ export function addWhereHelpers<TBase extends Whereable>(Base: TBase) {
24
29
 
25
30
  if (value !== undefined) {
26
31
  return new SQLWhereEqual(
27
- whereOrColumn,
32
+ typeof whereOrColumn === 'string' ? new SQLColumnExpression(whereOrColumn) : whereOrColumn,
28
33
  signOrValue as SQLWhereSign,
29
34
  readDynamicSQLExpression(value)
30
35
  )
31
36
  }
32
37
  return new SQLWhereEqual(
33
- whereOrColumn,
38
+ typeof whereOrColumn === 'string' ? new SQLColumnExpression(whereOrColumn) : whereOrColumn,
34
39
  SQLWhereSign.Equal,
35
40
  readDynamicSQLExpression(signOrValue)
36
41
  )
37
42
  }
38
43
 
44
+
39
45
  where<T>(this: T, ...args: ParseWhereArguments): T {
40
- const w = (this as any).parseWhere(...args);
41
- if (!(this as any)._where) {
42
- (this as any)._where = w;
43
- return this;
46
+ const me = assertWhereable(this)
47
+
48
+ const w = me.parseWhere(...args);
49
+ if (!me._where) {
50
+ me._where = w;
51
+ return me;
44
52
  }
45
- (this as any)._where = (this as any)._where.and(w);
46
- return this;
53
+ me._where = me._where.and(w);
54
+ return me;
47
55
  }
48
56
 
49
- andWhere(...args: ParseWhereArguments) {
50
- return this.where(...args)
57
+ andWhere<T>(this: T, ...args: ParseWhereArguments): T {
58
+ const me = assertWhereable(this)
59
+ return me.where(...args)
51
60
  }
52
61
 
53
- orWhere(...args: ParseWhereArguments) {
54
- const w = this.parseWhere(...args);
55
- if (!this._where) {
56
- this._where = w;
62
+ orWhere<T>(this: T, ...args: ParseWhereArguments): T {
63
+ const me = assertWhereable(this)
64
+ const w = me.parseWhere(...args);
65
+ if (!me._where) {
66
+ me._where = w;
57
67
  return this;
58
68
  }
59
- this._where = this._where.or(w);
69
+ me._where = me._where.or(w);
60
70
  return this;
61
71
  }
62
72
 
63
- whereNot(...args: ParseWhereArguments) {
64
- const w = new SQLWhereNot(this.parseWhere(...args));
65
- if (!this._where) {
66
- this._where = w;
73
+ whereNot<T>(this: T, ...args: ParseWhereArguments): T {
74
+ const me = assertWhereable(this)
75
+ const w = new SQLWhereNot(me.parseWhere(...args));
76
+ if (!me._where) {
77
+ me._where = w;
67
78
  return this;
68
79
  }
69
- this._where = this._where.and(w);
80
+ me._where = me._where.and(w);
70
81
  return this;
71
82
  }
72
83
 
73
- andWhereNot(...args: ParseWhereArguments) {
74
- return this.whereNot(...args)
84
+ andWhereNot<T>(this: T, ...args: ParseWhereArguments): T {
85
+ const me = assertWhereable(this)
86
+ return me.whereNot(...args)
75
87
  }
76
88
 
77
- orWhereNot(...args: ParseWhereArguments) {
78
- const w = new SQLWhereNot(this.parseWhere(...args));
79
- if (!this._where) {
80
- this._where = w;
89
+ orWhereNot<T>(this: T, ...args: ParseWhereArguments): T {
90
+ const me = assertWhereable(this)
91
+ const w = new SQLWhereNot(me.parseWhere(...args));
92
+ if (!me._where) {
93
+ me._where = w;
81
94
  return this;
82
95
  }
83
- this._where = this._where.or(w);
96
+ me._where = me._where.or(w);
84
97
  return this;
85
98
  }
86
99
  }
@@ -1,8 +1,8 @@
1
1
  import { SimpleError } from "@simonbackx/simple-errors";
2
- import { StamhoofdFilter, StamhoofdKeyFilterValue } from "@stamhoofd/structures";
2
+ import { StamhoofdFilter } from "@stamhoofd/structures";
3
3
  import { SQL } from "../SQL";
4
4
  import { SQLExpression } from "../SQLExpression";
5
- import { SQLArray, SQLColumnExpression, SQLNull, SQLSafeValue, SQLScalarValue, scalarToSQLExpression, scalarToSQLJSONExpression } from "../SQLExpressions";
5
+ import { SQLArray, SQLCast, SQLColumnExpression, SQLNull, SQLSafeValue, SQLScalarValue, scalarToSQLExpression, scalarToSQLJSONExpression } from "../SQLExpressions";
6
6
  import { SQLJsonContains, SQLJsonOverlaps, SQLJsonSearch, SQLJsonUnquote } from "../SQLJsonExpressions";
7
7
  import { SQLSelect } from "../SQLSelect";
8
8
  import { SQLWhere, SQLWhereAnd, SQLWhereEqual, SQLWhereExists, SQLWhereLike, SQLWhereNot, SQLWhereOr, SQLWhereSign } from "../SQLWhere";
@@ -65,7 +65,9 @@ export function createSQLFilterNamespace(definitions: SQLFilterDefinitions): SQL
65
65
  }
66
66
  }
67
67
 
68
- export function createSQLExpressionFilterCompiler(sqlExpression: SQLExpression, normalizeValue?: (v: SQLScalarValue|null) => SQLScalarValue|null, isJSONValue = false, isJSONObject = false): SQLFilterCompiler {
68
+ type SQLExpressionFilterOptions = {normalizeValue?: (v: SQLScalarValue|null) => SQLScalarValue|null, isJSONValue?: boolean, isJSONObject?: boolean, nullable?: boolean}
69
+
70
+ export function createSQLExpressionFilterCompiler(sqlExpression: SQLExpression, {normalizeValue, isJSONObject = false, isJSONValue = false, nullable = false}: SQLExpressionFilterOptions = {}): SQLFilterCompiler {
69
71
  const norm = normalizeValue ?? ((v) => v);
70
72
  const convertToExpression = isJSONValue ? scalarToSQLJSONExpression : scalarToSQLExpression
71
73
 
@@ -172,15 +174,6 @@ export function createSQLExpressionFilterCompiler(sqlExpression: SQLExpression,
172
174
  if (isJSONObject) {
173
175
  const v = norm(f.$eq);
174
176
 
175
- // if (typeof v === 'string') {
176
- // return new SQLWhereEqual(
177
- // new SQLJsonSearch(sqlExpression, 'one', convertToExpression(v)),
178
- // SQLWhereSign.Equal,
179
- // new SQLNull()
180
- // );
181
- // }
182
-
183
- // else
184
177
  return new SQLWhereEqual(
185
178
  new SQLJsonContains(
186
179
  sqlExpression,
@@ -204,6 +197,8 @@ export function createSQLExpressionFilterCompiler(sqlExpression: SQLExpression,
204
197
  // > null is same as not equal to null (everything is larger than null in mysql) - to be consistent with order by behaviour
205
198
  return new SQLWhereEqual(sqlExpression, SQLWhereSign.NotEqual, convertToExpression(null));
206
199
  }
200
+
201
+ // For MySQL null values are never included in greater than, but we need this for consistent sorting behaviour
207
202
  return new SQLWhereEqual(sqlExpression, SQLWhereSign.Greater, convertToExpression(norm(f.$gt)));
208
203
  }
209
204
 
@@ -232,6 +227,17 @@ export function createSQLExpressionFilterCompiler(sqlExpression: SQLExpression,
232
227
  // <= null is same as equal to null
233
228
  return new SQLWhereEqual(sqlExpression, SQLWhereSign.Equal, convertToExpression(norm(f.$lte)));
234
229
  }
230
+
231
+ const base = new SQLWhereEqual(sqlExpression, SQLWhereSign.LessEqual, convertToExpression(norm(f.$lte)));
232
+
233
+ if (nullable) {
234
+ return new SQLWhereOr([
235
+ // Null values are also smaller than any value - required for sorting
236
+ new SQLWhereEqual(sqlExpression, SQLWhereSign.Equal, new SQLNull()),
237
+ base
238
+ ]);
239
+ }
240
+
235
241
  return new SQLWhereEqual(sqlExpression, SQLWhereSign.LessEqual, convertToExpression(norm(f.$lte)));
236
242
  }
237
243
 
@@ -247,7 +253,18 @@ export function createSQLExpressionFilterCompiler(sqlExpression: SQLExpression,
247
253
  // < null is always nothing, there is nothing smaller than null in MySQL - to be consistent with order by behaviour
248
254
  return new SQLWhereEqual(new SQLSafeValue(1), SQLWhereSign.Equal, new SQLSafeValue(0));
249
255
  }
250
- return new SQLWhereEqual(sqlExpression, SQLWhereSign.Less, convertToExpression(norm(f.$lt)));
256
+
257
+ const base = new SQLWhereEqual(sqlExpression, SQLWhereSign.Less, convertToExpression(norm(f.$lt)))
258
+
259
+ if (nullable) {
260
+ return new SQLWhereOr([
261
+ // Null values are also smaller than any value - required for sorting
262
+ new SQLWhereEqual(sqlExpression, SQLWhereSign.Equal, new SQLNull()),
263
+ base
264
+ ]);
265
+ }
266
+
267
+ return base;
251
268
  }
252
269
 
253
270
  if ('$contains' in f) {
@@ -266,6 +283,16 @@ export function createSQLExpressionFilterCompiler(sqlExpression: SQLExpression,
266
283
  new SQLNull()
267
284
  );
268
285
  }
286
+
287
+ if (isJSONValue) {
288
+ // We need to do case insensitive search, so need to convert the sqlExpression from utf8mb4 to varchar
289
+ return new SQLWhereLike(
290
+ new SQLCast(new SQLJsonUnquote(sqlExpression), 'CHAR'),
291
+ convertToExpression(
292
+ '%'+SQLWhereLike.escape(f.$contains)+'%'
293
+ )
294
+ );
295
+ }
269
296
 
270
297
  return new SQLWhereLike(
271
298
  sqlExpression,
@@ -279,9 +306,9 @@ export function createSQLExpressionFilterCompiler(sqlExpression: SQLExpression,
279
306
  }
280
307
  }
281
308
 
282
- export function createSQLColumnFilterCompiler(name: string | SQLColumnExpression, normalizeValue?: (v: SQLScalarValue|null) => SQLScalarValue|null): SQLFilterCompiler {
309
+ export function createSQLColumnFilterCompiler(name: string | SQLColumnExpression, options?: SQLExpressionFilterOptions): SQLFilterCompiler {
283
310
  const column = name instanceof SQLColumnExpression ? name : SQL.column(name);
284
- return createSQLExpressionFilterCompiler(column, normalizeValue)
311
+ return createSQLExpressionFilterCompiler(column, options)
285
312
  }
286
313
 
287
314
  export const baseSQLFilterCompilers: SQLFilterDefinitions = {