@mikro-orm/sql 7.0.0-dev.300 → 7.0.0-dev.301
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AbstractSqlConnection.js +2 -1
- package/AbstractSqlDriver.js +135 -39
- package/AbstractSqlPlatform.js +2 -3
- package/PivotCollectionPersister.js +2 -2
- package/SqlEntityManager.d.ts +1 -1
- package/SqlEntityManager.js +5 -5
- package/dialects/mssql/MsSqlNativeQueryBuilder.js +3 -4
- package/dialects/mysql/BaseMySqlPlatform.js +1 -2
- package/dialects/mysql/MySqlSchemaHelper.js +21 -10
- package/dialects/postgresql/BasePostgreSqlPlatform.js +38 -30
- package/dialects/postgresql/PostgreSqlSchemaHelper.js +55 -45
- package/dialects/sqlite/BaseSqliteConnection.js +2 -2
- package/dialects/sqlite/NodeSqliteDialect.js +3 -1
- package/dialects/sqlite/SqlitePlatform.js +4 -1
- package/dialects/sqlite/SqliteSchemaHelper.js +11 -9
- package/package.json +29 -29
- package/plugin/transformer.js +17 -16
- package/query/CriteriaNode.js +28 -10
- package/query/CriteriaNodeFactory.js +5 -1
- package/query/NativeQueryBuilder.js +1 -1
- package/query/ObjectCriteriaNode.js +67 -43
- package/query/QueryBuilder.d.ts +25 -12
- package/query/QueryBuilder.js +105 -49
- package/query/QueryBuilderHelper.js +41 -14
- package/query/ScalarCriteriaNode.js +13 -6
- package/query/raw.js +1 -1
- package/schema/DatabaseSchema.js +21 -15
- package/schema/DatabaseTable.js +81 -51
- package/schema/SchemaComparator.js +54 -30
- package/schema/SchemaHelper.js +28 -8
- package/schema/SqlSchemaGenerator.js +13 -7
- package/tsconfig.build.tsbuildinfo +1 -1
- package/typings.d.ts +1 -1
|
@@ -113,8 +113,10 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
|
|
|
113
113
|
}
|
|
114
114
|
getMappedType(type) {
|
|
115
115
|
switch (this.extractSimpleType(type)) {
|
|
116
|
-
case 'tsvector':
|
|
117
|
-
|
|
116
|
+
case 'tsvector':
|
|
117
|
+
return Type.getType(FullTextType);
|
|
118
|
+
default:
|
|
119
|
+
return super.getMappedType(type);
|
|
118
120
|
}
|
|
119
121
|
}
|
|
120
122
|
getRegExpOperator(val, flags) {
|
|
@@ -132,7 +134,7 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
|
|
|
132
134
|
return { $re: val.source };
|
|
133
135
|
}
|
|
134
136
|
isBigIntProperty(prop) {
|
|
135
|
-
return super.isBigIntProperty(prop) ||
|
|
137
|
+
return super.isBigIntProperty(prop) || ['bigserial', 'int8'].includes(prop.columnTypes?.[0]);
|
|
136
138
|
}
|
|
137
139
|
getArrayDeclarationSQL() {
|
|
138
140
|
return 'text[]';
|
|
@@ -166,7 +168,7 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
|
|
|
166
168
|
return ['begin'];
|
|
167
169
|
}
|
|
168
170
|
marshallArray(values) {
|
|
169
|
-
const quote = (v) => v === '' || v.match(/["{},\\]/) ? JSON.stringify(v) : v;
|
|
171
|
+
const quote = (v) => (v === '' || v.match(/["{},\\]/) ? JSON.stringify(v) : v);
|
|
170
172
|
return `{${values.map(v => quote('' + v)).join(',')}}`;
|
|
171
173
|
}
|
|
172
174
|
/* v8 ignore next */
|
|
@@ -174,7 +176,10 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
|
|
|
174
176
|
if (value === '{}') {
|
|
175
177
|
return [];
|
|
176
178
|
}
|
|
177
|
-
return value
|
|
179
|
+
return value
|
|
180
|
+
.substring(1, value.length - 1)
|
|
181
|
+
.split(',')
|
|
182
|
+
.map(v => {
|
|
178
183
|
if (v === `""`) {
|
|
179
184
|
return '';
|
|
180
185
|
}
|
|
@@ -218,7 +223,8 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
|
|
|
218
223
|
const cast = (key) => raw(type in types ? `(${key})::${types[type]}` : key);
|
|
219
224
|
let lastOperator = '->>';
|
|
220
225
|
// force `->` for operator payloads with array values
|
|
221
|
-
if (Utils.isPlainObject(value) &&
|
|
226
|
+
if (Utils.isPlainObject(value) &&
|
|
227
|
+
Object.keys(value).every(key => ARRAY_OPERATORS.includes(key) && Array.isArray(value[key]))) {
|
|
222
228
|
lastOperator = '->';
|
|
223
229
|
}
|
|
224
230
|
if (path.length === 0) {
|
|
@@ -227,8 +233,7 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
|
|
|
227
233
|
return cast(`${root}->${path.map(a => this.quoteValue(a)).join('->')}${lastOperator}'${last}'`);
|
|
228
234
|
}
|
|
229
235
|
getJsonIndexDefinition(index) {
|
|
230
|
-
return index.columnNames
|
|
231
|
-
.map(column => {
|
|
236
|
+
return index.columnNames.map(column => {
|
|
232
237
|
if (!column.includes('.')) {
|
|
233
238
|
return column;
|
|
234
239
|
}
|
|
@@ -286,26 +291,26 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
|
|
|
286
291
|
getDefaultMappedType(type) {
|
|
287
292
|
const normalizedType = this.extractSimpleType(type);
|
|
288
293
|
const map = {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
294
|
+
int2: 'smallint',
|
|
295
|
+
smallserial: 'smallint',
|
|
296
|
+
int: 'integer',
|
|
297
|
+
int4: 'integer',
|
|
298
|
+
serial: 'integer',
|
|
299
|
+
serial4: 'integer',
|
|
300
|
+
int8: 'bigint',
|
|
301
|
+
bigserial: 'bigint',
|
|
302
|
+
serial8: 'bigint',
|
|
303
|
+
numeric: 'decimal',
|
|
304
|
+
bool: 'boolean',
|
|
305
|
+
real: 'float',
|
|
306
|
+
float4: 'float',
|
|
307
|
+
float8: 'double',
|
|
308
|
+
timestamp: 'datetime',
|
|
309
|
+
timestamptz: 'datetime',
|
|
310
|
+
bytea: 'blob',
|
|
311
|
+
jsonb: 'json',
|
|
307
312
|
'character varying': 'varchar',
|
|
308
|
-
|
|
313
|
+
bpchar: 'character',
|
|
309
314
|
};
|
|
310
315
|
return super.getDefaultMappedType(map[normalizedType] ?? type);
|
|
311
316
|
}
|
|
@@ -339,9 +344,12 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
|
|
|
339
344
|
*/
|
|
340
345
|
castColumn(prop) {
|
|
341
346
|
switch (prop?.columnTypes?.[0]) {
|
|
342
|
-
case this.getUuidTypeDeclarationSQL({}):
|
|
343
|
-
|
|
344
|
-
|
|
347
|
+
case this.getUuidTypeDeclarationSQL({}):
|
|
348
|
+
return '::text';
|
|
349
|
+
case this.getBooleanTypeDeclarationSQL():
|
|
350
|
+
return '::int';
|
|
351
|
+
default:
|
|
352
|
+
return '';
|
|
345
353
|
}
|
|
346
354
|
}
|
|
347
355
|
getDefaultClientUrl() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DeferMode, EnumType, Type, Utils } from '@mikro-orm/core';
|
|
1
|
+
import { DeferMode, EnumType, Type, Utils, } from '@mikro-orm/core';
|
|
2
2
|
import { SchemaHelper } from '../../schema/SchemaHelper.js';
|
|
3
3
|
/** PostGIS system views that should be automatically ignored */
|
|
4
4
|
const POSTGIS_VIEWS = ['geography_columns', 'geometry_columns'];
|
|
@@ -22,24 +22,24 @@ export class PostgreSqlSchemaHelper extends SchemaHelper {
|
|
|
22
22
|
return `create database ${name}`;
|
|
23
23
|
}
|
|
24
24
|
getListTablesSQL() {
|
|
25
|
-
return `select table_name, table_schema as schema_name, `
|
|
26
|
-
|
|
27
|
-
where c.oid = (select ('"' || table_schema || '"."' || table_name || '"')::regclass::oid) and c.relname = table_name) as table_comment `
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
return (`select table_name, table_schema as schema_name, ` +
|
|
26
|
+
`(select pg_catalog.obj_description(c.oid) from pg_catalog.pg_class c
|
|
27
|
+
where c.oid = (select ('"' || table_schema || '"."' || table_name || '"')::regclass::oid) and c.relname = table_name) as table_comment ` +
|
|
28
|
+
`from information_schema.tables ` +
|
|
29
|
+
`where ${this.getIgnoredNamespacesConditionSQL('table_schema')} ` +
|
|
30
|
+
`and table_name != 'geometry_columns' and table_name != 'spatial_ref_sys' and table_type != 'VIEW' ` +
|
|
31
|
+
`and table_name not in (select inhrelid::regclass::text from pg_inherits) ` +
|
|
32
|
+
`order by table_name`);
|
|
33
33
|
}
|
|
34
34
|
getIgnoredViewsCondition() {
|
|
35
35
|
return POSTGIS_VIEWS.map(v => `table_name != '${v}'`).join(' and ');
|
|
36
36
|
}
|
|
37
37
|
getListViewsSQL() {
|
|
38
|
-
return `select table_name as view_name, table_schema as schema_name, view_definition `
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
return (`select table_name as view_name, table_schema as schema_name, view_definition ` +
|
|
39
|
+
`from information_schema.views ` +
|
|
40
|
+
`where ${this.getIgnoredNamespacesConditionSQL('table_schema')} ` +
|
|
41
|
+
`and ${this.getIgnoredViewsCondition()} ` +
|
|
42
|
+
`order by table_name`);
|
|
43
43
|
}
|
|
44
44
|
async loadViews(schema, connection) {
|
|
45
45
|
const views = await connection.execute(this.getListViewsSQL());
|
|
@@ -51,10 +51,10 @@ export class PostgreSqlSchemaHelper extends SchemaHelper {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
getListMaterializedViewsSQL() {
|
|
54
|
-
return `select matviewname as view_name, schemaname as schema_name, definition as view_definition `
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
return (`select matviewname as view_name, schemaname as schema_name, definition as view_definition ` +
|
|
55
|
+
`from pg_matviews ` +
|
|
56
|
+
`where ${this.getIgnoredNamespacesConditionSQL('schemaname')} ` +
|
|
57
|
+
`order by matviewname`);
|
|
58
58
|
}
|
|
59
59
|
async loadMaterializedViews(schema, connection, schemaName) {
|
|
60
60
|
const views = await connection.execute(this.getListMaterializedViewsSQL());
|
|
@@ -78,9 +78,9 @@ export class PostgreSqlSchemaHelper extends SchemaHelper {
|
|
|
78
78
|
return `refresh materialized view${concurrent} ${this.quote(this.getTableName(name, schema))}`;
|
|
79
79
|
}
|
|
80
80
|
async getNamespaces(connection) {
|
|
81
|
-
const sql = `select schema_name from information_schema.schemata `
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
const sql = `select schema_name from information_schema.schemata ` +
|
|
82
|
+
`where ${this.getIgnoredNamespacesConditionSQL()} ` +
|
|
83
|
+
`order by schema_name`;
|
|
84
84
|
const res = await connection.execute(sql);
|
|
85
85
|
return res.map(row => row.schema_name);
|
|
86
86
|
}
|
|
@@ -90,13 +90,11 @@ export class PostgreSqlSchemaHelper extends SchemaHelper {
|
|
|
90
90
|
'tiger',
|
|
91
91
|
'topology',
|
|
92
92
|
/* v8 ignore next */
|
|
93
|
-
...this.platform.getConfig().get('schemaGenerator').ignoreSchema ?? [],
|
|
94
|
-
]
|
|
95
|
-
|
|
96
|
-
'
|
|
97
|
-
|
|
98
|
-
'_timescaledb_',
|
|
99
|
-
].map(p => `"${column}" not like '${p}%'`).join(' and ');
|
|
93
|
+
...(this.platform.getConfig().get('schemaGenerator').ignoreSchema ?? []),
|
|
94
|
+
]
|
|
95
|
+
.map(s => this.platform.quoteValue(s))
|
|
96
|
+
.join(', ');
|
|
97
|
+
const ignoredPrefixes = ['pg_', 'crdb_', '_timescaledb_'].map(p => `"${column}" not like '${p}%'`).join(' and ');
|
|
100
98
|
return `${ignoredPrefixes} and "${column}" not in (${ignored})`;
|
|
101
99
|
}
|
|
102
100
|
async loadInformationSchema(schema, connection, tables, schemas) {
|
|
@@ -130,9 +128,7 @@ export class PostgreSqlSchemaHelper extends SchemaHelper {
|
|
|
130
128
|
const key = this.getTableKey(index);
|
|
131
129
|
// Extract INCLUDE columns from expression first, to filter them from key columns
|
|
132
130
|
const includeMatch = index.expression?.match(/include\s*\(([^)]+)\)/i);
|
|
133
|
-
const includeColumns = includeMatch
|
|
134
|
-
? includeMatch[1].split(',').map((col) => unquote(col.trim()))
|
|
135
|
-
: [];
|
|
131
|
+
const includeColumns = includeMatch ? includeMatch[1].split(',').map((col) => unquote(col.trim())) : [];
|
|
136
132
|
// Filter out INCLUDE columns from the column definitions to get only key columns
|
|
137
133
|
const keyColumnDefs = index.index_def.filter((col) => !includeColumns.includes(unquote(col)));
|
|
138
134
|
// Parse sort order and NULLS ordering from the full expression
|
|
@@ -268,17 +264,18 @@ export class PostgreSqlSchemaHelper extends SchemaHelper {
|
|
|
268
264
|
where (${[...tablesBySchemas.entries()].map(([schema, tables]) => `(table_schema = ${this.platform.quoteValue(schema)} and table_name in (${tables.map(t => this.platform.quoteValue(t.table_name)).join(',')}))`).join(' or ')})
|
|
269
265
|
order by ordinal_position`;
|
|
270
266
|
const allColumns = await connection.execute(sql);
|
|
271
|
-
const str = (val) => val != null ? '' + val : val;
|
|
267
|
+
const str = (val) => (val != null ? '' + val : val);
|
|
272
268
|
const ret = {};
|
|
273
269
|
for (const col of allColumns) {
|
|
274
270
|
const mappedType = connection.getPlatform().getMappedType(col.data_type);
|
|
275
|
-
const increments = (col.column_default?.includes('nextval') || col.is_identity === 'YES') &&
|
|
271
|
+
const increments = (col.column_default?.includes('nextval') || col.is_identity === 'YES') &&
|
|
272
|
+
connection.getPlatform().isNumericColumn(mappedType);
|
|
276
273
|
const key = this.getTableKey(col);
|
|
277
274
|
ret[key] ??= [];
|
|
278
|
-
let type = col.data_type.toLowerCase() === 'array'
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
275
|
+
let type = col.data_type.toLowerCase() === 'array' ? col.udt_name.replace(/^_(.*)$/, '$1[]') : col.udt_name;
|
|
276
|
+
if (col.data_type === 'USER-DEFINED' &&
|
|
277
|
+
col.udt_schema &&
|
|
278
|
+
col.udt_schema !== this.platform.getDefaultSchemaName()) {
|
|
282
279
|
type = `${col.udt_schema}.${type}`;
|
|
283
280
|
}
|
|
284
281
|
if (type === 'bpchar') {
|
|
@@ -305,7 +302,13 @@ export class PostgreSqlSchemaHelper extends SchemaHelper {
|
|
|
305
302
|
default: str(this.normalizeDefaultValue(col.column_default, col.length)),
|
|
306
303
|
unsigned: increments,
|
|
307
304
|
autoincrement: increments,
|
|
308
|
-
generated: col.is_identity === 'YES'
|
|
305
|
+
generated: col.is_identity === 'YES'
|
|
306
|
+
? col.identity_generation === 'BY DEFAULT'
|
|
307
|
+
? 'by default as identity'
|
|
308
|
+
: 'identity'
|
|
309
|
+
: col.generation_expression
|
|
310
|
+
? col.generation_expression + ' stored'
|
|
311
|
+
: undefined,
|
|
309
312
|
comment: col.column_comment,
|
|
310
313
|
};
|
|
311
314
|
if (nativeEnums?.[column.type]) {
|
|
@@ -365,12 +368,17 @@ export class PostgreSqlSchemaHelper extends SchemaHelper {
|
|
|
365
368
|
}
|
|
366
369
|
/* v8 ignore next */
|
|
367
370
|
switch (value) {
|
|
368
|
-
case 'r':
|
|
369
|
-
|
|
370
|
-
case '
|
|
371
|
-
|
|
371
|
+
case 'r':
|
|
372
|
+
return 'RESTRICT';
|
|
373
|
+
case 'c':
|
|
374
|
+
return 'CASCADE';
|
|
375
|
+
case 'n':
|
|
376
|
+
return 'SET NULL';
|
|
377
|
+
case 'd':
|
|
378
|
+
return 'SET DEFAULT';
|
|
372
379
|
case 'a':
|
|
373
|
-
default:
|
|
380
|
+
default:
|
|
381
|
+
return 'NO ACTION';
|
|
374
382
|
}
|
|
375
383
|
}
|
|
376
384
|
for (const fk of allFks) {
|
|
@@ -651,7 +659,8 @@ export class PostgreSqlSchemaHelper extends SchemaHelper {
|
|
|
651
659
|
*/
|
|
652
660
|
getIndexColumns(index) {
|
|
653
661
|
if (index.columns?.length) {
|
|
654
|
-
return index.columns
|
|
662
|
+
return index.columns
|
|
663
|
+
.map(col => {
|
|
655
664
|
let colDef = this.quote(col.name);
|
|
656
665
|
// PostgreSQL supports collation with double quotes
|
|
657
666
|
if (col.collation) {
|
|
@@ -666,7 +675,8 @@ export class PostgreSqlSchemaHelper extends SchemaHelper {
|
|
|
666
675
|
colDef += ` nulls ${col.nulls}`;
|
|
667
676
|
}
|
|
668
677
|
return colDef;
|
|
669
|
-
})
|
|
678
|
+
})
|
|
679
|
+
.join(', ');
|
|
670
680
|
}
|
|
671
681
|
return index.columnNames.map(c => this.quote(c)).join(', ');
|
|
672
682
|
}
|
|
@@ -2,8 +2,8 @@ import { CompiledQuery } from 'kysely';
|
|
|
2
2
|
import { AbstractSqlConnection } from '../../AbstractSqlConnection.js';
|
|
3
3
|
export class BaseSqliteConnection extends AbstractSqlConnection {
|
|
4
4
|
createKyselyDialect(options) {
|
|
5
|
-
throw new Error('No SQLite dialect configured. Pass a Kysely dialect via the `driverOptions` config option, '
|
|
6
|
-
|
|
5
|
+
throw new Error('No SQLite dialect configured. Pass a Kysely dialect via the `driverOptions` config option, ' +
|
|
6
|
+
'e.g. `new NodeSqliteDialect(...)` for node:sqlite or a custom dialect for other libraries.');
|
|
7
7
|
}
|
|
8
8
|
async connect(options) {
|
|
9
9
|
await super.connect(options);
|
|
@@ -125,7 +125,10 @@ export class SqlitePlatform extends AbstractSqlPlatform {
|
|
|
125
125
|
convertVersionValue(value, prop) {
|
|
126
126
|
if (prop.runtimeType === 'Date') {
|
|
127
127
|
const ts = +value;
|
|
128
|
-
const str = new Date(ts)
|
|
128
|
+
const str = new Date(ts)
|
|
129
|
+
.toISOString()
|
|
130
|
+
.replace('T', ' ')
|
|
131
|
+
.replace(/\.\d{3}Z$/, '');
|
|
129
132
|
return { $in: [ts, str] };
|
|
130
133
|
}
|
|
131
134
|
return value;
|
|
@@ -31,8 +31,8 @@ export class SqliteSchemaHelper extends SchemaHelper {
|
|
|
31
31
|
return '';
|
|
32
32
|
}
|
|
33
33
|
getListTablesSQL() {
|
|
34
|
-
return `select name as table_name from sqlite_master where type = 'table' and name != 'sqlite_sequence' and name != 'geometry_columns' and name != 'spatial_ref_sys' `
|
|
35
|
-
|
|
34
|
+
return (`select name as table_name from sqlite_master where type = 'table' and name != 'sqlite_sequence' and name != 'geometry_columns' and name != 'spatial_ref_sys' ` +
|
|
35
|
+
`union all select name as table_name from sqlite_temp_master where type = 'table' order by name`);
|
|
36
36
|
}
|
|
37
37
|
async getAllTables(connection, schemas) {
|
|
38
38
|
const databases = await this.getDatabaseList(connection);
|
|
@@ -183,9 +183,11 @@ export class SqliteSchemaHelper extends SchemaHelper {
|
|
|
183
183
|
getDropColumnsSQL(tableName, columns, schemaName) {
|
|
184
184
|
/* v8 ignore next */
|
|
185
185
|
const name = this.quote((schemaName && schemaName !== this.platform.getDefaultSchemaName() ? schemaName + '.' : '') + tableName);
|
|
186
|
-
return columns
|
|
186
|
+
return columns
|
|
187
|
+
.map(column => {
|
|
187
188
|
return `alter table ${name} drop column ${this.quote(column.name)}`;
|
|
188
|
-
})
|
|
189
|
+
})
|
|
190
|
+
.join(';\n');
|
|
189
191
|
}
|
|
190
192
|
getCreateIndexSQL(tableName, index) {
|
|
191
193
|
/* v8 ignore next */
|
|
@@ -453,10 +455,10 @@ export class SqliteSchemaHelper extends SchemaHelper {
|
|
|
453
455
|
alterTable(diff, safe) {
|
|
454
456
|
const ret = [];
|
|
455
457
|
const [schemaName, tableName] = this.splitTableName(diff.name);
|
|
456
|
-
if (Utils.hasObjectKeys(diff.removedChecks)
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
458
|
+
if (Utils.hasObjectKeys(diff.removedChecks) ||
|
|
459
|
+
Utils.hasObjectKeys(diff.changedChecks) ||
|
|
460
|
+
Utils.hasObjectKeys(diff.changedForeignKeys) ||
|
|
461
|
+
Utils.hasObjectKeys(diff.changedColumns)) {
|
|
460
462
|
return this.getAlterTempTableSQL(diff);
|
|
461
463
|
}
|
|
462
464
|
for (const index of Object.values(diff.removedIndexes)) {
|
|
@@ -496,7 +498,7 @@ export class SqliteSchemaHelper extends SchemaHelper {
|
|
|
496
498
|
return ret;
|
|
497
499
|
}
|
|
498
500
|
getAlterTempTableSQL(changedTable) {
|
|
499
|
-
const tempName = `${
|
|
501
|
+
const tempName = `${changedTable.toTable.name}__temp_alter`;
|
|
500
502
|
const quotedName = this.quote(changedTable.toTable.name);
|
|
501
503
|
const quotedTempName = this.quote(tempName);
|
|
502
504
|
const [first, ...rest] = this.createTable(changedTable.toTable);
|
package/package.json
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/sql",
|
|
3
|
-
"version": "7.0.0-dev.
|
|
3
|
+
"version": "7.0.0-dev.301",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"exports": {
|
|
7
|
-
"./package.json": "./package.json",
|
|
8
|
-
".": "./index.js"
|
|
9
|
-
},
|
|
10
|
-
"repository": {
|
|
11
|
-
"type": "git",
|
|
12
|
-
"url": "git+ssh://git@github.com/mikro-orm/mikro-orm.git"
|
|
13
|
-
},
|
|
14
5
|
"keywords": [
|
|
15
|
-
"
|
|
6
|
+
"data-mapper",
|
|
7
|
+
"ddd",
|
|
8
|
+
"entity",
|
|
9
|
+
"identity-map",
|
|
10
|
+
"javascript",
|
|
11
|
+
"js",
|
|
12
|
+
"mariadb",
|
|
13
|
+
"mikro-orm",
|
|
16
14
|
"mongo",
|
|
17
15
|
"mongodb",
|
|
18
16
|
"mysql",
|
|
19
|
-
"
|
|
17
|
+
"orm",
|
|
20
18
|
"postgresql",
|
|
21
19
|
"sqlite",
|
|
22
20
|
"sqlite3",
|
|
23
21
|
"ts",
|
|
24
22
|
"typescript",
|
|
25
|
-
"
|
|
26
|
-
"javascript",
|
|
27
|
-
"entity",
|
|
28
|
-
"ddd",
|
|
29
|
-
"mikro-orm",
|
|
30
|
-
"unit-of-work",
|
|
31
|
-
"data-mapper",
|
|
32
|
-
"identity-map"
|
|
23
|
+
"unit-of-work"
|
|
33
24
|
],
|
|
34
|
-
"
|
|
35
|
-
"license": "MIT",
|
|
25
|
+
"homepage": "https://mikro-orm.io",
|
|
36
26
|
"bugs": {
|
|
37
27
|
"url": "https://github.com/mikro-orm/mikro-orm/issues"
|
|
38
28
|
},
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"author": "Martin Adámek",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+ssh://git@github.com/mikro-orm/mikro-orm.git"
|
|
34
|
+
},
|
|
35
|
+
"type": "module",
|
|
36
|
+
"exports": {
|
|
37
|
+
"./package.json": "./package.json",
|
|
38
|
+
".": "./index.js"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "yarn compile && yarn copy",
|
|
@@ -46,9 +46,6 @@
|
|
|
46
46
|
"compile": "yarn run -T tsc -p tsconfig.build.json",
|
|
47
47
|
"copy": "node ../../scripts/copy.mjs"
|
|
48
48
|
},
|
|
49
|
-
"publishConfig": {
|
|
50
|
-
"access": "public"
|
|
51
|
-
},
|
|
52
49
|
"dependencies": {
|
|
53
50
|
"kysely": "0.28.11"
|
|
54
51
|
},
|
|
@@ -56,6 +53,9 @@
|
|
|
56
53
|
"@mikro-orm/core": "^6.6.8"
|
|
57
54
|
},
|
|
58
55
|
"peerDependencies": {
|
|
59
|
-
"@mikro-orm/core": "7.0.0-dev.
|
|
56
|
+
"@mikro-orm/core": "7.0.0-dev.301"
|
|
57
|
+
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": ">= 22.17.0"
|
|
60
60
|
}
|
|
61
61
|
}
|
package/plugin/transformer.js
CHANGED
|
@@ -79,12 +79,8 @@ export class MikroTransformer extends OperationNodeTransformer {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
const nodeWithHooks = this.options.processOnCreateHooks && entityMeta
|
|
83
|
-
|
|
84
|
-
: node;
|
|
85
|
-
const nodeWithConvertedValues = this.options.convertValues && entityMeta
|
|
86
|
-
? this.processInsertValues(nodeWithHooks, entityMeta)
|
|
87
|
-
: nodeWithHooks;
|
|
82
|
+
const nodeWithHooks = this.options.processOnCreateHooks && entityMeta ? this.processOnCreateHooks(node, entityMeta) : node;
|
|
83
|
+
const nodeWithConvertedValues = this.options.convertValues && entityMeta ? this.processInsertValues(nodeWithHooks, entityMeta) : nodeWithHooks;
|
|
88
84
|
// Handle ON CONFLICT clause
|
|
89
85
|
let finalNode = nodeWithConvertedValues;
|
|
90
86
|
if (node.onConflict?.updates && entityMeta) {
|
|
@@ -150,12 +146,8 @@ export class MikroTransformer extends OperationNodeTransformer {
|
|
|
150
146
|
this.processJoinNode(join, currentContext);
|
|
151
147
|
}
|
|
152
148
|
}
|
|
153
|
-
const nodeWithHooks = this.options.processOnUpdateHooks && entityMeta
|
|
154
|
-
|
|
155
|
-
: node;
|
|
156
|
-
const nodeWithConvertedValues = this.options.convertValues && entityMeta
|
|
157
|
-
? this.processUpdateValues(nodeWithHooks, entityMeta)
|
|
158
|
-
: nodeWithHooks;
|
|
149
|
+
const nodeWithHooks = this.options.processOnUpdateHooks && entityMeta ? this.processOnUpdateHooks(node, entityMeta) : node;
|
|
150
|
+
const nodeWithConvertedValues = this.options.convertValues && entityMeta ? this.processUpdateValues(nodeWithHooks, entityMeta) : nodeWithHooks;
|
|
159
151
|
return super.transformUpdateQuery(nodeWithConvertedValues, queryId);
|
|
160
152
|
}
|
|
161
153
|
finally {
|
|
@@ -217,7 +209,9 @@ export class MikroTransformer extends OperationNodeTransformer {
|
|
|
217
209
|
}
|
|
218
210
|
// Transform column names when columnNamingStrategy is 'property'
|
|
219
211
|
// Support ColumnNode, ColumnUpdateNode, and ReferenceNode (for JOIN conditions)
|
|
220
|
-
if (this.options.columnNamingStrategy === 'property' &&
|
|
212
|
+
if (this.options.columnNamingStrategy === 'property' &&
|
|
213
|
+
parent &&
|
|
214
|
+
(ColumnNode.is(parent) || ColumnUpdateNode.is(parent) || ReferenceNode.is(parent))) {
|
|
221
215
|
const ownerMeta = this.findOwnerEntityInContext();
|
|
222
216
|
if (ownerMeta) {
|
|
223
217
|
const prop = ownerMeta.properties[node.name];
|
|
@@ -480,7 +474,11 @@ export class MikroTransformer extends OperationNodeTransformer {
|
|
|
480
474
|
}
|
|
481
475
|
}
|
|
482
476
|
if (prop.customType && !isRaw(value)) {
|
|
483
|
-
return prop.customType.convertToDatabaseValue(value, this.platform, {
|
|
477
|
+
return prop.customType.convertToDatabaseValue(value, this.platform, {
|
|
478
|
+
fromQuery: true,
|
|
479
|
+
key: prop.name,
|
|
480
|
+
mode: 'query-data',
|
|
481
|
+
});
|
|
484
482
|
}
|
|
485
483
|
if (value instanceof Date) {
|
|
486
484
|
return this.platform.processDateProperty(value);
|
|
@@ -723,7 +721,9 @@ export class MikroTransformer extends OperationNodeTransformer {
|
|
|
723
721
|
*/
|
|
724
722
|
transformResult(rows, entityMap) {
|
|
725
723
|
// Only transform if columnNamingStrategy is 'property' or convertValues is true, and we have data
|
|
726
|
-
if ((this.options.columnNamingStrategy !== 'property' && !this.options.convertValues) ||
|
|
724
|
+
if ((this.options.columnNamingStrategy !== 'property' && !this.options.convertValues) ||
|
|
725
|
+
!rows ||
|
|
726
|
+
rows.length === 0) {
|
|
727
727
|
return rows;
|
|
728
728
|
}
|
|
729
729
|
// If no entities found (e.g. raw query without known tables), return rows as is
|
|
@@ -870,7 +870,8 @@ export class MikroTransformer extends OperationNodeTransformer {
|
|
|
870
870
|
}
|
|
871
871
|
// For non-local timezone, check if value already has timezone info
|
|
872
872
|
// Number (timestamp) doesn't need timezone handling, string needs check
|
|
873
|
-
if (typeof value === 'number' ||
|
|
873
|
+
if (typeof value === 'number' ||
|
|
874
|
+
(typeof value === 'string' && (value.includes('+') || value.lastIndexOf('-') > 10 || value.endsWith('Z')))) {
|
|
874
875
|
return this.platform.parseDate(value);
|
|
875
876
|
}
|
|
876
877
|
// Append timezone if not present (only for string values)
|
package/query/CriteriaNode.js
CHANGED
|
@@ -53,22 +53,34 @@ export class CriteriaNode {
|
|
|
53
53
|
const type = this.prop ? this.prop.kind : null;
|
|
54
54
|
const composite = this.prop?.joinColumns ? this.prop.joinColumns.length > 1 : false;
|
|
55
55
|
const rawField = RawQueryFragment.isKnownFragmentSymbol(this.key);
|
|
56
|
-
const scalar = payload === null ||
|
|
56
|
+
const scalar = payload === null ||
|
|
57
|
+
Utils.isPrimaryKey(payload) ||
|
|
58
|
+
payload instanceof RegExp ||
|
|
59
|
+
payload instanceof Date ||
|
|
60
|
+
rawField;
|
|
57
61
|
const operator = Utils.isPlainObject(payload) && Utils.getObjectQueryKeys(payload).every(k => Utils.isOperator(k, false));
|
|
58
62
|
if (composite) {
|
|
59
63
|
return true;
|
|
60
64
|
}
|
|
61
65
|
switch (type) {
|
|
62
|
-
case ReferenceKind.MANY_TO_ONE:
|
|
63
|
-
|
|
64
|
-
case ReferenceKind.
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
case ReferenceKind.MANY_TO_ONE:
|
|
67
|
+
return false;
|
|
68
|
+
case ReferenceKind.ONE_TO_ONE:
|
|
69
|
+
return !this.prop.owner;
|
|
70
|
+
case ReferenceKind.ONE_TO_MANY:
|
|
71
|
+
return scalar || operator;
|
|
72
|
+
case ReferenceKind.MANY_TO_MANY:
|
|
73
|
+
return scalar || operator;
|
|
74
|
+
default:
|
|
75
|
+
return false;
|
|
67
76
|
}
|
|
68
77
|
}
|
|
69
78
|
renameFieldToPK(qb, ownerAlias) {
|
|
70
79
|
const joinAlias = qb.getAliasForJoinPath(this.getPath(), { matchPopulateJoins: true });
|
|
71
|
-
if (!joinAlias &&
|
|
80
|
+
if (!joinAlias &&
|
|
81
|
+
this.parent &&
|
|
82
|
+
[ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind) &&
|
|
83
|
+
this.prop.owner) {
|
|
72
84
|
const alias = qb.getAliasForJoinPath(this.parent.getPath()) ?? ownerAlias ?? qb.alias;
|
|
73
85
|
return Utils.getPrimaryKeyHash(this.prop.joinColumns.map(col => `${alias}.${col}`));
|
|
74
86
|
}
|
|
@@ -84,7 +96,9 @@ export class CriteriaNode {
|
|
|
84
96
|
const parentPath = opts?.parentPath ?? this.parent?.getPath({ addIndex: addParentIndex }) ?? Utils.className(this.entityName);
|
|
85
97
|
const index = opts?.addIndex && this.index != null ? `[${this.index}]` : '';
|
|
86
98
|
// ignore group operators to allow easier mapping (e.g. for orderBy)
|
|
87
|
-
const key = this.key && !RawQueryFragment.isKnownFragmentSymbol(this.key) && !['$and', '$or', '$not'].includes(this.key)
|
|
99
|
+
const key = this.key && !RawQueryFragment.isKnownFragmentSymbol(this.key) && !['$and', '$or', '$not'].includes(this.key)
|
|
100
|
+
? '.' + this.key
|
|
101
|
+
: '';
|
|
88
102
|
const ret = parentPath + index + key;
|
|
89
103
|
if (this.isPivotJoin()) {
|
|
90
104
|
// distinguish pivot table join from target entity join
|
|
@@ -97,7 +111,11 @@ export class CriteriaNode {
|
|
|
97
111
|
return false;
|
|
98
112
|
}
|
|
99
113
|
const rawField = RawQueryFragment.isKnownFragmentSymbol(this.key);
|
|
100
|
-
const scalar = this.payload === null ||
|
|
114
|
+
const scalar = this.payload === null ||
|
|
115
|
+
Utils.isPrimaryKey(this.payload) ||
|
|
116
|
+
this.payload instanceof RegExp ||
|
|
117
|
+
this.payload instanceof Date ||
|
|
118
|
+
rawField;
|
|
101
119
|
const operator = Utils.isObject(this.payload) && Utils.getObjectQueryKeys(this.payload).every(k => Utils.isOperator(k, false));
|
|
102
120
|
return this.prop.kind === ReferenceKind.MANY_TO_MANY && (scalar || operator);
|
|
103
121
|
}
|
|
@@ -116,7 +134,7 @@ export class CriteriaNode {
|
|
|
116
134
|
const o = {};
|
|
117
135
|
['entityName', 'key', 'index', 'payload']
|
|
118
136
|
.filter(k => this[k] !== undefined)
|
|
119
|
-
.forEach(k => o[k] = this[k]);
|
|
137
|
+
.forEach(k => (o[k] = this[k]));
|
|
120
138
|
return `${this.constructor.name} ${inspect(o)}`;
|
|
121
139
|
}
|
|
122
140
|
}
|
|
@@ -8,7 +8,11 @@ import { ScalarCriteriaNode } from './ScalarCriteriaNode.js';
|
|
|
8
8
|
export class CriteriaNodeFactory {
|
|
9
9
|
static createNode(metadata, entityName, payload, parent, key, validate = true) {
|
|
10
10
|
const rawField = RawQueryFragment.isKnownFragmentSymbol(key);
|
|
11
|
-
const scalar = Utils.isPrimaryKey(payload) ||
|
|
11
|
+
const scalar = Utils.isPrimaryKey(payload) ||
|
|
12
|
+
isRaw(payload) ||
|
|
13
|
+
payload instanceof RegExp ||
|
|
14
|
+
payload instanceof Date ||
|
|
15
|
+
rawField;
|
|
12
16
|
if (Array.isArray(payload) && !scalar) {
|
|
13
17
|
return this.createArrayNode(metadata, entityName, payload, parent, key, validate);
|
|
14
18
|
}
|