@mikro-orm/knex 6.0.0-dev.7 → 6.0.0-dev.70

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 (41) hide show
  1. package/AbstractSqlConnection.d.ts +5 -2
  2. package/AbstractSqlConnection.js +22 -14
  3. package/AbstractSqlDriver.d.ts +17 -17
  4. package/AbstractSqlDriver.js +111 -48
  5. package/AbstractSqlPlatform.d.ts +1 -0
  6. package/AbstractSqlPlatform.js +20 -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 -5
  11. package/SqlEntityManager.js +5 -9
  12. package/SqlEntityRepository.d.ts +6 -4
  13. package/SqlEntityRepository.js +10 -8
  14. package/index.d.ts +1 -0
  15. package/index.js +1 -0
  16. package/index.mjs +175 -0
  17. package/package.json +5 -5
  18. package/query/ArrayCriteriaNode.d.ts +3 -3
  19. package/query/CriteriaNode.d.ts +8 -8
  20. package/query/CriteriaNode.js +9 -9
  21. package/query/CriteriaNodeFactory.d.ts +6 -6
  22. package/query/CriteriaNodeFactory.js +10 -13
  23. package/query/ObjectCriteriaNode.d.ts +3 -3
  24. package/query/ObjectCriteriaNode.js +12 -8
  25. package/query/QueryBuilder.d.ts +20 -5
  26. package/query/QueryBuilder.js +215 -50
  27. package/query/QueryBuilderHelper.d.ts +3 -5
  28. package/query/QueryBuilderHelper.js +90 -74
  29. package/query/ScalarCriteriaNode.d.ts +3 -2
  30. package/query/ScalarCriteriaNode.js +9 -6
  31. package/schema/DatabaseSchema.d.ts +4 -1
  32. package/schema/DatabaseSchema.js +22 -6
  33. package/schema/DatabaseTable.d.ts +10 -9
  34. package/schema/DatabaseTable.js +25 -24
  35. package/schema/SchemaComparator.d.ts +4 -4
  36. package/schema/SchemaComparator.js +9 -2
  37. package/schema/SchemaHelper.d.ts +14 -12
  38. package/schema/SchemaHelper.js +10 -4
  39. package/schema/SqlSchemaGenerator.d.ts +2 -4
  40. package/schema/SqlSchemaGenerator.js +40 -20
  41. package/typings.d.ts +15 -13
@@ -19,6 +19,10 @@ class QueryBuilderHelper {
19
19
  this.metadata = this.driver.getMetadata();
20
20
  }
21
21
  mapper(field, type = enums_1.QueryType.SELECT, value, alias) {
22
+ if (core_1.Utils.isRawSql(field)) {
23
+ return this.knex.raw(field.sql, field.params);
24
+ }
25
+ /* istanbul ignore next */
22
26
  if (typeof field !== 'string') {
23
27
  return field;
24
28
  }
@@ -36,12 +40,26 @@ class QueryBuilderHelper {
36
40
  parts.push(this.mapper(a !== this.alias ? `${a}.${f}` : f, type, value, alias));
37
41
  }
38
42
  }
43
+ // flatten the value if we see we are expanding nested composite key
44
+ // hackish, but cleaner solution would require quite a lot of refactoring
45
+ if (fields.length !== parts.length && Array.isArray(value)) {
46
+ value.forEach(row => {
47
+ if (Array.isArray(row)) {
48
+ const tmp = core_1.Utils.flatten(row);
49
+ row.length = 0;
50
+ row.push(...tmp);
51
+ }
52
+ });
53
+ }
39
54
  return this.knex.raw('(' + parts.map(part => this.knex.ref(part)).join(', ') + ')');
40
55
  }
41
- let ret = field;
42
- const customExpression = QueryBuilderHelper.isCustomExpression(field, !!alias);
56
+ const rawField = core_1.RawQueryFragment.getKnownFragment(field);
57
+ if (rawField) {
58
+ return this.knex.raw(rawField.sql, rawField.params);
59
+ }
43
60
  const [a, f] = this.splitField(field);
44
61
  const prop = this.getProperty(f, a);
62
+ let ret = field;
45
63
  // embeddable nested path instead of a regular property with table alias, reset alias
46
64
  if (prop?.name === a && prop.embeddedProps[f]) {
47
65
  return this.alias + '.' + prop.fieldNames[0];
@@ -56,7 +74,7 @@ class QueryBuilderHelper {
56
74
  const as = alias === null ? '' : ` as ${aliased}`;
57
75
  return this.knex.raw(`${prop.formula(alias2)}${as}`);
58
76
  }
59
- if (prop?.customType?.convertToJSValueSQL) {
77
+ if (prop?.hasConvertToJSValueSQL) {
60
78
  const prefixed = this.prefix(field, isTableNameAliasRequired, true);
61
79
  const valueSQL = prop.customType.convertToJSValueSQL(prefixed, this.platform);
62
80
  if (alias === null) {
@@ -65,15 +83,12 @@ class QueryBuilderHelper {
65
83
  return this.knex.raw(`${valueSQL} as ${this.platform.quoteIdentifier(alias ?? prop.fieldNames[0])}`);
66
84
  }
67
85
  // do not wrap custom expressions
68
- if (!customExpression) {
86
+ if (!rawField) {
69
87
  ret = this.prefix(field);
70
88
  }
71
89
  if (alias) {
72
90
  ret += ' as ' + alias;
73
91
  }
74
- if (customExpression) {
75
- return this.knex.raw(ret, value);
76
- }
77
92
  if (!isTableNameAliasRequired || this.isPrefixed(ret) || noPrefix) {
78
93
  return ret;
79
94
  }
@@ -162,6 +177,11 @@ class QueryBuilderHelper {
162
177
  const right = `${join.alias}.${join.joinColumns[idx]}`;
163
178
  conditions.push(`${this.knex.ref(left)} = ${this.knex.ref(right)}`);
164
179
  });
180
+ if (join.prop.targetMeta.discriminatorValue && !join.path?.endsWith('[pivot]')) {
181
+ const typeProperty = join.prop.targetMeta.root.discriminatorColumn;
182
+ const alias = !join.prop.owner ? join.inverseAlias ?? join.alias : join.ownerAlias;
183
+ join.cond[`${alias}.${typeProperty}`] = join.prop.targetMeta.discriminatorValue;
184
+ }
165
185
  Object.keys(join.cond).forEach(key => {
166
186
  conditions.push(this.processJoinClause(key, join.cond[key], params));
167
187
  });
@@ -212,20 +232,14 @@ class QueryBuilderHelper {
212
232
  if (operator === '$exists') {
213
233
  value = null;
214
234
  }
215
- if (QueryBuilderHelper.isCustomExpression(key)) {
216
- // unwind parameters when ? found in field name
217
- const count = key.concat('?').match(/\?/g).length - 1;
218
- const values = core_1.Utils.asArray(value);
219
- const params1 = values.slice(0, count).map((c) => core_1.Utils.isObject(c) ? JSON.stringify(c) : c);
220
- const params2 = values.slice(count);
221
- const k = this.mapper(key, enums_1.QueryType.SELECT, params1);
222
- const { sql, bindings } = k.toSQL().toNative();
223
- if (params2.length > 0) {
224
- params.push(...bindings);
225
- params.push(...params2);
226
- return sql + ' = ?';
235
+ const rawField = core_1.RawQueryFragment.getKnownFragment(key);
236
+ if (rawField) {
237
+ let sql = rawField.sql;
238
+ params.push(...rawField.params);
239
+ params.push(...core_1.Utils.asArray(value));
240
+ if (core_1.Utils.asArray(value).length > 0) {
241
+ sql += ' = ?';
227
242
  }
228
- params.push(...bindings);
229
243
  return sql;
230
244
  }
231
245
  const sql = this.mapper(key);
@@ -241,7 +255,7 @@ class QueryBuilderHelper {
241
255
  return `(${parts.join(` ${core_1.GroupOperator[operator]} `)})`;
242
256
  }
243
257
  mapJoinColumns(type, join) {
244
- if (join.prop && join.prop.reference === core_1.ReferenceType.ONE_TO_ONE && !join.prop.owner) {
258
+ if (join.prop && join.prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !join.prop.owner) {
245
259
  return join.prop.fieldNames.map((fieldName, idx) => {
246
260
  return this.mapper(`${join.alias}.${join.inverseJoinColumns[idx]}`, type, undefined, fieldName);
247
261
  });
@@ -254,7 +268,7 @@ class QueryBuilderHelper {
254
268
  isOneToOneInverse(field) {
255
269
  const meta = this.metadata.find(this.entityName);
256
270
  const prop = meta.properties[field];
257
- return prop && prop.reference === core_1.ReferenceType.ONE_TO_ONE && !prop.owner;
271
+ return prop && prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner;
258
272
  }
259
273
  getTableName(entityName) {
260
274
  const meta = this.metadata.find(entityName);
@@ -293,13 +307,13 @@ class QueryBuilderHelper {
293
307
  }
294
308
  appendOnConflictClause(type, onConflict, qb) {
295
309
  onConflict.forEach(item => {
296
- const sub = qb.onConflict(item.fields);
310
+ const sub = item.fields.length > 0 ? qb.onConflict(item.fields) : qb.onConflict();
297
311
  core_1.Utils.runIfNotEmpty(() => sub.ignore(), item.ignore);
298
312
  core_1.Utils.runIfNotEmpty(() => {
299
313
  let mergeParam = item.merge;
300
314
  if (core_1.Utils.isObject(item.merge)) {
301
315
  mergeParam = {};
302
- Object.keys(item.merge).forEach(key => {
316
+ core_1.Utils.keys(item.merge).forEach(key => {
303
317
  const k = this.mapper(key, type);
304
318
  mergeParam[k] = item.merge[key];
305
319
  });
@@ -336,28 +350,20 @@ class QueryBuilderHelper {
336
350
  if (core_1.Utils.isPlainObject(cond[key]) || cond[key] instanceof RegExp) {
337
351
  return this.processObjectSubCondition(cond, key, qb, method, m, type);
338
352
  }
339
- if (QueryBuilderHelper.isCustomExpression(key)) {
340
- return this.processCustomExpression(qb, m, key, cond, type);
341
- }
342
353
  const op = cond[key] === null ? 'is' : '=';
354
+ const raw = core_1.RawQueryFragment.getKnownFragment(key);
355
+ if (raw) {
356
+ const value = core_1.Utils.asArray(cond[key]);
357
+ if (value.length > 0) {
358
+ return void qb[m](this.knex.raw(raw.sql, raw.params), op, value[0]);
359
+ }
360
+ return void qb[m](this.knex.raw(raw.sql, raw.params));
361
+ }
343
362
  if (this.subQueries[key]) {
344
363
  return void qb[m](this.knex.raw(`(${this.subQueries[key]})`), op, cond[key]);
345
364
  }
346
365
  qb[m](this.mapper(key, type, cond[key], null), op, cond[key]);
347
366
  }
348
- processCustomExpression(clause, m, key, cond, type) {
349
- // unwind parameters when ? found in field name
350
- const count = key.concat('?').match(/\?/g).length - 1;
351
- const value = core_1.Utils.asArray(cond[key]);
352
- const params1 = value.slice(0, count).map((c) => core_1.Utils.isObject(c) ? JSON.stringify(c) : c);
353
- const params2 = value.slice(count);
354
- const k = this.mapper(key, type, params1);
355
- if (params2.length > 0) {
356
- const val = params2.length === 1 && params2[0] === null ? null : this.knex.raw('?', params2);
357
- return void clause[m](k, val);
358
- }
359
- clause[m](k);
360
- }
361
367
  processObjectSubCondition(cond, key, qb, method, m, type) {
362
368
  // grouped condition for one field
363
369
  let value = cond[key];
@@ -394,7 +400,8 @@ class QueryBuilderHelper {
394
400
  }));
395
401
  }
396
402
  else {
397
- qb[m](this.mapper(key, type, undefined, null), replacement, value[op]);
403
+ const mappedKey = this.mapper(key, type, value[op], null);
404
+ qb[m](mappedKey, replacement, value[op]);
398
405
  }
399
406
  }
400
407
  getOperatorReplacement(op, value) {
@@ -422,20 +429,21 @@ class QueryBuilderHelper {
422
429
  }
423
430
  getQueryOrderFromObject(type, orderBy, populate) {
424
431
  const ret = [];
425
- Object.keys(orderBy).forEach(k => {
426
- const direction = orderBy[k];
432
+ Object.keys(orderBy).forEach(key => {
433
+ const direction = orderBy[key];
427
434
  const order = core_1.Utils.isNumber(direction) ? core_1.QueryOrderNumeric[direction] : direction;
428
- if (QueryBuilderHelper.isCustomExpression(k)) {
429
- ret.push(`${k} ${order.toLowerCase()}`);
435
+ const raw = core_1.RawQueryFragment.getKnownFragment(key);
436
+ if (raw) {
437
+ ret.push(`${this.platform.formatQuery(raw.sql, raw.params)} ${order.toLowerCase()}`);
430
438
  return;
431
439
  }
432
- // eslint-disable-next-line prefer-const
433
- let [alias, field] = this.splitField(k, true);
434
- alias = populate[alias] || alias;
435
- core_1.Utils.splitPrimaryKeys(field).forEach(f => {
436
- const prop = this.getProperty(f, alias);
437
- const noPrefix = (prop && prop.persist === false && !prop.formula) || QueryBuilderHelper.isCustomExpression(f);
438
- const column = this.mapper(noPrefix ? f : `${alias}.${f}`, type, undefined, null);
440
+ core_1.Utils.splitPrimaryKeys(key).forEach(f => {
441
+ // eslint-disable-next-line prefer-const
442
+ let [alias, field] = this.splitField(f, true);
443
+ alias = populate[alias] || alias;
444
+ const prop = this.getProperty(field, alias);
445
+ const noPrefix = (prop && prop.persist === false && !prop.formula) || core_1.RawQueryFragment.isKnownFragment(f);
446
+ const column = this.mapper(noPrefix ? field : `${alias}.${field}`, type, undefined, null);
439
447
  /* istanbul ignore next */
440
448
  const rawColumn = core_1.Utils.isString(column) ? column.split('.').map(e => this.knex.ref(e)).join('.') : column;
441
449
  const customOrder = prop?.customOrder;
@@ -447,11 +455,23 @@ class QueryBuilderHelper {
447
455
  });
448
456
  return ret.join(', ');
449
457
  }
450
- finalize(type, qb, meta) {
451
- const useReturningStatement = type === enums_1.QueryType.INSERT && this.platform.usesReturningStatement() && meta && !meta.compositePK;
452
- if (useReturningStatement) {
453
- const returningProps = meta.hydrateProps.filter(prop => prop.persist !== false && (prop.primary || prop.defaultRaw));
454
- qb.returning(core_1.Utils.flatten(returningProps.map(prop => prop.fieldNames)));
458
+ finalize(type, qb, meta, data) {
459
+ if (!meta || !data || !this.platform.usesReturningStatement()) {
460
+ return;
461
+ }
462
+ if (type === enums_1.QueryType.INSERT) {
463
+ const returningProps = meta.hydrateProps
464
+ .filter(prop => prop.persist !== false && ((prop.primary && prop.autoincrement) || prop.defaultRaw))
465
+ .filter(prop => !(prop.name in data) || core_1.Utils.isRawSql(data[prop.name]));
466
+ if (returningProps.length > 0) {
467
+ qb.returning(core_1.Utils.flatten(returningProps.map(prop => prop.fieldNames)));
468
+ }
469
+ }
470
+ if (type === enums_1.QueryType.UPDATE) {
471
+ const returningProps = meta.hydrateProps.filter(prop => core_1.Utils.isRawSql(data[prop.name]));
472
+ if (returningProps.length > 0) {
473
+ qb.returning(core_1.Utils.flatten(returningProps.map(prop => prop.fieldNames)));
474
+ }
455
475
  }
456
476
  }
457
477
  splitField(field, greedyAlias = false) {
@@ -494,18 +514,13 @@ class QueryBuilderHelper {
494
514
  }
495
515
  qb.update(versionProperty.fieldNames[0], this.knex.raw(sql));
496
516
  }
497
- static isCustomExpression(field, hasAlias = false) {
498
- // if we do not have alias, we don't consider spaces as custom expressions
499
- const re = hasAlias ? /[ ?<>=()'"`:]|^\d/ : /[?<>=()'"`:]|^\d/;
500
- return !!field.match(re);
501
- }
502
517
  prefix(field, always = false, quote = false) {
503
518
  let ret;
504
519
  if (!this.isPrefixed(field)) {
505
520
  const alias = always ? (quote ? this.alias : this.platform.quoteIdentifier(this.alias)) + '.' : '';
506
521
  const fieldName = this.fieldName(field, this.alias, always);
507
- if (QueryBuilderHelper.isCustomExpression(fieldName)) {
508
- return fieldName;
522
+ if (fieldName instanceof core_1.RawQueryFragment) {
523
+ return fieldName.sql;
509
524
  }
510
525
  ret = alias + fieldName;
511
526
  }
@@ -545,15 +560,15 @@ class QueryBuilderHelper {
545
560
  }
546
561
  if (prop.fieldNameRaw) {
547
562
  if (!always) {
548
- return prop.fieldNameRaw
549
- .replace(/\[::alias::]\.?/g, '')
550
- .replace(this.platform.quoteIdentifier('') + '.', '');
563
+ return (0, core_1.raw)(prop.fieldNameRaw
564
+ .replace(new RegExp(core_1.ALIAS_REPLACEMENT_RE + '\\.?', 'g'), '')
565
+ .replace(this.platform.quoteIdentifier('') + '.', ''));
551
566
  }
552
567
  if (alias) {
553
- return prop.fieldNameRaw.replace(/\[::alias::]/g, alias);
568
+ return (0, core_1.raw)(prop.fieldNameRaw.replace(new RegExp(core_1.ALIAS_REPLACEMENT_RE, 'g'), alias));
554
569
  }
555
570
  /* istanbul ignore next */
556
- return prop.fieldNameRaw;
571
+ return (0, core_1.raw)(prop.fieldNameRaw);
557
572
  }
558
573
  /* istanbul ignore next */
559
574
  return prop.fieldNames?.[0] ?? field;
@@ -564,7 +579,7 @@ class QueryBuilderHelper {
564
579
  // check if `alias` is not matching an embedded property name instead of alias, e.g. `address.city`
565
580
  if (alias && meta) {
566
581
  const prop = meta.properties[alias];
567
- if (prop?.reference === core_1.ReferenceType.EMBEDDED) {
582
+ if (prop?.kind === core_1.ReferenceKind.EMBEDDED) {
568
583
  // we want to select the full object property so hydration works as expected
569
584
  if (prop.object) {
570
585
  return prop;
@@ -596,17 +611,18 @@ class QueryBuilderHelper {
596
611
  return;
597
612
  }
598
613
  if (prop.joinColumns && Array.isArray(data[k])) {
599
- const copy = data[k];
614
+ const copy = core_1.Utils.flatten(data[k]);
600
615
  delete data[k];
601
616
  prop.joinColumns.forEach((joinColumn, idx) => data[joinColumn] = copy[idx]);
602
617
  return;
603
618
  }
604
619
  if (prop.customType && convertCustomTypes && !this.platform.isRaw(data[k])) {
605
- data[k] = prop.customType.convertToDatabaseValue(data[k], this.platform, { fromQuery: true, key: k, mode: 'query' });
620
+ data[k] = prop.customType.convertToDatabaseValue(data[k], this.platform, { fromQuery: true, key: k, mode: 'query-data' });
606
621
  }
607
- if (prop.customType && 'convertToDatabaseValueSQL' in prop.customType && !this.platform.isRaw(data[k])) {
622
+ if (prop.hasConvertToDatabaseValueSQL && !this.platform.isRaw(data[k])) {
608
623
  const quoted = this.platform.quoteValue(data[k]);
609
- data[k] = this.knex.raw(prop.customType.convertToDatabaseValueSQL(quoted, this.platform).replace(/\?/, '\\?'));
624
+ const sql = prop.customType.convertToDatabaseValueSQL(quoted, this.platform);
625
+ data[k] = this.knex.raw(sql.replace(/\?/, '\\?'));
610
626
  }
611
627
  if (!prop.customType && (Array.isArray(data[k]) || core_1.Utils.isPlainObject(data[k]))) {
612
628
  data[k] = JSON.stringify(data[k]);
@@ -3,7 +3,8 @@ import type { IQueryBuilder } from '../typings';
3
3
  /**
4
4
  * @internal
5
5
  */
6
- export declare class ScalarCriteriaNode extends CriteriaNode {
7
- process<T>(qb: IQueryBuilder<T>, alias?: string): any;
6
+ export declare class ScalarCriteriaNode<T extends object> extends CriteriaNode<T> {
7
+ process(qb: IQueryBuilder<T>, alias?: string): any;
8
+ willAutoJoin<T>(qb: IQueryBuilder<T>, alias?: string): boolean;
8
9
  shouldJoin(): boolean;
9
10
  }
@@ -13,23 +13,26 @@ class ScalarCriteriaNode extends CriteriaNode_1.CriteriaNode {
13
13
  const parentPath = this.parent.getPath(); // the parent is always there, otherwise `shouldJoin` would return `false`
14
14
  const nestedAlias = qb.getAliasForJoinPath(path) || qb.getNextAlias(this.prop?.pivotTable ?? this.entityName);
15
15
  const field = `${alias}.${this.prop.name}`;
16
- const type = this.prop.reference === core_1.ReferenceType.MANY_TO_MANY ? 'pivotJoin' : 'leftJoin';
16
+ const type = this.prop.kind === core_1.ReferenceKind.MANY_TO_MANY ? 'pivotJoin' : 'leftJoin';
17
17
  qb.join(field, nestedAlias, undefined, type, path);
18
18
  // select the owner as virtual property when joining from 1:1 inverse side, but only if the parent is root entity
19
- if (this.prop.reference === core_1.ReferenceType.ONE_TO_ONE && !parentPath.includes('.')) {
19
+ if (this.prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !parentPath.includes('.')) {
20
20
  qb.addSelect(field);
21
21
  }
22
22
  }
23
23
  return this.payload;
24
24
  }
25
+ willAutoJoin(qb, alias) {
26
+ return this.shouldJoin();
27
+ }
25
28
  shouldJoin() {
26
29
  if (!this.parent || !this.prop) {
27
30
  return false;
28
31
  }
29
- switch (this.prop.reference) {
30
- case core_1.ReferenceType.ONE_TO_MANY: return true;
31
- case core_1.ReferenceType.MANY_TO_MANY: return true;
32
- case core_1.ReferenceType.ONE_TO_ONE: return !this.prop.owner;
32
+ switch (this.prop.kind) {
33
+ case core_1.ReferenceKind.ONE_TO_MANY: return true;
34
+ case core_1.ReferenceKind.MANY_TO_MANY: return true;
35
+ case core_1.ReferenceKind.ONE_TO_ONE: return !this.prop.owner;
33
36
  default: return false; // SCALAR, MANY_TO_ONE
34
37
  }
35
38
  }
@@ -10,14 +10,17 @@ export declare class DatabaseSchema {
10
10
  readonly name: string;
11
11
  private tables;
12
12
  private namespaces;
13
+ private nativeEnums;
13
14
  constructor(platform: AbstractSqlPlatform, name: string);
14
15
  addTable(name: string, schema: string | undefined | null, comment?: string): DatabaseTable;
15
16
  getTables(): DatabaseTable[];
16
17
  getTable(name: string): DatabaseTable | undefined;
17
18
  hasTable(name: string): boolean;
19
+ setNativeEnums(nativeEnums: Dictionary<unknown[]>): void;
20
+ getNativeEnums(): Dictionary<unknown[]>;
18
21
  hasNamespace(namespace: string): boolean;
19
22
  getNamespaces(): string[];
20
- static create(connection: AbstractSqlConnection, platform: AbstractSqlPlatform, config: Configuration, schemaName?: string): Promise<DatabaseSchema>;
23
+ static create(connection: AbstractSqlConnection, platform: AbstractSqlPlatform, config: Configuration, schemaName?: string, schemas?: string[]): Promise<DatabaseSchema>;
21
24
  static fromMetadata(metadata: EntityMetadata[], platform: AbstractSqlPlatform, config: Configuration, schemaName?: string): DatabaseSchema;
22
25
  private static getSchemaName;
23
26
  private static shouldHaveColumn;
@@ -12,10 +12,12 @@ class DatabaseSchema {
12
12
  this.name = name;
13
13
  this.tables = [];
14
14
  this.namespaces = new Set();
15
+ this.nativeEnums = {}; // for postgres
15
16
  }
16
17
  addTable(name, schema, comment) {
17
18
  const namespaceName = schema ?? this.name;
18
19
  const table = new DatabaseTable_1.DatabaseTable(this.platform, name, namespaceName);
20
+ table.nativeEnums = this.nativeEnums;
19
21
  table.comment = comment;
20
22
  this.tables.push(table);
21
23
  if (namespaceName != null) {
@@ -32,24 +34,38 @@ class DatabaseSchema {
32
34
  hasTable(name) {
33
35
  return !!this.getTable(name);
34
36
  }
37
+ setNativeEnums(nativeEnums) {
38
+ this.nativeEnums = nativeEnums;
39
+ this.tables.forEach(t => t.nativeEnums = nativeEnums);
40
+ }
41
+ getNativeEnums() {
42
+ return this.nativeEnums;
43
+ }
35
44
  hasNamespace(namespace) {
36
45
  return this.namespaces.has(namespace);
37
46
  }
38
47
  getNamespaces() {
39
48
  return [...this.namespaces];
40
49
  }
41
- static async create(connection, platform, config, schemaName) {
42
- const schema = new DatabaseSchema(platform, schemaName ?? config.get('schema'));
50
+ static async create(connection, platform, config, schemaName, schemas) {
51
+ const schema = new DatabaseSchema(platform, schemaName ?? config.get('schema') ?? platform.getDefaultSchemaName());
43
52
  const allTables = await connection.execute(platform.getSchemaHelper().getListTablesSQL());
44
53
  const parts = config.get('migrations').tableName.split('.');
45
54
  const migrationsTableName = parts[1] ?? parts[0];
46
55
  const migrationsSchemaName = parts.length > 1 ? parts[0] : config.get('schema', platform.getDefaultSchemaName());
47
56
  const tables = allTables.filter(t => t.table_name !== migrationsTableName || (t.schema_name && t.schema_name !== migrationsSchemaName));
48
- await platform.getSchemaHelper().loadInformationSchema(schema, connection, tables);
57
+ await platform.getSchemaHelper().loadInformationSchema(schema, connection, tables, schemas && schemas.length > 0 ? schemas : undefined);
49
58
  return schema;
50
59
  }
51
60
  static fromMetadata(metadata, platform, config, schemaName) {
52
61
  const schema = new DatabaseSchema(platform, schemaName ?? config.get('schema'));
62
+ const nativeEnums = {};
63
+ for (const meta of metadata) {
64
+ meta.props
65
+ .filter(prop => prop.nativeEnumName)
66
+ .forEach(prop => nativeEnums[prop.nativeEnumName] = prop.items?.map(val => '' + val) ?? []);
67
+ }
68
+ schema.setNativeEnums(nativeEnums);
53
69
  for (const meta of metadata) {
54
70
  const table = schema.addTable(meta.collection, this.getSchemaName(meta, config, schemaName));
55
71
  table.comment = meta.comment;
@@ -78,15 +94,15 @@ class DatabaseSchema {
78
94
  if (prop.persist === false || !prop.fieldNames) {
79
95
  return false;
80
96
  }
81
- if (meta.pivotTable || (core_1.ReferenceType.EMBEDDED && prop.object)) {
97
+ if (meta.pivotTable || (core_1.ReferenceKind.EMBEDDED && prop.object)) {
82
98
  return true;
83
99
  }
84
100
  const getRootProperty = (prop) => prop.embedded ? getRootProperty(meta.properties[prop.embedded[0]]) : prop;
85
101
  const rootProp = getRootProperty(prop);
86
- if (rootProp.reference === core_1.ReferenceType.EMBEDDED) {
102
+ if (rootProp.kind === core_1.ReferenceKind.EMBEDDED) {
87
103
  return prop === rootProp || !rootProp.object;
88
104
  }
89
- return [core_1.ReferenceType.SCALAR, core_1.ReferenceType.MANY_TO_ONE].includes(prop.reference) || (prop.reference === core_1.ReferenceType.ONE_TO_ONE && prop.owner);
105
+ return [core_1.ReferenceKind.SCALAR, core_1.ReferenceKind.MANY_TO_ONE].includes(prop.kind) || (prop.kind === core_1.ReferenceKind.ONE_TO_ONE && prop.owner);
90
106
  }
91
107
  toJSON() {
92
108
  const { platform, namespaces, ...rest } = this;
@@ -1,6 +1,6 @@
1
1
  import type { Dictionary, EntityMetadata, EntityProperty, NamingStrategy } from '@mikro-orm/core';
2
2
  import type { SchemaHelper } from './SchemaHelper';
3
- import type { Check, Column, ForeignKey, Index } from '../typings';
3
+ import type { CheckDef, Column, ForeignKey, IndexDef } from '../typings';
4
4
  import type { AbstractSqlPlatform } from '../AbstractSqlPlatform';
5
5
  /**
6
6
  * @internal
@@ -13,13 +13,14 @@ export declare class DatabaseTable {
13
13
  private indexes;
14
14
  private checks;
15
15
  private foreignKeys;
16
+ nativeEnums: Dictionary<unknown[]>;
16
17
  comment?: string;
17
18
  constructor(platform: AbstractSqlPlatform, name: string, schema?: string | undefined);
18
19
  getColumns(): Column[];
19
20
  getColumn(name: string): Column | undefined;
20
- getIndexes(): Index[];
21
- getChecks(): Check[];
22
- init(cols: Column[], indexes: Index[] | undefined, checks: Check<unknown>[] | undefined, pks: string[], fks?: Dictionary<ForeignKey>, enums?: Dictionary<string[]>): void;
21
+ getIndexes(): IndexDef[];
22
+ getChecks(): CheckDef[];
23
+ init(cols: Column[], indexes: IndexDef[] | undefined, checks: CheckDef<unknown>[] | undefined, pks: string[], fks?: Dictionary<ForeignKey>, enums?: Dictionary<string[]>): void;
23
24
  addColumn(column: Column): void;
24
25
  addColumnFromProperty(prop: EntityProperty, meta: EntityMetadata): void;
25
26
  private getIndexName;
@@ -30,14 +31,14 @@ export declare class DatabaseTable {
30
31
  getShortestName(): string;
31
32
  getForeignKeys(): Dictionary<ForeignKey>;
32
33
  hasColumn(columnName: string): boolean;
33
- getIndex(indexName: string): Index | undefined;
34
+ getIndex(indexName: string): IndexDef | undefined;
34
35
  hasIndex(indexName: string): boolean;
35
- getCheck(checkName: string): Check<unknown> | undefined;
36
+ getCheck(checkName: string): CheckDef<unknown> | undefined;
36
37
  hasCheck(checkName: string): boolean;
37
- getPrimaryKey(): Index | undefined;
38
+ getPrimaryKey(): IndexDef | undefined;
38
39
  hasPrimaryKey(): boolean;
39
40
  private getPropertyDeclaration;
40
- private getReferenceType;
41
+ private getReferenceKind;
41
42
  private getPropertyName;
42
43
  private getPropertyType;
43
44
  private getPropertyDefaultValue;
@@ -48,6 +49,6 @@ export declare class DatabaseTable {
48
49
  expression?: string;
49
50
  options?: Dictionary;
50
51
  }, type: 'index' | 'unique' | 'primary'): void;
51
- addCheck(check: Check): void;
52
+ addCheck(check: CheckDef): void;
52
53
  toJSON(): Dictionary;
53
54
  }