@mikro-orm/sql
Advanced tools
@@ -15,2 +15,3 @@ import { type EntityProperty, type IsolationLevel, type SimpleColumnMeta, Type } from '@mikro-orm/core'; | ||
| usesEnumCheckConstraints(): boolean; | ||
| supportsMaterializedViews(): boolean; | ||
| supportsCustomPrimaryKeyNames(): boolean; | ||
@@ -17,0 +18,0 @@ getCurrentTimestampSQL(length: number): string; |
@@ -25,2 +25,5 @@ import { ALIAS_REPLACEMENT, ARRAY_OPERATORS, raw, RawQueryFragment, Type, Utils, } from '@mikro-orm/core'; | ||
| } | ||
| supportsMaterializedViews() { | ||
| return true; | ||
| } | ||
| supportsCustomPrimaryKeyNames() { | ||
@@ -27,0 +30,0 @@ return true; |
@@ -22,2 +22,7 @@ import { type Dictionary } from '@mikro-orm/core'; | ||
| loadViews(schema: DatabaseSchema, connection: AbstractSqlConnection): Promise<void>; | ||
| getListMaterializedViewsSQL(): string; | ||
| loadMaterializedViews(schema: DatabaseSchema, connection: AbstractSqlConnection, schemaName?: string): Promise<void>; | ||
| createMaterializedView(name: string, schema: string | undefined, definition: string, withData?: boolean): string; | ||
| dropMaterializedViewIfExists(name: string, schema?: string): string; | ||
| refreshMaterializedView(name: string, schema?: string, concurrently?: boolean): string; | ||
| getNamespaces(connection: AbstractSqlConnection): Promise<string[]>; | ||
@@ -24,0 +29,0 @@ private getIgnoredNamespacesConditionSQL; |
@@ -47,2 +47,29 @@ import { EnumType, Type, Utils, DeferMode } from '@mikro-orm/core'; | ||
| } | ||
| getListMaterializedViewsSQL() { | ||
| return `select matviewname as view_name, schemaname as schema_name, definition as view_definition ` | ||
| + `from pg_matviews ` | ||
| + `where ${this.getIgnoredNamespacesConditionSQL('schemaname')} ` | ||
| + `order by matviewname`; | ||
| } | ||
| async loadMaterializedViews(schema, connection, schemaName) { | ||
| const views = await connection.execute(this.getListMaterializedViewsSQL()); | ||
| for (const view of views) { | ||
| const definition = view.view_definition?.trim().replace(/;$/, '') ?? ''; | ||
| if (definition) { | ||
| schema.addView(view.view_name, view.schema_name, definition, true); | ||
| } | ||
| } | ||
| } | ||
| createMaterializedView(name, schema, definition, withData = true) { | ||
| const viewName = this.quote(this.getTableName(name, schema)); | ||
| const dataClause = withData ? ' with data' : ' with no data'; | ||
| return `create materialized view ${viewName} as ${definition}${dataClause}`; | ||
| } | ||
| dropMaterializedViewIfExists(name, schema) { | ||
| return `drop materialized view if exists ${this.quote(this.getTableName(name, schema))} cascade`; | ||
| } | ||
| refreshMaterializedView(name, schema, concurrently = false) { | ||
| const concurrent = concurrently ? ' concurrently' : ''; | ||
| return `refresh materialized view${concurrent} ${this.quote(this.getTableName(name, schema))}`; | ||
| } | ||
| async getNamespaces(connection) { | ||
@@ -49,0 +76,0 @@ const sql = `select schema_name from information_schema.schemata ` |
+2
-2
| { | ||
| "name": "@mikro-orm/sql", | ||
| "version": "7.0.0-dev.175", | ||
| "version": "7.0.0-dev.176", | ||
| "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.", | ||
@@ -59,4 +59,4 @@ "type": "module", | ||
| "peerDependencies": { | ||
| "@mikro-orm/core": "7.0.0-dev.175" | ||
| "@mikro-orm/core": "7.0.0-dev.176" | ||
| } | ||
| } |
@@ -21,3 +21,3 @@ import { type Configuration, type Dictionary, type EntityMetadata } from '@mikro-orm/core'; | ||
| hasTable(name: string): boolean; | ||
| addView(name: string, schema: string | undefined | null, definition: string): DatabaseView; | ||
| addView(name: string, schema: string | undefined | null, definition: string, materialized?: boolean, withData?: boolean): DatabaseView; | ||
| getViews(): DatabaseView[]; | ||
@@ -24,0 +24,0 @@ getView(name: string): DatabaseView | undefined; |
@@ -37,5 +37,5 @@ import { ReferenceKind, isRaw, } from '@mikro-orm/core'; | ||
| } | ||
| addView(name, schema, definition) { | ||
| addView(name, schema, definition, materialized, withData) { | ||
| const namespaceName = schema ?? this.name; | ||
| const view = { name, schema: namespaceName, definition }; | ||
| const view = { name, schema: namespaceName, definition, materialized, withData }; | ||
| this.views.push(view); | ||
@@ -89,2 +89,6 @@ if (namespaceName != null) { | ||
| await platform.getSchemaHelper().loadViews(schema, connection); | ||
| // Load materialized views (PostgreSQL only) | ||
| if (platform.supportsMaterializedViews()) { | ||
| await platform.getSchemaHelper().loadMaterializedViews(schema, connection, schemaName); | ||
| } | ||
| return schema; | ||
@@ -129,3 +133,3 @@ } | ||
| if (viewDefinition) { | ||
| schema.addView(meta.collection, this.getSchemaName(meta, config, schemaName), viewDefinition); | ||
| schema.addView(meta.collection, this.getSchemaName(meta, config, schemaName), viewDefinition, meta.materialized, meta.withData); | ||
| } | ||
@@ -132,0 +136,0 @@ continue; |
@@ -82,2 +82,7 @@ import { type Connection, type Dictionary, RawQueryFragment } from '@mikro-orm/core'; | ||
| dropViewIfExists(name: string, schema?: string): string; | ||
| createMaterializedView(name: string, schema: string | undefined, definition: string, withData?: boolean): string; | ||
| dropMaterializedViewIfExists(name: string, schema?: string): string; | ||
| refreshMaterializedView(name: string, schema?: string, concurrently?: boolean): string; | ||
| getListMaterializedViewsSQL(): string; | ||
| loadMaterializedViews(schema: DatabaseSchema, connection: AbstractSqlConnection, schemaName?: string): Promise<void>; | ||
| } |
@@ -561,2 +561,17 @@ import { RawQueryFragment, Utils } from '@mikro-orm/core'; | ||
| } | ||
| createMaterializedView(name, schema, definition, withData = true) { | ||
| throw new Error('Not supported by given driver'); | ||
| } | ||
| dropMaterializedViewIfExists(name, schema) { | ||
| throw new Error('Not supported by given driver'); | ||
| } | ||
| refreshMaterializedView(name, schema, concurrently = false) { | ||
| throw new Error('Not supported by given driver'); | ||
| } | ||
| getListMaterializedViewsSQL() { | ||
| throw new Error('Not supported by given driver'); | ||
| } | ||
| async loadMaterializedViews(schema, connection, schemaName) { | ||
| throw new Error('Not supported by given driver'); | ||
| } | ||
| } |
@@ -94,3 +94,8 @@ import { AbstractSchemaGenerator, CommitOrderCalculator, Utils, } from '@mikro-orm/core'; | ||
| for (const view of sortedViews) { | ||
| this.append(ret, this.helper.createView(view.name, view.schema, view.definition), true); | ||
| if (view.materialized) { | ||
| this.append(ret, this.helper.createMaterializedView(view.name, view.schema, view.definition, view.withData ?? true)); | ||
| } | ||
| else { | ||
| this.append(ret, this.helper.createView(view.name, view.schema, view.definition), true); | ||
| } | ||
| } | ||
@@ -145,3 +150,8 @@ return this.wrapSchema(ret, options); | ||
| for (const view of sortedViews) { | ||
| this.append(ret, this.helper.dropViewIfExists(view.name, view.schema)); | ||
| if (view.materialized) { | ||
| this.append(ret, this.helper.dropMaterializedViewIfExists(view.name, view.schema)); | ||
| } | ||
| else { | ||
| this.append(ret, this.helper.dropViewIfExists(view.name, view.schema)); | ||
| } | ||
| } | ||
@@ -240,3 +250,8 @@ // remove FKs explicitly if we can't use a cascading statement and we don't disable FK checks (we need this for circular relations) | ||
| for (const view of sortedRemovedViews) { | ||
| this.append(ret, this.helper.dropViewIfExists(view.name, view.schema)); | ||
| if (view.materialized) { | ||
| this.append(ret, this.helper.dropMaterializedViewIfExists(view.name, view.schema)); | ||
| } | ||
| else { | ||
| this.append(ret, this.helper.dropViewIfExists(view.name, view.schema)); | ||
| } | ||
| } | ||
@@ -249,3 +264,8 @@ } | ||
| for (const view of sortedChangedViewsFrom) { | ||
| this.append(ret, this.helper.dropViewIfExists(view.name, view.schema)); | ||
| if (view.materialized) { | ||
| this.append(ret, this.helper.dropMaterializedViewIfExists(view.name, view.schema)); | ||
| } | ||
| else { | ||
| this.append(ret, this.helper.dropViewIfExists(view.name, view.schema)); | ||
| } | ||
| } | ||
@@ -311,3 +331,8 @@ if (!options.safe && this.options.createForeignKeyConstraints) { | ||
| for (const view of sortedNewViews) { | ||
| this.append(ret, this.helper.createView(view.name, view.schema, view.definition), true); | ||
| if (view.materialized) { | ||
| this.append(ret, this.helper.createMaterializedView(view.name, view.schema, view.definition, view.withData ?? true)); | ||
| } | ||
| else { | ||
| this.append(ret, this.helper.createView(view.name, view.schema, view.definition), true); | ||
| } | ||
| } | ||
@@ -318,3 +343,8 @@ // Recreate changed views (also sorted by dependencies) | ||
| for (const view of sortedChangedViews) { | ||
| this.append(ret, this.helper.createView(view.name, view.schema, view.definition), true); | ||
| if (view.materialized) { | ||
| this.append(ret, this.helper.createMaterializedView(view.name, view.schema, view.definition, view.withData ?? true)); | ||
| } | ||
| else { | ||
| this.append(ret, this.helper.createView(view.name, view.schema, view.definition), true); | ||
| } | ||
| } | ||
@@ -321,0 +351,0 @@ return this.wrapSchema(ret, options); |
+4
-0
@@ -118,2 +118,6 @@ import type { Generated, Kysely } from 'kysely'; | ||
| definition: string; | ||
| /** True if this is a materialized view (PostgreSQL only). */ | ||
| materialized?: boolean; | ||
| /** For materialized views, whether data was populated on creation. */ | ||
| withData?: boolean; | ||
| } | ||
@@ -120,0 +124,0 @@ export interface SchemaDifference { |
Sorry, the diff of this file is not supported yet
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
835089
0.58%13779
0.69%