metal-orm 1.0.42 → 1.0.44
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/README.md +195 -37
- package/dist/index.cjs +1014 -538
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1267 -371
- package/dist/index.d.ts +1267 -371
- package/dist/index.js +1012 -536
- package/dist/index.js.map +1 -1
- package/package.json +8 -2
- package/scripts/run-eslint.mjs +34 -0
- package/src/codegen/typescript.ts +32 -15
- package/src/core/ast/adapters.ts +8 -2
- package/src/core/ast/builders.ts +105 -76
- package/src/core/ast/expression-builders.ts +430 -392
- package/src/core/ast/expression-nodes.ts +14 -5
- package/src/core/ast/expression-visitor.ts +56 -14
- package/src/core/ast/helpers.ts +23 -0
- package/src/core/ast/join-node.ts +18 -2
- package/src/core/ast/query.ts +6 -6
- package/src/core/ast/window-functions.ts +10 -2
- package/src/core/ddl/dialects/base-schema-dialect.ts +37 -4
- package/src/core/ddl/dialects/index.ts +1 -0
- package/src/core/ddl/dialects/mssql-schema-dialect.ts +5 -0
- package/src/core/ddl/dialects/mysql-schema-dialect.ts +3 -0
- package/src/core/ddl/dialects/postgres-schema-dialect.ts +14 -1
- package/src/core/ddl/dialects/render-reference.test.ts +69 -0
- package/src/core/ddl/dialects/sqlite-schema-dialect.ts +10 -0
- package/src/core/ddl/introspect/catalogs/index.ts +1 -0
- package/src/core/ddl/introspect/catalogs/postgres.ts +2 -0
- package/src/core/ddl/introspect/context.ts +6 -0
- package/src/core/ddl/introspect/functions/postgres.ts +13 -0
- package/src/core/ddl/introspect/mssql.ts +53 -8
- package/src/core/ddl/introspect/mysql.ts +32 -6
- package/src/core/ddl/introspect/postgres.ts +102 -34
- package/src/core/ddl/introspect/registry.ts +14 -0
- package/src/core/ddl/introspect/run-select.ts +19 -4
- package/src/core/ddl/introspect/sqlite.ts +78 -11
- package/src/core/ddl/introspect/types.ts +0 -1
- package/src/core/ddl/introspect/utils.ts +21 -3
- package/src/core/ddl/naming-strategy.ts +6 -0
- package/src/core/ddl/schema-dialect.ts +20 -6
- package/src/core/ddl/schema-diff.ts +22 -0
- package/src/core/ddl/schema-generator.ts +26 -12
- package/src/core/ddl/schema-plan-executor.ts +6 -0
- package/src/core/ddl/schema-types.ts +6 -0
- package/src/core/ddl/sql-writing.ts +4 -4
- package/src/core/dialect/abstract.ts +19 -7
- package/src/core/dialect/base/function-table-formatter.ts +3 -2
- package/src/core/dialect/base/join-compiler.ts +5 -3
- package/src/core/dialect/base/returning-strategy.ts +1 -0
- package/src/core/dialect/base/sql-dialect.ts +3 -3
- package/src/core/dialect/mssql/functions.ts +24 -25
- package/src/core/dialect/mssql/index.ts +1 -4
- package/src/core/dialect/mysql/functions.ts +0 -1
- package/src/core/dialect/postgres/functions.ts +33 -34
- package/src/core/dialect/postgres/index.ts +1 -0
- package/src/core/dialect/sqlite/functions.ts +18 -19
- package/src/core/dialect/sqlite/index.ts +2 -0
- package/src/core/execution/db-executor.ts +1 -1
- package/src/core/execution/executors/mysql-executor.ts +2 -2
- package/src/core/execution/executors/postgres-executor.ts +1 -1
- package/src/core/execution/pooling/pool.ts +12 -5
- package/src/core/functions/datetime.ts +58 -34
- package/src/core/functions/numeric.ts +96 -31
- package/src/core/functions/standard-strategy.ts +35 -0
- package/src/core/functions/text.ts +84 -23
- package/src/core/functions/types.ts +23 -8
- package/src/decorators/bootstrap.ts +42 -11
- package/src/decorators/column.ts +20 -11
- package/src/decorators/decorator-metadata.ts +30 -9
- package/src/decorators/entity.ts +29 -5
- package/src/decorators/index.ts +3 -0
- package/src/decorators/relations.ts +34 -11
- package/src/orm/als.ts +34 -9
- package/src/orm/entity-context.ts +62 -8
- package/src/orm/entity-meta.ts +8 -8
- package/src/orm/entity-metadata.ts +131 -16
- package/src/orm/entity.ts +28 -29
- package/src/orm/execute.ts +19 -4
- package/src/orm/hydration.ts +42 -39
- package/src/orm/identity-map.ts +1 -1
- package/src/orm/lazy-batch.ts +74 -104
- package/src/orm/orm-session.ts +24 -23
- package/src/orm/orm.ts +2 -5
- package/src/orm/relation-change-processor.ts +12 -11
- package/src/orm/relations/belongs-to.ts +11 -11
- package/src/orm/relations/has-many.ts +54 -10
- package/src/orm/relations/has-one.ts +8 -7
- package/src/orm/relations/many-to-many.ts +13 -13
- package/src/orm/runtime-types.ts +4 -4
- package/src/orm/save-graph.ts +31 -25
- package/src/orm/unit-of-work.ts +17 -17
- package/src/query/index.ts +74 -0
- package/src/query/target.ts +46 -0
- package/src/query-builder/delete-query-state.ts +30 -0
- package/src/query-builder/delete.ts +64 -18
- package/src/query-builder/hydration-manager.ts +52 -5
- package/src/query-builder/insert-query-state.ts +30 -0
- package/src/query-builder/insert.ts +58 -10
- package/src/query-builder/query-ast-service.ts +7 -2
- package/src/query-builder/query-resolution.ts +78 -0
- package/src/query-builder/raw-column-parser.ts +7 -1
- package/src/query-builder/relation-alias.ts +7 -0
- package/src/query-builder/relation-conditions.ts +61 -48
- package/src/query-builder/relation-service.ts +68 -63
- package/src/query-builder/relation-utils.ts +3 -0
- package/src/query-builder/select/cte-facet.ts +40 -0
- package/src/query-builder/select/from-facet.ts +80 -0
- package/src/query-builder/select/join-facet.ts +62 -0
- package/src/query-builder/select/predicate-facet.ts +103 -0
- package/src/query-builder/select/projection-facet.ts +69 -0
- package/src/query-builder/select/relation-facet.ts +81 -0
- package/src/query-builder/select/setop-facet.ts +36 -0
- package/src/query-builder/select-helpers.ts +15 -2
- package/src/query-builder/select-query-builder-deps.ts +19 -1
- package/src/query-builder/select-query-state.ts +2 -1
- package/src/query-builder/select.ts +795 -1163
- package/src/query-builder/update-query-state.ts +52 -0
- package/src/query-builder/update.ts +69 -18
- package/src/schema/column.ts +26 -26
- package/src/schema/table-guards.ts +31 -0
- package/src/schema/table.ts +47 -18
- package/src/schema/types.ts +22 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metal-orm",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.44",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"engines": {
|
|
@@ -28,7 +28,9 @@
|
|
|
28
28
|
"gen:entities": "node scripts/generate-entities.mjs",
|
|
29
29
|
"test": "vitest",
|
|
30
30
|
"test:ui": "vitest --ui",
|
|
31
|
-
"show-sql": "node scripts/show-sql.mjs"
|
|
31
|
+
"show-sql": "node scripts/show-sql.mjs",
|
|
32
|
+
"lint": "node scripts/run-eslint.mjs",
|
|
33
|
+
"lint:fix": "node scripts/run-eslint.mjs --fix"
|
|
32
34
|
},
|
|
33
35
|
"peerDependencies": {
|
|
34
36
|
"mysql2": "^3.9.0",
|
|
@@ -52,6 +54,10 @@
|
|
|
52
54
|
},
|
|
53
55
|
"devDependencies": {
|
|
54
56
|
"@vitest/ui": "^4.0.14",
|
|
57
|
+
"@typescript-eslint/eslint-plugin": "^8.20.0",
|
|
58
|
+
"@typescript-eslint/parser": "^8.20.0",
|
|
59
|
+
"eslint": "^8.57.0",
|
|
60
|
+
"eslint-plugin-deprecation": "^3.0.0",
|
|
55
61
|
"mysql2": "^3.15.3",
|
|
56
62
|
"pg": "^8.16.3",
|
|
57
63
|
"sqlite3": "^5.1.7",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
|
|
5
|
+
const [, , ...userArgs] = process.argv;
|
|
6
|
+
|
|
7
|
+
const TARGETS = {
|
|
8
|
+
src: ['./src'],
|
|
9
|
+
all: ['./src', './tests', './scripts', './playground'],
|
|
10
|
+
playground: ['./playground'],
|
|
11
|
+
'src/core': ['./src/core'],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const [firstArg, ...restArgs] = userArgs;
|
|
15
|
+
const hasTarget = firstArg && !firstArg.startsWith('-');
|
|
16
|
+
|
|
17
|
+
const targetKey = hasTarget ? firstArg : 'all';
|
|
18
|
+
const extraArgs = hasTarget ? restArgs : userArgs;
|
|
19
|
+
|
|
20
|
+
const paths = TARGETS[targetKey] ?? [targetKey];
|
|
21
|
+
|
|
22
|
+
if (paths.length === 0) {
|
|
23
|
+
console.error(`Unknown lint target: ${targetKey}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const eslintArgs = [...paths, '--ext', '.ts,.tsx,.mjs', ...extraArgs];
|
|
28
|
+
|
|
29
|
+
const eslintBinBase = path.join(process.cwd(), 'node_modules', '.bin', 'eslint');
|
|
30
|
+
const executable = process.platform === 'win32' ? `${eslintBinBase}.cmd` : eslintBinBase;
|
|
31
|
+
|
|
32
|
+
const child = spawn(executable, eslintArgs, { stdio: 'inherit', shell: true });
|
|
33
|
+
|
|
34
|
+
child.on('exit', (code) => process.exit(code));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SelectQueryNode } from '../core/ast/query.js';
|
|
1
|
+
import { OrderingTerm, SelectQueryNode } from '../core/ast/query.js';
|
|
2
2
|
import {
|
|
3
3
|
ExpressionNode,
|
|
4
4
|
OperandNode,
|
|
@@ -36,8 +36,15 @@ const assertNever = (value: never): never => {
|
|
|
36
36
|
/**
|
|
37
37
|
* Generates TypeScript code from query AST nodes
|
|
38
38
|
*/
|
|
39
|
+
type SelectionColumn =
|
|
40
|
+
| ColumnNode
|
|
41
|
+
| FunctionNode
|
|
42
|
+
| ScalarSubqueryNode
|
|
43
|
+
| CaseExpressionNode
|
|
44
|
+
| WindowFunctionNode;
|
|
45
|
+
|
|
39
46
|
export class TypeScriptGenerator implements ExpressionVisitor<string>, OperandVisitor<string> {
|
|
40
|
-
constructor(private namingStrategy: NamingStrategy = new DefaultNamingStrategy()) {}
|
|
47
|
+
constructor(private namingStrategy: NamingStrategy = new DefaultNamingStrategy()) { }
|
|
41
48
|
|
|
42
49
|
/**
|
|
43
50
|
* Generates TypeScript code from a query AST
|
|
@@ -62,12 +69,8 @@ export class TypeScriptGenerator implements ExpressionVisitor<string>, OperandVi
|
|
|
62
69
|
const hydratedRelations = new Set(hydration?.relations?.map(r => r.name) ?? []);
|
|
63
70
|
|
|
64
71
|
const selections = ast.columns
|
|
65
|
-
.filter(col => !(hydration && isRelationAlias(
|
|
66
|
-
.map(col => {
|
|
67
|
-
const key = (col as any).alias || (col as any).name;
|
|
68
|
-
const operand = col as OperandNode;
|
|
69
|
-
return `${key}: ${this.printOperand(operand)}`;
|
|
70
|
-
});
|
|
72
|
+
.filter((col): col is SelectionColumn => !(hydration && isRelationAlias(col.alias)))
|
|
73
|
+
.map((col, index) => `${this.getSelectionKey(col, index)}: ${this.printOperand(col)}`);
|
|
71
74
|
|
|
72
75
|
lines.push(`db.select({`);
|
|
73
76
|
selections.forEach((sel, index) => {
|
|
@@ -168,26 +171,40 @@ export class TypeScriptGenerator implements ExpressionVisitor<string>, OperandVi
|
|
|
168
171
|
/**
|
|
169
172
|
* Prints an ordering term (operand/expression/alias) to TypeScript code.
|
|
170
173
|
*/
|
|
171
|
-
private printOrderingTerm(term:
|
|
172
|
-
if (!term || !(
|
|
174
|
+
private printOrderingTerm(term: OrderingTerm): string {
|
|
175
|
+
if (!term || !('type' in term)) {
|
|
173
176
|
throw new Error('Unsupported ordering term');
|
|
174
177
|
}
|
|
175
178
|
|
|
176
|
-
switch (
|
|
179
|
+
switch (term.type) {
|
|
177
180
|
case 'Column':
|
|
178
|
-
return `${this.namingStrategy.tableToSymbol(
|
|
181
|
+
return `${this.namingStrategy.tableToSymbol(term.table)}.${term.name}`;
|
|
179
182
|
case 'AliasRef':
|
|
180
|
-
return this.visitAliasRef(term
|
|
183
|
+
return this.visitAliasRef(term);
|
|
181
184
|
case 'Literal':
|
|
182
185
|
case 'Function':
|
|
183
186
|
case 'JsonPath':
|
|
184
187
|
case 'ScalarSubquery':
|
|
185
188
|
case 'CaseExpression':
|
|
186
189
|
case 'WindowFunction':
|
|
187
|
-
return this.printOperand(term
|
|
190
|
+
return this.printOperand(term);
|
|
188
191
|
default:
|
|
189
|
-
return this.printExpression(term
|
|
192
|
+
return this.printExpression(term);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private getSelectionKey(selection: SelectionColumn, index: number): string {
|
|
197
|
+
if (selection.alias) {
|
|
198
|
+
return selection.alias;
|
|
199
|
+
}
|
|
200
|
+
if (this.isNamedSelection(selection)) {
|
|
201
|
+
return selection.name;
|
|
190
202
|
}
|
|
203
|
+
return `selection${index + 1}`;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private isNamedSelection(selection: SelectionColumn): selection is ColumnNode | FunctionNode | WindowFunctionNode {
|
|
207
|
+
return 'name' in selection;
|
|
191
208
|
}
|
|
192
209
|
|
|
193
210
|
public visitBinaryExpression(binary: BinaryExpressionNode): string {
|
package/src/core/ast/adapters.ts
CHANGED
|
@@ -2,13 +2,19 @@ import { ColumnDef } from '../../schema/column.js';
|
|
|
2
2
|
import { TableDef } from '../../schema/table.js';
|
|
3
3
|
import { ColumnRef, TableRef } from './types.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Type guard to check if an object has an alias property
|
|
7
|
+
*/
|
|
8
|
+
const hasAlias = (obj: unknown): obj is { alias?: string } =>
|
|
9
|
+
typeof obj === 'object' && obj !== null && 'alias' in obj;
|
|
10
|
+
|
|
5
11
|
/**
|
|
6
12
|
* Adapts a schema ColumnDef to an AST-friendly ColumnRef.
|
|
7
13
|
*/
|
|
8
14
|
export const toColumnRef = (col: ColumnRef | ColumnDef): ColumnRef => ({
|
|
9
15
|
name: col.name,
|
|
10
16
|
table: col.table,
|
|
11
|
-
alias: (col
|
|
17
|
+
alias: hasAlias(col) ? col.alias : undefined
|
|
12
18
|
});
|
|
13
19
|
|
|
14
20
|
/**
|
|
@@ -17,5 +23,5 @@ export const toColumnRef = (col: ColumnRef | ColumnDef): ColumnRef => ({
|
|
|
17
23
|
export const toTableRef = (table: TableRef | TableDef): TableRef => ({
|
|
18
24
|
name: table.name,
|
|
19
25
|
schema: table.schema,
|
|
20
|
-
alias: (table
|
|
26
|
+
alias: hasAlias(table) ? table.alias : undefined
|
|
21
27
|
});
|
package/src/core/ast/builders.ts
CHANGED
|
@@ -1,76 +1,105 @@
|
|
|
1
|
-
import { ColumnNode } from './expression-nodes.js';
|
|
2
|
-
import { TableNode, FunctionTableNode, DerivedTableNode } from './query.js';
|
|
3
|
-
import { ColumnRef, TableRef } from './types.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
*
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
1
|
+
import { ColumnNode, OperandNode } from './expression-nodes.js';
|
|
2
|
+
import { TableNode, FunctionTableNode, DerivedTableNode } from './query.js';
|
|
3
|
+
import { ColumnRef, TableRef } from './types.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Type guard to check if a column is already a ColumnNode
|
|
7
|
+
*/
|
|
8
|
+
const isColumnNode = (col: ColumnRef | ColumnNode): col is ColumnNode =>
|
|
9
|
+
'type' in col && col.type === 'Column';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Resolves the appropriate table name for a column reference
|
|
13
|
+
* @param def - Column reference definition
|
|
14
|
+
* @param table - Table reference providing context
|
|
15
|
+
* @returns The resolved table name to use
|
|
16
|
+
*/
|
|
17
|
+
const resolveTableName = (def: ColumnRef, table: TableRef): string => {
|
|
18
|
+
// If column doesn't specify a table, use the table's alias or name
|
|
19
|
+
if (!def.table) {
|
|
20
|
+
return table.alias || table.name;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// If column specifies the base table name and table has an alias, use the alias
|
|
24
|
+
if (table.alias && def.table === table.name) {
|
|
25
|
+
return table.alias;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Otherwise use the table specified in the column definition
|
|
29
|
+
return def.table;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Builds or normalizes a column AST node from a column definition or existing node
|
|
34
|
+
* @param table - Table definition providing a default table name
|
|
35
|
+
* @param column - Column definition or existing column node
|
|
36
|
+
*/
|
|
37
|
+
export const buildColumnNode = (table: TableRef, column: ColumnRef | ColumnNode): ColumnNode => {
|
|
38
|
+
if (isColumnNode(column)) {
|
|
39
|
+
return column;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const def = column as ColumnRef;
|
|
43
|
+
const baseTable = resolveTableName(def, table);
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
type: 'Column',
|
|
47
|
+
table: baseTable,
|
|
48
|
+
name: def.name
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Builds column AST nodes for a list of column names
|
|
54
|
+
* @param table - Table definition providing the table name
|
|
55
|
+
* @param names - Column names
|
|
56
|
+
*/
|
|
57
|
+
export const buildColumnNodes = (table: TableRef, names: string[]): ColumnNode[] =>
|
|
58
|
+
names.map(name => ({
|
|
59
|
+
type: 'Column',
|
|
60
|
+
table: table.alias || table.name,
|
|
61
|
+
name
|
|
62
|
+
}));
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Builds a table AST node for the provided table definition
|
|
66
|
+
* @param table - Table definition
|
|
67
|
+
*/
|
|
68
|
+
export const createTableNode = (table: TableRef): TableNode => ({
|
|
69
|
+
type: 'Table',
|
|
70
|
+
name: table.name,
|
|
71
|
+
schema: (table as unknown as { schema?: string }).schema
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Creates a FunctionTable node for expressions like `function_name(args...)` used in FROM
|
|
76
|
+
*/
|
|
77
|
+
export const fnTable = (
|
|
78
|
+
name: string,
|
|
79
|
+
args: OperandNode[] = [],
|
|
80
|
+
alias?: string,
|
|
81
|
+
opts?: { lateral?: boolean; withOrdinality?: boolean; columnAliases?: string[]; schema?: string }
|
|
82
|
+
): FunctionTableNode => ({
|
|
83
|
+
type: 'FunctionTable',
|
|
84
|
+
name,
|
|
85
|
+
args,
|
|
86
|
+
alias,
|
|
87
|
+
lateral: opts?.lateral,
|
|
88
|
+
withOrdinality: opts?.withOrdinality,
|
|
89
|
+
columnAliases: opts?.columnAliases,
|
|
90
|
+
schema: opts?.schema
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Creates a derived table node wrapping a subquery.
|
|
95
|
+
*/
|
|
96
|
+
export const derivedTable = (
|
|
97
|
+
query: import('./query.js').SelectQueryNode,
|
|
98
|
+
alias: string,
|
|
99
|
+
columnAliases?: string[]
|
|
100
|
+
): DerivedTableNode => ({
|
|
101
|
+
type: 'DerivedTable',
|
|
102
|
+
query,
|
|
103
|
+
alias,
|
|
104
|
+
columnAliases
|
|
105
|
+
});
|