Skip to content

Commit dacac83

Browse files
Gindenpleerock
authored andcommitted
feat: add materialized View support for Postgres (#4478)
feat: add option to synchronize or not to synchronize ViewEntity Fixes #4317 Fixes #3996
1 parent db8074a commit dacac83

File tree

7 files changed

+41
-5
lines changed

7 files changed

+41
-5
lines changed

src/decorator/entity-view/ViewEntity.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export function ViewEntity(nameOrOptions?: string|ViewEntityOptions, maybeOption
3030
type: "view",
3131
database: options.database ? options.database : undefined,
3232
schema: options.schema ? options.schema : undefined,
33+
synchronize: options.synchronize === false ? false : true,
34+
materialized: !!options.materialized
3335
} as TableMetadataArgs);
3436
};
3537
}

src/decorator/options/ViewEntityOptions.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,17 @@ export interface ViewEntityOptions {
2525
* Schema name. Used in Postgres and Sql Server.
2626
*/
2727
schema?: string;
28+
29+
/**
30+
* Indicates if schema synchronization is enabled or disabled for this entity.
31+
* If it will be set to false then schema sync will and migrations ignore this entity.
32+
* By default schema synchronization is enabled for all entities.
33+
*/
34+
synchronize?: boolean;
35+
36+
/**
37+
* Indicates if view should be materialized view.
38+
* It's supported by Postgres and Oracle.
39+
*/
40+
materialized?: boolean;
2841
}

src/driver/oracle/OracleQueryRunner.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,10 +1385,11 @@ export class OracleQueryRunner extends BaseQueryRunner implements QueryRunner {
13851385
}
13861386

13871387
protected createViewSql(view: View): Query {
1388+
const materializedClause = view.materialized ? "" : "MATERIALIZED ";
13881389
if (typeof view.expression === "string") {
1389-
return new Query(`CREATE VIEW "${view.name}" AS ${view.expression}`);
1390+
return new Query(`CREATE ${materializedClause}VIEW "${view.name}" AS ${view.expression}`);
13901391
} else {
1391-
return new Query(`CREATE VIEW "${view.name}" AS ${view.expression(this.connection).getQuery()}`);
1392+
return new Query(`CREATE ${materializedClause}VIEW "${view.name}" AS ${view.expression(this.connection).getQuery()}`);
13921393
}
13931394
}
13941395

src/metadata-args/TableMetadataArgs.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,10 @@ export interface TableMetadataArgs {
5656
*/
5757
expression?: string|((connection: Connection) => SelectQueryBuilder<any>);
5858

59+
/**
60+
* Indicates if view is materialized
61+
*/
62+
63+
materialized?: boolean;
64+
5965
}

src/schema-builder/RdbmsSchemaBuilder.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder {
139139
* Returns only entities that should be synced in the database.
140140
*/
141141
protected get viewEntityToSyncMetadatas(): EntityMetadata[] {
142-
return this.connection.entityMetadatas.filter(metadata => metadata.tableType === "view");
142+
return this.connection.entityMetadatas.filter(metadata => metadata.tableType === "view" && metadata.synchronize);
143143
}
144144

145145
/**

src/schema-builder/options/ViewOptions.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,9 @@ export interface ViewOptions {
1919
*/
2020
expression: string|((connection: Connection) => SelectQueryBuilder<any>);
2121

22+
/**
23+
* Indicates if view is materialized
24+
*/
25+
26+
materialized?: boolean;
2227
}

src/schema-builder/view/View.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,16 @@ export class View {
1717
*/
1818
name: string;
1919

20+
21+
/**
22+
* Indicates if view is materialized.
23+
*/
24+
materialized: boolean;
25+
2026
/**
2127
* View definition.
2228
*/
23-
expression: string|((connection: Connection) => SelectQueryBuilder<any>);
29+
expression: string | ((connection: Connection) => SelectQueryBuilder<any>);
2430

2531
// -------------------------------------------------------------------------
2632
// Constructor
@@ -30,6 +36,7 @@ export class View {
3036
if (options) {
3137
this.name = options.name;
3238
this.expression = options.expression;
39+
this.materialized = !!options.materialized;
3340
}
3441
}
3542

@@ -41,9 +48,10 @@ export class View {
4148
* Clones this table to a new table with all properties cloned.
4249
*/
4350
clone(): View {
44-
return new View(<ViewOptions> {
51+
return new View(<ViewOptions>{
4552
name: this.name,
4653
expression: this.expression,
54+
materialized: this.materialized,
4755
});
4856
}
4957

@@ -58,6 +66,7 @@ export class View {
5866
const options: ViewOptions = {
5967
name: driver.buildTableName(entityMetadata.tableName, entityMetadata.schema, entityMetadata.database),
6068
expression: entityMetadata.expression!,
69+
materialized: false
6170
};
6271

6372
return new View(options);

0 commit comments

Comments
 (0)