@stamhoofd/sql 2.108.0 → 2.109.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 +1 -0
- package/dist/index.js.map +1 -1
- package/dist/src/SQL.d.ts +6 -3
- package/dist/src/SQL.d.ts.map +1 -1
- package/dist/src/SQL.js +10 -1
- package/dist/src/SQL.js.map +1 -1
- package/dist/src/SQLExpressions.d.ts +11 -0
- package/dist/src/SQLExpressions.d.ts.map +1 -1
- package/dist/src/SQLExpressions.js +33 -1
- package/dist/src/SQLExpressions.js.map +1 -1
- package/dist/src/SQLJoin.d.ts.map +1 -1
- package/dist/src/SQLJoin.js +16 -0
- package/dist/src/SQLJoin.js.map +1 -1
- package/dist/src/SQLJsonExpressions.d.ts +5 -0
- package/dist/src/SQLJsonExpressions.d.ts.map +1 -1
- package/dist/src/SQLJsonExpressions.js +15 -1
- package/dist/src/SQLJsonExpressions.js.map +1 -1
- package/dist/src/SQLSelect.d.ts +11 -0
- package/dist/src/SQLSelect.d.ts.map +1 -1
- package/dist/src/SQLSelect.js +17 -2
- package/dist/src/SQLSelect.js.map +1 -1
- package/dist/src/SQLTranslatedStringHelper.d.ts +10 -0
- package/dist/src/SQLTranslatedStringHelper.d.ts.map +1 -0
- package/dist/src/SQLTranslatedStringHelper.js +37 -0
- package/dist/src/SQLTranslatedStringHelper.js.map +1 -0
- package/dist/src/filters/SQLSorter.d.ts +4 -4
- package/dist/src/filters/SQLSorter.d.ts.map +1 -1
- package/dist/tests/filters/$contains.test.js +4 -4
- package/dist/tests/filters/$contains.test.js.map +1 -1
- package/dist/tests/filters/$eq.test.js +6 -6
- package/dist/tests/filters/$eq.test.js.map +1 -1
- package/dist/tests/filters/$gt.test.js +4 -4
- package/dist/tests/filters/$gt.test.js.map +1 -1
- package/dist/tests/filters/$gte.test.js +3 -3
- package/dist/tests/filters/$gte.test.js.map +1 -1
- package/dist/tests/filters/$in.test.js +2 -2
- package/dist/tests/filters/$in.test.js.map +1 -1
- package/dist/tests/filters/$lt.test.js +3 -3
- package/dist/tests/filters/$lt.test.js.map +1 -1
- package/dist/tests/filters/$lte.test.js +3 -3
- package/dist/tests/filters/$lte.test.js.map +1 -1
- package/dist/tests/filters/SQLTranslatedStringHelper.test.d.ts +2 -0
- package/dist/tests/filters/SQLTranslatedStringHelper.test.d.ts.map +1 -0
- package/dist/tests/filters/SQLTranslatedStringHelper.test.js +491 -0
- package/dist/tests/filters/SQLTranslatedStringHelper.test.js.map +1 -0
- package/dist/tests/filters/dot-syntax.test.js +4 -4
- package/dist/tests/filters/dot-syntax.test.js.map +1 -1
- package/dist/tests/filters/wildcard.test.js +2 -2
- package/dist/tests/filters/wildcard.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/SQL.ts +16 -4
- package/src/SQLExpressions.ts +31 -0
- package/src/SQLJoin.ts +17 -0
- package/src/SQLJsonExpressions.ts +16 -0
- package/src/SQLSelect.ts +23 -2
- package/src/SQLTranslatedStringHelper.ts +40 -0
- package/src/filters/SQLSorter.ts +4 -4
package/src/SQLExpressions.ts
CHANGED
|
@@ -421,6 +421,21 @@ export class SQLColumnExpression implements SQLExpression {
|
|
|
421
421
|
}
|
|
422
422
|
}
|
|
423
423
|
|
|
424
|
+
export class SQLIfNull implements SQLExpression {
|
|
425
|
+
constructor(private readonly columnExpression: SQLColumnExpression, private readonly value: string | number) {
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
429
|
+
return joinSQLQuery([
|
|
430
|
+
'IFNULL(',
|
|
431
|
+
this.columnExpression.getSQL(options),
|
|
432
|
+
',',
|
|
433
|
+
new SQLSafeValue(this.value).getSQL(),
|
|
434
|
+
')',
|
|
435
|
+
]);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
424
439
|
export class SQLTableExpression implements SQLNamedExpression {
|
|
425
440
|
/**
|
|
426
441
|
* By default the table name will be used as the namespace by MySQL.
|
|
@@ -539,3 +554,19 @@ export class SQLIf implements SQLExpression {
|
|
|
539
554
|
]);
|
|
540
555
|
}
|
|
541
556
|
}
|
|
557
|
+
|
|
558
|
+
export class SQLCoalesce implements SQLExpression {
|
|
559
|
+
expressions: SQLExpression[] = [];
|
|
560
|
+
|
|
561
|
+
constructor(...expressions: SQLExpression[]) {
|
|
562
|
+
this.expressions = expressions;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
566
|
+
return joinSQLQuery([
|
|
567
|
+
'COALESCE(',
|
|
568
|
+
joinSQLQuery(this.expressions.map(e => e.getSQL(options)), ', '),
|
|
569
|
+
')',
|
|
570
|
+
]);
|
|
571
|
+
}
|
|
572
|
+
}
|
package/src/SQLJoin.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SQLExpression, SQLExpressionOptions, SQLNamedExpression, SQLQuery, joinSQLQuery } from './SQLExpression';
|
|
2
|
+
import { SQLSelect } from './SQLSelect';
|
|
2
3
|
import { Whereable } from './SQLWhere';
|
|
3
4
|
|
|
4
5
|
export enum SQLJoinType {
|
|
@@ -29,6 +30,22 @@ export class SQLJoin extends Whereable(EmptyClass) implements SQLExpression {
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
33
|
+
// add parenthesis if the table is a select
|
|
34
|
+
if (this.table instanceof SQLSelect) {
|
|
35
|
+
return joinSQLQuery([
|
|
36
|
+
this.getJoinPrefix(),
|
|
37
|
+
'(',
|
|
38
|
+
this.table?.getSQL(options),
|
|
39
|
+
`) as ${this.table.getName()}`,
|
|
40
|
+
this._where ? 'ON' : undefined,
|
|
41
|
+
this._where?.getSQL({
|
|
42
|
+
...options,
|
|
43
|
+
parentNamespace: options?.defaultNamespace,
|
|
44
|
+
defaultNamespace: this.table.getName(),
|
|
45
|
+
}),
|
|
46
|
+
], ' ');
|
|
47
|
+
}
|
|
48
|
+
|
|
32
49
|
return joinSQLQuery([
|
|
33
50
|
this.getJoinPrefix(),
|
|
34
51
|
this.table?.getSQL(options),
|
|
@@ -99,6 +99,22 @@ export class SQLJsonExtract implements SQLExpression {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
export class SQLJsonType implements SQLExpression {
|
|
103
|
+
target: SQLExpression;
|
|
104
|
+
|
|
105
|
+
constructor(target: SQLExpression) {
|
|
106
|
+
this.target = target;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
110
|
+
return joinSQLQuery([
|
|
111
|
+
'JSON_TYPE(',
|
|
112
|
+
this.target.getSQL(options),
|
|
113
|
+
')',
|
|
114
|
+
]);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
102
118
|
/**
|
|
103
119
|
* Same as target->path, JSON_EXTRACT(target, path)
|
|
104
120
|
*/
|
package/src/SQLSelect.ts
CHANGED
|
@@ -29,6 +29,8 @@ export type IterableSQLSelectOptions = {
|
|
|
29
29
|
maxQueries?: number;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
+
export type SQLNamedSelect<T extends object = SQLResultNamespacedRow> = SQLSelect<T> & { getName(): string };
|
|
33
|
+
|
|
32
34
|
export class SQLSelect<T extends object = SQLResultNamespacedRow> extends Whereable(Orderable(EmptyClass)) implements SQLExpression {
|
|
33
35
|
_columns: SQLExpression[];
|
|
34
36
|
_from: SQLNamedExpression;
|
|
@@ -38,6 +40,7 @@ export class SQLSelect<T extends object = SQLResultNamespacedRow> extends Wherea
|
|
|
38
40
|
_groupBy: SQLExpression[] = [];
|
|
39
41
|
_joins: (InstanceType<typeof SQLJoin>)[] = [];
|
|
40
42
|
_max_execution_time: number | null = null;
|
|
43
|
+
private _name: string | null = null;
|
|
41
44
|
|
|
42
45
|
_transformer: ((row: SQLResultNamespacedRow) => T) | null = null;
|
|
43
46
|
|
|
@@ -74,7 +77,11 @@ export class SQLSelect<T extends object = SQLResultNamespacedRow> extends Wherea
|
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
join(join: InstanceType<typeof SQLJoin>): this {
|
|
77
|
-
|
|
80
|
+
// prevent duplicate joins (reference of join should be the same)
|
|
81
|
+
if (!this._joins.includes(join)) {
|
|
82
|
+
this._joins.push(join);
|
|
83
|
+
}
|
|
84
|
+
|
|
78
85
|
return this;
|
|
79
86
|
}
|
|
80
87
|
|
|
@@ -248,7 +255,6 @@ export class SQLSelect<T extends object = SQLResultNamespacedRow> extends Wherea
|
|
|
248
255
|
this._orderBy = null;
|
|
249
256
|
|
|
250
257
|
const { query, params } = normalizeSQLQuery(this.getSQL());
|
|
251
|
-
// console.log(query, params);
|
|
252
258
|
|
|
253
259
|
const [rows] = await Database.select(query, params, { nestTables: true });
|
|
254
260
|
if (rows.length === 1) {
|
|
@@ -489,4 +495,19 @@ export class SQLSelect<T extends object = SQLResultNamespacedRow> extends Wherea
|
|
|
489
495
|
},
|
|
490
496
|
} as IterableSQLSelect<T[]> as any;
|
|
491
497
|
}
|
|
498
|
+
|
|
499
|
+
getName(): string | null {
|
|
500
|
+
return this._name;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* By calling this method we make sure a name is set so we can return an SQLNamedSelect.
|
|
505
|
+
* @param name name of the select
|
|
506
|
+
* @returns an SQLNamedSelect
|
|
507
|
+
*/
|
|
508
|
+
as(name: string): SQLNamedSelect {
|
|
509
|
+
this._name = name;
|
|
510
|
+
|
|
511
|
+
return this as SQLNamedSelect;
|
|
512
|
+
}
|
|
492
513
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { SQL, SQLColumnExpression, SQLExpression, SQLExpressionOptions, SQLQuery } from '@stamhoofd/sql';
|
|
2
|
+
import { Language } from '@stamhoofd/structures';
|
|
3
|
+
|
|
4
|
+
export class SQLTranslatedStringHelper implements SQLExpression {
|
|
5
|
+
constructor(private columnExpression: SQLColumnExpression, private path: string, private getLanguage: () => Language) {
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
9
|
+
const currentLanguage = this.getLanguage();
|
|
10
|
+
|
|
11
|
+
const languageOrder: Language[] = [
|
|
12
|
+
Language.English,
|
|
13
|
+
Language.Dutch,
|
|
14
|
+
Language.French,
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const languages = moveToFront(languageOrder, currentLanguage);
|
|
18
|
+
|
|
19
|
+
const languageValues: SQLExpression[] = languages.map((language) => {
|
|
20
|
+
return SQL.jsonValue(this.columnExpression, `${this.path}.${language}`, 'CHAR');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const type: SQLExpression = SQL.jsonType(SQL.jsonExtract(this.columnExpression, this.path));
|
|
24
|
+
|
|
25
|
+
return SQL.if(
|
|
26
|
+
type, '=', 'STRING',
|
|
27
|
+
).then(
|
|
28
|
+
SQL.jsonValue(this.columnExpression, this.path, 'CHAR'),
|
|
29
|
+
).else(
|
|
30
|
+
SQL.coalesce(...languageValues) as SQLExpression,
|
|
31
|
+
).getSQL(options);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function moveToFront<T>(arr: T[], value: T): T[] {
|
|
36
|
+
const index = arr.indexOf(value);
|
|
37
|
+
if (index === -1 || index === 0) return arr;
|
|
38
|
+
|
|
39
|
+
return [arr[index], ...arr.slice(0, index), ...arr.slice(index + 1)];
|
|
40
|
+
}
|
package/src/filters/SQLSorter.ts
CHANGED
|
@@ -2,10 +2,10 @@ import { PlainObject } from '@simonbackx/simple-encoding';
|
|
|
2
2
|
import { SortDefinition, SortList } from '@stamhoofd/structures';
|
|
3
3
|
|
|
4
4
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
5
|
-
import { SQLExpression } from '../SQLExpression';
|
|
6
|
-
import { SQLJoin } from '../SQLJoin';
|
|
7
|
-
import { SQLOrderBy, SQLOrderByDirection } from '../SQLOrderBy';
|
|
8
|
-
import { SQLSelect } from '../SQLSelect';
|
|
5
|
+
import { SQLExpression } from '../SQLExpression.js';
|
|
6
|
+
import { SQLJoin } from '../SQLJoin.js';
|
|
7
|
+
import { SQLOrderBy, SQLOrderByDirection } from '../SQLOrderBy.js';
|
|
8
|
+
import { SQLSelect } from '../SQLSelect.js';
|
|
9
9
|
|
|
10
10
|
export type SQLSortDefinition<T, B extends PlainObject | Date = PlainObject | Date> = SortDefinition<T, B> & {
|
|
11
11
|
toSQL(direction: SQLOrderByDirection): SQLOrderBy;
|