@mikro-orm/knex 6.0.0-dev.11 → 6.0.0-dev.110

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.
Files changed (39) hide show
  1. package/AbstractSqlConnection.d.ts +8 -4
  2. package/AbstractSqlConnection.js +30 -18
  3. package/AbstractSqlDriver.d.ts +16 -17
  4. package/AbstractSqlDriver.js +271 -113
  5. package/AbstractSqlPlatform.d.ts +5 -4
  6. package/AbstractSqlPlatform.js +34 -5
  7. package/MonkeyPatchable.d.ts +1 -0
  8. package/MonkeyPatchable.js +3 -0
  9. package/README.md +64 -107
  10. package/SqlEntityManager.d.ts +2 -6
  11. package/SqlEntityManager.js +5 -9
  12. package/SqlEntityRepository.d.ts +7 -6
  13. package/SqlEntityRepository.js +11 -8
  14. package/index.mjs +22 -6
  15. package/package.json +8 -8
  16. package/query/ArrayCriteriaNode.d.ts +3 -3
  17. package/query/CriteriaNode.d.ts +8 -8
  18. package/query/CriteriaNode.js +16 -9
  19. package/query/CriteriaNodeFactory.d.ts +6 -6
  20. package/query/CriteriaNodeFactory.js +10 -13
  21. package/query/ObjectCriteriaNode.d.ts +3 -3
  22. package/query/ObjectCriteriaNode.js +12 -8
  23. package/query/QueryBuilder.d.ts +39 -19
  24. package/query/QueryBuilder.js +331 -111
  25. package/query/QueryBuilderHelper.d.ts +9 -13
  26. package/query/QueryBuilderHelper.js +153 -107
  27. package/query/ScalarCriteriaNode.d.ts +3 -2
  28. package/query/ScalarCriteriaNode.js +9 -6
  29. package/query/enums.js +1 -1
  30. package/schema/DatabaseSchema.d.ts +5 -2
  31. package/schema/DatabaseSchema.js +26 -8
  32. package/schema/DatabaseTable.d.ts +4 -2
  33. package/schema/DatabaseTable.js +54 -29
  34. package/schema/SchemaComparator.js +12 -2
  35. package/schema/SchemaHelper.d.ts +6 -4
  36. package/schema/SchemaHelper.js +11 -4
  37. package/schema/SqlSchemaGenerator.d.ts +3 -6
  38. package/schema/SqlSchemaGenerator.js +61 -28
  39. package/typings.d.ts +13 -7
@@ -5,22 +5,12 @@ const core_1 = require("@mikro-orm/core");
5
5
  const DatabaseSchema_1 = require("./DatabaseSchema");
6
6
  const SchemaComparator_1 = require("./SchemaComparator");
7
7
  class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
8
- constructor() {
9
- super(...arguments);
10
- this.helper = this.platform.getSchemaHelper();
11
- this.options = this.config.get('schemaGenerator');
12
- }
8
+ helper = this.platform.getSchemaHelper();
9
+ options = this.config.get('schemaGenerator');
10
+ lastEnsuredDatabase;
13
11
  static register(orm) {
14
12
  orm.config.registerExtension('@mikro-orm/schema-generator', () => new SqlSchemaGenerator(orm.em));
15
13
  }
16
- /** @deprecated use `dropSchema` and `createSchema` commands respectively */
17
- async generate() {
18
- const [dropSchema, createSchema] = await Promise.all([
19
- this.getDropSchemaSQL({ wrap: false }),
20
- this.getCreateSchemaSQL({ wrap: false }),
21
- ]);
22
- return this.wrapSchema(dropSchema + createSchema);
23
- }
24
14
  async createSchema(options) {
25
15
  await this.ensureDatabase();
26
16
  const sql = await this.getCreateSchemaSQL(options);
@@ -101,7 +91,8 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
101
91
  await this.ensureDatabase();
102
92
  const wrap = options.wrap ?? this.options.disableForeignKeys;
103
93
  const metadata = this.getOrderedMetadata(options.schema).reverse();
104
- const schema = await DatabaseSchema_1.DatabaseSchema.create(this.connection, this.platform, this.config, options.schema);
94
+ const schemas = this.getTargetSchema(options.schema).getNamespaces();
95
+ const schema = await DatabaseSchema_1.DatabaseSchema.create(this.connection, this.platform, this.config, options.schema, schemas);
105
96
  let ret = '';
106
97
  // remove FKs explicitly if we can't use cascading statement and we don't disable FK checks (we need this for circular relations)
107
98
  for (const meta of metadata) {
@@ -118,6 +109,12 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
118
109
  for (const meta of metadata) {
119
110
  ret += await this.dump(this.dropTable(meta.collection, this.getSchemaName(meta, options)), '\n');
120
111
  }
112
+ if (this.platform.supportsNativeEnums()) {
113
+ for (const columnName of Object.keys(schema.getNativeEnums())) {
114
+ const sql = this.helper.getDropNativeEnumSQL(columnName, options.schema ?? this.config.get('schema'));
115
+ ret += await this.dump(this.knex.schema.raw(sql), '\n');
116
+ }
117
+ }
121
118
  if (options.dropMigrationsTable) {
122
119
  ret += await this.dump(this.dropTable(this.config.get('migrations').tableName, this.config.get('schema')), '\n');
123
120
  }
@@ -140,7 +137,9 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
140
137
  return this.diffToSQL(diffUp, options);
141
138
  }
142
139
  async getUpdateSchemaMigrationSQL(options = {}) {
143
- await this.ensureDatabase();
140
+ if (!options.fromSchema) {
141
+ await this.ensureDatabase();
142
+ }
144
143
  const { fromSchema, toSchema } = await this.prepareSchemaForComparison(options);
145
144
  const comparator = new SchemaComparator_1.SchemaComparator(this.platform);
146
145
  const diffUp = comparator.compare(fromSchema, toSchema);
@@ -151,14 +150,16 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
151
150
  };
152
151
  }
153
152
  async prepareSchemaForComparison(options) {
154
- options.wrap ?? (options.wrap = this.options.disableForeignKeys);
155
- options.safe ?? (options.safe = false);
156
- options.dropTables ?? (options.dropTables = true);
153
+ options.wrap ??= this.options.disableForeignKeys;
154
+ options.safe ??= false;
155
+ options.dropTables ??= true;
157
156
  const toSchema = this.getTargetSchema(options.schema);
158
- const fromSchema = options.fromSchema ?? await DatabaseSchema_1.DatabaseSchema.create(this.connection, this.platform, this.config, options.schema);
157
+ const schemas = toSchema.getNamespaces();
158
+ const fromSchema = options.fromSchema ?? await DatabaseSchema_1.DatabaseSchema.create(this.connection, this.platform, this.config, options.schema, schemas);
159
159
  const wildcardSchemaTables = Object.values(this.metadata.getAll()).filter(meta => meta.schema === '*').map(meta => meta.tableName);
160
160
  fromSchema.prune(options.schema, wildcardSchemaTables);
161
161
  toSchema.prune(options.schema, wildcardSchemaTables);
162
+ toSchema.setNativeEnums(fromSchema.getNativeEnums());
162
163
  return { fromSchema, toSchema };
163
164
  }
164
165
  async diffToSQL(schemaDiff, options) {
@@ -262,6 +263,12 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
262
263
  alterTable(diff, safe) {
263
264
  const ret = [];
264
265
  const [schemaName, tableName] = this.splitTableName(diff.name);
266
+ const changedNativeEnums = [];
267
+ for (const { column, changedProperties } of Object.values(diff.changedColumns)) {
268
+ if (column.nativeEnumName && changedProperties.has('enumItems') && column.nativeEnumName in diff.fromTable.nativeEnums) {
269
+ changedNativeEnums.push([column.nativeEnumName, column.enumItems, diff.fromTable.getColumn(column.name).enumItems]);
270
+ }
271
+ }
265
272
  ret.push(this.createSchemaBuilder(schemaName).alterTable(tableName, table => {
266
273
  for (const index of Object.values(diff.removedIndexes)) {
267
274
  this.dropIndex(table, index);
@@ -298,17 +305,20 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
298
305
  if (changedProperties.size === 1 && changedProperties.has('comment')) {
299
306
  continue;
300
307
  }
308
+ if (changedProperties.size === 1 && changedProperties.has('enumItems') && column.nativeEnumName) {
309
+ continue;
310
+ }
301
311
  const col = this.helper.createTableColumn(table, column, diff.fromTable, changedProperties).alter();
302
312
  this.helper.configureColumn(column, col, this.knex, changedProperties);
303
313
  }
304
314
  for (const { column } of Object.values(diff.changedColumns).filter(diff => diff.changedProperties.has('autoincrement'))) {
305
- this.helper.pushTableQuery(table, this.helper.getAlterColumnAutoincrement(tableName, column));
315
+ this.helper.pushTableQuery(table, this.helper.getAlterColumnAutoincrement(tableName, column, schemaName));
306
316
  }
307
317
  for (const { column, changedProperties } of Object.values(diff.changedColumns).filter(diff => diff.changedProperties.has('comment'))) {
308
318
  if (['type', 'nullable', 'autoincrement', 'unsigned', 'default', 'enumItems'].some(t => changedProperties.has(t))) {
309
319
  continue; // will be handled via knex
310
320
  }
311
- this.helper.pushTableQuery(table, this.helper.getChangeColumnCommentSQL(tableName, column));
321
+ this.helper.pushTableQuery(table, this.helper.getChangeColumnCommentSQL(tableName, column, schemaName));
312
322
  }
313
323
  for (const [oldColumnName, column] of Object.entries(diff.renamedColumns)) {
314
324
  this.helper.pushTableQuery(table, this.helper.getRenameColumnSQL(tableName, oldColumnName, column, schemaName));
@@ -345,6 +355,13 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
345
355
  table.comment(comment);
346
356
  }
347
357
  }));
358
+ if (this.platform.supportsNativeEnums()) {
359
+ changedNativeEnums.forEach(([enumName, itemsNew, itemsOld]) => {
360
+ // postgres allows only adding new items
361
+ const newItems = itemsNew.filter(val => !itemsOld.includes(val));
362
+ ret.push(...newItems.map(val => this.knex.schema.raw(this.helper.getAlterNativeEnumSQL(enumName, schemaName, val))));
363
+ });
364
+ }
348
365
  return ret;
349
366
  }
350
367
  /**
@@ -356,24 +373,26 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
356
373
  await this.driver.reconnect();
357
374
  }
358
375
  async dropDatabase(name) {
376
+ name ??= this.config.get('dbName');
359
377
  this.config.set('dbName', this.helper.getManagementDbName());
360
378
  await this.driver.reconnect();
361
379
  await this.driver.execute(this.helper.getDropDatabaseSQL('' + this.knex.ref(name)));
362
380
  }
363
381
  async execute(sql, options = {}) {
364
- options.wrap ?? (options.wrap = false);
382
+ options.wrap ??= false;
365
383
  const lines = this.wrapSchema(sql, options).split('\n').filter(i => i.trim());
366
384
  if (lines.length === 0) {
367
385
  return;
368
386
  }
369
387
  if (this.platform.supportsMultipleStatements()) {
370
388
  const query = lines.join('\n');
371
- return void await this.driver.execute(query);
389
+ await this.driver.execute(query);
390
+ return;
372
391
  }
373
392
  await core_1.Utils.runSerial(lines, line => this.driver.execute(line));
374
393
  }
375
- wrapSchema(sql, options = {}) {
376
- options.wrap ?? (options.wrap = this.options.disableForeignKeys);
394
+ wrapSchema(sql, options) {
395
+ options.wrap ??= this.options.disableForeignKeys;
377
396
  if (!options.wrap || sql.trim() === '') {
378
397
  return sql;
379
398
  }
@@ -423,7 +442,14 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
423
442
  table.primary(index.columnNames, keyName);
424
443
  }
425
444
  else if (index.unique) {
426
- table.unique(index.columnNames, { indexName: index.keyName });
445
+ // JSON columns can have unique index but not unique constraint, and we need to distinguish those, so we can properly drop them
446
+ if (index.columnNames.some(column => column.includes('.'))) {
447
+ const columns = this.platform.getJsonIndexDefinition(index);
448
+ table.index(columns.map(column => this.knex.raw(`(${column})`)), index.keyName, { indexType: 'unique' });
449
+ }
450
+ else {
451
+ table.unique(index.columnNames, { indexName: index.keyName });
452
+ }
427
453
  }
428
454
  else if (index.expression) {
429
455
  this.helper.pushTableQuery(table, index.expression);
@@ -435,14 +461,21 @@ class SqlSchemaGenerator extends core_1.AbstractSchemaGenerator {
435
461
  }
436
462
  }
437
463
  else {
438
- table.index(index.columnNames, index.keyName, index.type);
464
+ // JSON columns can have unique index but not unique constraint, and we need to distinguish those, so we can properly drop them
465
+ if (index.columnNames.some(column => column.includes('.'))) {
466
+ const columns = this.platform.getJsonIndexDefinition(index);
467
+ table.index(columns.map(column => this.knex.raw(`(${column})`)), index.keyName, index.type);
468
+ }
469
+ else {
470
+ table.index(index.columnNames, index.keyName, index.type);
471
+ }
439
472
  }
440
473
  }
441
474
  dropIndex(table, index, oldIndexName = index.keyName) {
442
475
  if (index.primary) {
443
476
  table.dropPrimary(oldIndexName);
444
477
  }
445
- else if (index.unique) {
478
+ else if (index.unique && index.constraint) {
446
479
  table.dropUnique(index.columnNames, oldIndexName);
447
480
  }
448
481
  else {
package/typings.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { Knex } from 'knex';
2
- import type { CheckCallback, Dictionary, EntityProperty, GroupOperator, QBFilterQuery, QueryOrderMap, Type } from '@mikro-orm/core';
2
+ import type { CheckCallback, Dictionary, EntityProperty, GroupOperator, RawQueryFragment, QBFilterQuery, QueryOrderMap, Type } from '@mikro-orm/core';
3
3
  import type { QueryType } from './query/enums';
4
4
  import type { DatabaseSchema, DatabaseTable } from './schema';
5
5
  export interface Table {
@@ -11,7 +11,7 @@ export type KnexStringRef = Knex.Ref<string, {
11
11
  [alias: string]: string;
12
12
  }>;
13
13
  type AnyString = string & {};
14
- export type Field<T> = AnyString | keyof T | KnexStringRef | Knex.QueryBuilder;
14
+ export type Field<T> = AnyString | keyof T | RawQueryFragment | KnexStringRef | Knex.QueryBuilder;
15
15
  export interface JoinOptions {
16
16
  table: string;
17
17
  schema?: string;
@@ -25,6 +25,8 @@ export interface JoinOptions {
25
25
  path?: string;
26
26
  prop: EntityProperty;
27
27
  cond: Dictionary;
28
+ cond_?: Dictionary;
29
+ subquery?: string;
28
30
  }
29
31
  export interface Column {
30
32
  name: string;
@@ -38,6 +40,7 @@ export interface Column {
38
40
  scale?: number;
39
41
  default?: string | null;
40
42
  comment?: string;
43
+ nativeEnumName?: string;
41
44
  enumItems?: string[];
42
45
  primary?: boolean;
43
46
  unique?: boolean;
@@ -58,9 +61,11 @@ export interface IndexDef {
58
61
  columnNames: string[];
59
62
  keyName: string;
60
63
  unique: boolean;
64
+ constraint: boolean;
61
65
  primary: boolean;
62
66
  composite?: boolean;
63
67
  expression?: string;
68
+ options?: Dictionary;
64
69
  type?: string | Readonly<{
65
70
  indexType?: string;
66
71
  storageEngineIndexType?: 'hash' | 'btree';
@@ -122,7 +127,8 @@ export interface IQueryBuilder<T> {
122
127
  join(field: string, alias: string, cond?: QBFilterQuery, type?: 'leftJoin' | 'innerJoin' | 'pivotJoin', path?: string): this;
123
128
  leftJoin(field: string, alias: string, cond?: QBFilterQuery): this;
124
129
  joinAndSelect(field: string, alias: string, cond?: QBFilterQuery): this;
125
- leftJoinAndSelect(field: string, alias: string, cond?: QBFilterQuery): this;
130
+ leftJoinAndSelect(field: string, alias: string, cond?: QBFilterQuery, fields?: string[]): this;
131
+ innerJoinAndSelect(field: string, alias: string, cond?: QBFilterQuery, fields?: string[]): this;
126
132
  withSubQuery(subQuery: Knex.QueryBuilder, alias: string): this;
127
133
  where(cond: QBFilterQuery<T>, operator?: keyof typeof GroupOperator): this;
128
134
  where(cond: string, params?: any[], operator?: keyof typeof GroupOperator): this;
@@ -136,16 +142,16 @@ export interface IQueryBuilder<T> {
136
142
  getAliasForJoinPath(path: string): string | undefined;
137
143
  getNextAlias(entityName?: string): string;
138
144
  }
139
- export interface ICriteriaNode {
145
+ export interface ICriteriaNode<T extends object> {
140
146
  readonly entityName: string;
141
- readonly parent?: ICriteriaNode | undefined;
147
+ readonly parent?: ICriteriaNode<T> | undefined;
142
148
  readonly key?: string | undefined;
143
149
  payload: any;
144
150
  prop?: EntityProperty;
145
151
  index?: number;
146
- process<T>(qb: IQueryBuilder<T>, alias?: string): any;
152
+ process(qb: IQueryBuilder<T>, alias?: string): any;
147
153
  shouldInline(payload: any): boolean;
148
- willAutoJoin<T>(qb: IQueryBuilder<T>, alias?: string): boolean;
154
+ willAutoJoin(qb: IQueryBuilder<T>, alias?: string): boolean;
149
155
  shouldRename(payload: any): boolean;
150
156
  renameFieldToPK<T>(qb: IQueryBuilder<T>): string;
151
157
  getPath(addIndex?: boolean): string;