metal-orm 1.0.45 → 1.0.47
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.cjs +1092 -323
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +99 -9
- package/dist/index.d.ts +99 -9
- package/dist/index.js +1087 -323
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/generate-entities.mjs +36 -9
- package/src/codegen/typescript.ts +22 -10
- package/src/core/ast/adapters.ts +2 -1
- package/src/core/ast/expression-builders.ts +13 -0
- package/src/core/ast/expression-nodes.ts +25 -5
- package/src/core/ast/expression-visitor.ts +5 -0
- package/src/core/ast/query.ts +9 -1
- package/src/core/ddl/dialects/base-schema-dialect.ts +2 -1
- package/src/core/ddl/dialects/mssql-schema-dialect.ts +10 -23
- package/src/core/ddl/dialects/mysql-schema-dialect.ts +10 -24
- package/src/core/ddl/dialects/postgres-schema-dialect.ts +10 -23
- package/src/core/ddl/dialects/render-reference.test.ts +2 -1
- package/src/core/ddl/dialects/sqlite-schema-dialect.ts +9 -23
- package/src/core/ddl/introspect/catalogs/index.ts +4 -1
- package/src/core/ddl/introspect/catalogs/mssql.ts +126 -0
- package/src/core/ddl/introspect/catalogs/mysql.ts +89 -0
- package/src/core/ddl/introspect/catalogs/postgres.ts +2 -1
- package/src/core/ddl/introspect/catalogs/sqlite.ts +47 -0
- package/src/core/ddl/introspect/functions/mssql.ts +84 -0
- package/src/core/ddl/introspect/mssql.ts +471 -194
- package/src/core/ddl/introspect/mysql.ts +336 -125
- package/src/core/ddl/introspect/postgres.ts +45 -5
- package/src/core/ddl/introspect/run-select.ts +3 -8
- package/src/core/ddl/introspect/sqlite.ts +113 -59
- package/src/core/ddl/schema-dialect.ts +2 -1
- package/src/core/ddl/schema-diff.ts +2 -1
- package/src/core/ddl/schema-generator.ts +2 -1
- package/src/core/ddl/schema-types.ts +3 -1
- package/src/core/ddl/sql-writing.ts +2 -1
- package/src/core/dialect/abstract.ts +12 -1
- package/src/core/dialect/mssql/index.ts +4 -10
- package/src/core/functions/datetime.ts +2 -1
- package/src/core/functions/numeric.ts +2 -1
- package/src/core/functions/text.ts +2 -1
- package/src/decorators/{column.ts → column-decorator.ts} +4 -1
- package/src/decorators/index.ts +1 -1
- package/src/index.ts +2 -1
- package/src/orm/entity-metadata.ts +2 -1
- package/src/orm/lazy-batch.ts +2 -1
- package/src/orm/orm-session.ts +2 -1
- package/src/query-builder/column-selector.ts +2 -1
- package/src/query-builder/delete.ts +2 -1
- package/src/query-builder/insert.ts +2 -1
- package/src/query-builder/query-ast-service.ts +4 -3
- package/src/query-builder/relation-projection-helper.ts +2 -1
- package/src/query-builder/relation-service.ts +2 -1
- package/src/query-builder/select/predicate-facet.ts +2 -1
- package/src/query-builder/select/projection-facet.ts +2 -1
- package/src/query-builder/select-helpers.ts +2 -1
- package/src/query-builder/select-query-state.ts +2 -0
- package/src/query-builder/select.ts +2 -1
- package/src/query-builder/update.ts +2 -1
- package/src/schema/{column.ts → column-types.ts} +317 -290
- package/src/schema/table-guards.ts +1 -1
- package/src/schema/table.ts +1 -1
- package/src/schema/types.ts +10 -8
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { SchemaIntrospector, IntrospectOptions } from './types.js';
|
|
2
|
-
import {
|
|
2
|
+
import { shouldIncludeTable } from './utils.js';
|
|
3
3
|
import { DatabaseSchema, DatabaseTable, DatabaseIndex } from '../schema-types.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import type { IntrospectContext } from './context.js';
|
|
5
|
+
import { runSelectNode } from './run-select.js';
|
|
6
|
+
import type { SelectQueryNode, TableNode } from '../../ast/query.js';
|
|
7
|
+
import type { ColumnNode } from '../../ast/expression-nodes.js';
|
|
8
|
+
import { eq, notLike, and, valueToOperand } from '../../ast/expression-builders.js';
|
|
9
|
+
import { fnTable } from '../../ast/builders.js';
|
|
10
|
+
import type { ReferentialAction } from '../../../schema/column-types.js';
|
|
6
11
|
|
|
7
|
-
/** Row type for SQLite table list from sqlite_master. */
|
|
8
12
|
type SqliteTableRow = {
|
|
9
13
|
name: string;
|
|
10
14
|
};
|
|
11
15
|
|
|
12
|
-
/** Row type for SQLite table column information from PRAGMA table_info. */
|
|
13
16
|
type SqliteTableInfoRow = {
|
|
17
|
+
cid: number;
|
|
14
18
|
name: string;
|
|
15
19
|
type: string;
|
|
16
20
|
notnull: number;
|
|
@@ -18,31 +22,28 @@ type SqliteTableInfoRow = {
|
|
|
18
22
|
pk: number;
|
|
19
23
|
};
|
|
20
24
|
|
|
21
|
-
/** Row type for SQLite foreign key information from PRAGMA foreign_key_list. */
|
|
22
25
|
type SqliteForeignKeyRow = {
|
|
26
|
+
id: number;
|
|
27
|
+
seq: number;
|
|
23
28
|
table: string;
|
|
24
29
|
from: string;
|
|
25
30
|
to: string;
|
|
26
|
-
on_delete: string | null;
|
|
27
31
|
on_update: string | null;
|
|
32
|
+
on_delete: string | null;
|
|
28
33
|
};
|
|
29
34
|
|
|
30
|
-
/** Row type for SQLite index list from PRAGMA index_list. */
|
|
31
35
|
type SqliteIndexListRow = {
|
|
36
|
+
seq: number;
|
|
32
37
|
name: string;
|
|
33
38
|
unique: number;
|
|
34
39
|
};
|
|
35
40
|
|
|
36
|
-
/** Row type for SQLite index column information from PRAGMA index_info. */
|
|
37
41
|
type SqliteIndexInfoRow = {
|
|
42
|
+
seqno: number;
|
|
43
|
+
cid: number;
|
|
38
44
|
name: string;
|
|
39
45
|
};
|
|
40
46
|
|
|
41
|
-
/**
|
|
42
|
-
* Converts a SQLite referential action string to a ReferentialAction enum value.
|
|
43
|
-
* @param value - The string value from SQLite pragma (e.g., 'CASCADE', 'SET NULL').
|
|
44
|
-
* @returns The corresponding ReferentialAction enum value, or undefined if the value is invalid or null.
|
|
45
|
-
*/
|
|
46
47
|
const toReferentialAction = (value: string | null | undefined): ReferentialAction | undefined => {
|
|
47
48
|
if (!value) return undefined;
|
|
48
49
|
const normalized = value.toUpperCase();
|
|
@@ -58,53 +59,101 @@ const toReferentialAction = (value: string | null | undefined): ReferentialActio
|
|
|
58
59
|
return undefined;
|
|
59
60
|
};
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
const columnNode = (table: string, name: string, alias?: string): ColumnNode => ({
|
|
63
|
+
type: 'Column',
|
|
64
|
+
table,
|
|
65
|
+
name,
|
|
66
|
+
alias
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const buildPragmaQuery = (
|
|
70
|
+
name: string,
|
|
71
|
+
table: string,
|
|
72
|
+
alias: string,
|
|
73
|
+
columnAliases: string[]
|
|
74
|
+
): SelectQueryNode => ({
|
|
75
|
+
type: 'SelectQuery',
|
|
76
|
+
from: fnTable(name, [valueToOperand(table)], alias, { columnAliases }),
|
|
77
|
+
columns: columnAliases.map(column => columnNode(alias, column)),
|
|
78
|
+
joins: []
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const runPragma = async <T>(
|
|
82
|
+
name: string,
|
|
83
|
+
table: string,
|
|
84
|
+
alias: string,
|
|
85
|
+
columnAliases: string[],
|
|
86
|
+
ctx: IntrospectContext
|
|
87
|
+
): Promise<T[]> => {
|
|
88
|
+
const query = buildPragmaQuery(name, table, alias, columnAliases);
|
|
89
|
+
return (await runSelectNode<T>(query, ctx)) as T[];
|
|
90
|
+
};
|
|
67
91
|
|
|
68
|
-
/** SQLite schema introspector. */
|
|
69
92
|
export const sqliteIntrospector: SchemaIntrospector = {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
93
|
+
async introspect(ctx: IntrospectContext, options: IntrospectOptions): Promise<DatabaseSchema> {
|
|
94
|
+
const alias = 'sqlite_master';
|
|
95
|
+
const tablesQuery: SelectQueryNode = {
|
|
96
|
+
type: 'SelectQuery',
|
|
97
|
+
from: { type: 'Table', name: 'sqlite_master' } as TableNode,
|
|
98
|
+
columns: [columnNode(alias, 'name')],
|
|
99
|
+
joins: [],
|
|
100
|
+
where: and(
|
|
101
|
+
eq(columnNode(alias, 'type'), 'table'),
|
|
102
|
+
notLike(columnNode(alias, 'name'), 'sqlite_%')
|
|
103
|
+
)
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const tableRows = (await runSelectNode<SqliteTableRow>(tablesQuery, ctx)) as SqliteTableRow[];
|
|
77
107
|
const tables: DatabaseTable[] = [];
|
|
78
|
-
const tableRows = (await queryRows(
|
|
79
|
-
ctx.executor,
|
|
80
|
-
`SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%';`
|
|
81
|
-
)) as SqliteTableRow[];
|
|
82
108
|
|
|
83
109
|
for (const row of tableRows) {
|
|
84
|
-
const
|
|
85
|
-
if (!shouldIncludeTable(
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
110
|
+
const tableName = row.name;
|
|
111
|
+
if (!shouldIncludeTable(tableName, options)) continue;
|
|
112
|
+
|
|
113
|
+
const tableInfo = await runPragma<SqliteTableInfoRow>(
|
|
114
|
+
'pragma_table_info',
|
|
115
|
+
tableName,
|
|
116
|
+
'ti',
|
|
117
|
+
['cid', 'name', 'type', 'notnull', 'dflt_value', 'pk'],
|
|
118
|
+
ctx
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const foreignKeys = await runPragma<SqliteForeignKeyRow>(
|
|
122
|
+
'pragma_foreign_key_list',
|
|
123
|
+
tableName,
|
|
124
|
+
'fk',
|
|
125
|
+
['id', 'seq', 'table', 'from', 'to', 'on_update', 'on_delete', 'match'],
|
|
126
|
+
ctx
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const indexList = await runPragma<SqliteIndexListRow>(
|
|
130
|
+
'pragma_index_list',
|
|
131
|
+
tableName,
|
|
132
|
+
'idx',
|
|
133
|
+
['seq', 'name', 'unique'],
|
|
134
|
+
ctx
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const tableEntry: DatabaseTable = { name: tableName, columns: [], primaryKey: [], indexes: [] };
|
|
138
|
+
|
|
139
|
+
tableInfo.forEach(info => {
|
|
140
|
+
tableEntry.columns.push({
|
|
141
|
+
name: info.name,
|
|
142
|
+
type: info.type,
|
|
143
|
+
notNull: info.notnull === 1,
|
|
144
|
+
default: info.dflt_value ?? undefined,
|
|
95
145
|
autoIncrement: false
|
|
96
146
|
});
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
147
|
+
if (info.pk && info.pk > 0) {
|
|
148
|
+
tableEntry.primaryKey = tableEntry.primaryKey || [];
|
|
149
|
+
tableEntry.primaryKey.push(info.name);
|
|
100
150
|
}
|
|
101
151
|
});
|
|
102
152
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
col.references = {
|
|
153
|
+
foreignKeys.forEach(fk => {
|
|
154
|
+
const column = tableEntry.columns.find(col => col.name === fk.from);
|
|
155
|
+
if (column) {
|
|
156
|
+
column.references = {
|
|
108
157
|
table: fk.table,
|
|
109
158
|
column: fk.to,
|
|
110
159
|
onDelete: toReferentialAction(fk.on_delete),
|
|
@@ -113,19 +162,24 @@ export const sqliteIntrospector: SchemaIntrospector = {
|
|
|
113
162
|
}
|
|
114
163
|
});
|
|
115
164
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
|
|
165
|
+
for (const idx of indexList) {
|
|
166
|
+
if (!idx.name) continue;
|
|
167
|
+
const indexColumns = await runPragma<SqliteIndexInfoRow>(
|
|
168
|
+
'pragma_index_info',
|
|
169
|
+
idx.name,
|
|
170
|
+
'info',
|
|
171
|
+
['seqno', 'cid', 'name'],
|
|
172
|
+
ctx
|
|
173
|
+
);
|
|
120
174
|
const idxEntry: DatabaseIndex = {
|
|
121
|
-
name:
|
|
122
|
-
columns:
|
|
175
|
+
name: idx.name,
|
|
176
|
+
columns: indexColumns.map(col => ({ column: col.name })),
|
|
123
177
|
unique: idx.unique === 1
|
|
124
178
|
};
|
|
125
|
-
|
|
179
|
+
tableEntry.indexes!.push(idxEntry);
|
|
126
180
|
}
|
|
127
181
|
|
|
128
|
-
tables.push(
|
|
182
|
+
tables.push(tableEntry);
|
|
129
183
|
}
|
|
130
184
|
|
|
131
185
|
return { tables };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TableDef, IndexDef } from '../../schema/table.js';
|
|
2
|
-
import type { ColumnDef, ForeignKeyReference } from '../../schema/column.js';
|
|
2
|
+
import type { ColumnDef, ForeignKeyReference } from '../../schema/column-types.js';
|
|
3
3
|
import type { DatabaseTable, DatabaseColumn, ColumnDiff } from './schema-types.js';
|
|
4
4
|
|
|
5
5
|
/** The name of a database dialect. */
|
|
@@ -53,3 +53,4 @@ export interface SchemaDialect {
|
|
|
53
53
|
/** Returns a warning message for altering a column. */
|
|
54
54
|
warnAlterColumn?(table: TableDef, column: ColumnDef, actualColumn: DatabaseColumn, diff: ColumnDiff): string | undefined;
|
|
55
55
|
}
|
|
56
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TableDef } from '../../schema/table.js';
|
|
2
|
-
import { ColumnDef } from '../../schema/column.js';
|
|
2
|
+
import { ColumnDef } from '../../schema/column-types.js';
|
|
3
3
|
import type { DbExecutor } from '../execution/db-executor.js';
|
|
4
4
|
import { SchemaDialect } from './schema-dialect.js';
|
|
5
5
|
import { deriveIndexName } from './naming-strategy.js';
|
|
@@ -231,3 +231,4 @@ export const synchronizeSchema = async (
|
|
|
231
231
|
}
|
|
232
232
|
return plan;
|
|
233
233
|
};
|
|
234
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TableDef } from '../../schema/table.js';
|
|
2
|
-
import type { ColumnDef } from '../../schema/column.js';
|
|
2
|
+
import type { ColumnDef } from '../../schema/column-types.js';
|
|
3
3
|
import type { SchemaDialect } from './schema-dialect.js';
|
|
4
4
|
import { resolvePrimaryKey } from './sql-writing.js';
|
|
5
5
|
import { DialectName } from './schema-dialect.js';
|
|
@@ -168,3 +168,4 @@ const orderTablesByDependencies = (tables: TableDef[]): TableDef[] => {
|
|
|
168
168
|
|
|
169
169
|
// Re-export DialectName for backward compatibility
|
|
170
170
|
export type { DialectName };
|
|
171
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ForeignKeyReference } from '../../schema/column.js';
|
|
1
|
+
import { ForeignKeyReference } from '../../schema/column-types.js';
|
|
2
2
|
import { IndexColumn } from '../../schema/table.js';
|
|
3
3
|
|
|
4
4
|
/** Represents the differences detected in a database column's properties. */
|
|
@@ -19,6 +19,7 @@ export interface DatabaseColumn {
|
|
|
19
19
|
generated?: 'always' | 'byDefault';
|
|
20
20
|
unique?: boolean | string;
|
|
21
21
|
references?: ForeignKeyReference;
|
|
22
|
+
comment?: string;
|
|
22
23
|
check?: string;
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -44,6 +45,7 @@ export interface DatabaseTable {
|
|
|
44
45
|
primaryKey?: string[];
|
|
45
46
|
indexes?: DatabaseIndex[];
|
|
46
47
|
checks?: DatabaseCheck[];
|
|
48
|
+
comment?: string;
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
/** Represents the overall database schema. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TableDef, IndexColumn } from '../../schema/table.js';
|
|
2
|
-
import type { ColumnDef, RawDefaultValue } from '../../schema/column.js';
|
|
2
|
+
import type { ColumnDef, RawDefaultValue } from '../../schema/column-types.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Minimal surface for anything that can quote identifiers.
|
|
@@ -168,3 +168,4 @@ export const resolvePrimaryKey = (table: TableDef): string[] => {
|
|
|
168
168
|
.filter(col => col.primary)
|
|
169
169
|
.map(col => col.name);
|
|
170
170
|
};
|
|
171
|
+
|
|
@@ -21,10 +21,11 @@ import {
|
|
|
21
21
|
JsonPathNode,
|
|
22
22
|
ScalarSubqueryNode,
|
|
23
23
|
CaseExpressionNode,
|
|
24
|
+
CastExpressionNode,
|
|
24
25
|
WindowFunctionNode,
|
|
25
26
|
BetweenExpressionNode,
|
|
26
|
-
AliasRefNode,
|
|
27
27
|
ArithmeticExpressionNode,
|
|
28
|
+
AliasRefNode,
|
|
28
29
|
isOperandNode
|
|
29
30
|
} from '../ast/expression.js';
|
|
30
31
|
import { DialectName } from '../sql/sql.js';
|
|
@@ -476,6 +477,11 @@ export abstract class Dialect
|
|
|
476
477
|
return parts.join(' ');
|
|
477
478
|
});
|
|
478
479
|
|
|
480
|
+
this.registerOperandCompiler('Cast', (node: CastExpressionNode, ctx) => {
|
|
481
|
+
const value = this.compileOperand(node.expression, ctx);
|
|
482
|
+
return `CAST(${value} AS ${node.castType})`;
|
|
483
|
+
});
|
|
484
|
+
|
|
479
485
|
this.registerOperandCompiler('WindowFunction', (node: WindowFunctionNode, ctx) => {
|
|
480
486
|
let result = `${node.name}(`;
|
|
481
487
|
if (node.args.length > 0) {
|
|
@@ -507,6 +513,11 @@ export abstract class Dialect
|
|
|
507
513
|
|
|
508
514
|
return result;
|
|
509
515
|
});
|
|
516
|
+
this.registerOperandCompiler('ArithmeticExpression', (node: ArithmeticExpressionNode, ctx) => {
|
|
517
|
+
const left = this.compileOperand(node.left, ctx);
|
|
518
|
+
const right = this.compileOperand(node.right, ctx);
|
|
519
|
+
return `(${left} ${node.operator} ${right})`;
|
|
520
|
+
});
|
|
510
521
|
}
|
|
511
522
|
|
|
512
523
|
// Default fallback, should be overridden by dialects if supported
|
|
@@ -105,16 +105,10 @@ export class SqlServerDialect extends SqlDialectBase {
|
|
|
105
105
|
|
|
106
106
|
private compileSelectCoreForMssql(ast: SelectQueryNode, ctx: CompilerContext): string {
|
|
107
107
|
const columns = ast.columns.map(c => {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
expr = `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`;
|
|
113
|
-
} else if (c.type === 'ScalarSubquery') {
|
|
114
|
-
expr = this.compileOperand(c, ctx);
|
|
115
|
-
} else if (c.type === 'WindowFunction') {
|
|
116
|
-
expr = this.compileOperand(c, ctx);
|
|
117
|
-
}
|
|
108
|
+
// Default to full operand compilation for all projection node types (Function, Column, Cast, Case, Window, etc)
|
|
109
|
+
const expr = c.type === 'Column'
|
|
110
|
+
? `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`
|
|
111
|
+
: this.compileOperand(c as unknown as import('../../ast/expression.js').OperandNode, ctx);
|
|
118
112
|
|
|
119
113
|
if (c.alias) {
|
|
120
114
|
if (c.alias.includes('(')) return c.alias;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Pure AST Builders - No Dialect Logic Here!
|
|
2
2
|
|
|
3
|
-
import { ColumnDef } from '../../schema/column.js';
|
|
3
|
+
import { ColumnDef } from '../../schema/column-types.js';
|
|
4
4
|
import { columnOperand, valueToOperand } from '../ast/expression-builders.js';
|
|
5
5
|
import { FunctionNode, OperandNode, isOperandNode } from '../ast/expression.js';
|
|
6
6
|
|
|
@@ -155,3 +155,4 @@ export const weekOfYear = (date: OperandInput): FunctionNode => fn('WEEK_OF_YEAR
|
|
|
155
155
|
* @returns A FunctionNode representing the DATE_TRUNC SQL function.
|
|
156
156
|
*/
|
|
157
157
|
export const dateTrunc = (part: OperandInput, date: OperandInput): FunctionNode => fn('DATE_TRUNC', [part, date]);
|
|
158
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Pure AST Builders - No Dialect Logic Here!
|
|
2
2
|
|
|
3
|
-
import { ColumnDef } from '../../schema/column.js';
|
|
3
|
+
import { ColumnDef } from '../../schema/column-types.js';
|
|
4
4
|
import { columnOperand, valueToOperand } from '../ast/expression-builders.js';
|
|
5
5
|
import { FunctionNode, OperandNode, isOperandNode } from '../ast/expression.js';
|
|
6
6
|
|
|
@@ -243,3 +243,4 @@ export const trunc = (value: OperandInput, decimals?: OperandInput): FunctionNod
|
|
|
243
243
|
*/
|
|
244
244
|
export const truncate = (value: OperandInput, decimals: OperandInput): FunctionNode =>
|
|
245
245
|
fn('TRUNCATE', [value, decimals]);
|
|
246
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Pure AST Builders - No Dialect Logic Here!
|
|
2
2
|
|
|
3
|
-
import { ColumnDef } from '../../schema/column.js';
|
|
3
|
+
import { ColumnDef } from '../../schema/column-types.js';
|
|
4
4
|
import { columnOperand, valueToOperand } from '../ast/expression-builders.js';
|
|
5
5
|
import { FunctionNode, OperandNode, isOperandNode } from '../ast/expression.js';
|
|
6
6
|
|
|
@@ -207,3 +207,4 @@ export const rpad = (value: OperandInput, len: OperandInput, pad: OperandInput):
|
|
|
207
207
|
* @returns A FunctionNode representing the SPACE SQL function.
|
|
208
208
|
*/
|
|
209
209
|
export const space = (count: OperandInput): FunctionNode => fn('SPACE', [count]);
|
|
210
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ColumnDef, ColumnType } from '../schema/column.js';
|
|
1
|
+
import { ColumnDef, ColumnType } from '../schema/column-types.js';
|
|
2
2
|
import {
|
|
3
3
|
addColumnMetadata,
|
|
4
4
|
EntityConstructor,
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
export interface ColumnOptions {
|
|
19
19
|
type: ColumnType;
|
|
20
20
|
args?: ColumnDef['args'];
|
|
21
|
+
dialectTypes?: ColumnDef['dialectTypes'];
|
|
21
22
|
notNull?: boolean;
|
|
22
23
|
primary?: boolean;
|
|
23
24
|
tsType?: ColumnDef['tsType'];
|
|
@@ -34,6 +35,7 @@ const normalizeColumnInput = (input: ColumnInput): ColumnDefLike => {
|
|
|
34
35
|
const column: ColumnDefLike = {
|
|
35
36
|
type: asOptions.type ?? asDefinition.type,
|
|
36
37
|
args: asOptions.args ?? asDefinition.args,
|
|
38
|
+
dialectTypes: asOptions.dialectTypes ?? asDefinition.dialectTypes,
|
|
37
39
|
notNull: asOptions.notNull ?? asDefinition.notNull,
|
|
38
40
|
primary: asOptions.primary ?? asDefinition.primary,
|
|
39
41
|
tsType: asDefinition.tsType ?? asOptions.tsType,
|
|
@@ -130,3 +132,4 @@ export function PrimaryKey(definition: ColumnInput) {
|
|
|
130
132
|
normalized.primary = true;
|
|
131
133
|
return Column(normalized);
|
|
132
134
|
}
|
|
135
|
+
|
package/src/decorators/index.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from './schema/table.js';
|
|
2
|
-
export * from './schema/column.js';
|
|
2
|
+
export * from './schema/column-types.js';
|
|
3
3
|
export * from './schema/relation.js';
|
|
4
4
|
export * from './schema/types.js';
|
|
5
5
|
export * from './query-builder/select.js';
|
|
@@ -52,3 +52,4 @@ export * from './core/execution/executors/mssql-executor.js';
|
|
|
52
52
|
|
|
53
53
|
// NEW: first-class pooling integration
|
|
54
54
|
export * from './orm/pooled-executor-factory.js';
|
|
55
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ColumnDef } from '../schema/column.js';
|
|
1
|
+
import { ColumnDef } from '../schema/column-types.js';
|
|
2
2
|
import { defineTable, TableDef, TableHooks } from '../schema/table.js';
|
|
3
3
|
import { CascadeMode, RelationKinds } from '../schema/relation.js';
|
|
4
4
|
|
|
@@ -262,3 +262,4 @@ export const buildTableDef = <TColumns extends Record<string, ColumnDefLike>>(me
|
|
|
262
262
|
meta.table = table;
|
|
263
263
|
return table;
|
|
264
264
|
};
|
|
265
|
+
|
package/src/orm/lazy-batch.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { SelectQueryBuilder } from '../query-builder/select.js';
|
|
|
4
4
|
import { inList, LiteralNode } from '../core/ast/expression.js';
|
|
5
5
|
import { EntityContext } from './entity-context.js';
|
|
6
6
|
import type { QueryResult } from '../core/execution/db-executor.js';
|
|
7
|
-
import { ColumnDef } from '../schema/column.js';
|
|
7
|
+
import { ColumnDef } from '../schema/column-types.js';
|
|
8
8
|
import { findPrimaryKey } from '../query-builder/hydration-planner.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -307,3 +307,4 @@ export const loadBelongsToManyRelation = async (
|
|
|
307
307
|
|
|
308
308
|
return result;
|
|
309
309
|
};
|
|
310
|
+
|
package/src/orm/orm-session.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { eq } from '../core/ast/expression.js';
|
|
|
3
3
|
import type { DbExecutor } from '../core/execution/db-executor.js';
|
|
4
4
|
import { SelectQueryBuilder } from '../query-builder/select.js';
|
|
5
5
|
import { findPrimaryKey } from '../query-builder/hydration-planner.js';
|
|
6
|
-
import type { ColumnDef } from '../schema/column.js';
|
|
6
|
+
import type { ColumnDef } from '../schema/column-types.js';
|
|
7
7
|
import type { TableDef } from '../schema/table.js';
|
|
8
8
|
import { EntityInstance } from '../schema/types.js';
|
|
9
9
|
import { RelationDef } from '../schema/relation.js';
|
|
@@ -464,3 +464,4 @@ const buildRelationChangeEntry = (
|
|
|
464
464
|
relation,
|
|
465
465
|
change
|
|
466
466
|
});
|
|
467
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ColumnDef } from '../schema/column.js';
|
|
1
|
+
import { ColumnDef } from '../schema/column-types.js';
|
|
2
2
|
import { CaseExpressionNode, ColumnNode, FunctionNode, WindowFunctionNode } from '../core/ast/expression.js';
|
|
3
3
|
import { SelectQueryNode } from '../core/ast/query.js';
|
|
4
4
|
import { buildColumnNode } from '../core/ast/builders.js';
|
|
@@ -78,3 +78,4 @@ export class ColumnSelector {
|
|
|
78
78
|
return { state: nextState, hydration: context.hydration };
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TableDef } from '../schema/table.js';
|
|
2
|
-
import { ColumnDef } from '../schema/column.js';
|
|
2
|
+
import { ColumnDef } from '../schema/column-types.js';
|
|
3
3
|
import { ColumnNode, ExpressionNode } from '../core/ast/expression.js';
|
|
4
4
|
import { JOIN_KINDS, JoinKind } from '../core/sql/sql.js';
|
|
5
5
|
import { CompiledQuery, Dialect } from '../core/dialect/abstract.js';
|
|
@@ -143,3 +143,4 @@ export class DeleteQueryBuilder<T> {
|
|
|
143
143
|
|
|
144
144
|
const isTableSourceNode = (source: TableDef | TableSourceNode): source is TableSourceNode =>
|
|
145
145
|
typeof (source as TableSourceNode).type === 'string';
|
|
146
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SelectQueryBuilder } from './select.js';
|
|
2
2
|
import { TableDef } from '../schema/table.js';
|
|
3
|
-
import { ColumnDef } from '../schema/column.js';
|
|
3
|
+
import { ColumnDef } from '../schema/column-types.js';
|
|
4
4
|
import { ColumnNode } from '../core/ast/expression.js';
|
|
5
5
|
import { CompiledQuery, InsertCompiler, Dialect } from '../core/dialect/abstract.js';
|
|
6
6
|
import { DialectKey, resolveDialectInput } from '../core/dialect/dialect-factory.js';
|
|
@@ -137,3 +137,4 @@ export class InsertQueryBuilder<T> {
|
|
|
137
137
|
return this.state.ast;
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TableDef } from '../schema/table.js';
|
|
2
|
-
import { ColumnDef } from '../schema/column.js';
|
|
2
|
+
import { ColumnDef } from '../schema/column-types.js';
|
|
3
3
|
import {
|
|
4
4
|
SelectQueryNode,
|
|
5
5
|
CommonTableExpressionNode,
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
ExpressionNode,
|
|
16
16
|
FunctionNode,
|
|
17
17
|
CaseExpressionNode,
|
|
18
|
+
CastExpressionNode,
|
|
18
19
|
WindowFunctionNode,
|
|
19
20
|
ScalarSubqueryNode,
|
|
20
21
|
and,
|
|
@@ -57,7 +58,7 @@ export class QueryAstService {
|
|
|
57
58
|
* @returns Column selection result with updated state and added columns
|
|
58
59
|
*/
|
|
59
60
|
select(
|
|
60
|
-
columns: Record<string, ColumnDef | FunctionNode | CaseExpressionNode | WindowFunctionNode>
|
|
61
|
+
columns: Record<string, ColumnDef | FunctionNode | CaseExpressionNode | CastExpressionNode | WindowFunctionNode>
|
|
61
62
|
): ColumnSelectionResult {
|
|
62
63
|
const existingAliases = new Set(
|
|
63
64
|
this.state.ast.columns.map(c => (c as ColumnNode).alias || (c as ColumnNode).name)
|
|
@@ -69,7 +70,7 @@ export class QueryAstService {
|
|
|
69
70
|
if (existingAliases.has(alias)) return acc;
|
|
70
71
|
|
|
71
72
|
if (isExpressionSelectionNode(val)) {
|
|
72
|
-
acc.push({ ...(val as FunctionNode | CaseExpressionNode | WindowFunctionNode), alias } as ProjectionNode);
|
|
73
|
+
acc.push({ ...(val as FunctionNode | CaseExpressionNode | CastExpressionNode | WindowFunctionNode), alias } as ProjectionNode);
|
|
73
74
|
return acc;
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TableDef } from '../schema/table.js';
|
|
2
|
-
import { ColumnDef } from '../schema/column.js';
|
|
2
|
+
import { ColumnDef } from '../schema/column-types.js';
|
|
3
3
|
import { SelectQueryState } from './select-query-state.js';
|
|
4
4
|
import { HydrationManager } from './hydration-manager.js';
|
|
5
5
|
import { ColumnNode } from '../core/ast/expression.js';
|
|
@@ -99,3 +99,4 @@ export class RelationProjectionHelper {
|
|
|
99
99
|
}, {} as Record<string, ColumnDef>);
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TableDef } from '../schema/table.js';
|
|
2
|
-
import { ColumnDef } from '../schema/column.js';
|
|
2
|
+
import { ColumnDef } from '../schema/column-types.js';
|
|
3
3
|
import { RelationDef, RelationKinds, BelongsToManyRelation } from '../schema/relation.js';
|
|
4
4
|
import { SelectQueryNode } from '../core/ast/query.js';
|
|
5
5
|
import {
|
|
@@ -301,3 +301,4 @@ export class RelationService {
|
|
|
301
301
|
}
|
|
302
302
|
|
|
303
303
|
export type { RelationResult } from './relation-projection-helper.js';
|
|
304
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ColumnDef } from '../../schema/column.js';
|
|
1
|
+
import { ColumnDef } from '../../schema/column-types.js';
|
|
2
2
|
import { ExpressionNode } from '../../core/ast/expression.js';
|
|
3
3
|
import { OrderingTerm } from '../../core/ast/query.js';
|
|
4
4
|
import { OrderDirection } from '../../core/sql/sql.js';
|
|
@@ -101,3 +101,4 @@ export class SelectPredicateFacet {
|
|
|
101
101
|
return { state: nextState, hydration: context.hydration };
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ColumnDef } from '../../schema/column.js';
|
|
1
|
+
import { ColumnDef } from '../../schema/column-types.js';
|
|
2
2
|
import { ColumnNode, FunctionNode, CaseExpressionNode, WindowFunctionNode } from '../../core/ast/expression.js';
|
|
3
3
|
import { SelectQueryBuilderContext } from '../select-query-builder-deps.js';
|
|
4
4
|
import { ColumnSelector } from '../column-selector.js';
|
|
@@ -67,3 +67,4 @@ export class SelectProjectionFacet {
|
|
|
67
67
|
return { ...context, state: this.columnSelector.distinct(context, cols).state };
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TableDef } from '../schema/table.js';
|
|
2
|
-
import type { ColumnDef } from '../schema/column.js';
|
|
2
|
+
import type { ColumnDef } from '../schema/column-types.js';
|
|
3
3
|
import { getTableDefFromEntity } from '../decorators/bootstrap.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -61,3 +61,4 @@ export function esel<TEntity extends object, K extends keyof TEntity & string>(
|
|
|
61
61
|
|
|
62
62
|
return selection;
|
|
63
63
|
}
|
|
64
|
+
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
FunctionNode,
|
|
15
15
|
ScalarSubqueryNode,
|
|
16
16
|
CaseExpressionNode,
|
|
17
|
+
CastExpressionNode,
|
|
17
18
|
WindowFunctionNode
|
|
18
19
|
} from '../core/ast/expression.js';
|
|
19
20
|
import { JoinNode } from '../core/ast/join.js';
|
|
@@ -26,6 +27,7 @@ export type ProjectionNode =
|
|
|
26
27
|
| FunctionNode
|
|
27
28
|
| ScalarSubqueryNode
|
|
28
29
|
| CaseExpressionNode
|
|
30
|
+
| CastExpressionNode
|
|
29
31
|
| WindowFunctionNode;
|
|
30
32
|
|
|
31
33
|
/**
|