@stamhoofd/sql 2.118.1 → 2.119.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 (52) hide show
  1. package/dist/src/SQLJsonExpressions.js +1 -1
  2. package/dist/src/SQLJsonExpressions.js.map +1 -1
  3. package/dist/src/filters/SQLFilter.d.ts +6 -2
  4. package/dist/src/filters/SQLFilter.d.ts.map +1 -1
  5. package/dist/src/filters/SQLFilter.js +13 -9
  6. package/dist/src/filters/SQLFilter.js.map +1 -1
  7. package/dist/src/filters/SQLSorter.js +1 -1
  8. package/dist/src/filters/SQLSorter.js.map +1 -1
  9. package/dist/src/filters/compilers/contains.d.ts.map +1 -1
  10. package/dist/src/filters/compilers/contains.js +3 -2
  11. package/dist/src/filters/compilers/contains.js.map +1 -1
  12. package/dist/src/filters/compilers/equals.d.ts.map +1 -1
  13. package/dist/src/filters/compilers/equals.js +3 -2
  14. package/dist/src/filters/compilers/equals.js.map +1 -1
  15. package/dist/src/filters/compilers/greater.d.ts.map +1 -1
  16. package/dist/src/filters/compilers/greater.js +3 -2
  17. package/dist/src/filters/compilers/greater.js.map +1 -1
  18. package/dist/src/filters/compilers/in.d.ts.map +1 -1
  19. package/dist/src/filters/compilers/in.js +4 -4
  20. package/dist/src/filters/compilers/in.js.map +1 -1
  21. package/dist/src/filters/compilers/less.d.ts.map +1 -1
  22. package/dist/src/filters/compilers/less.js +3 -2
  23. package/dist/src/filters/compilers/less.js.map +1 -1
  24. package/dist/src/filters/helpers/isJSONColumn.d.ts.map +1 -1
  25. package/dist/src/filters/helpers/isJSONColumn.js +1 -0
  26. package/dist/src/filters/helpers/isJSONColumn.js.map +1 -1
  27. package/dist/src/filters/helpers/normalizeCompareValue.d.ts.map +1 -1
  28. package/dist/src/filters/helpers/normalizeCompareValue.js +1 -1
  29. package/dist/src/filters/helpers/normalizeCompareValue.js.map +1 -1
  30. package/dist/tests/filters/$contains.test.js +216 -0
  31. package/dist/tests/filters/$contains.test.js.map +1 -1
  32. package/dist/tests/filters/$eq.test.js +420 -4
  33. package/dist/tests/filters/$eq.test.js.map +1 -1
  34. package/dist/tests/filters/$gt.test.js +179 -1
  35. package/dist/tests/filters/$gt.test.js.map +1 -1
  36. package/dist/tests/filters/$in.test.js +183 -0
  37. package/dist/tests/filters/$in.test.js.map +1 -1
  38. package/dist/tests/filters/dot-syntax.test.js +7 -7
  39. package/dist/tests/filters/dot-syntax.test.js.map +1 -1
  40. package/dist/tests/filters/wildcard.test.js +2 -2
  41. package/dist/tests/filters/wildcard.test.js.map +1 -1
  42. package/package.json +2 -2
  43. package/src/SQLJsonExpressions.ts +1 -1
  44. package/src/filters/SQLFilter.ts +16 -11
  45. package/src/filters/SQLSorter.ts +1 -1
  46. package/src/filters/compilers/contains.ts +3 -2
  47. package/src/filters/compilers/equals.ts +3 -2
  48. package/src/filters/compilers/greater.ts +3 -2
  49. package/src/filters/compilers/in.ts +5 -6
  50. package/src/filters/compilers/less.ts +3 -2
  51. package/src/filters/helpers/isJSONColumn.ts +1 -0
  52. package/src/filters/helpers/normalizeCompareValue.ts +2 -1
@@ -1,13 +1,13 @@
1
1
  import { SimpleError } from '@simonbackx/simple-errors';
2
- import { compileFilter, FilterCompiler, FilterDefinitions, filterDefinitionsToCompiler, RequiredFilterCompiler, StamhoofdFilter } from '@stamhoofd/structures';
2
+ import { compileFilter, FilterCompiler, FilterDefinitions, filterDefinitionsToCompiler, RequiredFilterCompiler, type StamhoofdCompareValue, StamhoofdFilter } from '@stamhoofd/structures';
3
3
  import { SQLExpression, SQLExpressionOptions, SQLQuery } from '../SQLExpression.js';
4
+ import { SQLSafeValue } from '../SQLExpressions.js';
4
5
  import { SQLJoin } from '../SQLJoin.js';
5
6
  import { SQLJsonValue } from '../SQLJsonExpressions.js';
6
7
  import { SQLSelect } from '../SQLSelect.js';
7
8
  import { SQLWhere, SQLWhereAnd, SQLWhereExists, SQLWhereJoin, SQLWhereNot, SQLWhereOr } from '../SQLWhere.js';
8
- import { $equalsSQLFilterCompiler, $greaterThanSQLFilterCompiler, $inSQLFilterCompiler, $lessThanSQLFilterCompiler } from './compilers/index.js';
9
9
  import { $containsSQLFilterCompiler } from './compilers/contains.js';
10
- import { SQLSafeValue } from '../SQLExpressions.js';
10
+ import { $equalsSQLFilterCompiler, $greaterThanSQLFilterCompiler, $inSQLFilterCompiler, $lessThanSQLFilterCompiler } from './compilers/index.js';
11
11
 
12
12
  export type SQLSyncFilterRunner = (column: SQLCurrentColumn) => SQLWhere;
13
13
  export type SQLFilterRunner = (column: SQLCurrentColumn) => Promise<SQLWhere> | SQLWhere;
@@ -34,9 +34,13 @@ export enum SQLValueType {
34
34
  /** True or false in JSON */
35
35
  JSONBoolean = 'JSONBoolean',
36
36
  JSONString = 'JSONString',
37
-
38
37
  JSONNumber = 'JSONNumber',
39
38
 
39
+ /**
40
+ * Either boolean, string, number or null (if nullable). Only use this if you cannot determine the type at compile time.
41
+ */
42
+ JSONScalar = 'JSONScalar',
43
+
40
44
  /** [...] */
41
45
  JSONArray = 'JSONArray',
42
46
 
@@ -244,8 +248,8 @@ export async function compileToSQLFilter(filter: StamhoofdFilter, filters: SQLFi
244
248
  /**
245
249
  * Casts json strings, numbers and booleans to native MySQL types. This includes json null to mysql null.
246
250
  */
247
- export function normalizeColumn(column: SQLCurrentColumn): SQLCurrentColumn {
248
- if (column.type === SQLValueType.JSONString) {
251
+ export function normalizeColumn(column: SQLCurrentColumn, hint?: StamhoofdCompareValue): SQLCurrentColumn {
252
+ if (column.type === SQLValueType.JSONString || (column.type === SQLValueType.JSONScalar && typeof hint === 'string')) {
249
253
  return {
250
254
  expression: new SQLJsonValue(column.expression, 'CHAR'),
251
255
  type: SQLValueType.String,
@@ -253,20 +257,21 @@ export function normalizeColumn(column: SQLCurrentColumn): SQLCurrentColumn {
253
257
  };
254
258
  }
255
259
 
256
- if (column.type === SQLValueType.JSONBoolean) {
260
+ if (column.type === SQLValueType.JSONNumber || (column.type === SQLValueType.JSONScalar && typeof hint === 'number')) {
257
261
  return {
258
- expression: new SQLJsonValue(column.expression, 'UNSIGNED'),
259
- type: SQLValueType.Boolean,
262
+ expression: new SQLJsonValue(column.expression, 'SIGNED'),
263
+ type: SQLValueType.Number,
260
264
  nullable: column.nullable,
261
265
  };
262
266
  }
263
267
 
264
- if (column.type === SQLValueType.JSONNumber) {
268
+ if (column.type === SQLValueType.JSONBoolean || (column.type === SQLValueType.JSONScalar && typeof hint === 'boolean')) {
265
269
  return {
266
270
  expression: new SQLJsonValue(column.expression, 'UNSIGNED'),
267
- type: SQLValueType.Number,
271
+ type: SQLValueType.Boolean,
268
272
  nullable: column.nullable,
269
273
  };
270
274
  }
275
+
271
276
  return column;
272
277
  }
@@ -44,7 +44,7 @@ export function applySQLSorter(selectQuery: SQLSelect<any>, sortBy: SortList, de
44
44
  throw new SimpleError({
45
45
  code: 'sorter_join_overlap',
46
46
  message: 'This combination of sorters is not possible',
47
- human: $t('e328a7c2-318c-4425-b61a-61e6f4211707'),
47
+ human: $t('%GU'),
48
48
  });
49
49
  }
50
50
  }
@@ -8,8 +8,9 @@ import { normalizeCompareValue } from '../helpers/normalizeCompareValue.js';
8
8
 
9
9
  export function $containsSQLFilterCompiler(filter: StamhoofdFilter): SQLSyncFilterRunner {
10
10
  return (originalColumn: SQLCurrentColumn) => {
11
- const column = normalizeColumn(originalColumn);
12
- const value = normalizeCompareValue(assertFilterCompareValue(filter), column.type);
11
+ const v = assertFilterCompareValue(filter);
12
+ const column = normalizeColumn(originalColumn, v);
13
+ const value = normalizeCompareValue(v, column.type);
13
14
 
14
15
  if (typeof value !== 'string') {
15
16
  throw new SimpleError({
@@ -8,8 +8,9 @@ import { normalizeCompareValue } from '../helpers/normalizeCompareValue.js';
8
8
 
9
9
  export function $equalsSQLFilterCompiler(filter: StamhoofdFilter): SQLSyncFilterRunner {
10
10
  return (originalColumn: SQLCurrentColumn) => {
11
- const column = normalizeColumn(originalColumn);
12
- const value = normalizeCompareValue(assertFilterCompareValue(filter), column.type);
11
+ const v = assertFilterCompareValue(filter);
12
+ const column = normalizeColumn(originalColumn, v);
13
+ const value = normalizeCompareValue(v, column.type);
13
14
  /**
14
15
  * Special case, checking for equality with a JSON array.
15
16
  * This should return true if the JSON array contains the value exactly.
@@ -6,8 +6,9 @@ import { normalizeCompareValue } from '../helpers/normalizeCompareValue.js';
6
6
 
7
7
  export function $greaterThanSQLFilterCompiler(filter: StamhoofdFilter): SQLSyncFilterRunner {
8
8
  return (originalColumn: SQLCurrentColumn) => {
9
- const column = normalizeColumn(originalColumn);
10
- const value = normalizeCompareValue(assertFilterCompareValue(filter), column.type);
9
+ const v = assertFilterCompareValue(filter);
10
+ const column = normalizeColumn(originalColumn, v);
11
+ const value = normalizeCompareValue(v, column.type);
11
12
 
12
13
  const base = new SQLWhereEqual(
13
14
  column.expression,
@@ -20,18 +20,17 @@ export function $inSQLFilterCompiler(filter: StamhoofdFilter): SQLSyncFilterRunn
20
20
  throw new SimpleError({
21
21
  code: 'invalid_filter',
22
22
  message: 'Too many values in $in filter, maximum is 1000',
23
- human: $t('2f4b0c22-044e-486b-8a75-80a5b51beaf3', { count: filter.length }),
23
+ human: $t('%1HH', { count: filter.length }),
24
24
  });
25
25
  }
26
-
27
- const column = normalizeColumn(originalColumn);
28
- const values = filter.map(val => normalizeCompareValue(assertFilterCompareValue(val), column.type));
29
-
30
- if (values.length === 0) {
26
+ if (filter.length === 0) {
31
27
  // Return always false
32
28
  return new SQLWhereOr([]);
33
29
  }
34
30
 
31
+ const column = normalizeColumn(originalColumn, assertFilterCompareValue(filter.find(f => f !== null) ?? null));
32
+ const values = filter.map(val => normalizeCompareValue(assertFilterCompareValue(val), column.type));
33
+
35
34
  const valuesWithoutNulls = values.filter(val => val !== null);
36
35
  const hasNull = values.length !== valuesWithoutNulls.length;
37
36
 
@@ -6,8 +6,9 @@ import { normalizeCompareValue } from '../helpers/normalizeCompareValue.js';
6
6
 
7
7
  export function $lessThanSQLFilterCompiler(filter: StamhoofdFilter): SQLSyncFilterRunner {
8
8
  return (originalColumn: SQLCurrentColumn) => {
9
- const column = normalizeColumn(originalColumn);
10
- const value = normalizeCompareValue(assertFilterCompareValue(filter), column.type);
9
+ const v = assertFilterCompareValue(filter);
10
+ const column = normalizeColumn(originalColumn, v);
11
+ const value = normalizeCompareValue(v, column.type);
11
12
 
12
13
  const base = new SQLWhereEqual(
13
14
  column.expression,
@@ -8,6 +8,7 @@ export function isJSONType(type: SQLValueType): boolean {
8
8
  return type === SQLValueType.JSONString
9
9
  || type === SQLValueType.JSONBoolean
10
10
  || type === SQLValueType.JSONNumber
11
+ || type === SQLValueType.JSONScalar
11
12
  || type === SQLValueType.JSONArray
12
13
  || type === SQLValueType.JSONObject;
13
14
  }
@@ -1,5 +1,6 @@
1
1
  import { StamhoofdCompareValue } from '@stamhoofd/structures';
2
2
  import { SQLValueType } from '../SQLFilter.js';
3
+ import { isJSONType } from './isJSONColumn.js';
3
4
 
4
5
  /**
5
6
  * Prepares a compare value so we can compare it, given a certain column type.
@@ -26,7 +27,7 @@ export function normalizeCompareValue(val: StamhoofdCompareValue, againstType: S
26
27
  }
27
28
 
28
29
  if (typeof val === 'string') {
29
- if (againstType === SQLValueType.String || againstType === SQLValueType.JSONString) {
30
+ if (againstType === SQLValueType.String) {
30
31
  return val.toLocaleLowerCase();
31
32
  }
32
33