@stamhoofd/sql 2.64.0 → 2.65.1
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 +11 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/src/QueryableModel.d.ts +12 -0
- package/dist/src/QueryableModel.d.ts.map +1 -0
- package/dist/src/QueryableModel.js +30 -0
- package/dist/src/QueryableModel.js.map +1 -0
- package/dist/src/SQL.d.ts +3 -3
- package/dist/src/SQL.d.ts.map +1 -1
- package/dist/src/SQL.js +5 -5
- package/dist/src/SQL.js.map +1 -1
- package/dist/src/SQLExpression.d.ts +1 -0
- package/dist/src/SQLExpression.d.ts.map +1 -1
- package/dist/src/SQLExpression.js +2 -2
- package/dist/src/SQLExpression.js.map +1 -1
- package/dist/src/SQLExpressions.d.ts +28 -3
- package/dist/src/SQLExpressions.d.ts.map +1 -1
- package/dist/src/SQLExpressions.js +75 -6
- package/dist/src/SQLExpressions.js.map +1 -1
- package/dist/src/SQLInsert.d.ts.map +1 -1
- package/dist/src/SQLInsert.js +6 -1
- package/dist/src/SQLInsert.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 +2 -2
- package/dist/src/SQLJoin.js.map +1 -1
- package/dist/src/SQLOrderBy.d.ts +3 -3
- package/dist/src/SQLOrderBy.d.ts.map +1 -1
- package/dist/src/SQLOrderBy.js +8 -4
- package/dist/src/SQLOrderBy.js.map +1 -1
- package/dist/src/SQLSelect.d.ts +19 -2
- package/dist/src/SQLSelect.d.ts.map +1 -1
- package/dist/src/SQLSelect.js +164 -2
- package/dist/src/SQLSelect.js.map +1 -1
- package/dist/src/SQLUpdate.d.ts.map +1 -1
- package/dist/src/SQLUpdate.js +6 -1
- package/dist/src/SQLUpdate.js.map +1 -1
- package/dist/src/SQLWhere.d.ts +18 -10
- package/dist/src/SQLWhere.d.ts.map +1 -1
- package/dist/src/SQLWhere.js +32 -17
- package/dist/src/SQLWhere.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/QueryableModel.ts +35 -0
- package/src/SQL.ts +7 -8
- package/src/SQLExpression.ts +12 -12
- package/src/SQLExpressions.ts +92 -8
- package/src/SQLInsert.ts +7 -1
- package/src/SQLJoin.ts +11 -11
- package/src/SQLOrderBy.ts +28 -24
- package/src/SQLSelect.ts +210 -4
- package/src/SQLUpdate.ts +7 -1
- package/src/SQLWhere.ts +54 -26
package/src/SQLExpression.ts
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
export type SQLExpressionOptions = {
|
|
2
|
-
defaultNamespace?: string
|
|
2
|
+
defaultNamespace?: string;
|
|
3
|
+
parentNamespace?: string;
|
|
3
4
|
};
|
|
4
5
|
|
|
5
|
-
export type NormalizedSQLQuery = {query: string; params: any[]}
|
|
6
|
-
export type SQLQuery = NormalizedSQLQuery|string
|
|
6
|
+
export type NormalizedSQLQuery = { query: string; params: any[] };
|
|
7
|
+
export type SQLQuery = NormalizedSQLQuery | string;
|
|
7
8
|
|
|
8
|
-
export function joinSQLQuery(queries: (SQLQuery|undefined|null)[], seperator?: string): NormalizedSQLQuery {
|
|
9
|
-
queries = queries.filter(q => q !== undefined && q !== null)
|
|
9
|
+
export function joinSQLQuery(queries: (SQLQuery | undefined | null)[], seperator?: string): NormalizedSQLQuery {
|
|
10
|
+
queries = queries.filter(q => q !== undefined && q !== null);
|
|
10
11
|
return {
|
|
11
12
|
query: queries.map(q => typeof q === 'string' ? q : q!.query).join(seperator ?? ''),
|
|
12
|
-
params: queries.flatMap(q => typeof q === 'string' ? [] : q!.params)
|
|
13
|
-
}
|
|
13
|
+
params: queries.flatMap(q => typeof q === 'string' ? [] : q!.params),
|
|
14
|
+
};
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export function normalizeSQLQuery(q: SQLQuery): NormalizedSQLQuery {
|
|
17
18
|
return {
|
|
18
19
|
query: typeof q === 'string' ? q : q.query,
|
|
19
|
-
params: typeof q === 'string' ? [] : q.params
|
|
20
|
-
}
|
|
20
|
+
params: typeof q === 'string' ? [] : q.params,
|
|
21
|
+
};
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
|
|
24
24
|
export interface SQLExpression {
|
|
25
|
-
getSQL(options?: SQLExpressionOptions): SQLQuery
|
|
25
|
+
getSQL(options?: SQLExpressionOptions): SQLQuery;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export function isSQLExpression(obj: unknown): obj is SQLExpression {
|
|
29
|
-
return typeof obj === 'object' && obj !== null && !!(obj as any).getSQL && typeof (obj as any).getSQL === 'function'
|
|
29
|
+
return typeof obj === 'object' && obj !== null && !!(obj as any).getSQL && typeof (obj as any).getSQL === 'function';
|
|
30
30
|
}
|
package/src/SQLExpressions.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Database } from '@simonbackx/simple-database';
|
|
2
2
|
import { joinSQLQuery, SQLExpression, SQLExpressionOptions, SQLQuery } from './SQLExpression';
|
|
3
|
+
import { ParseWhereArguments, SQLEmptyWhere } from './SQLWhere';
|
|
3
4
|
|
|
4
5
|
export type SQLScalarValue = string | number | boolean | Date;
|
|
5
6
|
export type SQLDynamicExpression = SQLScalarValue | SQLScalarValue[] | null | SQLExpression;
|
|
@@ -329,23 +330,74 @@ export class SQLWildcardSelectExpression implements SQLExpression {
|
|
|
329
330
|
}
|
|
330
331
|
}
|
|
331
332
|
|
|
333
|
+
export class SQLNamespaceExpression implements SQLExpression {
|
|
334
|
+
namespace: string;
|
|
335
|
+
|
|
336
|
+
constructor(namespace: string) {
|
|
337
|
+
this.namespace = namespace;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
341
|
+
return Database.escapeId(this.namespace);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export const SQLDefaultNamespace: SQLExpression = {
|
|
346
|
+
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
347
|
+
if (!options?.defaultNamespace) {
|
|
348
|
+
throw new Error('No default namespace provided');
|
|
349
|
+
}
|
|
350
|
+
return Database.escapeId(options.defaultNamespace);
|
|
351
|
+
},
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Reference the table of the parent query
|
|
356
|
+
*/
|
|
357
|
+
export const SQLParentNamespace: SQLExpression = {
|
|
358
|
+
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
359
|
+
if (!options?.parentNamespace) {
|
|
360
|
+
throw new Error('No parent namespace provided');
|
|
361
|
+
}
|
|
362
|
+
return Database.escapeId(options.parentNamespace);
|
|
363
|
+
},
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
export type SQLColumnExpressionParams = [
|
|
367
|
+
namespace: string | SQLExpression,
|
|
368
|
+
column: string,
|
|
369
|
+
] | [
|
|
370
|
+
column: string,
|
|
371
|
+
];
|
|
372
|
+
|
|
332
373
|
export class SQLColumnExpression implements SQLExpression {
|
|
333
|
-
namespace
|
|
374
|
+
namespace: SQLExpression;
|
|
334
375
|
column: string;
|
|
335
376
|
|
|
336
|
-
constructor(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
this.column = namespaceOrColumn;
|
|
377
|
+
constructor(...args: SQLColumnExpressionParams) {
|
|
378
|
+
if (args.length === 1) {
|
|
379
|
+
this.namespace = SQLDefaultNamespace;
|
|
380
|
+
this.column = args[0];
|
|
341
381
|
return;
|
|
342
382
|
}
|
|
343
|
-
|
|
383
|
+
|
|
384
|
+
const [namespace, column] = args;
|
|
385
|
+
|
|
386
|
+
if (typeof namespace === 'string') {
|
|
387
|
+
this.namespace = new SQLNamespaceExpression(namespace);
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
this.namespace = namespace;
|
|
391
|
+
}
|
|
344
392
|
this.column = column;
|
|
345
393
|
}
|
|
346
394
|
|
|
347
395
|
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
348
|
-
return
|
|
396
|
+
return joinSQLQuery([
|
|
397
|
+
this.namespace.getSQL(options),
|
|
398
|
+
'.',
|
|
399
|
+
Database.escapeId(this.column),
|
|
400
|
+
]);
|
|
349
401
|
}
|
|
350
402
|
}
|
|
351
403
|
|
|
@@ -371,3 +423,35 @@ export class SQLTableExpression implements SQLExpression {
|
|
|
371
423
|
return Database.escapeId(this.table) + ' ' + Database.escapeId(this.namespace);
|
|
372
424
|
}
|
|
373
425
|
}
|
|
426
|
+
|
|
427
|
+
export class SQLIf implements SQLExpression {
|
|
428
|
+
_if: SQLExpression;
|
|
429
|
+
_then: SQLExpression = new SQLNull();
|
|
430
|
+
_else: SQLExpression = new SQLNull();
|
|
431
|
+
|
|
432
|
+
constructor(...args: ParseWhereArguments) {
|
|
433
|
+
this._if = new SQLEmptyWhere().and(...args);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
then(then: SQLDynamicExpression): SQLIf {
|
|
437
|
+
this._then = readDynamicSQLExpression(then);
|
|
438
|
+
return this;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
else(_else: SQLDynamicExpression): SQLIf {
|
|
442
|
+
this._else = readDynamicSQLExpression(_else);
|
|
443
|
+
return this;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
447
|
+
return joinSQLQuery([
|
|
448
|
+
'IF(',
|
|
449
|
+
this._if.getSQL(options),
|
|
450
|
+
',',
|
|
451
|
+
this._then.getSQL(options),
|
|
452
|
+
',',
|
|
453
|
+
this._else.getSQL(options),
|
|
454
|
+
')',
|
|
455
|
+
]);
|
|
456
|
+
}
|
|
457
|
+
}
|
package/src/SQLInsert.ts
CHANGED
|
@@ -47,9 +47,15 @@ export class SQLInsert implements SQLExpression {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
50
|
-
|
|
50
|
+
// Create a clone since we are mutating the default namespaces
|
|
51
|
+
const parentOptions = options;
|
|
52
|
+
options = options ? { ...options } : {};
|
|
51
53
|
options.defaultNamespace = (this._into as any).namespace ?? (this._into).table ?? undefined;
|
|
52
54
|
|
|
55
|
+
if (parentOptions?.defaultNamespace) {
|
|
56
|
+
options.parentNamespace = parentOptions.defaultNamespace;
|
|
57
|
+
}
|
|
58
|
+
|
|
53
59
|
const query: SQLQuery[] = [
|
|
54
60
|
'INSERT INTO',
|
|
55
61
|
this._into.getSQL(options),
|
package/src/SQLJoin.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { SQLExpression, SQLExpressionOptions, SQLQuery, joinSQLQuery } from
|
|
2
|
-
import { SQLWhere, Whereable } from
|
|
1
|
+
import { SQLExpression, SQLExpressionOptions, SQLQuery, joinSQLQuery } from './SQLExpression';
|
|
2
|
+
import { SQLWhere, Whereable } from './SQLWhere';
|
|
3
3
|
|
|
4
4
|
export enum SQLJoinType {
|
|
5
|
-
Left =
|
|
6
|
-
Right =
|
|
7
|
-
Inner =
|
|
8
|
-
Outer =
|
|
5
|
+
Left = 'Left',
|
|
6
|
+
Right = 'Right',
|
|
7
|
+
Inner = 'Inner',
|
|
8
|
+
Outer = 'Outer',
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
class EmptyClass {}
|
|
12
12
|
export class SQLJoin extends Whereable(EmptyClass) implements SQLExpression {
|
|
13
|
-
type = SQLJoinType.Left
|
|
13
|
+
type = SQLJoinType.Left;
|
|
14
14
|
table: SQLExpression;
|
|
15
15
|
|
|
16
16
|
constructor(type: SQLJoinType, table: SQLExpression) {
|
|
@@ -28,12 +28,12 @@ export class SQLJoin extends Whereable(EmptyClass) implements SQLExpression {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
getSQL(options?: SQLExpressionOptions
|
|
31
|
+
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
32
32
|
return joinSQLQuery([
|
|
33
33
|
this.getJoinPrefix(),
|
|
34
|
-
this.table?.getSQL(),
|
|
34
|
+
this.table?.getSQL(options),
|
|
35
35
|
this._where ? 'ON' : undefined,
|
|
36
|
-
this._where?.getSQL()
|
|
37
|
-
], ' ')
|
|
36
|
+
this._where?.getSQL(options),
|
|
37
|
+
], ' ');
|
|
38
38
|
}
|
|
39
39
|
}
|
package/src/SQLOrderBy.ts
CHANGED
|
@@ -1,50 +1,54 @@
|
|
|
1
|
-
import { SQLExpression, SQLExpressionOptions, SQLQuery, joinSQLQuery } from
|
|
1
|
+
import { SQLExpression, SQLExpressionOptions, SQLQuery, joinSQLQuery } from './SQLExpression';
|
|
2
|
+
import { SQLColumnExpression } from './SQLExpressions';
|
|
2
3
|
|
|
3
4
|
type Constructor<T = {}> = new (...args: any[]) => T;
|
|
4
5
|
|
|
5
6
|
export function Orderable<Sup extends Constructor<{}>>(Base: Sup) {
|
|
6
7
|
return class extends Base {
|
|
7
|
-
_orderBy: SQLOrderBy|null = null
|
|
8
|
+
_orderBy: SQLOrderBy | null = null;
|
|
8
9
|
|
|
9
|
-
orderBy<T>(this: T, orderBy: SQLOrderBy): T
|
|
10
|
-
orderBy<T>(this: T, column: SQLExpression, direction?: SQLOrderByDirection)
|
|
11
|
-
orderBy<T>(this: T, columnOrOrderBy: SQLExpression, direction?: SQLOrderByDirection): T {
|
|
12
|
-
let o = columnOrOrderBy as SQLOrderBy
|
|
10
|
+
orderBy<T>(this: T, orderBy: SQLOrderBy): T;
|
|
11
|
+
orderBy<T>(this: T, column: SQLExpression | string, direction?: SQLOrderByDirection): T;
|
|
12
|
+
orderBy<T>(this: T, columnOrOrderBy: SQLExpression | string, direction?: SQLOrderByDirection): T {
|
|
13
|
+
let o = columnOrOrderBy as SQLOrderBy;
|
|
13
14
|
if (!(columnOrOrderBy instanceof SQLOrderBy)) {
|
|
14
|
-
o = new SQLOrderBy({
|
|
15
|
+
o = new SQLOrderBy({
|
|
16
|
+
column: typeof columnOrOrderBy === 'string' ? new SQLColumnExpression(columnOrOrderBy) : columnOrOrderBy,
|
|
17
|
+
direction: direction ?? 'ASC',
|
|
18
|
+
});
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
const me = this as any; // stupid typescript looses type information if we don't do the this: T dance
|
|
18
22
|
|
|
19
23
|
if (me._orderBy) {
|
|
20
|
-
me._orderBy.add(o)
|
|
21
|
-
}
|
|
24
|
+
me._orderBy.add(o);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
22
27
|
me._orderBy = o;
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
return me;
|
|
26
31
|
}
|
|
27
|
-
}
|
|
32
|
+
};
|
|
28
33
|
}
|
|
29
34
|
|
|
30
|
-
|
|
31
35
|
export type SQLOrderByDirection = 'ASC' | 'DESC';
|
|
32
36
|
export class SQLOrderBy implements SQLExpression {
|
|
33
|
-
orderBy: {column: SQLExpression
|
|
37
|
+
orderBy: { column: SQLExpression; direction: SQLOrderByDirection }[] = [];
|
|
34
38
|
|
|
35
|
-
constructor(...orderBy: {column: SQLExpression
|
|
36
|
-
this.orderBy = orderBy
|
|
39
|
+
constructor(...orderBy: { column: SQLExpression; direction: SQLOrderByDirection }[]) {
|
|
40
|
+
this.orderBy = orderBy;
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
static combine(orderBy: SQLOrderBy[]) {
|
|
40
|
-
return new SQLOrderBy(...orderBy.flatMap(o => o.orderBy))
|
|
44
|
+
return new SQLOrderBy(...orderBy.flatMap(o => o.orderBy));
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
add(orderBy: SQLOrderBy) {
|
|
44
|
-
this.orderBy.push(...orderBy.orderBy)
|
|
48
|
+
this.orderBy.push(...orderBy.orderBy);
|
|
45
49
|
}
|
|
46
50
|
|
|
47
|
-
getSQL(options?: SQLExpressionOptions
|
|
51
|
+
getSQL(options?: SQLExpressionOptions): SQLQuery {
|
|
48
52
|
if (this.orderBy.length === 0) {
|
|
49
53
|
return '';
|
|
50
54
|
}
|
|
@@ -52,14 +56,14 @@ export class SQLOrderBy implements SQLExpression {
|
|
|
52
56
|
return joinSQLQuery([
|
|
53
57
|
'ORDER BY ',
|
|
54
58
|
joinSQLQuery(
|
|
55
|
-
this.orderBy.map(o => {
|
|
59
|
+
this.orderBy.map((o) => {
|
|
56
60
|
return joinSQLQuery([
|
|
57
61
|
o.column.getSQL(options),
|
|
58
|
-
o.direction
|
|
59
|
-
], ' ')
|
|
60
|
-
}),
|
|
61
|
-
', '
|
|
62
|
-
)
|
|
63
|
-
])
|
|
62
|
+
o.direction,
|
|
63
|
+
], ' ');
|
|
64
|
+
}),
|
|
65
|
+
', ',
|
|
66
|
+
),
|
|
67
|
+
]);
|
|
64
68
|
}
|
|
65
69
|
}
|
package/src/SQLSelect.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { SQLExpression, SQLExpressionOptions, SQLQuery, joinSQLQuery, normalizeS
|
|
|
3
3
|
import { SQLAlias, SQLColumnExpression, SQLCount, SQLSelectAs, SQLSum, SQLTableExpression } from './SQLExpressions';
|
|
4
4
|
import { SQLJoin } from './SQLJoin';
|
|
5
5
|
import { Orderable } from './SQLOrderBy';
|
|
6
|
-
import { Whereable } from './SQLWhere';
|
|
6
|
+
import { SQLWhereSign, Whereable } from './SQLWhere';
|
|
7
7
|
|
|
8
8
|
class EmptyClass {}
|
|
9
9
|
|
|
@@ -19,7 +19,19 @@ export function parseTable(tableOrExpressiongOrNamespace: SQLExpression | string
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export
|
|
22
|
+
export type IterableSQLSelect<T extends object = SQLResultNamespacedRow> = AsyncIterableIterator<T, undefined> & {
|
|
23
|
+
isDone: boolean;
|
|
24
|
+
options: IterableSQLSelectOptions;
|
|
25
|
+
maxQueries(maxQueries: number): IterableSQLSelect<T>;
|
|
26
|
+
};
|
|
27
|
+
export type IterableSQLSelectOptions = {
|
|
28
|
+
/**
|
|
29
|
+
* The loop will cancel after this amount of queries - but you can continue to loop over the results when starting a new for loop.
|
|
30
|
+
*/
|
|
31
|
+
maxQueries?: number;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export class SQLSelect<T extends object = SQLResultNamespacedRow> extends Whereable(Orderable(EmptyClass)) implements SQLExpression {
|
|
23
35
|
_columns: SQLExpression[];
|
|
24
36
|
_from: SQLExpression;
|
|
25
37
|
|
|
@@ -81,9 +93,15 @@ export class SQLSelect<T = SQLResultNamespacedRow> extends Whereable(Orderable(E
|
|
|
81
93
|
query.push('/*+ MAX_EXECUTION_TIME(' + this._max_execution_time + ') */');
|
|
82
94
|
}
|
|
83
95
|
|
|
84
|
-
|
|
96
|
+
// Create a clone since we are mutating the default namespaces
|
|
97
|
+
const parentOptions = options;
|
|
98
|
+
options = options ? { ...options } : {};
|
|
85
99
|
options.defaultNamespace = (this._from as any).namespace ?? (this._from as any).table ?? undefined;
|
|
86
100
|
|
|
101
|
+
if (parentOptions?.defaultNamespace) {
|
|
102
|
+
options.parentNamespace = parentOptions.defaultNamespace;
|
|
103
|
+
}
|
|
104
|
+
|
|
87
105
|
const columns = this._columns.map(c => c.getSQL(options));
|
|
88
106
|
query.push(
|
|
89
107
|
joinSQLQuery(columns, ', '),
|
|
@@ -136,7 +154,7 @@ export class SQLSelect<T = SQLResultNamespacedRow> extends Whereable(Orderable(E
|
|
|
136
154
|
const { query, params } = normalizeSQLQuery(this.getSQL());
|
|
137
155
|
|
|
138
156
|
// when debugging: log all queries
|
|
139
|
-
|
|
157
|
+
console.log(query, params);
|
|
140
158
|
const [rows] = await Database.select(query, params, { nestTables: true });
|
|
141
159
|
|
|
142
160
|
// Now map aggregated queries to the correct namespace
|
|
@@ -238,4 +256,192 @@ export class SQLSelect<T = SQLResultNamespacedRow> extends Whereable(Orderable(E
|
|
|
238
256
|
console.warn('Invalid sum SQL response', rows);
|
|
239
257
|
return 0;
|
|
240
258
|
}
|
|
259
|
+
|
|
260
|
+
all(options: IterableSQLSelectOptions = {}): T extends { id: string } ? IterableSQLSelect<T> : never {
|
|
261
|
+
if (this._orderBy) {
|
|
262
|
+
throw new Error('Cannot use async iterator with custom order by. Results should be ordered by ID');
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (this._offset !== null) {
|
|
266
|
+
throw new Error('Cannot use async iterator with offset');
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (!this._limit) {
|
|
270
|
+
this._limit = 100;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const limit = this._limit;
|
|
274
|
+
this.orderBy('id');
|
|
275
|
+
|
|
276
|
+
let next: this | null = this.clone();
|
|
277
|
+
const base = this;
|
|
278
|
+
|
|
279
|
+
let stack: T[] = [];
|
|
280
|
+
let stackIndex = 0;
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
queryCount: 0,
|
|
284
|
+
options,
|
|
285
|
+
[Symbol.asyncIterator]() {
|
|
286
|
+
return {
|
|
287
|
+
...this,
|
|
288
|
+
|
|
289
|
+
// Reset the iterator
|
|
290
|
+
queryCount: 0,
|
|
291
|
+
};
|
|
292
|
+
},
|
|
293
|
+
get isDone() {
|
|
294
|
+
return !next && (stackIndex + 1) >= stack.length;
|
|
295
|
+
},
|
|
296
|
+
async next(): Promise<IteratorResult<T, undefined>> {
|
|
297
|
+
stackIndex++;
|
|
298
|
+
|
|
299
|
+
if (stackIndex < stack.length) {
|
|
300
|
+
return {
|
|
301
|
+
done: false,
|
|
302
|
+
value: stack[stackIndex],
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (!next) {
|
|
307
|
+
stack = []; // Clean up memory
|
|
308
|
+
return {
|
|
309
|
+
done: true,
|
|
310
|
+
value: undefined,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (this.options.maxQueries !== undefined && this.queryCount >= this.options.maxQueries) {
|
|
315
|
+
// Stopping early
|
|
316
|
+
return {
|
|
317
|
+
done: true,
|
|
318
|
+
value: undefined,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
stack = await next.fetch();
|
|
323
|
+
next = null;
|
|
324
|
+
this.queryCount += 1;
|
|
325
|
+
|
|
326
|
+
if (stack.length === 0) {
|
|
327
|
+
return {
|
|
328
|
+
done: true,
|
|
329
|
+
value: undefined,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
stackIndex = 0;
|
|
333
|
+
|
|
334
|
+
if (stack.length >= limit) {
|
|
335
|
+
next = base.clone();
|
|
336
|
+
const lastResult = stack[stack.length - 1]!;
|
|
337
|
+
if (!('id' in lastResult)) {
|
|
338
|
+
throw new Error('Cannot use async iterator without ID column');
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const lastId = lastResult.id;
|
|
342
|
+
if (typeof lastId !== 'string') {
|
|
343
|
+
throw new Error('Cannot use async iterator without string ID column');
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
next.andWhere('id', '>', lastId);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return {
|
|
350
|
+
done: false,
|
|
351
|
+
value: stack[stackIndex],
|
|
352
|
+
};
|
|
353
|
+
},
|
|
354
|
+
maxQueries(maxQueries: number) {
|
|
355
|
+
this.options.maxQueries = maxQueries;
|
|
356
|
+
return this;
|
|
357
|
+
},
|
|
358
|
+
} as IterableSQLSelect<T> as any;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
allBatched(options: IterableSQLSelectOptions = {}): T extends { id: string } ? IterableSQLSelect<T[]> : never {
|
|
362
|
+
if (this._orderBy) {
|
|
363
|
+
throw new Error('Cannot use async iterator with custom order by. Results should be ordered by ID');
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (this._offset !== null) {
|
|
367
|
+
throw new Error('Cannot use async iterator with offset');
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (!this._limit) {
|
|
371
|
+
this._limit = 100;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const limit = this._limit;
|
|
375
|
+
this.orderBy('id');
|
|
376
|
+
|
|
377
|
+
let next: this | null = this.clone();
|
|
378
|
+
const base = this;
|
|
379
|
+
|
|
380
|
+
return {
|
|
381
|
+
queryCount: 0,
|
|
382
|
+
options,
|
|
383
|
+
[Symbol.asyncIterator]() {
|
|
384
|
+
return {
|
|
385
|
+
...this,
|
|
386
|
+
|
|
387
|
+
// Reset the iterator
|
|
388
|
+
queryCount: 0,
|
|
389
|
+
};
|
|
390
|
+
},
|
|
391
|
+
get isDone() {
|
|
392
|
+
return !next;
|
|
393
|
+
},
|
|
394
|
+
async next(): Promise<IteratorResult<T[], undefined>> {
|
|
395
|
+
if (!next) {
|
|
396
|
+
return {
|
|
397
|
+
done: true,
|
|
398
|
+
value: undefined,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
if (this.options.maxQueries !== undefined && this.queryCount >= this.options.maxQueries) {
|
|
403
|
+
// Stopping early
|
|
404
|
+
return {
|
|
405
|
+
done: true,
|
|
406
|
+
value: undefined,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const stack = await next.fetch();
|
|
411
|
+
next = null;
|
|
412
|
+
this.queryCount += 1;
|
|
413
|
+
|
|
414
|
+
if (stack.length === 0) {
|
|
415
|
+
return {
|
|
416
|
+
done: true,
|
|
417
|
+
value: undefined,
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (stack.length >= limit) {
|
|
422
|
+
next = base.clone();
|
|
423
|
+
const lastResult = stack[stack.length - 1]!;
|
|
424
|
+
if (!('id' in lastResult)) {
|
|
425
|
+
throw new Error('Cannot use async iterator without ID column');
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const lastId = lastResult.id;
|
|
429
|
+
if (typeof lastId !== 'string') {
|
|
430
|
+
throw new Error('Cannot use async iterator without string ID column');
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
next.andWhere('id', '>', lastId);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return {
|
|
437
|
+
done: false,
|
|
438
|
+
value: stack,
|
|
439
|
+
};
|
|
440
|
+
},
|
|
441
|
+
maxQueries(maxQueries: number) {
|
|
442
|
+
this.options.maxQueries = maxQueries;
|
|
443
|
+
return this;
|
|
444
|
+
},
|
|
445
|
+
} as IterableSQLSelect<T[]> as any;
|
|
446
|
+
}
|
|
241
447
|
}
|
package/src/SQLUpdate.ts
CHANGED
|
@@ -34,9 +34,15 @@ export class SQLUpdate extends Whereable(EmptyClass) implements SQLExpression {
|
|
|
34
34
|
throw new Error('No assignments provided');
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
// Create a clone since we are mutating the default namespaces
|
|
38
|
+
const parentOptions = options;
|
|
39
|
+
options = options ? { ...options } : {};
|
|
38
40
|
options.defaultNamespace = (this._table as any).namespace ?? (this._table).table ?? undefined;
|
|
39
41
|
|
|
42
|
+
if (parentOptions?.defaultNamespace) {
|
|
43
|
+
options.parentNamespace = parentOptions.defaultNamespace;
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
const query: SQLQuery[] = [
|
|
41
47
|
'UPDATE ',
|
|
42
48
|
this._table.getSQL(options),
|