@mikro-orm/sql 7.1.0-dev.9 → 7.1.1-dev.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 (56) hide show
  1. package/AbstractSqlConnection.d.ts +1 -1
  2. package/AbstractSqlConnection.js +27 -6
  3. package/AbstractSqlDriver.d.ts +15 -1
  4. package/AbstractSqlDriver.js +143 -26
  5. package/AbstractSqlPlatform.d.ts +15 -3
  6. package/AbstractSqlPlatform.js +25 -7
  7. package/PivotCollectionPersister.d.ts +2 -2
  8. package/PivotCollectionPersister.js +6 -1
  9. package/README.md +2 -1
  10. package/SqlEntityManager.d.ts +44 -5
  11. package/SqlEntityManager.js +41 -6
  12. package/SqlMikroORM.d.ts +23 -0
  13. package/SqlMikroORM.js +23 -0
  14. package/dialects/mysql/BaseMySqlPlatform.d.ts +3 -5
  15. package/dialects/mysql/BaseMySqlPlatform.js +6 -10
  16. package/dialects/mysql/MySqlSchemaHelper.d.ts +16 -3
  17. package/dialects/mysql/MySqlSchemaHelper.js +197 -49
  18. package/dialects/oracledb/OracleDialect.d.ts +1 -1
  19. package/dialects/oracledb/OracleDialect.js +2 -1
  20. package/dialects/postgresql/BasePostgreSqlEntityManager.d.ts +19 -0
  21. package/dialects/postgresql/BasePostgreSqlEntityManager.js +24 -0
  22. package/dialects/postgresql/BasePostgreSqlPlatform.d.ts +11 -5
  23. package/dialects/postgresql/BasePostgreSqlPlatform.js +75 -17
  24. package/dialects/postgresql/PostgreSqlSchemaHelper.d.ts +31 -1
  25. package/dialects/postgresql/PostgreSqlSchemaHelper.js +269 -28
  26. package/dialects/postgresql/index.d.ts +2 -0
  27. package/dialects/postgresql/index.js +2 -0
  28. package/dialects/postgresql/typeOverrides.d.ts +14 -0
  29. package/dialects/postgresql/typeOverrides.js +12 -0
  30. package/dialects/sqlite/SqlitePlatform.d.ts +2 -1
  31. package/dialects/sqlite/SqlitePlatform.js +4 -0
  32. package/dialects/sqlite/SqliteSchemaHelper.d.ts +4 -1
  33. package/dialects/sqlite/SqliteSchemaHelper.js +49 -19
  34. package/index.d.ts +2 -0
  35. package/index.js +2 -0
  36. package/package.json +4 -4
  37. package/plugin/transformer.d.ts +11 -3
  38. package/plugin/transformer.js +138 -29
  39. package/query/CriteriaNode.d.ts +1 -1
  40. package/query/CriteriaNode.js +2 -2
  41. package/query/ObjectCriteriaNode.js +1 -1
  42. package/query/QueryBuilder.d.ts +42 -1
  43. package/query/QueryBuilder.js +78 -7
  44. package/schema/DatabaseSchema.d.ts +29 -2
  45. package/schema/DatabaseSchema.js +131 -4
  46. package/schema/DatabaseTable.d.ts +14 -1
  47. package/schema/DatabaseTable.js +165 -32
  48. package/schema/SchemaComparator.d.ts +18 -0
  49. package/schema/SchemaComparator.js +196 -1
  50. package/schema/SchemaHelper.d.ts +67 -1
  51. package/schema/SchemaHelper.js +255 -25
  52. package/schema/SqlSchemaGenerator.d.ts +2 -2
  53. package/schema/SqlSchemaGenerator.js +40 -10
  54. package/schema/partitioning.d.ts +13 -0
  55. package/schema/partitioning.js +326 -0
  56. package/typings.d.ts +59 -5
@@ -66,13 +66,14 @@ class OracleConnection {
66
66
  bindParams: query.parameters,
67
67
  };
68
68
  }
69
- async *streamQuery(compiledQuery, _chunkSize) {
69
+ async *streamQuery(compiledQuery, chunkSize) {
70
70
  const { sql, bindParams } = this.formatQuery(compiledQuery);
71
71
  const result = await this.#connection.execute(sql, bindParams, {
72
72
  resultSet: true,
73
73
  autoCommit: compiledQuery.autoCommit,
74
74
  outFormat: OUT_FORMAT_OBJECT,
75
75
  ...this.#executeOptions,
76
+ ...(chunkSize != null ? { fetchArraySize: chunkSize } : {}),
76
77
  });
77
78
  const rs = result.resultSet;
78
79
  try {
@@ -0,0 +1,19 @@
1
+ import { type EntityName } from '@mikro-orm/core';
2
+ import { SqlEntityManager } from '../../SqlEntityManager.js';
3
+ import type { AbstractSqlDriver } from '../../AbstractSqlDriver.js';
4
+ /**
5
+ * Shared base class for PostgreSQL-flavoured entity managers (`pg`, `pglite`).
6
+ * Adds Postgres-only helpers on top of `SqlEntityManager`.
7
+ */
8
+ export declare class BasePostgreSqlEntityManager<Driver extends AbstractSqlDriver = AbstractSqlDriver> extends SqlEntityManager<Driver> {
9
+ /**
10
+ * Refreshes a materialized view.
11
+ *
12
+ * @param entityName - The entity name or class of the materialized view
13
+ * @param options - Optional settings
14
+ * @param options.concurrently - If true, refreshes the view concurrently (requires a unique index on the view)
15
+ */
16
+ refreshMaterializedView<Entity extends object>(entityName: EntityName<Entity>, options?: {
17
+ concurrently?: boolean;
18
+ }): Promise<void>;
19
+ }
@@ -0,0 +1,24 @@
1
+ import { SqlEntityManager } from '../../SqlEntityManager.js';
2
+ /**
3
+ * Shared base class for PostgreSQL-flavoured entity managers (`pg`, `pglite`).
4
+ * Adds Postgres-only helpers on top of `SqlEntityManager`.
5
+ */
6
+ export class BasePostgreSqlEntityManager extends SqlEntityManager {
7
+ /**
8
+ * Refreshes a materialized view.
9
+ *
10
+ * @param entityName - The entity name or class of the materialized view
11
+ * @param options - Optional settings
12
+ * @param options.concurrently - If true, refreshes the view concurrently (requires a unique index on the view)
13
+ */
14
+ async refreshMaterializedView(entityName, options) {
15
+ const meta = this.getMetadata(entityName);
16
+ if (!meta.view || !meta.materialized) {
17
+ throw new Error(`Entity ${meta.className} is not a materialized view`);
18
+ }
19
+ const helper = this.getDriver().getPlatform().getSchemaHelper();
20
+ const schema = meta.schema ?? this.config.get('schema');
21
+ const sql = helper.refreshMaterializedView(meta.tableName, schema, options?.concurrently);
22
+ await this.execute(sql);
23
+ }
24
+ }
@@ -15,6 +15,7 @@ export declare class BasePostgreSqlPlatform extends AbstractSqlPlatform {
15
15
  usesEnumCheckConstraints(): boolean;
16
16
  getEnumArrayCheckConstraintExpression(column: string, items: string[]): string;
17
17
  supportsMaterializedViews(): boolean;
18
+ supportsPartitionedTables(): boolean;
18
19
  supportsCustomPrimaryKeyNames(): boolean;
19
20
  getCurrentTimestampSQL(length: number): string;
20
21
  getDateTimeTypeDeclarationSQL(column: {
@@ -46,6 +47,7 @@ export declare class BasePostgreSqlPlatform extends AbstractSqlPlatform {
46
47
  precision?: number;
47
48
  scale?: number;
48
49
  autoincrement?: boolean;
50
+ columnTypes?: string[];
49
51
  }): string;
50
52
  getMappedType(type: string): Type<unknown>;
51
53
  getRegExpOperator(val?: unknown, flags?: string): string;
@@ -69,6 +71,12 @@ export declare class BasePostgreSqlPlatform extends AbstractSqlPlatform {
69
71
  }): string[];
70
72
  marshallArray(values: string[]): string;
71
73
  unmarshallArray(value: string): string[];
74
+ escape(value: any): string;
75
+ /**
76
+ * Ported from PostgreSQL 9.2.4 source code (`src/interfaces/libpq/fe-exec.c`),
77
+ * matching `pg.Client.prototype.escapeLiteral` so we don't need a `pg` dep here.
78
+ */
79
+ private escapeLiteral;
72
80
  getVarcharTypeDeclarationSQL(column: {
73
81
  length?: number;
74
82
  }): string;
@@ -92,11 +100,8 @@ export declare class BasePostgreSqlPlatform extends AbstractSqlPlatform {
92
100
  getDefaultMappedType(type: string): Type<unknown>;
93
101
  supportsSchemas(): boolean;
94
102
  getDefaultSchemaName(): string | undefined;
95
- /**
96
- * Returns the default name of index for the given columns
97
- * cannot go past 63 character length for identifiers in MySQL
98
- */
99
- getIndexName(tableName: string, columns: string[], type: 'index' | 'unique' | 'foreign' | 'primary' | 'sequence'): string;
103
+ /** Postgres identifier limit (NAMEDATALEN - 1). */
104
+ getMaxIdentifierLength(): number;
100
105
  getDefaultPrimaryName(tableName: string, columns: string[]): string;
101
106
  /**
102
107
  * @inheritDoc
@@ -110,4 +115,5 @@ export declare class BasePostgreSqlPlatform extends AbstractSqlPlatform {
110
115
  }[]): string;
111
116
  getJsonArrayElementPropertySQL(alias: string, property: string, type: string): string;
112
117
  getDefaultClientUrl(): string;
118
+ caseInsensitiveCollationNames(): boolean;
113
119
  }
@@ -30,6 +30,9 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
30
30
  supportsMaterializedViews() {
31
31
  return true;
32
32
  }
33
+ supportsPartitionedTables() {
34
+ return true;
35
+ }
33
36
  supportsCustomPrimaryKeyNames() {
34
37
  return true;
35
38
  }
@@ -90,18 +93,27 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
90
93
  }
91
94
  normalizeColumnType(type, options) {
92
95
  const simpleType = this.extractSimpleType(type);
93
- if (['int', 'int4', 'integer'].includes(simpleType)) {
96
+ if (['int', 'int4', 'integer', 'serial'].includes(simpleType)) {
94
97
  return this.getIntegerTypeDeclarationSQL({});
95
98
  }
96
- if (['bigint', 'int8'].includes(simpleType)) {
99
+ if (['bigint', 'int8', 'bigserial'].includes(simpleType)) {
97
100
  return this.getBigIntTypeDeclarationSQL({});
98
101
  }
99
- if (['smallint', 'int2'].includes(simpleType)) {
102
+ if (['smallint', 'int2', 'smallserial'].includes(simpleType)) {
100
103
  return this.getSmallIntTypeDeclarationSQL({});
101
104
  }
102
105
  if (['boolean', 'bool'].includes(simpleType)) {
103
106
  return this.getBooleanTypeDeclarationSQL();
104
107
  }
108
+ if (['double', 'double precision', 'float8'].includes(simpleType)) {
109
+ return this.getDoubleDeclarationSQL();
110
+ }
111
+ if (['real', 'float4'].includes(simpleType)) {
112
+ return this.getFloatDeclarationSQL();
113
+ }
114
+ if (['timestamptz', 'timestamp with time zone'].includes(simpleType)) {
115
+ return this.getDateTimeTypeDeclarationSQL(options);
116
+ }
105
117
  if (['varchar', 'character varying'].includes(simpleType)) {
106
118
  return this.getVarcharTypeDeclarationSQL(options);
107
119
  }
@@ -114,6 +126,12 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
114
126
  if (['interval'].includes(simpleType)) {
115
127
  return this.getIntervalTypeDeclarationSQL(options);
116
128
  }
129
+ // TimeType.getColumnType drops the timezone qualifier, so detect tz aliases from the original column type.
130
+ const originalType = options.columnTypes?.[0]?.toLowerCase() ?? type;
131
+ if (/^timetz\b/.test(originalType) || /^time\s+with\s+time\s+zone\b/.test(originalType)) {
132
+ const length = options.length ?? this.getDefaultDateTimeLength();
133
+ return `timetz(${length})`;
134
+ }
117
135
  return super.normalizeColumnType(type, options);
118
136
  }
119
137
  getMappedType(type) {
@@ -194,6 +212,50 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
194
212
  return v;
195
213
  });
196
214
  }
215
+ escape(value) {
216
+ if (typeof value === 'bigint') {
217
+ value = value.toString();
218
+ }
219
+ if (typeof value === 'string') {
220
+ return this.escapeLiteral(value);
221
+ }
222
+ if (value instanceof Date) {
223
+ return `'${this.formatDate(value)}'`;
224
+ }
225
+ if (ArrayBuffer.isView(value)) {
226
+ return `E'\\\\x${value.toString('hex')}'`;
227
+ }
228
+ if (Array.isArray(value)) {
229
+ return value.map(v => this.escape(v)).join(', ');
230
+ }
231
+ return value;
232
+ }
233
+ /**
234
+ * Ported from PostgreSQL 9.2.4 source code (`src/interfaces/libpq/fe-exec.c`),
235
+ * matching `pg.Client.prototype.escapeLiteral` so we don't need a `pg` dep here.
236
+ */
237
+ escapeLiteral(str) {
238
+ let hasBackslash = false;
239
+ let escaped = `'`;
240
+ for (let i = 0; i < str.length; i++) {
241
+ const c = str[i];
242
+ if (c === `'`) {
243
+ escaped += c + c;
244
+ }
245
+ else if (c === '\\') {
246
+ escaped += c + c;
247
+ hasBackslash = true;
248
+ }
249
+ else {
250
+ escaped += c;
251
+ }
252
+ }
253
+ escaped += `'`;
254
+ if (hasBackslash) {
255
+ escaped = ` E${escaped}`;
256
+ }
257
+ return escaped;
258
+ }
197
259
  getVarcharTypeDeclarationSQL(column) {
198
260
  if (column.length === -1) {
199
261
  return 'varchar';
@@ -228,9 +290,9 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
228
290
  lastOperator = '->';
229
291
  }
230
292
  if (path.length === 0) {
231
- return cast(`${root}${lastOperator}'${last}'`);
293
+ return cast(`${root}${lastOperator}${this.quoteValue(last)}`);
232
294
  }
233
- return cast(`${root}->${path.map(a => this.quoteValue(a)).join('->')}${lastOperator}'${last}'`);
295
+ return cast(`${root}->${path.map(a => this.quoteValue(a)).join('->')}${lastOperator}${this.quoteValue(last)}`);
234
296
  }
235
297
  getJsonIndexDefinition(index) {
236
298
  return index.columnNames.map(column => {
@@ -250,7 +312,8 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
250
312
  if (RawQueryFragment.isKnownFragment(id)) {
251
313
  return super.quoteIdentifier(id);
252
314
  }
253
- return `${quote}${id.toString().replace('.', `${quote}.${quote}`)}${quote}`;
315
+ const escaped = id.toString().replaceAll(quote, quote + quote);
316
+ return `${quote}${escaped.replace('.', `${quote}.${quote}`)}${quote}`;
254
317
  }
255
318
  pad(number, digits) {
256
319
  return String(number).padStart(digits, '0');
@@ -320,17 +383,9 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
320
383
  getDefaultSchemaName() {
321
384
  return 'public';
322
385
  }
323
- /**
324
- * Returns the default name of index for the given columns
325
- * cannot go past 63 character length for identifiers in MySQL
326
- */
327
- getIndexName(tableName, columns, type) {
328
- const indexName = super.getIndexName(tableName, columns, type);
329
- if (indexName.length > 63) {
330
- const suffix = type === 'primary' ? 'pkey' : type;
331
- return `${indexName.substring(0, 55 - type.length)}_${Utils.hash(indexName, 5)}_${suffix}`;
332
- }
333
- return indexName;
386
+ /** Postgres identifier limit (NAMEDATALEN - 1). */
387
+ getMaxIdentifierLength() {
388
+ return 63;
334
389
  }
335
390
  getDefaultPrimaryName(tableName, columns) {
336
391
  const indexName = `${tableName}_pkey`;
@@ -362,4 +417,7 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
362
417
  getDefaultClientUrl() {
363
418
  return 'postgresql://postgres@127.0.0.1:5432';
364
419
  }
420
+ caseInsensitiveCollationNames() {
421
+ return false;
422
+ }
365
423
  }
@@ -1,7 +1,7 @@
1
1
  import { type Dictionary, type Transaction } from '@mikro-orm/core';
2
2
  import { SchemaHelper } from '../../schema/SchemaHelper.js';
3
3
  import type { AbstractSqlConnection } from '../../AbstractSqlConnection.js';
4
- import type { CheckDef, Column, ForeignKey, IndexDef, Table, TableDifference, SqlTriggerDef } from '../../typings.js';
4
+ import type { CheckDef, Column, ForeignKey, IndexDef, Table, TableDifference, TablePartitioning, SqlTriggerDef, SqlRoutineDef } from '../../typings.js';
5
5
  import type { DatabaseSchema } from '../../schema/DatabaseSchema.js';
6
6
  import type { DatabaseTable } from '../../schema/DatabaseTable.js';
7
7
  export declare class PostgreSqlSchemaHelper extends SchemaHelper {
@@ -14,7 +14,12 @@ export declare class PostgreSqlSchemaHelper extends SchemaHelper {
14
14
  'null::timestamp with time zone': string[];
15
15
  'null::timestamp without time zone': string[];
16
16
  };
17
+ private static readonly PARTIAL_WHERE_RE;
18
+ private static readonly FUNCTIONAL_COL_RE;
17
19
  getSchemaBeginning(charset: string, disableForeignKeys?: boolean): string;
20
+ getSetSchemaSQL(schema: string): string;
21
+ getResetSchemaSQL(_defaultSchema: string): string;
22
+ supportsMigrationSchema(): boolean;
18
23
  getCreateDatabaseSQL(name: string): string;
19
24
  getListTablesSQL(): string;
20
25
  private getIgnoredViewsCondition;
@@ -23,11 +28,22 @@ export declare class PostgreSqlSchemaHelper extends SchemaHelper {
23
28
  getListMaterializedViewsSQL(): string;
24
29
  loadMaterializedViews(schema: DatabaseSchema, connection: AbstractSqlConnection, schemaName?: string, ctx?: Transaction): Promise<void>;
25
30
  createMaterializedView(name: string, schema: string | undefined, definition: string, withData?: boolean): string;
31
+ createTable(table: DatabaseTable, alter?: boolean): string[];
26
32
  dropMaterializedViewIfExists(name: string, schema?: string): string;
27
33
  refreshMaterializedView(name: string, schema?: string, concurrently?: boolean): string;
28
34
  getNamespaces(connection: AbstractSqlConnection, ctx?: Transaction): Promise<string[]>;
29
35
  private getIgnoredNamespacesConditionSQL;
30
36
  loadInformationSchema(schema: DatabaseSchema, connection: AbstractSqlConnection, tables: Table[], schemas?: string[], ctx?: Transaction): Promise<void>;
37
+ /**
38
+ * Introspects direct partitions only: the `pg_inherits` join surfaces a parent's children but
39
+ * does not recurse into sub-partitioning (e.g. hash-of-range). Declarative `partitionBy`
40
+ * metadata does not express multi-level partitioning either, so grandchildren are intentionally
41
+ * invisible to schema diffing.
42
+ *
43
+ * Entries with an undefined schema bucket are resolved against `current_schema()` so they do
44
+ * not match same-named tables in unrelated schemas.
45
+ */
46
+ getPartitions(connection: AbstractSqlConnection, tablesBySchemas: Map<string | undefined, Table[]>, ctx?: Transaction): Promise<Dictionary<TablePartitioning>>;
31
47
  getAllIndexes(connection: AbstractSqlConnection, tables: Table[], ctx?: Transaction): Promise<Dictionary<IndexDef[]>>;
32
48
  /**
33
49
  * Parses column definitions from the full CREATE INDEX expression.
@@ -53,7 +69,20 @@ export declare class PostgreSqlSchemaHelper extends SchemaHelper {
53
69
  createTrigger(table: DatabaseTable, trigger: SqlTriggerDef): string;
54
70
  /** Generates SQL to drop a PostgreSQL trigger and its associated function. */
55
71
  dropTrigger(table: DatabaseTable, trigger: SqlTriggerDef): string;
72
+ createRoutine(routine: SqlRoutineDef): string;
73
+ dropRoutine(routine: SqlRoutineDef): string;
74
+ getAllRoutines(connection: AbstractSqlConnection, schemas?: string[]): Promise<SqlRoutineDef[]>;
75
+ private formatRoutineParams;
76
+ private parseRoutineParams;
77
+ /** PG canonicalises `$$` quoting to a tagged form like `$function$ ... $function$`; match the tag-aware form. */
78
+ private extractRoutineBody;
56
79
  private getSchemaQualifiedTriggerFnName;
80
+ /**
81
+ * Resolves the real name of the implicit 'default' collation (the DB's `datcollate`),
82
+ * so the comparator can treat `@Property({ collation: '<datcollate>' })` as equivalent
83
+ * to a column that introspects as using the default.
84
+ */
85
+ getDatabaseCollation(connection: AbstractSqlConnection, ctx?: Transaction): Promise<string | undefined>;
57
86
  getAllTriggers(connection: AbstractSqlConnection, tablesBySchemas: Map<string | undefined, Table[]>): Promise<Dictionary<SqlTriggerDef[]>>;
58
87
  private getTriggersSQL;
59
88
  getAllForeignKeys(connection: AbstractSqlConnection, tablesBySchemas: Map<string | undefined, Table[]>, ctx?: Transaction): Promise<Dictionary<Dictionary<ForeignKey>>>;
@@ -66,6 +95,7 @@ export declare class PostgreSqlSchemaHelper extends SchemaHelper {
66
95
  getDropNativeEnumSQL(name: string, schema?: string): string;
67
96
  getAlterNativeEnumSQL(name: string, schema?: string, value?: string, items?: string[], oldItems?: string[]): string;
68
97
  private getEnumDefinitions;
98
+ protected getCollateSQL(collation: string): string;
69
99
  createTableColumn(column: Column, table: DatabaseTable): string | undefined;
70
100
  getPreAlterTable(tableDiff: TableDifference, safe: boolean): string[];
71
101
  castColumn(name: string, type: string): string;