@mikro-orm/sql 7.0.0-rc.2 → 7.0.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.
Files changed (66) hide show
  1. package/AbstractSqlConnection.d.ts +5 -4
  2. package/AbstractSqlConnection.js +20 -6
  3. package/AbstractSqlDriver.d.ts +19 -13
  4. package/AbstractSqlDriver.js +225 -47
  5. package/AbstractSqlPlatform.d.ts +35 -0
  6. package/AbstractSqlPlatform.js +51 -5
  7. package/PivotCollectionPersister.d.ts +2 -11
  8. package/PivotCollectionPersister.js +59 -59
  9. package/README.md +5 -4
  10. package/SqlEntityManager.d.ts +2 -2
  11. package/SqlEntityManager.js +5 -5
  12. package/dialects/index.d.ts +1 -0
  13. package/dialects/index.js +1 -0
  14. package/dialects/mssql/MsSqlNativeQueryBuilder.d.ts +2 -0
  15. package/dialects/mssql/MsSqlNativeQueryBuilder.js +8 -4
  16. package/dialects/mysql/BaseMySqlPlatform.d.ts +6 -0
  17. package/dialects/mysql/BaseMySqlPlatform.js +18 -2
  18. package/dialects/mysql/MySqlSchemaHelper.d.ts +1 -1
  19. package/dialects/mysql/MySqlSchemaHelper.js +25 -14
  20. package/dialects/oracledb/OracleDialect.d.ts +78 -0
  21. package/dialects/oracledb/OracleDialect.js +166 -0
  22. package/dialects/oracledb/OracleNativeQueryBuilder.d.ts +19 -0
  23. package/dialects/oracledb/OracleNativeQueryBuilder.js +249 -0
  24. package/dialects/oracledb/index.d.ts +2 -0
  25. package/dialects/oracledb/index.js +2 -0
  26. package/dialects/postgresql/BasePostgreSqlPlatform.d.ts +6 -0
  27. package/dialects/postgresql/BasePostgreSqlPlatform.js +49 -37
  28. package/dialects/postgresql/PostgreSqlSchemaHelper.js +75 -59
  29. package/dialects/sqlite/BaseSqliteConnection.js +2 -2
  30. package/dialects/sqlite/NodeSqliteDialect.js +3 -1
  31. package/dialects/sqlite/SqlitePlatform.d.ts +1 -0
  32. package/dialects/sqlite/SqlitePlatform.js +7 -1
  33. package/dialects/sqlite/SqliteSchemaHelper.js +23 -17
  34. package/index.d.ts +1 -1
  35. package/index.js +0 -1
  36. package/package.json +30 -30
  37. package/plugin/index.d.ts +1 -14
  38. package/plugin/index.js +13 -13
  39. package/plugin/transformer.d.ts +6 -22
  40. package/plugin/transformer.js +91 -82
  41. package/query/ArrayCriteriaNode.d.ts +1 -1
  42. package/query/CriteriaNode.js +28 -10
  43. package/query/CriteriaNodeFactory.js +20 -4
  44. package/query/NativeQueryBuilder.d.ts +28 -3
  45. package/query/NativeQueryBuilder.js +65 -3
  46. package/query/ObjectCriteriaNode.js +75 -31
  47. package/query/QueryBuilder.d.ts +199 -100
  48. package/query/QueryBuilder.js +544 -358
  49. package/query/QueryBuilderHelper.d.ts +18 -14
  50. package/query/QueryBuilderHelper.js +364 -147
  51. package/query/ScalarCriteriaNode.js +17 -8
  52. package/query/enums.d.ts +2 -0
  53. package/query/enums.js +2 -0
  54. package/query/raw.js +1 -1
  55. package/schema/DatabaseSchema.d.ts +7 -5
  56. package/schema/DatabaseSchema.js +68 -45
  57. package/schema/DatabaseTable.d.ts +8 -6
  58. package/schema/DatabaseTable.js +191 -107
  59. package/schema/SchemaComparator.d.ts +1 -3
  60. package/schema/SchemaComparator.js +76 -50
  61. package/schema/SchemaHelper.d.ts +2 -13
  62. package/schema/SchemaHelper.js +30 -9
  63. package/schema/SqlSchemaGenerator.d.ts +4 -14
  64. package/schema/SqlSchemaGenerator.js +26 -12
  65. package/typings.d.ts +10 -5
  66. package/tsconfig.build.tsbuildinfo +0 -1
@@ -7,7 +7,8 @@ import { QueryBuilder } from './QueryBuilder.js';
7
7
  */
8
8
  export class ScalarCriteriaNode extends CriteriaNode {
9
9
  process(qb, options) {
10
- const matchPopulateJoins = options?.matchPopulateJoins || (this.prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind));
10
+ const matchPopulateJoins = options?.matchPopulateJoins ||
11
+ (this.prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind));
11
12
  const nestedAlias = qb.getAliasForJoinPath(this.getPath(options), { ...options, matchPopulateJoins });
12
13
  if (this.shouldJoin(qb, nestedAlias)) {
13
14
  const path = this.getPath();
@@ -17,12 +18,14 @@ export class ScalarCriteriaNode extends CriteriaNode {
17
18
  const type = this.prop.kind === ReferenceKind.MANY_TO_MANY ? JoinType.pivotJoin : JoinType.leftJoin;
18
19
  qb.join(field, nestedAlias, undefined, type, path);
19
20
  // select the owner as virtual property when joining from 1:1 inverse side, but only if the parent is root entity
20
- if (this.prop.kind === ReferenceKind.ONE_TO_ONE && !parentPath.includes('.') && !qb._fields?.includes(field)) {
21
+ if (this.prop.kind === ReferenceKind.ONE_TO_ONE &&
22
+ !parentPath.includes('.') &&
23
+ !qb.state.fields?.includes(field)) {
21
24
  qb.addSelect(field);
22
25
  }
23
26
  }
24
27
  if (this.payload instanceof QueryBuilder) {
25
- return this.payload.getNativeQuery().toRaw();
28
+ return this.payload.toRaw();
26
29
  }
27
30
  if (this.payload && typeof this.payload === 'object') {
28
31
  const keys = Object.keys(this.payload).filter(key => ARRAY_OPERATORS.includes(key) && Array.isArray(this.payload[key]));
@@ -36,14 +39,20 @@ export class ScalarCriteriaNode extends CriteriaNode {
36
39
  return this.shouldJoin(qb, alias);
37
40
  }
38
41
  shouldJoin(qb, nestedAlias) {
39
- if (!this.parent || !this.prop || (nestedAlias && [QueryType.SELECT, QueryType.COUNT].includes(qb.type ?? QueryType.SELECT))) {
42
+ if (!this.parent ||
43
+ !this.prop ||
44
+ (nestedAlias && [QueryType.SELECT, QueryType.COUNT].includes(qb.type ?? QueryType.SELECT))) {
40
45
  return false;
41
46
  }
42
47
  switch (this.prop.kind) {
43
- case ReferenceKind.ONE_TO_MANY: return true;
44
- case ReferenceKind.MANY_TO_MANY: return true;
45
- case ReferenceKind.ONE_TO_ONE: return !this.prop.owner;
46
- default: return false; // SCALAR, MANY_TO_ONE
48
+ case ReferenceKind.ONE_TO_MANY:
49
+ return true;
50
+ case ReferenceKind.MANY_TO_MANY:
51
+ return true;
52
+ case ReferenceKind.ONE_TO_ONE:
53
+ return !this.prop.owner;
54
+ default:
55
+ return false; // SCALAR, MANY_TO_ONE
47
56
  }
48
57
  }
49
58
  }
package/query/enums.d.ts CHANGED
@@ -7,6 +7,8 @@ export declare enum QueryType {
7
7
  DELETE = "DELETE",
8
8
  UPSERT = "UPSERT"
9
9
  }
10
+ /** Operators that apply to the embedded array column itself, not to individual elements. */
11
+ export declare const EMBEDDABLE_ARRAY_OPS: string[];
10
12
  export declare enum JoinType {
11
13
  leftJoin = "left join",
12
14
  innerJoin = "inner join",
package/query/enums.js CHANGED
@@ -8,6 +8,8 @@ export var QueryType;
8
8
  QueryType["DELETE"] = "DELETE";
9
9
  QueryType["UPSERT"] = "UPSERT";
10
10
  })(QueryType || (QueryType = {}));
11
+ /** Operators that apply to the embedded array column itself, not to individual elements. */
12
+ export const EMBEDDABLE_ARRAY_OPS = ['$contains', '$contained', '$overlap'];
11
13
  export var JoinType;
12
14
  (function (JoinType) {
13
15
  JoinType["leftJoin"] = "left join";
package/query/raw.js CHANGED
@@ -1,4 +1,4 @@
1
- import { raw as raw_, Utils } from '@mikro-orm/core';
1
+ import { raw as raw_, Utils, } from '@mikro-orm/core';
2
2
  /**
3
3
  * Creates raw SQL query fragment that can be assigned to a property or part of a filter. This fragment is represented
4
4
  * by `RawQueryFragment` class instance that can be serialized to a string, so it can be used both as an object value
@@ -7,19 +7,21 @@ import type { AbstractSqlPlatform } from '../AbstractSqlPlatform.js';
7
7
  * @internal
8
8
  */
9
9
  export declare class DatabaseSchema {
10
- private readonly platform;
10
+ #private;
11
11
  readonly name: string;
12
- private tables;
13
- private views;
14
- private namespaces;
15
- private nativeEnums;
16
12
  constructor(platform: AbstractSqlPlatform, name: string);
17
13
  addTable(name: string, schema: string | undefined | null, comment?: string): DatabaseTable;
18
14
  getTables(): DatabaseTable[];
15
+ /** @internal */
16
+ setTables(tables: DatabaseTable[]): void;
17
+ /** @internal */
18
+ setNamespaces(namespaces: Set<string>): void;
19
19
  getTable(name: string): DatabaseTable | undefined;
20
20
  hasTable(name: string): boolean;
21
21
  addView(name: string, schema: string | undefined | null, definition: string, materialized?: boolean, withData?: boolean): DatabaseView;
22
22
  getViews(): DatabaseView[];
23
+ /** @internal */
24
+ setViews(views: DatabaseView[]): void;
23
25
  getView(name: string): DatabaseView | undefined;
24
26
  hasView(name: string): boolean;
25
27
  setNativeEnums(nativeEnums: Dictionary<{
@@ -4,32 +4,40 @@ import { DatabaseTable } from './DatabaseTable.js';
4
4
  * @internal
5
5
  */
6
6
  export class DatabaseSchema {
7
- platform;
8
7
  name;
9
- tables = [];
10
- views = [];
11
- namespaces = new Set();
12
- nativeEnums = {}; // for postgres
8
+ #tables = [];
9
+ #views = [];
10
+ #namespaces = new Set();
11
+ #nativeEnums = {}; // for postgres
12
+ #platform;
13
13
  constructor(platform, name) {
14
- this.platform = platform;
15
14
  this.name = name;
15
+ this.#platform = platform;
16
16
  }
17
17
  addTable(name, schema, comment) {
18
18
  const namespaceName = schema ?? this.name;
19
- const table = new DatabaseTable(this.platform, name, namespaceName);
20
- table.nativeEnums = this.nativeEnums;
19
+ const table = new DatabaseTable(this.#platform, name, namespaceName);
20
+ table.nativeEnums = this.#nativeEnums;
21
21
  table.comment = comment;
22
- this.tables.push(table);
22
+ this.#tables.push(table);
23
23
  if (namespaceName != null) {
24
- this.namespaces.add(namespaceName);
24
+ this.#namespaces.add(namespaceName);
25
25
  }
26
26
  return table;
27
27
  }
28
28
  getTables() {
29
- return this.tables;
29
+ return this.#tables;
30
+ }
31
+ /** @internal */
32
+ setTables(tables) {
33
+ this.#tables = tables;
34
+ }
35
+ /** @internal */
36
+ setNamespaces(namespaces) {
37
+ this.#namespaces = namespaces;
30
38
  }
31
39
  getTable(name) {
32
- return this.tables.find(t => t.name === name || `${t.schema}.${t.name}` === name);
40
+ return this.#tables.find(t => t.name === name || `${t.schema}.${t.name}` === name);
33
41
  }
34
42
  hasTable(name) {
35
43
  return !!this.getTable(name);
@@ -37,43 +45,47 @@ export class DatabaseSchema {
37
45
  addView(name, schema, definition, materialized, withData) {
38
46
  const namespaceName = schema ?? this.name;
39
47
  const view = { name, schema: namespaceName, definition, materialized, withData };
40
- this.views.push(view);
48
+ this.#views.push(view);
41
49
  if (namespaceName != null) {
42
- this.namespaces.add(namespaceName);
50
+ this.#namespaces.add(namespaceName);
43
51
  }
44
52
  return view;
45
53
  }
46
54
  getViews() {
47
- return this.views;
55
+ return this.#views;
56
+ }
57
+ /** @internal */
58
+ setViews(views) {
59
+ this.#views = views;
48
60
  }
49
61
  getView(name) {
50
- return this.views.find(v => v.name === name || `${v.schema}.${v.name}` === name);
62
+ return this.#views.find(v => v.name === name || `${v.schema}.${v.name}` === name);
51
63
  }
52
64
  hasView(name) {
53
65
  return !!this.getView(name);
54
66
  }
55
67
  setNativeEnums(nativeEnums) {
56
- this.nativeEnums = nativeEnums;
68
+ this.#nativeEnums = nativeEnums;
57
69
  for (const nativeEnum of Object.values(nativeEnums)) {
58
70
  if (nativeEnum.schema && nativeEnum.schema !== '*') {
59
- this.namespaces.add(nativeEnum.schema);
71
+ this.#namespaces.add(nativeEnum.schema);
60
72
  }
61
73
  }
62
74
  }
63
75
  getNativeEnums() {
64
- return this.nativeEnums;
76
+ return this.#nativeEnums;
65
77
  }
66
78
  getNativeEnum(name) {
67
- return this.nativeEnums[name];
79
+ return this.#nativeEnums[name];
68
80
  }
69
81
  hasNamespace(namespace) {
70
- return this.namespaces.has(namespace);
82
+ return this.#namespaces.has(namespace);
71
83
  }
72
84
  hasNativeEnum(name) {
73
- return name in this.nativeEnums;
85
+ return name in this.#nativeEnums;
74
86
  }
75
87
  getNamespaces() {
76
- return [...this.namespaces];
88
+ return [...this.#namespaces];
77
89
  }
78
90
  static async create(connection, platform, config, schemaName, schemas, takeTables, skipTables, skipViews) {
79
91
  const schema = new DatabaseSchema(platform, schemaName ?? config.get('schema') ?? platform.getDefaultSchemaName());
@@ -81,8 +93,11 @@ export class DatabaseSchema {
81
93
  const parts = config.get('migrations').tableName.split('.');
82
94
  const migrationsTableName = parts[1] ?? parts[0];
83
95
  const migrationsSchemaName = parts.length > 1 ? parts[0] : config.get('schema', platform.getDefaultSchemaName());
84
- const tables = allTables.filter(t => this.isTableNameAllowed(t.table_name, takeTables, skipTables) && (t.table_name !== migrationsTableName || (t.schema_name && t.schema_name !== migrationsSchemaName)));
85
- await platform.getSchemaHelper().loadInformationSchema(schema, connection, tables, schemas && schemas.length > 0 ? schemas : undefined);
96
+ const tables = allTables.filter(t => this.isTableNameAllowed(t.table_name, takeTables, skipTables) &&
97
+ (t.table_name !== migrationsTableName || (t.schema_name && t.schema_name !== migrationsSchemaName)));
98
+ await platform
99
+ .getSchemaHelper()
100
+ .loadInformationSchema(schema, connection, tables, schemas && schemas.length > 0 ? schemas : undefined);
86
101
  // Load views from database
87
102
  await platform.getSchemaHelper().loadViews(schema, connection);
88
103
  // Load materialized views (PostgreSQL only)
@@ -91,7 +106,7 @@ export class DatabaseSchema {
91
106
  }
92
107
  // Filter out skipped views
93
108
  if (skipViews && skipViews.length > 0) {
94
- schema.views = schema.views.filter(v => this.isNameAllowed(v.name, skipViews));
109
+ schema.#views = schema.#views.filter(v => this.isNameAllowed(v.name, skipViews));
95
110
  }
96
111
  return schema;
97
112
  }
@@ -140,9 +155,7 @@ export class DatabaseSchema {
140
155
  table.comment = meta.comment;
141
156
  // For TPT child entities, only use ownProps (properties defined in this entity only)
142
157
  // For all other entities (including TPT root), use all props
143
- const propsToProcess = meta.inheritanceType === 'tpt' && meta.tptParent && meta.ownProps
144
- ? meta.ownProps
145
- : meta.props;
158
+ const propsToProcess = meta.inheritanceType === 'tpt' && meta.tptParent && meta.ownProps ? meta.ownProps : meta.props;
146
159
  for (const prop of propsToProcess) {
147
160
  if (!this.shouldHaveColumn(meta, prop, skipColumns)) {
148
161
  continue;
@@ -177,7 +190,9 @@ export class DatabaseSchema {
177
190
  table.addIndex(meta, { properties: pkPropsForIndex.map(prop => prop.name) }, 'primary');
178
191
  for (const check of meta.checks) {
179
192
  const columnName = check.property ? meta.properties[check.property].fieldNames[0] : undefined;
180
- const expression = isRaw(check.expression) ? platform.formatQuery(check.expression.sql, check.expression.params) : check.expression;
193
+ const expression = isRaw(check.expression)
194
+ ? platform.formatQuery(check.expression.sql, check.expression.params)
195
+ : check.expression;
181
196
  table.addCheck({
182
197
  name: check.name,
183
198
  expression,
@@ -229,7 +244,7 @@ export class DatabaseSchema {
229
244
  const pkColumnNames = meta.primaryKeys.flatMap(pk => meta.properties[pk].fieldNames);
230
245
  const parentPkColumnNames = parent.primaryKeys.flatMap(pk => parent.properties[pk].fieldNames);
231
246
  // Determine the parent table name with schema
232
- const parentSchema = parent.schema === '*' ? undefined : parent.schema ?? config.get('schema', platform.getDefaultSchemaName());
247
+ const parentSchema = parent.schema === '*' ? undefined : (parent.schema ?? config.get('schema', platform.getDefaultSchemaName()));
233
248
  const parentTableName = parentSchema ? `${parentSchema}.${parent.tableName}` : parent.tableName;
234
249
  // Create FK constraint name
235
250
  const constraintName = platform.getIndexName(table.name, pkColumnNames, 'foreign');
@@ -284,29 +299,37 @@ export class DatabaseSchema {
284
299
  if (rootProp.kind === ReferenceKind.EMBEDDED) {
285
300
  return prop === rootProp || !rootProp.object;
286
301
  }
287
- return [ReferenceKind.SCALAR, ReferenceKind.MANY_TO_ONE].includes(prop.kind) || (prop.kind === ReferenceKind.ONE_TO_ONE && prop.owner);
302
+ return ([ReferenceKind.SCALAR, ReferenceKind.MANY_TO_ONE].includes(prop.kind) ||
303
+ (prop.kind === ReferenceKind.ONE_TO_ONE && prop.owner));
288
304
  }
289
305
  toJSON() {
290
- const { platform, namespaces, ...rest } = this;
291
- return { namespaces: [...namespaces], ...rest };
306
+ return {
307
+ name: this.name,
308
+ namespaces: [...this.#namespaces],
309
+ tables: this.#tables,
310
+ views: this.#views,
311
+ nativeEnums: this.#nativeEnums,
312
+ };
292
313
  }
293
314
  prune(schema, wildcardSchemaTables) {
294
315
  const hasWildcardSchema = wildcardSchemaTables.length > 0;
295
- this.tables = this.tables.filter(table => {
296
- return (!schema && !hasWildcardSchema) // no schema specified and we don't have any multi-schema entity
297
- || table.schema === schema // specified schema matches the table's one
298
- || (!schema && !wildcardSchemaTables.includes(table.name)); // no schema specified and the table has fixed one provided
316
+ this.#tables = this.#tables.filter(table => {
317
+ return ((!schema && !hasWildcardSchema) || // no schema specified and we don't have any multi-schema entity
318
+ table.schema === schema || // specified schema matches the table's one
319
+ (!schema && !wildcardSchemaTables.includes(table.name))); // no schema specified and the table has fixed one provided
299
320
  });
300
- this.views = this.views.filter(view => {
321
+ this.#views = this.#views.filter(view => {
301
322
  /* v8 ignore next */
302
- return (!schema && !hasWildcardSchema)
303
- || view.schema === schema
304
- || (!schema && !wildcardSchemaTables.includes(view.name));
323
+ return ((!schema && !hasWildcardSchema) ||
324
+ view.schema === schema ||
325
+ (!schema && !wildcardSchemaTables.includes(view.name)));
305
326
  });
306
327
  // remove namespaces of ignored tables and views
307
- for (const ns of this.namespaces) {
308
- if (!this.tables.some(t => t.schema === ns) && !this.views.some(v => v.schema === ns) && !Object.values(this.nativeEnums).some(e => e.schema === ns)) {
309
- this.namespaces.delete(ns);
328
+ for (const ns of this.#namespaces) {
329
+ if (!this.#tables.some(t => t.schema === ns) &&
330
+ !this.#views.some(v => v.schema === ns) &&
331
+ !Object.values(this.#nativeEnums).some(e => e.schema === ns)) {
332
+ this.#namespaces.delete(ns);
310
333
  }
311
334
  }
312
335
  }
@@ -6,13 +6,9 @@ import type { AbstractSqlPlatform } from '../AbstractSqlPlatform.js';
6
6
  * @internal
7
7
  */
8
8
  export declare class DatabaseTable {
9
- private readonly platform;
9
+ #private;
10
10
  readonly name: string;
11
11
  readonly schema?: string | undefined;
12
- private columns;
13
- private indexes;
14
- private checks;
15
- private foreignKeys;
16
12
  nativeEnums: Dictionary<{
17
13
  name: string;
18
14
  schema?: string;
@@ -26,6 +22,12 @@ export declare class DatabaseTable {
26
22
  removeColumn(name: string): void;
27
23
  getIndexes(): IndexDef[];
28
24
  getChecks(): CheckDef[];
25
+ /** @internal */
26
+ setIndexes(indexes: IndexDef[]): void;
27
+ /** @internal */
28
+ setChecks(checks: CheckDef[]): void;
29
+ /** @internal */
30
+ setForeignKeys(fks: Dictionary<ForeignKey>): void;
29
31
  init(cols: Column[], indexes: IndexDef[] | undefined, checks: CheckDef[] | undefined, pks: string[], fks?: Dictionary<ForeignKey>, enums?: Dictionary<string[]>): void;
30
32
  addColumn(column: Column): void;
31
33
  addColumnFromProperty(prop: EntityProperty, meta: EntityMetadata, config: Configuration): void;
@@ -43,7 +45,7 @@ export declare class DatabaseTable {
43
45
  hasColumn(columnName: string): boolean;
44
46
  getIndex(indexName: string): IndexDef | undefined;
45
47
  hasIndex(indexName: string): boolean;
46
- getCheck(checkName: string): CheckDef<unknown> | undefined;
48
+ getCheck(checkName: string): CheckDef | undefined;
47
49
  hasCheck(checkName: string): boolean;
48
50
  getPrimaryKey(): IndexDef | undefined;
49
51
  hasPrimaryKey(): boolean;