@mikro-orm/sql 7.0.4-dev.8 → 7.0.4

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 (87) hide show
  1. package/AbstractSqlConnection.d.ts +94 -58
  2. package/AbstractSqlConnection.js +235 -238
  3. package/AbstractSqlDriver.d.ts +410 -155
  4. package/AbstractSqlDriver.js +2064 -1941
  5. package/AbstractSqlPlatform.d.ts +83 -73
  6. package/AbstractSqlPlatform.js +162 -158
  7. package/PivotCollectionPersister.d.ts +33 -15
  8. package/PivotCollectionPersister.js +158 -160
  9. package/README.md +1 -1
  10. package/SqlEntityManager.d.ts +67 -22
  11. package/SqlEntityManager.js +54 -38
  12. package/SqlEntityRepository.d.ts +14 -14
  13. package/SqlEntityRepository.js +23 -23
  14. package/dialects/mssql/MsSqlNativeQueryBuilder.d.ts +12 -12
  15. package/dialects/mssql/MsSqlNativeQueryBuilder.js +192 -194
  16. package/dialects/mysql/BaseMySqlPlatform.d.ts +64 -45
  17. package/dialects/mysql/BaseMySqlPlatform.js +134 -131
  18. package/dialects/mysql/MySqlExceptionConverter.d.ts +6 -6
  19. package/dialects/mysql/MySqlExceptionConverter.js +91 -77
  20. package/dialects/mysql/MySqlNativeQueryBuilder.d.ts +3 -3
  21. package/dialects/mysql/MySqlNativeQueryBuilder.js +66 -69
  22. package/dialects/mysql/MySqlSchemaHelper.d.ts +39 -39
  23. package/dialects/mysql/MySqlSchemaHelper.js +327 -319
  24. package/dialects/oracledb/OracleDialect.d.ts +81 -52
  25. package/dialects/oracledb/OracleDialect.js +155 -149
  26. package/dialects/oracledb/OracleNativeQueryBuilder.d.ts +12 -12
  27. package/dialects/oracledb/OracleNativeQueryBuilder.js +232 -236
  28. package/dialects/postgresql/BasePostgreSqlPlatform.d.ts +109 -105
  29. package/dialects/postgresql/BasePostgreSqlPlatform.js +354 -350
  30. package/dialects/postgresql/FullTextType.d.ts +10 -6
  31. package/dialects/postgresql/FullTextType.js +51 -51
  32. package/dialects/postgresql/PostgreSqlExceptionConverter.d.ts +5 -5
  33. package/dialects/postgresql/PostgreSqlExceptionConverter.js +55 -43
  34. package/dialects/postgresql/PostgreSqlNativeQueryBuilder.d.ts +1 -1
  35. package/dialects/postgresql/PostgreSqlNativeQueryBuilder.js +4 -4
  36. package/dialects/postgresql/PostgreSqlSchemaHelper.d.ts +102 -82
  37. package/dialects/postgresql/PostgreSqlSchemaHelper.js +733 -705
  38. package/dialects/sqlite/BaseSqliteConnection.d.ts +3 -5
  39. package/dialects/sqlite/BaseSqliteConnection.js +21 -19
  40. package/dialects/sqlite/NodeSqliteDialect.d.ts +1 -1
  41. package/dialects/sqlite/NodeSqliteDialect.js +23 -23
  42. package/dialects/sqlite/SqliteDriver.d.ts +1 -1
  43. package/dialects/sqlite/SqliteDriver.js +3 -3
  44. package/dialects/sqlite/SqliteExceptionConverter.d.ts +6 -6
  45. package/dialects/sqlite/SqliteExceptionConverter.js +67 -51
  46. package/dialects/sqlite/SqliteNativeQueryBuilder.d.ts +2 -2
  47. package/dialects/sqlite/SqliteNativeQueryBuilder.js +7 -7
  48. package/dialects/sqlite/SqlitePlatform.d.ts +63 -72
  49. package/dialects/sqlite/SqlitePlatform.js +139 -139
  50. package/dialects/sqlite/SqliteSchemaHelper.d.ts +70 -60
  51. package/dialects/sqlite/SqliteSchemaHelper.js +533 -520
  52. package/package.json +3 -3
  53. package/plugin/index.d.ts +42 -35
  54. package/plugin/index.js +43 -36
  55. package/plugin/transformer.d.ts +117 -94
  56. package/plugin/transformer.js +890 -881
  57. package/query/ArrayCriteriaNode.d.ts +4 -4
  58. package/query/ArrayCriteriaNode.js +18 -18
  59. package/query/CriteriaNode.d.ts +35 -25
  60. package/query/CriteriaNode.js +133 -123
  61. package/query/CriteriaNodeFactory.d.ts +49 -6
  62. package/query/CriteriaNodeFactory.js +97 -94
  63. package/query/NativeQueryBuilder.d.ts +118 -118
  64. package/query/NativeQueryBuilder.js +484 -480
  65. package/query/ObjectCriteriaNode.d.ts +12 -12
  66. package/query/ObjectCriteriaNode.js +298 -282
  67. package/query/QueryBuilder.d.ts +1557 -905
  68. package/query/QueryBuilder.js +2322 -2192
  69. package/query/QueryBuilderHelper.d.ts +153 -72
  70. package/query/QueryBuilderHelper.js +1079 -1028
  71. package/query/ScalarCriteriaNode.d.ts +3 -3
  72. package/query/ScalarCriteriaNode.js +53 -46
  73. package/query/enums.d.ts +14 -14
  74. package/query/enums.js +14 -14
  75. package/query/raw.d.ts +16 -6
  76. package/query/raw.js +10 -10
  77. package/schema/DatabaseSchema.d.ts +73 -50
  78. package/schema/DatabaseSchema.js +331 -307
  79. package/schema/DatabaseTable.d.ts +96 -73
  80. package/schema/DatabaseTable.js +1012 -927
  81. package/schema/SchemaComparator.d.ts +70 -66
  82. package/schema/SchemaComparator.js +766 -740
  83. package/schema/SchemaHelper.d.ts +109 -95
  84. package/schema/SchemaHelper.js +675 -659
  85. package/schema/SqlSchemaGenerator.d.ts +78 -58
  86. package/schema/SqlSchemaGenerator.js +535 -501
  87. package/typings.d.ts +380 -266
@@ -1,336 +1,360 @@
1
- import { ReferenceKind, isRaw, } from '@mikro-orm/core';
1
+ import { ReferenceKind, isRaw } from '@mikro-orm/core';
2
2
  import { DatabaseTable } from './DatabaseTable.js';
3
3
  /**
4
4
  * @internal
5
5
  */
6
6
  export class DatabaseSchema {
7
- name;
8
- #tables = [];
9
- #views = [];
10
- #namespaces = new Set();
11
- #nativeEnums = {}; // for postgres
12
- #platform;
13
- constructor(platform, name) {
14
- this.name = name;
15
- this.#platform = platform;
7
+ name;
8
+ #tables = [];
9
+ #views = [];
10
+ #namespaces = new Set();
11
+ #nativeEnums = {}; // for postgres
12
+ #platform;
13
+ constructor(platform, name) {
14
+ this.name = name;
15
+ this.#platform = platform;
16
+ }
17
+ addTable(name, schema, comment) {
18
+ const namespaceName = schema ?? this.name;
19
+ const table = new DatabaseTable(this.#platform, name, namespaceName);
20
+ table.nativeEnums = this.#nativeEnums;
21
+ table.comment = comment;
22
+ this.#tables.push(table);
23
+ if (namespaceName != null) {
24
+ this.#namespaces.add(namespaceName);
16
25
  }
17
- addTable(name, schema, comment) {
18
- const namespaceName = schema ?? this.name;
19
- const table = new DatabaseTable(this.#platform, name, namespaceName);
20
- table.nativeEnums = this.#nativeEnums;
21
- table.comment = comment;
22
- this.#tables.push(table);
23
- if (namespaceName != null) {
24
- this.#namespaces.add(namespaceName);
25
- }
26
- return table;
27
- }
28
- getTables() {
29
- return this.#tables;
30
- }
31
- /** @internal */
32
- setTables(tables) {
33
- this.#tables = tables;
34
- }
35
- /** @internal */
36
- setNamespaces(namespaces) {
37
- this.#namespaces = namespaces;
38
- }
39
- getTable(name) {
40
- return this.#tables.find(t => t.name === name || `${t.schema}.${t.name}` === name);
26
+ return table;
27
+ }
28
+ getTables() {
29
+ return this.#tables;
30
+ }
31
+ /** @internal */
32
+ setTables(tables) {
33
+ this.#tables = tables;
34
+ }
35
+ /** @internal */
36
+ setNamespaces(namespaces) {
37
+ this.#namespaces = namespaces;
38
+ }
39
+ getTable(name) {
40
+ return this.#tables.find(t => t.name === name || `${t.schema}.${t.name}` === name);
41
+ }
42
+ hasTable(name) {
43
+ return !!this.getTable(name);
44
+ }
45
+ addView(name, schema, definition, materialized, withData) {
46
+ const namespaceName = schema ?? this.name;
47
+ const view = { name, schema: namespaceName, definition, materialized, withData };
48
+ this.#views.push(view);
49
+ if (namespaceName != null) {
50
+ this.#namespaces.add(namespaceName);
41
51
  }
42
- hasTable(name) {
43
- return !!this.getTable(name);
52
+ return view;
53
+ }
54
+ getViews() {
55
+ return this.#views;
56
+ }
57
+ /** @internal */
58
+ setViews(views) {
59
+ this.#views = views;
60
+ }
61
+ getView(name) {
62
+ return this.#views.find(v => v.name === name || `${v.schema}.${v.name}` === name);
63
+ }
64
+ hasView(name) {
65
+ return !!this.getView(name);
66
+ }
67
+ setNativeEnums(nativeEnums) {
68
+ this.#nativeEnums = nativeEnums;
69
+ for (const nativeEnum of Object.values(nativeEnums)) {
70
+ if (nativeEnum.schema && nativeEnum.schema !== '*') {
71
+ this.#namespaces.add(nativeEnum.schema);
72
+ }
44
73
  }
45
- addView(name, schema, definition, materialized, withData) {
46
- const namespaceName = schema ?? this.name;
47
- const view = { name, schema: namespaceName, definition, materialized, withData };
48
- this.#views.push(view);
49
- if (namespaceName != null) {
50
- this.#namespaces.add(namespaceName);
51
- }
52
- return view;
53
- }
54
- getViews() {
55
- return this.#views;
56
- }
57
- /** @internal */
58
- setViews(views) {
59
- this.#views = views;
74
+ }
75
+ getNativeEnums() {
76
+ return this.#nativeEnums;
77
+ }
78
+ getNativeEnum(name) {
79
+ return this.#nativeEnums[name];
80
+ }
81
+ hasNamespace(namespace) {
82
+ return this.#namespaces.has(namespace);
83
+ }
84
+ hasNativeEnum(name) {
85
+ return name in this.#nativeEnums;
86
+ }
87
+ getNamespaces() {
88
+ return [...this.#namespaces];
89
+ }
90
+ static async create(connection, platform, config, schemaName, schemas, takeTables, skipTables, skipViews) {
91
+ const schema = new DatabaseSchema(platform, schemaName ?? config.get('schema') ?? platform.getDefaultSchemaName());
92
+ const allTables = await platform.getSchemaHelper().getAllTables(connection, schemas);
93
+ const parts = config.get('migrations').tableName.split('.');
94
+ const migrationsTableName = parts[1] ?? parts[0];
95
+ const migrationsSchemaName = parts.length > 1 ? parts[0] : config.get('schema', platform.getDefaultSchemaName());
96
+ const tables = allTables.filter(
97
+ t =>
98
+ this.isTableNameAllowed(t.table_name, takeTables, skipTables) &&
99
+ (t.table_name !== migrationsTableName || (t.schema_name && t.schema_name !== migrationsSchemaName)),
100
+ );
101
+ await platform
102
+ .getSchemaHelper()
103
+ .loadInformationSchema(schema, connection, tables, schemas && schemas.length > 0 ? schemas : undefined);
104
+ // Load views from database
105
+ await platform.getSchemaHelper().loadViews(schema, connection);
106
+ // Load materialized views (PostgreSQL only)
107
+ if (platform.supportsMaterializedViews()) {
108
+ await platform.getSchemaHelper().loadMaterializedViews(schema, connection, schemaName);
60
109
  }
61
- getView(name) {
62
- return this.#views.find(v => v.name === name || `${v.schema}.${v.name}` === name);
110
+ // Filter out skipped views
111
+ if (skipViews && skipViews.length > 0) {
112
+ schema.#views = schema.#views.filter(v => this.isNameAllowed(v.name, skipViews));
63
113
  }
64
- hasView(name) {
65
- return !!this.getView(name);
66
- }
67
- setNativeEnums(nativeEnums) {
68
- this.#nativeEnums = nativeEnums;
69
- for (const nativeEnum of Object.values(nativeEnums)) {
70
- if (nativeEnum.schema && nativeEnum.schema !== '*') {
71
- this.#namespaces.add(nativeEnum.schema);
72
- }
114
+ return schema;
115
+ }
116
+ static fromMetadata(metadata, platform, config, schemaName, em) {
117
+ const schema = new DatabaseSchema(platform, schemaName ?? config.get('schema'));
118
+ const nativeEnums = {};
119
+ const skipColumns = config.get('schemaGenerator').skipColumns || {};
120
+ for (const meta of metadata) {
121
+ // Skip view entities when collecting native enums
122
+ if (meta.view) {
123
+ continue;
124
+ }
125
+ for (const prop of meta.props) {
126
+ if (prop.nativeEnumName) {
127
+ let key = prop.nativeEnumName;
128
+ let enumName = prop.nativeEnumName;
129
+ let enumSchema = meta.schema ?? schema.name;
130
+ if (key.includes('.')) {
131
+ const [explicitSchema, ...parts] = prop.nativeEnumName.split('.');
132
+ enumName = parts.join('.');
133
+ key = enumName;
134
+ enumSchema = explicitSchema;
135
+ }
136
+ if (enumSchema && enumSchema !== '*' && enumSchema !== platform.getDefaultSchemaName()) {
137
+ key = enumSchema + '.' + key;
138
+ }
139
+ nativeEnums[key] = {
140
+ name: enumName,
141
+ schema: enumSchema,
142
+ items: prop.items?.map(val => '' + val) ?? [],
143
+ };
73
144
  }
145
+ }
74
146
  }
75
- getNativeEnums() {
76
- return this.#nativeEnums;
77
- }
78
- getNativeEnum(name) {
79
- return this.#nativeEnums[name];
80
- }
81
- hasNamespace(namespace) {
82
- return this.#namespaces.has(namespace);
83
- }
84
- hasNativeEnum(name) {
85
- return name in this.#nativeEnums;
86
- }
87
- getNamespaces() {
88
- return [...this.#namespaces];
89
- }
90
- static async create(connection, platform, config, schemaName, schemas, takeTables, skipTables, skipViews) {
91
- const schema = new DatabaseSchema(platform, schemaName ?? config.get('schema') ?? platform.getDefaultSchemaName());
92
- const allTables = await platform.getSchemaHelper().getAllTables(connection, schemas);
93
- const parts = config.get('migrations').tableName.split('.');
94
- const migrationsTableName = parts[1] ?? parts[0];
95
- const migrationsSchemaName = parts.length > 1 ? parts[0] : config.get('schema', platform.getDefaultSchemaName());
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);
101
- // Load views from database
102
- await platform.getSchemaHelper().loadViews(schema, connection);
103
- // Load materialized views (PostgreSQL only)
104
- if (platform.supportsMaterializedViews()) {
105
- await platform.getSchemaHelper().loadMaterializedViews(schema, connection, schemaName);
147
+ schema.setNativeEnums(nativeEnums);
148
+ for (const meta of metadata) {
149
+ // Handle view entities separately
150
+ if (meta.view) {
151
+ const viewDefinition = this.getViewDefinition(meta, em, platform);
152
+ if (viewDefinition) {
153
+ schema.addView(
154
+ meta.collection,
155
+ this.getSchemaName(meta, config, schemaName),
156
+ viewDefinition,
157
+ meta.materialized,
158
+ meta.withData,
159
+ );
106
160
  }
107
- // Filter out skipped views
108
- if (skipViews && skipViews.length > 0) {
109
- schema.#views = schema.#views.filter(v => this.isNameAllowed(v.name, skipViews));
161
+ continue;
162
+ }
163
+ const table = schema.addTable(meta.collection, this.getSchemaName(meta, config, schemaName));
164
+ table.comment = meta.comment;
165
+ // For TPT child entities, only use ownProps (properties defined in this entity only)
166
+ // For all other entities (including TPT root), use all props
167
+ const propsToProcess =
168
+ meta.inheritanceType === 'tpt' && meta.tptParent && meta.ownProps ? meta.ownProps : meta.props;
169
+ for (const prop of propsToProcess) {
170
+ if (!this.shouldHaveColumn(meta, prop, skipColumns)) {
171
+ continue;
110
172
  }
111
- return schema;
112
- }
113
- static fromMetadata(metadata, platform, config, schemaName, em) {
114
- const schema = new DatabaseSchema(platform, schemaName ?? config.get('schema'));
115
- const nativeEnums = {};
116
- const skipColumns = config.get('schemaGenerator').skipColumns || {};
117
- for (const meta of metadata) {
118
- // Skip view entities when collecting native enums
119
- if (meta.view) {
120
- continue;
121
- }
122
- for (const prop of meta.props) {
123
- if (prop.nativeEnumName) {
124
- let key = prop.nativeEnumName;
125
- let enumName = prop.nativeEnumName;
126
- let enumSchema = meta.schema ?? schema.name;
127
- if (key.includes('.')) {
128
- const [explicitSchema, ...parts] = prop.nativeEnumName.split('.');
129
- enumName = parts.join('.');
130
- key = enumName;
131
- enumSchema = explicitSchema;
132
- }
133
- if (enumSchema && enumSchema !== '*' && enumSchema !== platform.getDefaultSchemaName()) {
134
- key = enumSchema + '.' + key;
135
- }
136
- nativeEnums[key] = {
137
- name: enumName,
138
- schema: enumSchema,
139
- items: prop.items?.map(val => '' + val) ?? [],
140
- };
141
- }
173
+ table.addColumnFromProperty(prop, meta, config);
174
+ }
175
+ // For TPT child entities, always include the PK columns (they form the FK to parent)
176
+ if (meta.inheritanceType === 'tpt' && meta.tptParent) {
177
+ const pkProps = meta.primaryKeys.map(pk => meta.properties[pk]);
178
+ for (const pkProp of pkProps) {
179
+ // Only add if not already added (it might be in ownProps if defined in this entity)
180
+ if (!propsToProcess.includes(pkProp)) {
181
+ table.addColumnFromProperty(pkProp, meta, config);
182
+ }
183
+ // Child PK must not be autoincrement — it references the parent PK via FK
184
+ for (const field of pkProp.fieldNames) {
185
+ const col = table.getColumn(field);
186
+ if (col) {
187
+ col.autoincrement = false;
142
188
  }
189
+ }
143
190
  }
144
- schema.setNativeEnums(nativeEnums);
145
- for (const meta of metadata) {
146
- // Handle view entities separately
147
- if (meta.view) {
148
- const viewDefinition = this.getViewDefinition(meta, em, platform);
149
- if (viewDefinition) {
150
- schema.addView(meta.collection, this.getSchemaName(meta, config, schemaName), viewDefinition, meta.materialized, meta.withData);
151
- }
152
- continue;
153
- }
154
- const table = schema.addTable(meta.collection, this.getSchemaName(meta, config, schemaName));
155
- table.comment = meta.comment;
156
- // For TPT child entities, only use ownProps (properties defined in this entity only)
157
- // For all other entities (including TPT root), use all props
158
- const propsToProcess = meta.inheritanceType === 'tpt' && meta.tptParent && meta.ownProps ? meta.ownProps : meta.props;
159
- for (const prop of propsToProcess) {
160
- if (!this.shouldHaveColumn(meta, prop, skipColumns)) {
161
- continue;
162
- }
163
- table.addColumnFromProperty(prop, meta, config);
164
- }
165
- // For TPT child entities, always include the PK columns (they form the FK to parent)
166
- if (meta.inheritanceType === 'tpt' && meta.tptParent) {
167
- const pkProps = meta.primaryKeys.map(pk => meta.properties[pk]);
168
- for (const pkProp of pkProps) {
169
- // Only add if not already added (it might be in ownProps if defined in this entity)
170
- if (!propsToProcess.includes(pkProp)) {
171
- table.addColumnFromProperty(pkProp, meta, config);
172
- }
173
- // Child PK must not be autoincrement — it references the parent PK via FK
174
- for (const field of pkProp.fieldNames) {
175
- const col = table.getColumn(field);
176
- if (col) {
177
- col.autoincrement = false;
178
- }
179
- }
180
- }
181
- // Add FK from child PK to parent PK with ON DELETE CASCADE
182
- this.addTPTForeignKey(table, meta, config, platform);
183
- }
184
- meta.indexes.forEach(index => table.addIndex(meta, index, 'index'));
185
- meta.uniques.forEach(index => table.addIndex(meta, index, 'unique'));
186
- // For TPT child entities, the PK is also defined here
187
- const pkPropsForIndex = meta.inheritanceType === 'tpt' && meta.tptParent
188
- ? meta.primaryKeys.map(pk => meta.properties[pk])
189
- : meta.props.filter(prop => prop.primary);
190
- table.addIndex(meta, { properties: pkPropsForIndex.map(prop => prop.name) }, 'primary');
191
- for (const check of meta.checks) {
192
- const columnName = check.property ? meta.properties[check.property].fieldNames[0] : undefined;
193
- const expression = isRaw(check.expression)
194
- ? platform.formatQuery(check.expression.sql, check.expression.params)
195
- : check.expression;
196
- table.addCheck({
197
- name: check.name,
198
- expression,
199
- definition: `check (${expression})`,
200
- columnName,
201
- });
202
- }
203
- }
204
- return schema;
191
+ // Add FK from child PK to parent PK with ON DELETE CASCADE
192
+ this.addTPTForeignKey(table, meta, config, platform);
193
+ }
194
+ meta.indexes.forEach(index => table.addIndex(meta, index, 'index'));
195
+ meta.uniques.forEach(index => table.addIndex(meta, index, 'unique'));
196
+ // For TPT child entities, the PK is also defined here
197
+ const pkPropsForIndex =
198
+ meta.inheritanceType === 'tpt' && meta.tptParent
199
+ ? meta.primaryKeys.map(pk => meta.properties[pk])
200
+ : meta.props.filter(prop => prop.primary);
201
+ table.addIndex(meta, { properties: pkPropsForIndex.map(prop => prop.name) }, 'primary');
202
+ for (const check of meta.checks) {
203
+ const columnName = check.property ? meta.properties[check.property].fieldNames[0] : undefined;
204
+ const expression = isRaw(check.expression)
205
+ ? platform.formatQuery(check.expression.sql, check.expression.params)
206
+ : check.expression;
207
+ table.addCheck({
208
+ name: check.name,
209
+ expression,
210
+ definition: `check (${expression})`,
211
+ columnName,
212
+ });
213
+ }
205
214
  }
206
- static getViewDefinition(meta, em, platform) {
207
- if (typeof meta.expression === 'string') {
208
- return meta.expression;
209
- }
210
- // Expression is a function, need to evaluate it
211
- /* v8 ignore next */
212
- if (!em) {
213
- return undefined;
214
- }
215
- const result = meta.expression(em, {}, {});
216
- // Async expressions are not supported for view entities
217
- if (result && typeof result.then === 'function') {
218
- throw new Error(`View entity ${meta.className} expression returned a Promise. Async expressions are not supported for view entities.`);
219
- }
220
- /* v8 ignore next */
221
- if (typeof result === 'string') {
222
- return result;
223
- }
224
- /* v8 ignore next */
225
- if (isRaw(result)) {
226
- return platform.formatQuery(result.sql, result.params);
227
- }
228
- // Check if it's a QueryBuilder (has getFormattedQuery method)
229
- if (result && typeof result.getFormattedQuery === 'function') {
230
- return result.getFormattedQuery();
231
- }
232
- /* v8 ignore next - fallback for unknown result types */
233
- return undefined;
215
+ return schema;
216
+ }
217
+ static getViewDefinition(meta, em, platform) {
218
+ if (typeof meta.expression === 'string') {
219
+ return meta.expression;
220
+ }
221
+ // Expression is a function, need to evaluate it
222
+ /* v8 ignore next */
223
+ if (!em) {
224
+ return undefined;
234
225
  }
235
- static getSchemaName(meta, config, schema) {
236
- return (meta.schema === '*' ? schema : meta.schema) ?? config.get('schema');
226
+ const result = meta.expression(em, {}, {});
227
+ // Async expressions are not supported for view entities
228
+ if (result && typeof result.then === 'function') {
229
+ throw new Error(
230
+ `View entity ${meta.className} expression returned a Promise. Async expressions are not supported for view entities.`,
231
+ );
237
232
  }
238
- /**
239
- * Add a foreign key from a TPT child entity's PK to its parent entity's PK.
240
- * This FK uses ON DELETE CASCADE to ensure child rows are deleted when parent is deleted.
241
- */
242
- static addTPTForeignKey(table, meta, config, platform) {
243
- const parent = meta.tptParent;
244
- const pkColumnNames = meta.primaryKeys.flatMap(pk => meta.properties[pk].fieldNames);
245
- const parentPkColumnNames = parent.primaryKeys.flatMap(pk => parent.properties[pk].fieldNames);
246
- // Determine the parent table name with schema
247
- const parentSchema = parent.schema === '*' ? undefined : (parent.schema ?? config.get('schema', platform.getDefaultSchemaName()));
248
- const parentTableName = parentSchema ? `${parentSchema}.${parent.tableName}` : parent.tableName;
249
- // Create FK constraint name
250
- const constraintName = platform.getIndexName(table.name, pkColumnNames, 'foreign');
251
- // Add the foreign key to the table
252
- const fks = table.getForeignKeys();
253
- fks[constraintName] = {
254
- constraintName,
255
- columnNames: pkColumnNames,
256
- localTableName: table.getShortestName(false),
257
- referencedColumnNames: parentPkColumnNames,
258
- referencedTableName: parentTableName,
259
- deleteRule: 'cascade', // TPT always uses cascade delete
260
- updateRule: 'cascade', // TPT always uses cascade update
261
- };
233
+ /* v8 ignore next */
234
+ if (typeof result === 'string') {
235
+ return result;
262
236
  }
263
- static matchName(name, nameToMatch) {
264
- return typeof nameToMatch === 'string'
265
- ? name.toLocaleLowerCase() === nameToMatch.toLocaleLowerCase()
266
- : nameToMatch.test(name);
237
+ /* v8 ignore next */
238
+ if (isRaw(result)) {
239
+ return platform.formatQuery(result.sql, result.params);
267
240
  }
268
- static isNameAllowed(name, skipNames) {
269
- return !(skipNames?.some(pattern => this.matchName(name, pattern)) ?? false);
241
+ // Check if it's a QueryBuilder (has getFormattedQuery method)
242
+ if (result && typeof result.getFormattedQuery === 'function') {
243
+ return result.getFormattedQuery();
270
244
  }
271
- static isTableNameAllowed(tableName, takeTables, skipTables) {
272
- return ((takeTables?.some(tableNameToMatch => this.matchName(tableName, tableNameToMatch)) ?? true) &&
273
- this.isNameAllowed(tableName, skipTables));
245
+ /* v8 ignore next - fallback for unknown result types */
246
+ return undefined;
247
+ }
248
+ static getSchemaName(meta, config, schema) {
249
+ return (meta.schema === '*' ? schema : meta.schema) ?? config.get('schema');
250
+ }
251
+ /**
252
+ * Add a foreign key from a TPT child entity's PK to its parent entity's PK.
253
+ * This FK uses ON DELETE CASCADE to ensure child rows are deleted when parent is deleted.
254
+ */
255
+ static addTPTForeignKey(table, meta, config, platform) {
256
+ const parent = meta.tptParent;
257
+ const pkColumnNames = meta.primaryKeys.flatMap(pk => meta.properties[pk].fieldNames);
258
+ const parentPkColumnNames = parent.primaryKeys.flatMap(pk => parent.properties[pk].fieldNames);
259
+ // Determine the parent table name with schema
260
+ const parentSchema =
261
+ parent.schema === '*' ? undefined : (parent.schema ?? config.get('schema', platform.getDefaultSchemaName()));
262
+ const parentTableName = parentSchema ? `${parentSchema}.${parent.tableName}` : parent.tableName;
263
+ // Create FK constraint name
264
+ const constraintName = platform.getIndexName(table.name, pkColumnNames, 'foreign');
265
+ // Add the foreign key to the table
266
+ const fks = table.getForeignKeys();
267
+ fks[constraintName] = {
268
+ constraintName,
269
+ columnNames: pkColumnNames,
270
+ localTableName: table.getShortestName(false),
271
+ referencedColumnNames: parentPkColumnNames,
272
+ referencedTableName: parentTableName,
273
+ deleteRule: 'cascade', // TPT always uses cascade delete
274
+ updateRule: 'cascade', // TPT always uses cascade update
275
+ };
276
+ }
277
+ static matchName(name, nameToMatch) {
278
+ return typeof nameToMatch === 'string'
279
+ ? name.toLocaleLowerCase() === nameToMatch.toLocaleLowerCase()
280
+ : nameToMatch.test(name);
281
+ }
282
+ static isNameAllowed(name, skipNames) {
283
+ return !(skipNames?.some(pattern => this.matchName(name, pattern)) ?? false);
284
+ }
285
+ static isTableNameAllowed(tableName, takeTables, skipTables) {
286
+ return (
287
+ (takeTables?.some(tableNameToMatch => this.matchName(tableName, tableNameToMatch)) ?? true) &&
288
+ this.isNameAllowed(tableName, skipTables)
289
+ );
290
+ }
291
+ static shouldHaveColumn(meta, prop, skipColumns) {
292
+ if (prop.persist === false || (prop.columnTypes?.length ?? 0) === 0) {
293
+ return false;
274
294
  }
275
- static shouldHaveColumn(meta, prop, skipColumns) {
276
- if (prop.persist === false || (prop.columnTypes?.length ?? 0) === 0) {
295
+ // Check if column should be skipped
296
+ if (skipColumns) {
297
+ const tableName = meta.tableName;
298
+ const tableSchema = meta.schema;
299
+ const fullTableName = tableSchema ? `${tableSchema}.${tableName}` : tableName;
300
+ // Check for skipColumns by table name or fully qualified table name
301
+ const columnsToSkip = skipColumns[tableName] || skipColumns[fullTableName];
302
+ if (columnsToSkip) {
303
+ for (const fieldName of prop.fieldNames) {
304
+ if (columnsToSkip.some(pattern => this.matchName(fieldName, pattern))) {
277
305
  return false;
306
+ }
278
307
  }
279
- // Check if column should be skipped
280
- if (skipColumns) {
281
- const tableName = meta.tableName;
282
- const tableSchema = meta.schema;
283
- const fullTableName = tableSchema ? `${tableSchema}.${tableName}` : tableName;
284
- // Check for skipColumns by table name or fully qualified table name
285
- const columnsToSkip = skipColumns[tableName] || skipColumns[fullTableName];
286
- if (columnsToSkip) {
287
- for (const fieldName of prop.fieldNames) {
288
- if (columnsToSkip.some(pattern => this.matchName(fieldName, pattern))) {
289
- return false;
290
- }
291
- }
292
- }
293
- }
294
- if (prop.kind === ReferenceKind.EMBEDDED && prop.object) {
295
- return true;
296
- }
297
- const getRootProperty = (prop) => prop.embedded ? getRootProperty(meta.properties[prop.embedded[0]]) : prop;
298
- const rootProp = getRootProperty(prop);
299
- if (rootProp.kind === ReferenceKind.EMBEDDED) {
300
- return prop === rootProp || !rootProp.object;
301
- }
302
- return ([ReferenceKind.SCALAR, ReferenceKind.MANY_TO_ONE].includes(prop.kind) ||
303
- (prop.kind === ReferenceKind.ONE_TO_ONE && prop.owner));
308
+ }
304
309
  }
305
- toJSON() {
306
- return {
307
- name: this.name,
308
- namespaces: [...this.#namespaces],
309
- tables: this.#tables,
310
- views: this.#views,
311
- nativeEnums: this.#nativeEnums,
312
- };
310
+ if (prop.kind === ReferenceKind.EMBEDDED && prop.object) {
311
+ return true;
313
312
  }
314
- prune(schema, wildcardSchemaTables) {
315
- const hasWildcardSchema = wildcardSchemaTables.length > 0;
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
320
- });
321
- this.#views = this.#views.filter(view => {
322
- /* v8 ignore next */
323
- return ((!schema && !hasWildcardSchema) ||
324
- view.schema === schema ||
325
- (!schema && !wildcardSchemaTables.includes(view.name)));
326
- });
327
- // remove namespaces of ignored tables and views
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);
333
- }
334
- }
313
+ const getRootProperty = prop => (prop.embedded ? getRootProperty(meta.properties[prop.embedded[0]]) : prop);
314
+ const rootProp = getRootProperty(prop);
315
+ if (rootProp.kind === ReferenceKind.EMBEDDED) {
316
+ return prop === rootProp || !rootProp.object;
317
+ }
318
+ return (
319
+ [ReferenceKind.SCALAR, ReferenceKind.MANY_TO_ONE].includes(prop.kind) ||
320
+ (prop.kind === ReferenceKind.ONE_TO_ONE && prop.owner)
321
+ );
322
+ }
323
+ toJSON() {
324
+ return {
325
+ name: this.name,
326
+ namespaces: [...this.#namespaces],
327
+ tables: this.#tables,
328
+ views: this.#views,
329
+ nativeEnums: this.#nativeEnums,
330
+ };
331
+ }
332
+ prune(schema, wildcardSchemaTables) {
333
+ const hasWildcardSchema = wildcardSchemaTables.length > 0;
334
+ this.#tables = this.#tables.filter(table => {
335
+ return (
336
+ (!schema && !hasWildcardSchema) || // no schema specified and we don't have any multi-schema entity
337
+ table.schema === schema || // specified schema matches the table's one
338
+ (!schema && !wildcardSchemaTables.includes(table.name))
339
+ ); // no schema specified and the table has fixed one provided
340
+ });
341
+ this.#views = this.#views.filter(view => {
342
+ /* v8 ignore next */
343
+ return (
344
+ (!schema && !hasWildcardSchema) ||
345
+ view.schema === schema ||
346
+ (!schema && !wildcardSchemaTables.includes(view.name))
347
+ );
348
+ });
349
+ // remove namespaces of ignored tables and views
350
+ for (const ns of this.#namespaces) {
351
+ if (
352
+ !this.#tables.some(t => t.schema === ns) &&
353
+ !this.#views.some(v => v.schema === ns) &&
354
+ !Object.values(this.#nativeEnums).some(e => e.schema === ns)
355
+ ) {
356
+ this.#namespaces.delete(ns);
357
+ }
335
358
  }
359
+ }
336
360
  }