metal-orm 1.0.14 → 1.0.15
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 +40 -45
- package/dist/decorators/index.cjs +1600 -27
- package/dist/decorators/index.cjs.map +1 -1
- package/dist/decorators/index.d.cts +6 -2
- package/dist/decorators/index.d.ts +6 -2
- package/dist/decorators/index.js +1599 -27
- package/dist/decorators/index.js.map +1 -1
- package/dist/index.cjs +4608 -3429
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +511 -159
- package/dist/index.d.ts +511 -159
- package/dist/index.js +4526 -3415
- package/dist/index.js.map +1 -1
- package/dist/{select-CCp1oz9p.d.cts → select-Bkv8g8u_.d.cts} +193 -67
- package/dist/{select-CCp1oz9p.d.ts → select-Bkv8g8u_.d.ts} +193 -67
- package/package.json +1 -1
- package/src/codegen/typescript.ts +38 -35
- package/src/core/ast/adapters.ts +21 -0
- package/src/core/ast/aggregate-functions.ts +13 -13
- package/src/core/ast/builders.ts +56 -43
- package/src/core/ast/expression-builders.ts +34 -34
- package/src/core/ast/expression-nodes.ts +18 -16
- package/src/core/ast/expression-visitor.ts +122 -69
- package/src/core/ast/expression.ts +6 -4
- package/src/core/ast/join-metadata.ts +15 -0
- package/src/core/ast/join-node.ts +22 -20
- package/src/core/ast/join.ts +5 -5
- package/src/core/ast/query.ts +52 -88
- package/src/core/ast/types.ts +20 -0
- package/src/core/ast/window-functions.ts +55 -55
- package/src/core/ddl/dialects/base-schema-dialect.ts +20 -6
- package/src/core/ddl/dialects/mssql-schema-dialect.ts +32 -8
- package/src/core/ddl/dialects/mysql-schema-dialect.ts +21 -10
- package/src/core/ddl/dialects/postgres-schema-dialect.ts +52 -7
- package/src/core/ddl/dialects/sqlite-schema-dialect.ts +23 -9
- package/src/core/ddl/introspect/catalogs/index.ts +1 -0
- package/src/core/ddl/introspect/catalogs/postgres.ts +143 -0
- package/src/core/ddl/introspect/context.ts +9 -0
- package/src/core/ddl/introspect/functions/postgres.ts +26 -0
- package/src/core/ddl/introspect/mssql.ts +149 -149
- package/src/core/ddl/introspect/mysql.ts +99 -99
- package/src/core/ddl/introspect/postgres.ts +245 -154
- package/src/core/ddl/introspect/registry.ts +26 -0
- package/src/core/ddl/introspect/run-select.ts +25 -0
- package/src/core/ddl/introspect/sqlite.ts +7 -7
- package/src/core/ddl/introspect/types.ts +23 -19
- package/src/core/ddl/introspect/utils.ts +1 -1
- package/src/core/ddl/naming-strategy.ts +10 -0
- package/src/core/ddl/schema-dialect.ts +41 -0
- package/src/core/ddl/schema-diff.ts +211 -179
- package/src/core/ddl/schema-generator.ts +16 -90
- package/src/core/ddl/schema-introspect.ts +25 -32
- package/src/core/ddl/schema-plan-executor.ts +17 -0
- package/src/core/ddl/schema-types.ts +46 -39
- package/src/core/ddl/sql-writing.ts +170 -0
- package/src/core/dialect/abstract.ts +144 -126
- package/src/core/dialect/base/cte-compiler.ts +33 -0
- package/src/core/dialect/base/function-table-formatter.ts +132 -0
- package/src/core/dialect/base/groupby-compiler.ts +21 -0
- package/src/core/dialect/base/join-compiler.ts +26 -0
- package/src/core/dialect/base/orderby-compiler.ts +21 -0
- package/src/core/dialect/base/pagination-strategy.ts +32 -0
- package/src/core/dialect/base/returning-strategy.ts +56 -0
- package/src/core/dialect/base/sql-dialect.ts +181 -204
- package/src/core/dialect/dialect-factory.ts +91 -0
- package/src/core/dialect/mssql/functions.ts +101 -0
- package/src/core/dialect/mssql/index.ts +128 -126
- package/src/core/dialect/mysql/functions.ts +101 -0
- package/src/core/dialect/mysql/index.ts +20 -18
- package/src/core/dialect/postgres/functions.ts +95 -0
- package/src/core/dialect/postgres/index.ts +30 -28
- package/src/core/dialect/sqlite/functions.ts +115 -0
- package/src/core/dialect/sqlite/index.ts +30 -28
- package/src/core/driver/database-driver.ts +11 -0
- package/src/core/driver/mssql-driver.ts +20 -0
- package/src/core/driver/mysql-driver.ts +20 -0
- package/src/core/driver/postgres-driver.ts +20 -0
- package/src/core/driver/sqlite-driver.ts +20 -0
- package/src/core/execution/db-executor.ts +63 -0
- package/src/core/execution/executors/mssql-executor.ts +39 -0
- package/src/core/execution/executors/mysql-executor.ts +47 -0
- package/src/core/execution/executors/postgres-executor.ts +32 -0
- package/src/core/execution/executors/sqlite-executor.ts +31 -0
- package/src/core/functions/datetime.ts +132 -0
- package/src/core/functions/numeric.ts +179 -0
- package/src/core/functions/standard-strategy.ts +47 -0
- package/src/core/functions/text.ts +147 -0
- package/src/core/functions/types.ts +18 -0
- package/src/core/hydration/types.ts +57 -0
- package/src/decorators/bootstrap.ts +10 -0
- package/src/decorators/relations.ts +15 -0
- package/src/index.ts +30 -19
- package/src/orm/entity-metadata.ts +7 -0
- package/src/orm/entity.ts +58 -27
- package/src/orm/hydration.ts +25 -17
- package/src/orm/lazy-batch.ts +46 -2
- package/src/orm/orm-context.ts +60 -60
- package/src/orm/query-logger.ts +1 -1
- package/src/orm/relation-change-processor.ts +43 -2
- package/src/orm/relations/has-one.ts +139 -0
- package/src/orm/transaction-runner.ts +1 -1
- package/src/orm/unit-of-work.ts +60 -60
- package/src/query-builder/delete.ts +22 -5
- package/src/query-builder/hydration-manager.ts +2 -1
- package/src/query-builder/hydration-planner.ts +8 -7
- package/src/query-builder/insert.ts +22 -5
- package/src/query-builder/relation-conditions.ts +9 -8
- package/src/query-builder/relation-service.ts +3 -2
- package/src/query-builder/select.ts +66 -61
- package/src/query-builder/update.ts +22 -5
- package/src/schema/column.ts +246 -246
- package/src/schema/relation.ts +35 -1
- package/src/schema/table.ts +28 -28
- package/src/schema/types.ts +41 -31
- package/src/orm/db-executor.ts +0 -11
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './postgres.js';
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { defineTable } from '../../../../schema/table.js';
|
|
2
|
+
import { col } from '../../../../schema/column.js';
|
|
3
|
+
|
|
4
|
+
export const PgInformationSchemaColumns = defineTable(
|
|
5
|
+
'columns',
|
|
6
|
+
{
|
|
7
|
+
table_schema: col.varchar(255),
|
|
8
|
+
table_name: col.varchar(255),
|
|
9
|
+
column_name: col.varchar(255),
|
|
10
|
+
data_type: col.varchar(255),
|
|
11
|
+
is_nullable: col.varchar(3),
|
|
12
|
+
column_default: col.varchar(1024),
|
|
13
|
+
ordinal_position: col.int()
|
|
14
|
+
},
|
|
15
|
+
{},
|
|
16
|
+
undefined,
|
|
17
|
+
{ schema: 'information_schema' }
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const PgClass = defineTable(
|
|
21
|
+
'pg_class',
|
|
22
|
+
{
|
|
23
|
+
oid: col.int(),
|
|
24
|
+
relname: col.varchar(255),
|
|
25
|
+
relnamespace: col.int(),
|
|
26
|
+
relkind: col.varchar(1)
|
|
27
|
+
},
|
|
28
|
+
{},
|
|
29
|
+
undefined,
|
|
30
|
+
{ schema: 'pg_catalog' }
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
export const PgNamespace = defineTable(
|
|
34
|
+
'pg_namespace',
|
|
35
|
+
{
|
|
36
|
+
oid: col.int(),
|
|
37
|
+
nspname: col.varchar(255)
|
|
38
|
+
},
|
|
39
|
+
{},
|
|
40
|
+
undefined,
|
|
41
|
+
{ schema: 'pg_catalog' }
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
export const PgIndex = defineTable(
|
|
45
|
+
'pg_index',
|
|
46
|
+
{
|
|
47
|
+
indrelid: col.int(),
|
|
48
|
+
indexrelid: col.int(),
|
|
49
|
+
indisprimary: col.boolean(),
|
|
50
|
+
indkey: col.varchar(255),
|
|
51
|
+
indpred: col.varchar(1024)
|
|
52
|
+
},
|
|
53
|
+
{},
|
|
54
|
+
undefined,
|
|
55
|
+
{ schema: 'pg_catalog' }
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
export const PgAttribute = defineTable(
|
|
59
|
+
'pg_attribute',
|
|
60
|
+
{
|
|
61
|
+
attrelid: col.int(),
|
|
62
|
+
attname: col.varchar(255),
|
|
63
|
+
attnum: col.int()
|
|
64
|
+
},
|
|
65
|
+
{},
|
|
66
|
+
undefined,
|
|
67
|
+
{ schema: 'pg_catalog' }
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
export const PgTableConstraints = defineTable(
|
|
71
|
+
'table_constraints',
|
|
72
|
+
{
|
|
73
|
+
constraint_catalog: col.varchar(255),
|
|
74
|
+
constraint_schema: col.varchar(255),
|
|
75
|
+
constraint_name: col.varchar(255),
|
|
76
|
+
table_catalog: col.varchar(255),
|
|
77
|
+
table_schema: col.varchar(255),
|
|
78
|
+
table_name: col.varchar(255),
|
|
79
|
+
constraint_type: col.varchar(255)
|
|
80
|
+
},
|
|
81
|
+
{},
|
|
82
|
+
undefined,
|
|
83
|
+
{ schema: 'information_schema' }
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
export const PgKeyColumnUsage = defineTable(
|
|
87
|
+
'key_column_usage',
|
|
88
|
+
{
|
|
89
|
+
constraint_catalog: col.varchar(255),
|
|
90
|
+
constraint_schema: col.varchar(255),
|
|
91
|
+
constraint_name: col.varchar(255),
|
|
92
|
+
table_catalog: col.varchar(255),
|
|
93
|
+
table_schema: col.varchar(255),
|
|
94
|
+
table_name: col.varchar(255),
|
|
95
|
+
column_name: col.varchar(255),
|
|
96
|
+
ordinal_position: col.int()
|
|
97
|
+
},
|
|
98
|
+
{},
|
|
99
|
+
undefined,
|
|
100
|
+
{ schema: 'information_schema' }
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
export const PgConstraintColumnUsage = defineTable(
|
|
104
|
+
'constraint_column_usage',
|
|
105
|
+
{
|
|
106
|
+
constraint_catalog: col.varchar(255),
|
|
107
|
+
constraint_schema: col.varchar(255),
|
|
108
|
+
constraint_name: col.varchar(255),
|
|
109
|
+
table_catalog: col.varchar(255),
|
|
110
|
+
table_schema: col.varchar(255),
|
|
111
|
+
table_name: col.varchar(255),
|
|
112
|
+
column_name: col.varchar(255)
|
|
113
|
+
},
|
|
114
|
+
{},
|
|
115
|
+
undefined,
|
|
116
|
+
{ schema: 'information_schema' }
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
export const PgReferentialConstraints = defineTable(
|
|
120
|
+
'referential_constraints',
|
|
121
|
+
{
|
|
122
|
+
constraint_catalog: col.varchar(255),
|
|
123
|
+
constraint_schema: col.varchar(255),
|
|
124
|
+
constraint_name: col.varchar(255),
|
|
125
|
+
unique_constraint_catalog: col.varchar(255),
|
|
126
|
+
unique_constraint_schema: col.varchar(255),
|
|
127
|
+
unique_constraint_name: col.varchar(255),
|
|
128
|
+
match_option: col.varchar(64),
|
|
129
|
+
update_rule: col.varchar(64),
|
|
130
|
+
delete_rule: col.varchar(64)
|
|
131
|
+
},
|
|
132
|
+
{},
|
|
133
|
+
undefined,
|
|
134
|
+
{ schema: 'information_schema' }
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
export default {
|
|
138
|
+
PgInformationSchemaColumns,
|
|
139
|
+
PgClass,
|
|
140
|
+
PgNamespace,
|
|
141
|
+
PgIndex,
|
|
142
|
+
PgAttribute
|
|
143
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Small helpers to build Postgres-specific function calls as AST FunctionNodes
|
|
2
|
+
import { columnOperand, valueToOperand } from '../../../ast/expression-builders.js';
|
|
3
|
+
import type { OperandNode, FunctionNode } from '../../../ast/expression.js';
|
|
4
|
+
|
|
5
|
+
type OperandInput = OperandNode | string | number | boolean | null;
|
|
6
|
+
|
|
7
|
+
const toOperand = (v: OperandInput) => {
|
|
8
|
+
if (v === null) return valueToOperand(null);
|
|
9
|
+
if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') return valueToOperand(v);
|
|
10
|
+
return v as OperandNode;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const fn = (name: string, args: OperandInput[]): FunctionNode => ({
|
|
14
|
+
type: 'Function',
|
|
15
|
+
name,
|
|
16
|
+
fn: name,
|
|
17
|
+
args: args.map(toOperand)
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const pgGetExpr = (expr: OperandInput, relid: OperandInput): FunctionNode =>
|
|
21
|
+
fn('pg_get_expr', [expr, relid]);
|
|
22
|
+
|
|
23
|
+
export const formatType = (typeOid: OperandInput, typmod: OperandInput): FunctionNode =>
|
|
24
|
+
fn('format_type', [typeOid, typmod]);
|
|
25
|
+
|
|
26
|
+
export default { pgGetExpr, formatType };
|
|
@@ -1,149 +1,149 @@
|
|
|
1
|
-
import { SchemaIntrospector, IntrospectOptions } from './types.js';
|
|
2
|
-
import { queryRows, shouldIncludeTable } from './utils.js';
|
|
3
|
-
import { DatabaseSchema, DatabaseTable, DatabaseIndex, DatabaseColumn } from '../schema-types.js';
|
|
4
|
-
import { DbExecutor } from '../../
|
|
5
|
-
|
|
6
|
-
export const mssqlIntrospector: SchemaIntrospector = {
|
|
7
|
-
async introspect(executor: DbExecutor, options: IntrospectOptions): Promise<DatabaseSchema> {
|
|
8
|
-
const schema = options.schema;
|
|
9
|
-
const filterSchema = schema ? 'sch.name = @p1' : '1=1';
|
|
10
|
-
const params = schema ? [schema] : [];
|
|
11
|
-
|
|
12
|
-
const columnRows = await queryRows(
|
|
13
|
-
executor,
|
|
14
|
-
`
|
|
15
|
-
SELECT
|
|
16
|
-
sch.name AS table_schema,
|
|
17
|
-
t.name AS table_name,
|
|
18
|
-
c.name AS column_name,
|
|
19
|
-
ty.name AS data_type,
|
|
20
|
-
c.is_nullable,
|
|
21
|
-
c.is_identity,
|
|
22
|
-
object_definition(c.default_object_id) AS column_default
|
|
23
|
-
FROM sys.columns c
|
|
24
|
-
JOIN sys.tables t ON t.object_id = c.object_id
|
|
25
|
-
JOIN sys.schemas sch ON sch.schema_id = t.schema_id
|
|
26
|
-
JOIN sys.types ty ON ty.user_type_id = c.user_type_id
|
|
27
|
-
WHERE t.is_ms_shipped = 0 AND ${filterSchema}
|
|
28
|
-
`,
|
|
29
|
-
params
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
const pkRows = await queryRows(
|
|
33
|
-
executor,
|
|
34
|
-
`
|
|
35
|
-
SELECT
|
|
36
|
-
sch.name AS table_schema,
|
|
37
|
-
t.name AS table_name,
|
|
38
|
-
c.name AS column_name,
|
|
39
|
-
ic.key_ordinal
|
|
40
|
-
FROM sys.indexes i
|
|
41
|
-
JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
|
|
42
|
-
JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
|
|
43
|
-
JOIN sys.tables t ON t.object_id = i.object_id
|
|
44
|
-
JOIN sys.schemas sch ON sch.schema_id = t.schema_id
|
|
45
|
-
WHERE i.is_primary_key = 1 AND ${filterSchema}
|
|
46
|
-
ORDER BY ic.key_ordinal
|
|
47
|
-
`,
|
|
48
|
-
params
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
const pkMap = new Map<string, string[]>();
|
|
52
|
-
pkRows.forEach(r => {
|
|
53
|
-
const key = `${r.table_schema}.${r.table_name}`;
|
|
54
|
-
const list = pkMap.get(key) || [];
|
|
55
|
-
list.push(r.column_name);
|
|
56
|
-
pkMap.set(key, list);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
const indexRows = await queryRows(
|
|
60
|
-
executor,
|
|
61
|
-
`
|
|
62
|
-
SELECT
|
|
63
|
-
sch.name AS table_schema,
|
|
64
|
-
t.name AS table_name,
|
|
65
|
-
i.name AS index_name,
|
|
66
|
-
i.is_unique,
|
|
67
|
-
i.has_filter,
|
|
68
|
-
i.filter_definition
|
|
69
|
-
FROM sys.indexes i
|
|
70
|
-
JOIN sys.tables t ON t.object_id = i.object_id
|
|
71
|
-
JOIN sys.schemas sch ON sch.schema_id = t.schema_id
|
|
72
|
-
WHERE i.is_primary_key = 0 AND i.is_hypothetical = 0 AND ${filterSchema}
|
|
73
|
-
`,
|
|
74
|
-
params
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
const indexColsRows = await queryRows(
|
|
78
|
-
executor,
|
|
79
|
-
`
|
|
80
|
-
SELECT
|
|
81
|
-
sch.name AS table_schema,
|
|
82
|
-
t.name AS table_name,
|
|
83
|
-
i.name AS index_name,
|
|
84
|
-
c.name AS column_name,
|
|
85
|
-
ic.key_ordinal
|
|
86
|
-
FROM sys.index_columns ic
|
|
87
|
-
JOIN sys.indexes i ON i.object_id = ic.object_id AND i.index_id = ic.index_id
|
|
88
|
-
JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
|
|
89
|
-
JOIN sys.tables t ON t.object_id = i.object_id
|
|
90
|
-
JOIN sys.schemas sch ON sch.schema_id = t.schema_id
|
|
91
|
-
WHERE i.is_primary_key = 0 AND ${filterSchema}
|
|
92
|
-
ORDER BY ic.key_ordinal
|
|
93
|
-
`,
|
|
94
|
-
params
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
const indexColumnsMap = new Map<string, { column: string; order: number }[]>();
|
|
98
|
-
indexColsRows.forEach(r => {
|
|
99
|
-
const key = `${r.table_schema}.${r.table_name}.${r.index_name}`;
|
|
100
|
-
const list = indexColumnsMap.get(key) || [];
|
|
101
|
-
list.push({ column: r.column_name, order: r.key_ordinal });
|
|
102
|
-
indexColumnsMap.set(key, list);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
const tablesByKey = new Map<string, DatabaseTable>();
|
|
106
|
-
|
|
107
|
-
columnRows.forEach(r => {
|
|
108
|
-
if (!shouldIncludeTable(r.table_name, options)) return;
|
|
109
|
-
const key = `${r.table_schema}.${r.table_name}`;
|
|
110
|
-
if (!tablesByKey.has(key)) {
|
|
111
|
-
tablesByKey.set(key, {
|
|
112
|
-
name: r.table_name,
|
|
113
|
-
schema: r.table_schema,
|
|
114
|
-
columns: [],
|
|
115
|
-
primaryKey: pkMap.get(key) || [],
|
|
116
|
-
indexes: []
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
const t = tablesByKey.get(key)!;
|
|
120
|
-
const column: DatabaseColumn = {
|
|
121
|
-
name: r.column_name,
|
|
122
|
-
type: r.data_type,
|
|
123
|
-
notNull: r.is_nullable === false || r.is_nullable === 0,
|
|
124
|
-
default: r.column_default ?? undefined,
|
|
125
|
-
autoIncrement: !!r.is_identity
|
|
126
|
-
};
|
|
127
|
-
t.columns.push(column);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
indexRows.forEach(r => {
|
|
131
|
-
const key = `${r.table_schema}.${r.table_name}`;
|
|
132
|
-
const table = tablesByKey.get(key);
|
|
133
|
-
if (!table) return;
|
|
134
|
-
const cols = (indexColumnsMap.get(`${r.table_schema}.${r.table_name}.${r.index_name}`) || [])
|
|
135
|
-
.sort((a, b) => a.order - b.order)
|
|
136
|
-
.map(c => ({ column: c.column }));
|
|
137
|
-
const idx: DatabaseIndex = {
|
|
138
|
-
name: r.index_name,
|
|
139
|
-
columns: cols,
|
|
140
|
-
unique: !!r.is_unique,
|
|
141
|
-
where: r.has_filter ? r.filter_definition : undefined
|
|
142
|
-
};
|
|
143
|
-
table.indexes = table.indexes || [];
|
|
144
|
-
table.indexes.push(idx);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
return { tables: Array.from(tablesByKey.values()) };
|
|
148
|
-
}
|
|
149
|
-
};
|
|
1
|
+
import { SchemaIntrospector, IntrospectOptions } from './types.js';
|
|
2
|
+
import { queryRows, shouldIncludeTable } from './utils.js';
|
|
3
|
+
import { DatabaseSchema, DatabaseTable, DatabaseIndex, DatabaseColumn } from '../schema-types.js';
|
|
4
|
+
import { DbExecutor } from '../../execution/db-executor.js';
|
|
5
|
+
|
|
6
|
+
export const mssqlIntrospector: SchemaIntrospector = {
|
|
7
|
+
async introspect(ctx: { executor: DbExecutor }, options: IntrospectOptions): Promise<DatabaseSchema> {
|
|
8
|
+
const schema = options.schema;
|
|
9
|
+
const filterSchema = schema ? 'sch.name = @p1' : '1=1';
|
|
10
|
+
const params = schema ? [schema] : [];
|
|
11
|
+
|
|
12
|
+
const columnRows = await queryRows(
|
|
13
|
+
ctx.executor,
|
|
14
|
+
`
|
|
15
|
+
SELECT
|
|
16
|
+
sch.name AS table_schema,
|
|
17
|
+
t.name AS table_name,
|
|
18
|
+
c.name AS column_name,
|
|
19
|
+
ty.name AS data_type,
|
|
20
|
+
c.is_nullable,
|
|
21
|
+
c.is_identity,
|
|
22
|
+
object_definition(c.default_object_id) AS column_default
|
|
23
|
+
FROM sys.columns c
|
|
24
|
+
JOIN sys.tables t ON t.object_id = c.object_id
|
|
25
|
+
JOIN sys.schemas sch ON sch.schema_id = t.schema_id
|
|
26
|
+
JOIN sys.types ty ON ty.user_type_id = c.user_type_id
|
|
27
|
+
WHERE t.is_ms_shipped = 0 AND ${filterSchema}
|
|
28
|
+
`,
|
|
29
|
+
params
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const pkRows = await queryRows(
|
|
33
|
+
ctx.executor,
|
|
34
|
+
`
|
|
35
|
+
SELECT
|
|
36
|
+
sch.name AS table_schema,
|
|
37
|
+
t.name AS table_name,
|
|
38
|
+
c.name AS column_name,
|
|
39
|
+
ic.key_ordinal
|
|
40
|
+
FROM sys.indexes i
|
|
41
|
+
JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
|
|
42
|
+
JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
|
|
43
|
+
JOIN sys.tables t ON t.object_id = i.object_id
|
|
44
|
+
JOIN sys.schemas sch ON sch.schema_id = t.schema_id
|
|
45
|
+
WHERE i.is_primary_key = 1 AND ${filterSchema}
|
|
46
|
+
ORDER BY ic.key_ordinal
|
|
47
|
+
`,
|
|
48
|
+
params
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const pkMap = new Map<string, string[]>();
|
|
52
|
+
pkRows.forEach(r => {
|
|
53
|
+
const key = `${r.table_schema}.${r.table_name}`;
|
|
54
|
+
const list = pkMap.get(key) || [];
|
|
55
|
+
list.push(r.column_name);
|
|
56
|
+
pkMap.set(key, list);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const indexRows = await queryRows(
|
|
60
|
+
ctx.executor,
|
|
61
|
+
`
|
|
62
|
+
SELECT
|
|
63
|
+
sch.name AS table_schema,
|
|
64
|
+
t.name AS table_name,
|
|
65
|
+
i.name AS index_name,
|
|
66
|
+
i.is_unique,
|
|
67
|
+
i.has_filter,
|
|
68
|
+
i.filter_definition
|
|
69
|
+
FROM sys.indexes i
|
|
70
|
+
JOIN sys.tables t ON t.object_id = i.object_id
|
|
71
|
+
JOIN sys.schemas sch ON sch.schema_id = t.schema_id
|
|
72
|
+
WHERE i.is_primary_key = 0 AND i.is_hypothetical = 0 AND ${filterSchema}
|
|
73
|
+
`,
|
|
74
|
+
params
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const indexColsRows = await queryRows(
|
|
78
|
+
ctx.executor,
|
|
79
|
+
`
|
|
80
|
+
SELECT
|
|
81
|
+
sch.name AS table_schema,
|
|
82
|
+
t.name AS table_name,
|
|
83
|
+
i.name AS index_name,
|
|
84
|
+
c.name AS column_name,
|
|
85
|
+
ic.key_ordinal
|
|
86
|
+
FROM sys.index_columns ic
|
|
87
|
+
JOIN sys.indexes i ON i.object_id = ic.object_id AND i.index_id = ic.index_id
|
|
88
|
+
JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
|
|
89
|
+
JOIN sys.tables t ON t.object_id = i.object_id
|
|
90
|
+
JOIN sys.schemas sch ON sch.schema_id = t.schema_id
|
|
91
|
+
WHERE i.is_primary_key = 0 AND ${filterSchema}
|
|
92
|
+
ORDER BY ic.key_ordinal
|
|
93
|
+
`,
|
|
94
|
+
params
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const indexColumnsMap = new Map<string, { column: string; order: number }[]>();
|
|
98
|
+
indexColsRows.forEach(r => {
|
|
99
|
+
const key = `${r.table_schema}.${r.table_name}.${r.index_name}`;
|
|
100
|
+
const list = indexColumnsMap.get(key) || [];
|
|
101
|
+
list.push({ column: r.column_name, order: r.key_ordinal });
|
|
102
|
+
indexColumnsMap.set(key, list);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const tablesByKey = new Map<string, DatabaseTable>();
|
|
106
|
+
|
|
107
|
+
columnRows.forEach(r => {
|
|
108
|
+
if (!shouldIncludeTable(r.table_name, options)) return;
|
|
109
|
+
const key = `${r.table_schema}.${r.table_name}`;
|
|
110
|
+
if (!tablesByKey.has(key)) {
|
|
111
|
+
tablesByKey.set(key, {
|
|
112
|
+
name: r.table_name,
|
|
113
|
+
schema: r.table_schema,
|
|
114
|
+
columns: [],
|
|
115
|
+
primaryKey: pkMap.get(key) || [],
|
|
116
|
+
indexes: []
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const t = tablesByKey.get(key)!;
|
|
120
|
+
const column: DatabaseColumn = {
|
|
121
|
+
name: r.column_name,
|
|
122
|
+
type: r.data_type,
|
|
123
|
+
notNull: r.is_nullable === false || r.is_nullable === 0,
|
|
124
|
+
default: r.column_default ?? undefined,
|
|
125
|
+
autoIncrement: !!r.is_identity
|
|
126
|
+
};
|
|
127
|
+
t.columns.push(column);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
indexRows.forEach(r => {
|
|
131
|
+
const key = `${r.table_schema}.${r.table_name}`;
|
|
132
|
+
const table = tablesByKey.get(key);
|
|
133
|
+
if (!table) return;
|
|
134
|
+
const cols = (indexColumnsMap.get(`${r.table_schema}.${r.table_name}.${r.index_name}`) || [])
|
|
135
|
+
.sort((a, b) => a.order - b.order)
|
|
136
|
+
.map(c => ({ column: c.column }));
|
|
137
|
+
const idx: DatabaseIndex = {
|
|
138
|
+
name: r.index_name,
|
|
139
|
+
columns: cols,
|
|
140
|
+
unique: !!r.is_unique,
|
|
141
|
+
where: r.has_filter ? r.filter_definition : undefined
|
|
142
|
+
};
|
|
143
|
+
table.indexes = table.indexes || [];
|
|
144
|
+
table.indexes.push(idx);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return { tables: Array.from(tablesByKey.values()) };
|
|
148
|
+
}
|
|
149
|
+
};
|
|
@@ -1,99 +1,99 @@
|
|
|
1
|
-
import { SchemaIntrospector, IntrospectOptions } from './types.js';
|
|
2
|
-
import { queryRows, shouldIncludeTable } from './utils.js';
|
|
3
|
-
import { DatabaseSchema, DatabaseTable, DatabaseIndex, DatabaseColumn } from '../schema-types.js';
|
|
4
|
-
import { DbExecutor } from '../../
|
|
5
|
-
|
|
6
|
-
export const mysqlIntrospector: SchemaIntrospector = {
|
|
7
|
-
async introspect(executor: DbExecutor, options: IntrospectOptions): Promise<DatabaseSchema> {
|
|
8
|
-
const schema = options.schema;
|
|
9
|
-
const filterClause = schema ? 'table_schema = ?' : 'table_schema = database()';
|
|
10
|
-
const params = schema ? [schema] : [];
|
|
11
|
-
|
|
12
|
-
const columnRows = await queryRows(
|
|
13
|
-
executor,
|
|
14
|
-
`
|
|
15
|
-
SELECT table_schema, table_name, column_name, data_type, is_nullable, column_default, extra
|
|
16
|
-
FROM information_schema.columns
|
|
17
|
-
WHERE ${filterClause}
|
|
18
|
-
ORDER BY table_name, ordinal_position
|
|
19
|
-
`,
|
|
20
|
-
params
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
const pkRows = await queryRows(
|
|
24
|
-
executor,
|
|
25
|
-
`
|
|
26
|
-
SELECT table_schema, table_name, column_name
|
|
27
|
-
FROM information_schema.key_column_usage
|
|
28
|
-
WHERE constraint_name = 'PRIMARY' AND ${filterClause}
|
|
29
|
-
ORDER BY ordinal_position
|
|
30
|
-
`,
|
|
31
|
-
params
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
const pkMap = new Map<string, string[]>();
|
|
35
|
-
pkRows.forEach(r => {
|
|
36
|
-
const key = `${r.table_schema}.${r.table_name}`;
|
|
37
|
-
const list = pkMap.get(key) || [];
|
|
38
|
-
list.push(r.column_name);
|
|
39
|
-
pkMap.set(key, list);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const indexRows = await queryRows(
|
|
43
|
-
executor,
|
|
44
|
-
`
|
|
45
|
-
SELECT
|
|
46
|
-
table_schema,
|
|
47
|
-
table_name,
|
|
48
|
-
index_name,
|
|
49
|
-
non_unique,
|
|
50
|
-
GROUP_CONCAT(column_name ORDER BY seq_in_index) AS cols
|
|
51
|
-
FROM information_schema.statistics
|
|
52
|
-
WHERE ${filterClause} AND index_name <> 'PRIMARY'
|
|
53
|
-
GROUP BY table_schema, table_name, index_name, non_unique
|
|
54
|
-
`,
|
|
55
|
-
params
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
const tablesByKey = new Map<string, DatabaseTable>();
|
|
59
|
-
|
|
60
|
-
columnRows.forEach(r => {
|
|
61
|
-
const key = `${r.table_schema}.${r.table_name}`;
|
|
62
|
-
if (!shouldIncludeTable(r.table_name, options)) return;
|
|
63
|
-
if (!tablesByKey.has(key)) {
|
|
64
|
-
tablesByKey.set(key, {
|
|
65
|
-
name: r.table_name,
|
|
66
|
-
schema: r.table_schema,
|
|
67
|
-
columns: [],
|
|
68
|
-
primaryKey: pkMap.get(key) || [],
|
|
69
|
-
indexes: []
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
const cols = tablesByKey.get(key)!;
|
|
73
|
-
const column: DatabaseColumn = {
|
|
74
|
-
name: r.column_name,
|
|
75
|
-
type: r.data_type,
|
|
76
|
-
notNull: r.is_nullable === 'NO',
|
|
77
|
-
default: r.column_default ?? undefined,
|
|
78
|
-
autoIncrement: typeof r.extra === 'string' && r.extra.includes('auto_increment')
|
|
79
|
-
};
|
|
80
|
-
cols.columns.push(column);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
indexRows.forEach(r => {
|
|
84
|
-
const key = `${r.table_schema}.${r.table_name}`;
|
|
85
|
-
const table = tablesByKey.get(key);
|
|
86
|
-
if (!table) return;
|
|
87
|
-
const cols = (typeof r.cols === 'string' ? r.cols.split(',') : []).map((c: string) => ({ column: c.trim() }));
|
|
88
|
-
const idx: DatabaseIndex = {
|
|
89
|
-
name: r.index_name,
|
|
90
|
-
columns: cols,
|
|
91
|
-
unique: r.non_unique === 0
|
|
92
|
-
};
|
|
93
|
-
table.indexes = table.indexes || [];
|
|
94
|
-
table.indexes.push(idx);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
return { tables: Array.from(tablesByKey.values()) };
|
|
98
|
-
}
|
|
99
|
-
};
|
|
1
|
+
import { SchemaIntrospector, IntrospectOptions } from './types.js';
|
|
2
|
+
import { queryRows, shouldIncludeTable } from './utils.js';
|
|
3
|
+
import { DatabaseSchema, DatabaseTable, DatabaseIndex, DatabaseColumn } from '../schema-types.js';
|
|
4
|
+
import { DbExecutor } from '../../execution/db-executor.js';
|
|
5
|
+
|
|
6
|
+
export const mysqlIntrospector: SchemaIntrospector = {
|
|
7
|
+
async introspect(ctx: { executor: DbExecutor }, options: IntrospectOptions): Promise<DatabaseSchema> {
|
|
8
|
+
const schema = options.schema;
|
|
9
|
+
const filterClause = schema ? 'table_schema = ?' : 'table_schema = database()';
|
|
10
|
+
const params = schema ? [schema] : [];
|
|
11
|
+
|
|
12
|
+
const columnRows = await queryRows(
|
|
13
|
+
ctx.executor,
|
|
14
|
+
`
|
|
15
|
+
SELECT table_schema, table_name, column_name, data_type, is_nullable, column_default, extra
|
|
16
|
+
FROM information_schema.columns
|
|
17
|
+
WHERE ${filterClause}
|
|
18
|
+
ORDER BY table_name, ordinal_position
|
|
19
|
+
`,
|
|
20
|
+
params
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const pkRows = await queryRows(
|
|
24
|
+
ctx.executor,
|
|
25
|
+
`
|
|
26
|
+
SELECT table_schema, table_name, column_name
|
|
27
|
+
FROM information_schema.key_column_usage
|
|
28
|
+
WHERE constraint_name = 'PRIMARY' AND ${filterClause}
|
|
29
|
+
ORDER BY ordinal_position
|
|
30
|
+
`,
|
|
31
|
+
params
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const pkMap = new Map<string, string[]>();
|
|
35
|
+
pkRows.forEach(r => {
|
|
36
|
+
const key = `${r.table_schema}.${r.table_name}`;
|
|
37
|
+
const list = pkMap.get(key) || [];
|
|
38
|
+
list.push(r.column_name);
|
|
39
|
+
pkMap.set(key, list);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const indexRows = await queryRows(
|
|
43
|
+
ctx.executor,
|
|
44
|
+
`
|
|
45
|
+
SELECT
|
|
46
|
+
table_schema,
|
|
47
|
+
table_name,
|
|
48
|
+
index_name,
|
|
49
|
+
non_unique,
|
|
50
|
+
GROUP_CONCAT(column_name ORDER BY seq_in_index) AS cols
|
|
51
|
+
FROM information_schema.statistics
|
|
52
|
+
WHERE ${filterClause} AND index_name <> 'PRIMARY'
|
|
53
|
+
GROUP BY table_schema, table_name, index_name, non_unique
|
|
54
|
+
`,
|
|
55
|
+
params
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const tablesByKey = new Map<string, DatabaseTable>();
|
|
59
|
+
|
|
60
|
+
columnRows.forEach(r => {
|
|
61
|
+
const key = `${r.table_schema}.${r.table_name}`;
|
|
62
|
+
if (!shouldIncludeTable(r.table_name, options)) return;
|
|
63
|
+
if (!tablesByKey.has(key)) {
|
|
64
|
+
tablesByKey.set(key, {
|
|
65
|
+
name: r.table_name,
|
|
66
|
+
schema: r.table_schema,
|
|
67
|
+
columns: [],
|
|
68
|
+
primaryKey: pkMap.get(key) || [],
|
|
69
|
+
indexes: []
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const cols = tablesByKey.get(key)!;
|
|
73
|
+
const column: DatabaseColumn = {
|
|
74
|
+
name: r.column_name,
|
|
75
|
+
type: r.data_type,
|
|
76
|
+
notNull: r.is_nullable === 'NO',
|
|
77
|
+
default: r.column_default ?? undefined,
|
|
78
|
+
autoIncrement: typeof r.extra === 'string' && r.extra.includes('auto_increment')
|
|
79
|
+
};
|
|
80
|
+
cols.columns.push(column);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
indexRows.forEach(r => {
|
|
84
|
+
const key = `${r.table_schema}.${r.table_name}`;
|
|
85
|
+
const table = tablesByKey.get(key);
|
|
86
|
+
if (!table) return;
|
|
87
|
+
const cols = (typeof r.cols === 'string' ? r.cols.split(',') : []).map((c: string) => ({ column: c.trim() }));
|
|
88
|
+
const idx: DatabaseIndex = {
|
|
89
|
+
name: r.index_name,
|
|
90
|
+
columns: cols,
|
|
91
|
+
unique: r.non_unique === 0
|
|
92
|
+
};
|
|
93
|
+
table.indexes = table.indexes || [];
|
|
94
|
+
table.indexes.push(idx);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
return { tables: Array.from(tablesByKey.values()) };
|
|
98
|
+
}
|
|
99
|
+
};
|