uql-orm 0.65.1 → 0.67.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/querier/httpQuerier.js +1 -8
- package/dist/browser/uql-browser.min.js.map +5 -5
- package/dist/bunSql/bunSql.util.d.ts +2 -6
- package/dist/bunSql/bunSql.util.js +2 -6
- package/dist/bunSql/bunSqlQuerier.d.ts +2 -5
- package/dist/bunSql/bunSqlQuerier.js +2 -5
- package/dist/cockroachdb/cockroachDialect.d.ts +4 -13
- package/dist/cockroachdb/cockroachDialect.js +4 -13
- package/dist/context/context.browser.js +2 -10
- package/dist/context/context.d.ts +4 -17
- package/dist/context/context.js +4 -17
- package/dist/dialect/abstractDialect.d.ts +4 -19
- package/dist/dialect/abstractDialect.js +2 -20
- package/dist/dialect/abstractSqlDialect.d.ts +47 -212
- package/dist/dialect/abstractSqlDialect.js +68 -222
- package/dist/dialect/aliases.d.ts +2 -12
- package/dist/dialect/aliases.js +4 -12
- package/dist/dialect/hydrateColumn.d.ts +2 -6
- package/dist/dialect/hydrateColumn.js +3 -13
- package/dist/dialect/jsonArrayElemMatchUtils.d.ts +1 -7
- package/dist/dialect/jsonArrayElemMatchUtils.js +1 -7
- package/dist/dialect/jsonSql.d.ts +6 -27
- package/dist/dialect/jsonSql.js +6 -27
- package/dist/dialect/mergeSqlDialect.d.ts +4 -22
- package/dist/dialect/mergeSqlDialect.js +4 -22
- package/dist/dialect/mysqlLikeSqlDialect.d.ts +11 -37
- package/dist/dialect/mysqlLikeSqlDialect.js +35 -51
- package/dist/dialect/pgLikeSqlDialect.d.ts +8 -22
- package/dist/dialect/pgLikeSqlDialect.js +36 -39
- package/dist/dialect/queryContext.d.ts +4 -22
- package/dist/dialect/queryContext.js +4 -22
- package/dist/dialect/queryJoins.d.ts +3 -12
- package/dist/dialect/queryJoins.js +3 -12
- package/dist/dialect/vectorCast.d.ts +2 -12
- package/dist/dialect/vectorCast.js +3 -19
- package/dist/dialect/vectorSqlDialect.d.ts +8 -38
- package/dist/dialect/vectorSqlDialect.js +7 -38
- package/dist/entity/decorator/bag.d.ts +6 -19
- package/dist/entity/decorator/bag.js +6 -22
- package/dist/entity/decorator/entity.d.ts +5 -10
- package/dist/entity/decorator/entity.js +2 -7
- package/dist/entity/decorator/members.d.ts +10 -31
- package/dist/entity/decorator/members.js +3 -12
- package/dist/entity/metadata/definition.d.ts +5 -21
- package/dist/entity/metadata/definition.js +69 -91
- package/dist/http/handler.d.ts +2 -14
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/libsql/libsqlDialect.d.ts +1 -8
- package/dist/libsql/libsqlDialect.js +1 -8
- package/dist/maria/mariaDialect.d.ts +3 -5
- package/dist/maria/mariaDialect.js +5 -5
- package/dist/maria/mariadbQuerier.js +2 -2
- package/dist/maria/mariadbQuerierPool.js +1 -6
- package/dist/migrate/builder/migrationBuilder.js +3 -19
- package/dist/migrate/builder/splitSqlStatements.d.ts +1 -14
- package/dist/migrate/builder/splitSqlStatements.js +2 -22
- package/dist/migrate/builder/types.d.ts +2 -15
- package/dist/migrate/cli-config.js +2 -11
- package/dist/migrate/cli.js +2 -7
- package/dist/migrate/codegen/entityCodeGenerator.d.ts +0 -15
- package/dist/migrate/codegen/entityCodeGenerator.js +15 -44
- package/dist/migrate/codegen/fieldOptionsSource.d.ts +1 -8
- package/dist/migrate/codegen/fieldOptionsSource.js +3 -22
- package/dist/migrate/ddl/indexDdl.d.ts +2 -5
- package/dist/migrate/ddl/indexDdl.js +2 -5
- package/dist/migrate/ddl/pgIndexDdl.d.ts +3 -13
- package/dist/migrate/ddl/pgIndexDdl.js +3 -13
- package/dist/migrate/generator/definitionToNode.d.ts +2 -9
- package/dist/migrate/generator/definitionToNode.js +3 -17
- package/dist/migrate/generator/indexNodeToSchema.d.ts +2 -3
- package/dist/migrate/generator/indexNodeToSchema.js +2 -3
- package/dist/migrate/generator/mongoCommand.d.ts +1 -8
- package/dist/migrate/generator/mongoSchemaGenerator.d.ts +1 -8
- package/dist/migrate/generator/mongoSchemaGenerator.js +1 -8
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts +6 -26
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js +9 -41
- package/dist/migrate/introspection/baseSqlIntrospector.js +0 -1
- package/dist/migrate/introspection/mongoIntrospector.d.ts +3 -1
- package/dist/migrate/introspection/mongoIntrospector.js +48 -46
- package/dist/migrate/introspection/mssqlIntrospector.d.ts +4 -4
- package/dist/migrate/introspection/mssqlIntrospector.js +18 -27
- package/dist/migrate/introspection/mysqlIntrospector.d.ts +7 -2
- package/dist/migrate/introspection/mysqlIntrospector.js +16 -14
- package/dist/migrate/introspection/postgresIntrospector.d.ts +24 -9
- package/dist/migrate/introspection/postgresIntrospector.js +68 -59
- package/dist/migrate/introspection/sqliteIntrospector.d.ts +1 -1
- package/dist/migrate/introspection/sqliteIntrospector.js +8 -10
- package/dist/migrate/migrator.d.ts +9 -53
- package/dist/migrate/migrator.js +32 -65
- package/dist/migrate/schemaGenerator.d.ts +20 -66
- package/dist/migrate/schemaGenerator.js +32 -93
- package/dist/mongo/mongoDialect.d.ts +21 -53
- package/dist/mongo/mongoDialect.js +25 -70
- package/dist/mongo/mongodbQuerier.d.ts +5 -8
- package/dist/mongo/mongodbQuerier.js +31 -65
- package/dist/mssql/mssqlDialect.d.ts +8 -34
- package/dist/mssql/mssqlDialect.js +37 -51
- package/dist/mssql/mssqlQuerier.d.ts +37 -4
- package/dist/mssql/mssqlQuerier.js +2 -2
- package/dist/mssql/mssqlWireTypes.d.ts +2 -14
- package/dist/mssql/mssqlWireTypes.js +2 -14
- package/dist/nestjs/uqlModule.js +2 -7
- package/dist/pglite/pgliteQuerier.d.ts +1 -9
- package/dist/pglite/pgliteQuerierPool.d.ts +4 -26
- package/dist/pglite/pgliteQuerierPool.js +3 -18
- package/dist/postgres/abstractPgQuerierPool.d.ts +1 -8
- package/dist/postgres/abstractPgQuerierPool.js +1 -8
- package/dist/postgres/pgNumericTypes.d.ts +3 -26
- package/dist/postgres/pgNumericTypes.js +3 -26
- package/dist/postgres/postgresDialect.d.ts +4 -10
- package/dist/postgres/postgresDialect.js +4 -10
- package/dist/querier/abstractQuerier.d.ts +35 -103
- package/dist/querier/abstractQuerier.js +105 -201
- package/dist/querier/abstractSharedHandleQuerierPool.d.ts +3 -17
- package/dist/querier/abstractSharedHandleQuerierPool.js +3 -17
- package/dist/querier/abstractSqlQuerier.d.ts +15 -36
- package/dist/querier/abstractSqlQuerier.js +49 -131
- package/dist/schema/canonicalType.d.ts +3 -21
- package/dist/schema/canonicalType.js +22 -67
- package/dist/schema/dependencyGraph.d.ts +2 -8
- package/dist/schema/dependencyGraph.js +2 -32
- package/dist/schema/index.d.ts +1 -25
- package/dist/schema/index.js +0 -26
- package/dist/schema/indexColumns.d.ts +1 -8
- package/dist/schema/indexColumns.js +1 -8
- package/dist/schema/indexDifferences.d.ts +7 -40
- package/dist/schema/indexDifferences.js +6 -31
- package/dist/schema/schemaAST.d.ts +8 -175
- package/dist/schema/schemaAST.js +13 -365
- package/dist/schema/schemaASTBuilder.d.ts +2 -24
- package/dist/schema/schemaASTBuilder.js +6 -41
- package/dist/schema/schemaASTDiffer.d.ts +6 -46
- package/dist/schema/schemaASTDiffer.js +8 -56
- package/dist/schema/types.d.ts +5 -61
- package/dist/schema/types.js +3 -6
- package/dist/sqlite/abstractSqliteQuerier.d.ts +1 -8
- package/dist/sqlite/localSqliteQuerierPool.d.ts +1 -7
- package/dist/sqlite/localSqliteQuerierPool.js +1 -7
- package/dist/sqlite/nodeSqliteQuerierPool.d.ts +2 -7
- package/dist/sqlite/nodeSqliteQuerierPool.js +2 -7
- package/dist/sqlite/sqliteDialect.d.ts +5 -20
- package/dist/sqlite/sqliteDialect.js +29 -35
- package/dist/turso/tursoDialect.d.ts +4 -6
- package/dist/turso/tursoDialect.js +4 -6
- package/dist/turso/tursoLocalQuerierPool.d.ts +1 -7
- package/dist/turso/tursoLocalQuerierPool.js +1 -7
- package/dist/turso/tursoQuerierPool.d.ts +2 -6
- package/dist/turso/tursoQuerierPool.js +2 -6
- package/dist/turso/tursoSessionQuerier.d.ts +1 -7
- package/dist/turso/tursoSessionQuerier.js +1 -7
- package/dist/type/dialect.d.ts +42 -94
- package/dist/type/dialect.js +3 -13
- package/dist/type/entity.d.ts +189 -551
- package/dist/type/entity.js +26 -9
- package/dist/type/logger.d.ts +2 -14
- package/dist/type/migration.d.ts +9 -38
- package/dist/type/querier.d.ts +9 -28
- package/dist/type/querierPool.d.ts +4 -26
- package/dist/type/query.d.ts +28 -78
- package/dist/type/query.js +2 -7
- package/dist/type/queryAggregate.d.ts +18 -98
- package/dist/type/queryRaw.d.ts +1 -8
- package/dist/type/queryRaw.js +1 -8
- package/dist/type/queryWhere.d.ts +13 -61
- package/dist/type/universalQuerier.d.ts +18 -105
- package/dist/type/utility.d.ts +12 -24
- package/dist/type/vector.d.ts +8 -38
- package/dist/type/vector.js +1 -1
- package/dist/type/wire.d.ts +2 -5
- package/dist/util/dialect.util.d.ts +9 -27
- package/dist/util/dialect.util.js +10 -27
- package/dist/util/field.util.d.ts +5 -37
- package/dist/util/field.util.js +7 -50
- package/dist/util/fieldOption.util.d.ts +7 -15
- package/dist/util/fieldOption.util.js +1 -1
- package/dist/util/filters.util.d.ts +2 -5
- package/dist/util/filters.util.js +2 -5
- package/dist/util/logger.d.ts +2 -6
- package/dist/util/logger.js +2 -6
- package/dist/util/object.util.d.ts +2 -6
- package/dist/util/object.util.js +1 -5
- package/dist/util/raw.d.ts +3 -23
- package/dist/util/relationQuery.util.d.ts +3 -14
- package/dist/util/relationQuery.util.js +3 -14
- package/dist/util/rowKey.util.d.ts +2 -10
- package/dist/util/rowKey.util.js +2 -10
- package/dist/util/sql.util.d.ts +6 -37
- package/dist/util/sql.util.js +13 -73
- package/dist/util/sqlLiteral.d.ts +2 -13
- package/dist/util/sqlLiteral.js +8 -13
- package/dist/util/string.util.js +0 -2
- package/package.json +4 -4
|
@@ -46,13 +46,7 @@ export declare class Migrator {
|
|
|
46
46
|
to?: string;
|
|
47
47
|
step?: number;
|
|
48
48
|
}): Promise<MigrationResult[]>;
|
|
49
|
-
/**
|
|
50
|
-
* Narrow a run list by `to`/`step` and execute it, stopping at the first failure.
|
|
51
|
-
*
|
|
52
|
-
* Both directions do exactly this and differ only in the list they start from: `up` takes the
|
|
53
|
-
* pending migrations, `down` the executed ones reversed. Keeping the selection in one place is what
|
|
54
|
-
* makes `--to` and `--step` mean the same thing whichever way you are going.
|
|
55
|
-
*/
|
|
49
|
+
/** Runs the list narrowed by `to`/`step`, stopping at the first failure: `up` over the pending, `down` over the executed reversed. */
|
|
56
50
|
private runInOrder;
|
|
57
51
|
/**
|
|
58
52
|
* Run a single migration, within a transaction where the dialect has one for it
|
|
@@ -73,29 +67,13 @@ export declare class Migrator {
|
|
|
73
67
|
*/
|
|
74
68
|
getDiffs(): Promise<SchemaDiff[]>;
|
|
75
69
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* that wants it spells the key: `undefined` on both sides for the connection's default, a name on
|
|
79
|
-
* both sides otherwise. Ordinarily that is one schema and one pass, as before, and that pass keeps
|
|
80
|
-
* {@link schemaIntrospector} so a caller that replaced it still wins.
|
|
81
|
-
*/
|
|
82
|
-
private introspectClaimedSchemas;
|
|
83
|
-
/**
|
|
84
|
-
* Applies the entity schema to the database: every registered entity, or the one `entity` names.
|
|
85
|
-
*
|
|
86
|
-
* The whole surface is this and {@link planSync}, which answers the same question without running
|
|
87
|
-
* it - `force` and a single entity included, so `--dry-run` means the same thing whatever else was
|
|
88
|
-
* asked for.
|
|
70
|
+
* The tables `entities` name, read a schema at a time so each is keyed as its entity spells it. Those
|
|
71
|
+
* alone: nothing else is diffed, and another table can be dropped mid-scan by whatever else is running.
|
|
89
72
|
*/
|
|
73
|
+
private introspectEntities;
|
|
74
|
+
/** Applies the entity schema: every entity, or the one `entity` names. {@link planSync} answers the same without running it. */
|
|
90
75
|
sync(options?: SyncOptions): Promise<void>;
|
|
91
|
-
/**
|
|
92
|
-
* Every table dropped and recreated.
|
|
93
|
-
*
|
|
94
|
-
* Both directions span the whole entity set rather than looping an entity at a time. A per-entity
|
|
95
|
-
* AST cannot resolve a cross-entity foreign key, so the old create loop silently produced a schema
|
|
96
|
-
* with no referential integrity; and the old drop loop went in reverse *declaration* order, which
|
|
97
|
-
* says nothing about the relation graph and is rejected as soon as the constraints are really there.
|
|
98
|
-
*/
|
|
76
|
+
/** Every table dropped and recreated, the whole entity set at once, so foreign keys resolve and drop in graph order. */
|
|
99
77
|
private forceStatements;
|
|
100
78
|
/**
|
|
101
79
|
* The DDL for one entity: {@link planSync} narrowed to the table it names. A new table costs one
|
|
@@ -114,14 +92,7 @@ export declare class Migrator {
|
|
|
114
92
|
* statements rather than a summary of a second, differently-computed diff.
|
|
115
93
|
*/
|
|
116
94
|
planSync(options?: SyncOptions): Promise<string[]>;
|
|
117
|
-
/**
|
|
118
|
-
* New tables are emitted together, never one at a time: a single-entity AST has no other table for a
|
|
119
|
-
* relation to resolve against, so every cross-entity foreign key was dropped and generated schemas
|
|
120
|
-
* carried none. Spanning the graph is also what lets a cyclic relation (any `createdBy`
|
|
121
|
-
* back-reference) be created at all.
|
|
122
|
-
*
|
|
123
|
-
* Empty in, empty out, so a diff with no new tables does not build an AST for the whole graph.
|
|
124
|
-
*/
|
|
95
|
+
/** The new tables, created together so a foreign key between them, cyclic included, resolves. Empty in, empty out. */
|
|
125
96
|
private createSchema;
|
|
126
97
|
/**
|
|
127
98
|
* The pending diffs a sync or a generated migration acts on: the tables to create and the tables to
|
|
@@ -184,22 +155,7 @@ export interface BuilderMigrationDefinition<Q extends Querier = SqlQuerier> {
|
|
|
184
155
|
down(builder: IMigrationBuilder, querier: Q): Promise<void>;
|
|
185
156
|
}
|
|
186
157
|
/**
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* @example
|
|
190
|
-
* ```ts
|
|
191
|
-
* export default defineBuilderMigration({
|
|
192
|
-
* async up(m) {
|
|
193
|
-
* await m.createTable('users', (t) => {
|
|
194
|
-
* t.id();
|
|
195
|
-
* t.string('email', { length: 255 }).unique();
|
|
196
|
-
* t.timestamps();
|
|
197
|
-
* });
|
|
198
|
-
* },
|
|
199
|
-
* async down(m) {
|
|
200
|
-
* await m.dropTable('users');
|
|
201
|
-
* }
|
|
202
|
-
* });
|
|
203
|
-
* ```
|
|
158
|
+
* Defines a migration with the builder:
|
|
159
|
+
* `defineBuilderMigration({ up: (m) => m.createTable('users', (t) => t.id()), down: (m) => m.dropTable('users') })`.
|
|
204
160
|
*/
|
|
205
161
|
export declare function defineBuilderMigration<Q extends Querier = SqlQuerier>(migration: BuilderMigrationDefinition<Q>): MigrationDefinition<Q>;
|
package/dist/migrate/migrator.js
CHANGED
|
@@ -2,7 +2,7 @@ import { mkdir, readdir, writeFile } from 'node:fs/promises';
|
|
|
2
2
|
import { basename, extname, join } from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
4
|
import { getEntities, getMeta } from '../entity/index.js';
|
|
5
|
-
import {
|
|
5
|
+
import { SchemaAST } from '../schema/index.js';
|
|
6
6
|
import { LoggerWrapper } from '../util/index.js';
|
|
7
7
|
import { buildMigrationModule } from './codegen/migrationFile.js';
|
|
8
8
|
import { introspectorFor } from './introspection/registry.js';
|
|
@@ -88,13 +88,7 @@ export class Migrator {
|
|
|
88
88
|
const executedMigrations = migrations.filter((m) => executedSet.has(m.name)).reverse(); // Rollback in reverse order
|
|
89
89
|
return this.runInOrder(executedMigrations, 'down', options);
|
|
90
90
|
}
|
|
91
|
-
/**
|
|
92
|
-
* Narrow a run list by `to`/`step` and execute it, stopping at the first failure.
|
|
93
|
-
*
|
|
94
|
-
* Both directions do exactly this and differ only in the list they start from: `up` takes the
|
|
95
|
-
* pending migrations, `down` the executed ones reversed. Keeping the selection in one place is what
|
|
96
|
-
* makes `--to` and `--step` mean the same thing whichever way you are going.
|
|
97
|
-
*/
|
|
91
|
+
/** Runs the list narrowed by `to`/`step`, stopping at the first failure: `up` over the pending, `down` over the executed reversed. */
|
|
98
92
|
async runInOrder(migrations, direction, options) {
|
|
99
93
|
let selected = migrations;
|
|
100
94
|
if (options.to) {
|
|
@@ -211,7 +205,7 @@ export class Migrator {
|
|
|
211
205
|
*/
|
|
212
206
|
async getDiffs() {
|
|
213
207
|
const generator = await this.getSchemaGenerator();
|
|
214
|
-
const ast = await this.
|
|
208
|
+
const ast = await this.introspectEntities(this.entities);
|
|
215
209
|
// Both sides built once: the database's above, the entities' here. Left to `diffSchema`, each
|
|
216
210
|
// entity would rebuild the whole AST, which is quadratic in the number of entities. Absent on a
|
|
217
211
|
// generator that compares no schema of its own - MongoDB, which reads only indexes.
|
|
@@ -223,29 +217,22 @@ export class Migrator {
|
|
|
223
217
|
});
|
|
224
218
|
}
|
|
225
219
|
/**
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
* that wants it spells the key: `undefined` on both sides for the connection's default, a name on
|
|
229
|
-
* both sides otherwise. Ordinarily that is one schema and one pass, as before, and that pass keeps
|
|
230
|
-
* {@link schemaIntrospector} so a caller that replaced it still wins.
|
|
220
|
+
* The tables `entities` name, read a schema at a time so each is keyed as its entity spells it. Those
|
|
221
|
+
* alone: nothing else is diffed, and another table can be dropped mid-scan by whatever else is running.
|
|
231
222
|
*/
|
|
232
|
-
async
|
|
233
|
-
const
|
|
223
|
+
async introspectEntities(entities) {
|
|
224
|
+
const { dialect } = this.pool;
|
|
225
|
+
const bySchema = Map.groupBy(new Set(entities), (entity) => dialect.resolveSchema(getMeta(entity)));
|
|
234
226
|
const merged = new SchemaAST();
|
|
235
|
-
for (const schema of
|
|
236
|
-
|
|
227
|
+
for (const [schema, members] of bySchema) {
|
|
228
|
+
const tables = members.map((entity) => dialect.resolveTableAlias(getMeta(entity)));
|
|
229
|
+
for (const table of (await this.schemaIntrospectorFor(schema).introspect(tables)).getTables()) {
|
|
237
230
|
merged.addTable(table);
|
|
238
231
|
}
|
|
239
232
|
}
|
|
240
233
|
return merged;
|
|
241
234
|
}
|
|
242
|
-
/**
|
|
243
|
-
* Applies the entity schema to the database: every registered entity, or the one `entity` names.
|
|
244
|
-
*
|
|
245
|
-
* The whole surface is this and {@link planSync}, which answers the same question without running
|
|
246
|
-
* it - `force` and a single entity included, so `--dry-run` means the same thing whatever else was
|
|
247
|
-
* asked for.
|
|
248
|
-
*/
|
|
235
|
+
/** Applies the entity schema: every entity, or the one `entity` names. {@link planSync} answers the same without running it. */
|
|
249
236
|
async sync(options = {}) {
|
|
250
237
|
const statements = await this.planSync(options);
|
|
251
238
|
if (statements.length) {
|
|
@@ -255,14 +242,7 @@ export class Migrator {
|
|
|
255
242
|
this.logger.logSchema('Schema is already in sync.');
|
|
256
243
|
}
|
|
257
244
|
}
|
|
258
|
-
/**
|
|
259
|
-
* Every table dropped and recreated.
|
|
260
|
-
*
|
|
261
|
-
* Both directions span the whole entity set rather than looping an entity at a time. A per-entity
|
|
262
|
-
* AST cannot resolve a cross-entity foreign key, so the old create loop silently produced a schema
|
|
263
|
-
* with no referential integrity; and the old drop loop went in reverse *declaration* order, which
|
|
264
|
-
* says nothing about the relation graph and is rejected as soon as the constraints are really there.
|
|
265
|
-
*/
|
|
245
|
+
/** Every table dropped and recreated, the whole entity set at once, so foreign keys resolve and drop in graph order. */
|
|
266
246
|
forceStatements(generator) {
|
|
267
247
|
return [
|
|
268
248
|
...generator.generateDropSchema(this.entities, { ifExists: true, cascade: true }),
|
|
@@ -276,14 +256,17 @@ export class Migrator {
|
|
|
276
256
|
*/
|
|
277
257
|
async planEntity(generator, entity, options) {
|
|
278
258
|
const meta = getMeta(entity);
|
|
279
|
-
const
|
|
259
|
+
const { dialect } = this.pool;
|
|
260
|
+
const introspector = this.schemaIntrospectorFor(dialect.resolveSchema(meta));
|
|
280
261
|
const tableName = generator.resolveTableName(meta);
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
262
|
+
if (!(await introspector.tableExists(dialect.resolveTableAlias(meta)))) {
|
|
263
|
+
// Spanning the whole set, so a foreign key resolves against the tables it points at, and always
|
|
264
|
+
// including this entity: `only` is what keeps the statements to this table.
|
|
265
|
+
return generator.generateCreateSchema(this.entitiesWith(entity), { only: [tableName], ifNotExists: true });
|
|
266
|
+
}
|
|
267
|
+
// With the tables it references, which its foreign keys resolve against.
|
|
268
|
+
const ast = await this.introspectEntities([entity, ...referencedEntities(meta)]);
|
|
269
|
+
return this.alterFromEntity(generator, entity, ast.getTable(tableName), options);
|
|
287
270
|
}
|
|
288
271
|
/** The same for one entity against the table it already has, and nothing where the two agree. */
|
|
289
272
|
alterFromEntity(generator, entity, table, options) {
|
|
@@ -319,14 +302,7 @@ export class Migrator {
|
|
|
319
302
|
...altered.flatMap((diff) => generator.generateAlterTable(this.filterDiff(diff, options))),
|
|
320
303
|
];
|
|
321
304
|
}
|
|
322
|
-
/**
|
|
323
|
-
* New tables are emitted together, never one at a time: a single-entity AST has no other table for a
|
|
324
|
-
* relation to resolve against, so every cross-entity foreign key was dropped and generated schemas
|
|
325
|
-
* carried none. Spanning the graph is also what lets a cyclic relation (any `createdBy`
|
|
326
|
-
* back-reference) be created at all.
|
|
327
|
-
*
|
|
328
|
-
* Empty in, empty out, so a diff with no new tables does not build an AST for the whole graph.
|
|
329
|
-
*/
|
|
305
|
+
/** The new tables, created together so a foreign key between them, cyclic included, resolves. Empty in, empty out. */
|
|
330
306
|
createSchema(generator, tableNames) {
|
|
331
307
|
return tableNames.length ? generator.generateCreateSchema(this.entities, { only: tableNames }) : [];
|
|
332
308
|
}
|
|
@@ -484,23 +460,8 @@ export function defineMigration(migration) {
|
|
|
484
460
|
return migration;
|
|
485
461
|
}
|
|
486
462
|
/**
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
* @example
|
|
490
|
-
* ```ts
|
|
491
|
-
* export default defineBuilderMigration({
|
|
492
|
-
* async up(m) {
|
|
493
|
-
* await m.createTable('users', (t) => {
|
|
494
|
-
* t.id();
|
|
495
|
-
* t.string('email', { length: 255 }).unique();
|
|
496
|
-
* t.timestamps();
|
|
497
|
-
* });
|
|
498
|
-
* },
|
|
499
|
-
* async down(m) {
|
|
500
|
-
* await m.dropTable('users');
|
|
501
|
-
* }
|
|
502
|
-
* });
|
|
503
|
-
* ```
|
|
463
|
+
* Defines a migration with the builder:
|
|
464
|
+
* `defineBuilderMigration({ up: (m) => m.createTable('users', (t) => t.id()), down: (m) => m.dropTable('users') })`.
|
|
504
465
|
*/
|
|
505
466
|
export function defineBuilderMigration(migration) {
|
|
506
467
|
return {
|
|
@@ -509,3 +470,9 @@ export function defineBuilderMigration(migration) {
|
|
|
509
470
|
down: async (querier) => migration.down(await migrationBuilderFor(querier), querier),
|
|
510
471
|
};
|
|
511
472
|
}
|
|
473
|
+
/** The entities `meta` points at, through a relation or a foreign key field. */
|
|
474
|
+
function referencedEntities(meta) {
|
|
475
|
+
const fields = Object.values(meta.fields).flatMap((field) => field?.references?.() ?? []);
|
|
476
|
+
const relations = Object.values(meta.relations).flatMap((relation) => relation?.entity?.() ?? []);
|
|
477
|
+
return [...fields, ...relations];
|
|
478
|
+
}
|
|
@@ -28,35 +28,18 @@ export declare class SqlSchemaGenerator implements SchemaGenerator {
|
|
|
28
28
|
/** Escape an identifier (table name, column name, etc.) */
|
|
29
29
|
protected escapeId(identifier: string): string;
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* Derived rather than a fixed string per dialect, because a foreign key column takes its type from
|
|
35
|
-
* the key it points at, resolved through the same canonical type. A key whose spelling ignored that
|
|
36
|
-
* type could never be referenced: `@Id({ columnType: 'int' })` emitted `BIGINT` while the column
|
|
37
|
-
* pointing at it emitted `INT`, and every engine refuses that constraint.
|
|
31
|
+
* An auto-increment key's type: its canonical type rendered like any column's, plus the engine's generated
|
|
32
|
+
* suffix, so a foreign key taking its type from this key gets the same one.
|
|
38
33
|
*/
|
|
39
34
|
protected serialType(type: CanonicalType): string;
|
|
40
|
-
/**
|
|
41
|
-
* The SQL type a column is spelled with: the engine's generated-key form for an auto-increment key,
|
|
42
|
-
* the canonical type otherwise.
|
|
43
|
-
*
|
|
44
|
-
* One method because both paths that spell a column need the same answer - written twice, with a
|
|
45
|
-
* comment asking the two to stay in sync, is how the generated key and the column referencing it
|
|
46
|
-
* came to disagree in the first place.
|
|
47
|
-
*/
|
|
35
|
+
/** The SQL type a column is spelled with: the generated-key form for an auto-increment key, the canonical type otherwise. */
|
|
48
36
|
protected columnSqlType(col: ColumnNode): string;
|
|
49
37
|
protected canonicalTypeToSql(type: CanonicalType): string;
|
|
50
38
|
/** The entity side as an AST, carrying this generator's default referential action. */
|
|
51
39
|
buildAST(entities: readonly Type<object>[]): SchemaAST;
|
|
52
40
|
/**
|
|
53
|
-
* Every `CREATE TABLE` for `entities`, then their foreign keys
|
|
54
|
-
*
|
|
55
|
-
* Two phases rather than inline constraints, because a relation graph is routinely cyclic: any
|
|
56
|
-
* `createdBy`-style back-reference makes `A` reference `B` while `B` references `A`, and no create
|
|
57
|
-
* order satisfies that. TypeORM's schema builder splits for the same reason (`createNewTables()`
|
|
58
|
-
* then `createForeignKeys()`). SQLite is the exception and keeps them inline: it cannot `ALTER` a
|
|
59
|
-
* foreign key in, but it resolves targets lazily, so a forward reference is fine there.
|
|
41
|
+
* Every `CREATE TABLE` for `entities`, then their foreign keys, since a relation graph is routinely
|
|
42
|
+
* cyclic. SQLite keeps them inline: it cannot add one later, and resolves a forward reference lazily.
|
|
60
43
|
*/
|
|
61
44
|
generateCreateSchema(entities: readonly Type<object>[], options?: CreateSchemaOptions): string[];
|
|
62
45
|
/**
|
|
@@ -88,13 +71,8 @@ export declare class SqlSchemaGenerator implements SchemaGenerator {
|
|
|
88
71
|
*/
|
|
89
72
|
generateDropIndex(tableName: string, indexName: string, schema?: string): string;
|
|
90
73
|
/**
|
|
91
|
-
* A column definition from a {@link ColumnSchema}, whose type is already the engine's
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* Kept apart from {@link generateColumnFromNode} rather than folded into it: a `ColumnSchema` has no
|
|
95
|
-
* `enum`, because introspection reads one back as a `CHECK` constraint and not as a property of the
|
|
96
|
-
* column, so only the node knows enough to emit that clause. Both spell the definition through
|
|
97
|
-
* {@link renderColumn}, which is the part that must not be written twice.
|
|
74
|
+
* A column definition from a {@link ColumnSchema}, whose type is already the engine's spelling. Apart from
|
|
75
|
+
* {@link generateColumnFromNode}, which alone knows an `enum`; both render through {@link renderColumn}.
|
|
98
76
|
*/
|
|
99
77
|
generateColumnDefinitionFromSchema(column: ColumnSchema): string;
|
|
100
78
|
/**
|
|
@@ -104,35 +82,25 @@ export declare class SqlSchemaGenerator implements SchemaGenerator {
|
|
|
104
82
|
* enum's `CHECK` comes last, the only place MariaDB takes it.
|
|
105
83
|
*/
|
|
106
84
|
private renderColumn;
|
|
85
|
+
/**
|
|
86
|
+
* The column type a field gets, resolved as its table resolves it. A field alone cannot tell that it is
|
|
87
|
+
* one column of a composite key, which its table never makes serial.
|
|
88
|
+
*/
|
|
107
89
|
getSqlType(field: FieldMeta): string;
|
|
108
90
|
/** The statements that alter `column` in place, as this dialect spells them. */
|
|
109
91
|
generateAlterColumnStatements(tableName: string, column: ColumnSchema, newDefinition: string): string[];
|
|
110
92
|
/** The inline ` COMMENT '...'` a column declaration carries, where the engine takes one there. */
|
|
111
93
|
generateColumnComment(comment: string): string;
|
|
112
|
-
/**
|
|
113
|
-
* The `COMMENT ON` statements a table and its columns need, on an engine that carries a comment
|
|
114
|
-
* that way. Empty on the others: MySQL writes them inline, SQLite has no comments at all.
|
|
115
|
-
*
|
|
116
|
-
* Emitted after the `CREATE TABLE` rather than folded into it, which is what `COMMENT ON` requires -
|
|
117
|
-
* and what makes a comment reach Postgres, where it was previously read as unsupported and dropped.
|
|
118
|
-
*/
|
|
94
|
+
/** The `COMMENT ON` statements a table and its columns need, after the `CREATE TABLE`, where the engine uses them. */
|
|
119
95
|
protected generateCommentStatements(table: TableNode): string[];
|
|
120
|
-
/**
|
|
121
|
-
* The `COMMENT ON COLUMN` one column needs, on an engine that carries a comment that way.
|
|
122
|
-
*
|
|
123
|
-
* Shared by `CREATE TABLE` and every path that adds a column: written only for the former, a column
|
|
124
|
-
* added later reached the database undocumented, the way its enum `CHECK` used to.
|
|
125
|
-
*/
|
|
96
|
+
/** The `COMMENT ON COLUMN` a column needs where the engine uses one, for `CREATE TABLE` and every path adding a column. */
|
|
126
97
|
protected generateColumnCommentStatement(tableName: string, column: {
|
|
127
98
|
name: string;
|
|
128
99
|
comment?: string;
|
|
129
100
|
}, schema?: string): string[];
|
|
130
101
|
/**
|
|
131
|
-
* How
|
|
132
|
-
*
|
|
133
|
-
* The comparison itself is {@link diffTable}, the same one drift detection runs, so the two can no
|
|
134
|
-
* longer disagree about what has changed. Only two things are this side's own: the entity becomes a
|
|
135
|
-
* table node first, and types are compared as the *engine* would store them - see `normalizeType`.
|
|
102
|
+
* How the entity differs from the table the database reported, compared by {@link diffTable}, the one
|
|
103
|
+
* drift detection runs, with types normalized as the engine stores them.
|
|
136
104
|
*/
|
|
137
105
|
diffSchema(entity: Type<object>, currentTable: TableNode | undefined, desiredAst?: SchemaAST): SchemaDiff | undefined;
|
|
138
106
|
/**
|
|
@@ -171,13 +139,7 @@ export declare class SqlSchemaGenerator implements SchemaGenerator {
|
|
|
171
139
|
generateRenameTableSql(oldName: string, newName: string): string;
|
|
172
140
|
/** `raw` is split, being the one SQL no generator wrote. */
|
|
173
141
|
generateOperation(operation: AnyMigrationOperation): string[];
|
|
174
|
-
/**
|
|
175
|
-
* `ADD COLUMN`, plus the constraint and index the column declares.
|
|
176
|
-
*
|
|
177
|
-
* `CREATE TABLE` lifts a column's `references` and `index` onto the table it is building; this had
|
|
178
|
-
* no lift, so a hand-written `addColumn(...).references(...).index()` emitted the column alone and
|
|
179
|
-
* dropped both without a word.
|
|
180
|
-
*/
|
|
142
|
+
/** `ADD COLUMN`, plus the foreign key and index the column declares, as `CREATE TABLE` lifts them. */
|
|
181
143
|
generateAddColumnSql(tableName: string, column: FullColumnDefinition): string[];
|
|
182
144
|
generateAlterColumnSql(tableName: string, columnName: string, column: FullColumnDefinition): string[];
|
|
183
145
|
generateDropColumnSql(tableName: string, columnName: string): string[];
|
|
@@ -198,12 +160,8 @@ export declare class SqlSchemaGenerator implements SchemaGenerator {
|
|
|
198
160
|
*/
|
|
199
161
|
generateAddPrimaryKeySql(tableName: string, columns: readonly string[], name?: string): string;
|
|
200
162
|
/**
|
|
201
|
-
* Drops
|
|
202
|
-
*
|
|
203
|
-
* `constraintName` has to be what the constraint is *actually* called: the name introspection
|
|
204
|
-
* reported for a key the database already had, or the derived one for a key this generator itself
|
|
205
|
-
* added, which is what reversing a migration drops. Guessing either way names nothing. MySQL takes
|
|
206
|
-
* no name at all - a table's key is always `PRIMARY` there.
|
|
163
|
+
* Drops the table's key, by the name the constraint really has: introspected, or derived where this
|
|
164
|
+
* generator added it. MySQL takes no name.
|
|
207
165
|
*/
|
|
208
166
|
generateDropPrimaryKeySql(tableName: string, constraintName?: string): string;
|
|
209
167
|
/**
|
|
@@ -214,11 +172,7 @@ export declare class SqlSchemaGenerator implements SchemaGenerator {
|
|
|
214
172
|
private assertPrimaryKeyAlterable;
|
|
215
173
|
}
|
|
216
174
|
/**
|
|
217
|
-
* The entities as an AST, named
|
|
218
|
-
*
|
|
219
|
-
* Its resolvers rather than a naming strategy, because the two disagree: a strategy renames whatever
|
|
220
|
-
* it is handed, while a generator leaves an explicit `@Entity({ name })` alone. Build the AST the
|
|
221
|
-
* other way and the table is created under one name and compared under another, which reports every
|
|
222
|
-
* table of a project using a naming strategy as both missing and unexpected.
|
|
175
|
+
* The entities as an AST, named by `generator`'s resolvers rather than a naming strategy, which would
|
|
176
|
+
* also rename an explicit `@Entity({ name })` and so compare each table under another name.
|
|
223
177
|
*/
|
|
224
178
|
export declare function buildEntityAST(generator: Pick<SchemaGenerator, 'resolveTableAlias' | 'resolveSchema' | 'resolveColumnName' | 'compileDdl' | 'compileIndexPredicate'>, entities: readonly Type<object>[], defaultForeignKeyAction?: ForeignKeyAction): SchemaAST;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { getMeta
|
|
2
|
-
import { canonicalToSql, engineType,
|
|
1
|
+
import { getMeta } from '../entity/index.js';
|
|
2
|
+
import { canonicalToSql, engineType, isVectorCategory } from '../schema/canonicalType.js';
|
|
3
3
|
import { indexSignature } from '../schema/indexDifferences.js';
|
|
4
|
-
import { buildSchemaAST } from '../schema/schemaASTBuilder.js';
|
|
4
|
+
import { buildSchemaAST, resolveColumnCanonicalType } from '../schema/schemaASTBuilder.js';
|
|
5
5
|
import { diffRelationshipNodes, diffTable } from '../schema/schemaASTDiffer.js';
|
|
6
6
|
import { isAutoIncrement, qualifyName } from '../util/index.js';
|
|
7
7
|
import { derivedCheckName, derivedForeignKeyName, derivedPrimaryKeyName } from '../util/sql.util.js';
|
|
@@ -59,25 +59,13 @@ export class SqlSchemaGenerator {
|
|
|
59
59
|
return this.dialect.escapeId(identifier);
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* Derived rather than a fixed string per dialect, because a foreign key column takes its type from
|
|
66
|
-
* the key it points at, resolved through the same canonical type. A key whose spelling ignored that
|
|
67
|
-
* type could never be referenced: `@Id({ columnType: 'int' })` emitted `BIGINT` while the column
|
|
68
|
-
* pointing at it emitted `INT`, and every engine refuses that constraint.
|
|
62
|
+
* An auto-increment key's type: its canonical type rendered like any column's, plus the engine's generated
|
|
63
|
+
* suffix, so a foreign key taking its type from this key gets the same one.
|
|
69
64
|
*/
|
|
70
65
|
serialType(type) {
|
|
71
66
|
return `${this.canonicalTypeToSql(type)} ${this.dialect.autoIncrementSuffix}`;
|
|
72
67
|
}
|
|
73
|
-
/**
|
|
74
|
-
* The SQL type a column is spelled with: the engine's generated-key form for an auto-increment key,
|
|
75
|
-
* the canonical type otherwise.
|
|
76
|
-
*
|
|
77
|
-
* One method because both paths that spell a column need the same answer - written twice, with a
|
|
78
|
-
* comment asking the two to stay in sync, is how the generated key and the column referencing it
|
|
79
|
-
* came to disagree in the first place.
|
|
80
|
-
*/
|
|
68
|
+
/** The SQL type a column is spelled with: the generated-key form for an auto-increment key, the canonical type otherwise. */
|
|
81
69
|
columnSqlType(col) {
|
|
82
70
|
return col.isPrimaryKey && col.isAutoIncrement ? this.serialType(col.type) : this.canonicalTypeToSql(col.type);
|
|
83
71
|
}
|
|
@@ -89,13 +77,8 @@ export class SqlSchemaGenerator {
|
|
|
89
77
|
return buildEntityAST(this, entities, this.defaultForeignKeyAction);
|
|
90
78
|
}
|
|
91
79
|
/**
|
|
92
|
-
* Every `CREATE TABLE` for `entities`, then their foreign keys
|
|
93
|
-
*
|
|
94
|
-
* Two phases rather than inline constraints, because a relation graph is routinely cyclic: any
|
|
95
|
-
* `createdBy`-style back-reference makes `A` reference `B` while `B` references `A`, and no create
|
|
96
|
-
* order satisfies that. TypeORM's schema builder splits for the same reason (`createNewTables()`
|
|
97
|
-
* then `createForeignKeys()`). SQLite is the exception and keeps them inline: it cannot `ALTER` a
|
|
98
|
-
* foreign key in, but it resolves targets lazily, so a forward reference is fine there.
|
|
80
|
+
* Every `CREATE TABLE` for `entities`, then their foreign keys, since a relation graph is routinely
|
|
81
|
+
* cyclic. SQLite keeps them inline: it cannot add one later, and resolves a forward reference lazily.
|
|
99
82
|
*/
|
|
100
83
|
generateCreateSchema(entities, options = {}) {
|
|
101
84
|
const tables = this.orderedTables(entities, 'create', options.only);
|
|
@@ -271,13 +254,8 @@ export class SqlSchemaGenerator {
|
|
|
271
254
|
return `DROP INDEX IF EXISTS ${this.dialect.escapeQualifiedId(indexName, schema)};`;
|
|
272
255
|
}
|
|
273
256
|
/**
|
|
274
|
-
* A column definition from a {@link ColumnSchema}, whose type is already the engine's
|
|
275
|
-
*
|
|
276
|
-
*
|
|
277
|
-
* Kept apart from {@link generateColumnFromNode} rather than folded into it: a `ColumnSchema` has no
|
|
278
|
-
* `enum`, because introspection reads one back as a `CHECK` constraint and not as a property of the
|
|
279
|
-
* column, so only the node knows enough to emit that clause. Both spell the definition through
|
|
280
|
-
* {@link renderColumn}, which is the part that must not be written twice.
|
|
257
|
+
* A column definition from a {@link ColumnSchema}, whose type is already the engine's spelling. Apart from
|
|
258
|
+
* {@link generateColumnFromNode}, which alone knows an `enum`; both render through {@link renderColumn}.
|
|
281
259
|
*/
|
|
282
260
|
generateColumnDefinitionFromSchema(column) {
|
|
283
261
|
return this.renderColumn({ ...column, type: sizedType(column) });
|
|
@@ -309,23 +287,15 @@ export class SqlSchemaGenerator {
|
|
|
309
287
|
}
|
|
310
288
|
return def;
|
|
311
289
|
}
|
|
290
|
+
/**
|
|
291
|
+
* The column type a field gets, resolved as its table resolves it. A field alone cannot tell that it is
|
|
292
|
+
* one column of a composite key, which its table never makes serial.
|
|
293
|
+
*/
|
|
312
294
|
getSqlType(field) {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
const refIdField = refMeta.fields[field.referencedKey ?? soleIdOf(refMeta, 'a foreign key')];
|
|
318
|
-
if (refIdField) {
|
|
319
|
-
return this.getSqlType({ ...refIdField, references: undefined, isId: undefined, autoIncrement: false });
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
// Get canonical type and convert to SQL
|
|
323
|
-
const canonical = fieldOptionsToCanonical(field);
|
|
324
|
-
// Special case for serial primary keys
|
|
325
|
-
if (isAutoIncrement(field, field.isId === true)) {
|
|
326
|
-
return this.serialType(canonical);
|
|
327
|
-
}
|
|
328
|
-
return this.canonicalTypeToSql(canonical);
|
|
295
|
+
const canonical = resolveColumnCanonicalType(field);
|
|
296
|
+
return isAutoIncrement(field, field.isId === true)
|
|
297
|
+
? this.serialType(canonical)
|
|
298
|
+
: this.canonicalTypeToSql(canonical);
|
|
329
299
|
}
|
|
330
300
|
/** The statements that alter `column` in place, as this dialect spells them. */
|
|
331
301
|
generateAlterColumnStatements(tableName, column, newDefinition) {
|
|
@@ -335,13 +305,7 @@ export class SqlSchemaGenerator {
|
|
|
335
305
|
generateColumnComment(comment) {
|
|
336
306
|
return this.features.commentSyntax === 'inline' ? ` COMMENT ${this.dialect.escape(comment)}` : '';
|
|
337
307
|
}
|
|
338
|
-
/**
|
|
339
|
-
* The `COMMENT ON` statements a table and its columns need, on an engine that carries a comment
|
|
340
|
-
* that way. Empty on the others: MySQL writes them inline, SQLite has no comments at all.
|
|
341
|
-
*
|
|
342
|
-
* Emitted after the `CREATE TABLE` rather than folded into it, which is what `COMMENT ON` requires -
|
|
343
|
-
* and what makes a comment reach Postgres, where it was previously read as unsupported and dropped.
|
|
344
|
-
*/
|
|
308
|
+
/** The `COMMENT ON` statements a table and its columns need, after the `CREATE TABLE`, where the engine uses them. */
|
|
345
309
|
generateCommentStatements(table) {
|
|
346
310
|
if (this.features.commentSyntax !== 'statement') {
|
|
347
311
|
return [];
|
|
@@ -353,12 +317,7 @@ export class SqlSchemaGenerator {
|
|
|
353
317
|
}
|
|
354
318
|
return statements;
|
|
355
319
|
}
|
|
356
|
-
/**
|
|
357
|
-
* The `COMMENT ON COLUMN` one column needs, on an engine that carries a comment that way.
|
|
358
|
-
*
|
|
359
|
-
* Shared by `CREATE TABLE` and every path that adds a column: written only for the former, a column
|
|
360
|
-
* added later reached the database undocumented, the way its enum `CHECK` used to.
|
|
361
|
-
*/
|
|
320
|
+
/** The `COMMENT ON COLUMN` a column needs where the engine uses one, for `CREATE TABLE` and every path adding a column. */
|
|
362
321
|
generateColumnCommentStatement(tableName, column, schema) {
|
|
363
322
|
if (!column.comment || this.features.commentSyntax !== 'statement') {
|
|
364
323
|
return [];
|
|
@@ -367,11 +326,8 @@ export class SqlSchemaGenerator {
|
|
|
367
326
|
return [`COMMENT ON COLUMN ${tableRef}.${this.escapeId(column.name)} IS ${this.dialect.escape(column.comment)};`];
|
|
368
327
|
}
|
|
369
328
|
/**
|
|
370
|
-
* How
|
|
371
|
-
*
|
|
372
|
-
* The comparison itself is {@link diffTable}, the same one drift detection runs, so the two can no
|
|
373
|
-
* longer disagree about what has changed. Only two things are this side's own: the entity becomes a
|
|
374
|
-
* table node first, and types are compared as the *engine* would store them - see `normalizeType`.
|
|
329
|
+
* How the entity differs from the table the database reported, compared by {@link diffTable}, the one
|
|
330
|
+
* drift detection runs, with types normalized as the engine stores them.
|
|
375
331
|
*/
|
|
376
332
|
diffSchema(entity, currentTable, desiredAst) {
|
|
377
333
|
const meta = getMeta(entity);
|
|
@@ -412,13 +368,8 @@ export class SqlSchemaGenerator {
|
|
|
412
368
|
to: tableDiff.primaryKeyDiff.expected,
|
|
413
369
|
fromName: tableDiff.primaryKeyDiff.actualName,
|
|
414
370
|
};
|
|
415
|
-
// This table's own
|
|
416
|
-
//
|
|
417
|
-
//
|
|
418
|
-
// None at all where the engine cannot alter one: SQLite resolves foreign keys lazily and keeps
|
|
419
|
-
// them inline at CREATE time, and its only way to change one afterwards is the twelve-step table
|
|
420
|
-
// rebuild, which a sync does not do. Reporting a difference nothing can apply would throw on
|
|
421
|
-
// every sync of an entity that has a relation. `drift:check` still names it.
|
|
371
|
+
// This table's own foreign keys. None where the engine cannot alter one (SQLite, short of rebuilding
|
|
372
|
+
// the table), since a difference nothing can apply would throw on every sync; `drift:check` names it.
|
|
422
373
|
const relationDiffs = this.features.foreignKeyAlter
|
|
423
374
|
? diffRelationshipNodes(desired.outgoingRelations, currentTable.outgoingRelations, this.diffOptions())
|
|
424
375
|
: [];
|
|
@@ -512,7 +463,9 @@ export class SqlSchemaGenerator {
|
|
|
512
463
|
// later `DROP` has something to name. The exception is a dialect whose serial type states the key
|
|
513
464
|
// itself (SQLite's `INTEGER PRIMARY KEY AUTOINCREMENT`, which cannot be split): there the column
|
|
514
465
|
// has already declared it, and saying it again is a second primary key.
|
|
515
|
-
const declaredByColumn = this.dialect.serialDeclaresPrimaryKey &&
|
|
466
|
+
const declaredByColumn = this.dialect.features.serialDeclaresPrimaryKey &&
|
|
467
|
+
table.primaryKey.length === 1 &&
|
|
468
|
+
table.primaryKey[0].isAutoIncrement;
|
|
516
469
|
if (table.primaryKey.length && !declaredByColumn) {
|
|
517
470
|
const pkColumns = table.primaryKey.map((c) => c.name);
|
|
518
471
|
const pkName = table.primaryKeyName ?? derivedPrimaryKeyName(table.name, pkColumns);
|
|
@@ -614,13 +567,7 @@ export class SqlSchemaGenerator {
|
|
|
614
567
|
return splitSqlStatements(operation.sql);
|
|
615
568
|
}
|
|
616
569
|
}
|
|
617
|
-
/**
|
|
618
|
-
* `ADD COLUMN`, plus the constraint and index the column declares.
|
|
619
|
-
*
|
|
620
|
-
* `CREATE TABLE` lifts a column's `references` and `index` onto the table it is building; this had
|
|
621
|
-
* no lift, so a hand-written `addColumn(...).references(...).index()` emitted the column alone and
|
|
622
|
-
* dropped both without a word.
|
|
623
|
-
*/
|
|
570
|
+
/** `ADD COLUMN`, plus the foreign key and index the column declares, as `CREATE TABLE` lifts them. */
|
|
624
571
|
generateAddColumnSql(tableName, column) {
|
|
625
572
|
this.assertColumnAddable(tableName, column);
|
|
626
573
|
const colSql = this.generateColumnFromNode(fullColumnDefinitionToNode(column, tableName));
|
|
@@ -682,12 +629,8 @@ export class SqlSchemaGenerator {
|
|
|
682
629
|
return `ALTER TABLE ${this.escapeId(tableName)} ADD CONSTRAINT ${constraintName} PRIMARY KEY (${pkCols});`;
|
|
683
630
|
}
|
|
684
631
|
/**
|
|
685
|
-
* Drops
|
|
686
|
-
*
|
|
687
|
-
* `constraintName` has to be what the constraint is *actually* called: the name introspection
|
|
688
|
-
* reported for a key the database already had, or the derived one for a key this generator itself
|
|
689
|
-
* added, which is what reversing a migration drops. Guessing either way names nothing. MySQL takes
|
|
690
|
-
* no name at all - a table's key is always `PRIMARY` there.
|
|
632
|
+
* Drops the table's key, by the name the constraint really has: introspected, or derived where this
|
|
633
|
+
* generator added it. MySQL takes no name.
|
|
691
634
|
*/
|
|
692
635
|
generateDropPrimaryKeySql(tableName, constraintName) {
|
|
693
636
|
this.assertPrimaryKeyAlterable(tableName);
|
|
@@ -747,12 +690,8 @@ function foreignKeyOf(relation) {
|
|
|
747
690
|
};
|
|
748
691
|
}
|
|
749
692
|
/**
|
|
750
|
-
* The entities as an AST, named
|
|
751
|
-
*
|
|
752
|
-
* Its resolvers rather than a naming strategy, because the two disagree: a strategy renames whatever
|
|
753
|
-
* it is handed, while a generator leaves an explicit `@Entity({ name })` alone. Build the AST the
|
|
754
|
-
* other way and the table is created under one name and compared under another, which reports every
|
|
755
|
-
* table of a project using a naming strategy as both missing and unexpected.
|
|
693
|
+
* The entities as an AST, named by `generator`'s resolvers rather than a naming strategy, which would
|
|
694
|
+
* also rename an explicit `@Entity({ name })` and so compare each table under another name.
|
|
756
695
|
*/
|
|
757
696
|
export function buildEntityAST(generator, entities, defaultForeignKeyAction) {
|
|
758
697
|
return buildSchemaAST(entities, {
|