From 2782efb694d08c58401e0282204fdd1620268808 Mon Sep 17 00:00:00 2001 From: Kononnable Date: Sun, 22 Apr 2018 15:03:26 +0200 Subject: [PATCH] Relational Integrity support #47 --- src/drivers/MssqlDriver.ts | 10 ++++++---- src/drivers/MysqlDriver.ts | 10 ++++++---- src/drivers/OracleDriver.ts | 5 +++-- src/drivers/PostgresDriver.ts | 10 ++++++---- src/entity.mst | 2 +- src/models/RelationInfo.ts | 4 ++-- src/models/RelationTempInfo.ts | 4 ++-- .../examples/sample2-one-to-one/entity/Post.ts | 9 +++++---- .../examples/sample2-one-to-one/entity/PostDetails.ts | 1 - 9 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/drivers/MssqlDriver.ts b/src/drivers/MssqlDriver.ts index 6ec5075..11d6c85 100644 --- a/src/drivers/MssqlDriver.ts +++ b/src/drivers/MssqlDriver.ts @@ -284,8 +284,8 @@ ORDER BY ForeignKeyColumn: string; TableReferenced: string; ForeignKeyColumnReferenced: string; - onDelete: "RESTRICT" | "CASCADE" | "SET NULL"; - onUpdate: "RESTRICT" | "CASCADE" | "SET NULL"; + onDelete: "RESTRICT" | "CASCADE" | "SET NULL" | "NO_ACTION"; + onUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | "NO_ACTION"; object_id: number; }[] = (await request.query(`select parentTable.name as TableWithForeignKey, @@ -323,8 +323,10 @@ order by rels = {}; rels.ownerColumnsNames = []; rels.referencedColumnsNames = []; - rels.actionOnDelete = resp.onDelete; - rels.actionOnUpdate = resp.onUpdate; + rels.actionOnDelete = + resp.onDelete == "NO_ACTION" ? null : resp.onDelete; + rels.actionOnUpdate = + resp.onUpdate == "NO_ACTION" ? null : resp.onUpdate; rels.object_id = resp.object_id; rels.ownerTable = resp.TableWithForeignKey; rels.referencedTable = resp.TableReferenced; diff --git a/src/drivers/MysqlDriver.ts b/src/drivers/MysqlDriver.ts index 7269aab..2cb8b55 100644 --- a/src/drivers/MysqlDriver.ts +++ b/src/drivers/MysqlDriver.ts @@ -277,8 +277,8 @@ export class MysqlDriver extends AbstractDriver { ForeignKeyColumn: string; TableReferenced: string; ForeignKeyColumnReferenced: string; - onDelete: "RESTRICT" | "CASCADE" | "SET NULL"; - onUpdate: "RESTRICT" | "CASCADE" | "SET NULL"; + onDelete: "RESTRICT" | "CASCADE" | "SET NULL" | "NO_ACTION"; + onUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | "NO_ACTION"; object_id: string; }>(`SELECT CU.TABLE_NAME TableWithForeignKey, @@ -306,8 +306,10 @@ export class MysqlDriver extends AbstractDriver { rels = {}; rels.ownerColumnsNames = []; rels.referencedColumnsNames = []; - rels.actionOnDelete = resp.onDelete; - rels.actionOnUpdate = resp.onUpdate; + rels.actionOnDelete = + resp.onDelete == "NO_ACTION" ? null : resp.onDelete; + rels.actionOnUpdate = + resp.onUpdate == "NO_ACTION" ? null : resp.onUpdate; rels.object_id = resp.object_id; rels.ownerTable = resp.TableWithForeignKey; rels.referencedTable = resp.TableReferenced; diff --git a/src/drivers/OracleDriver.ts b/src/drivers/OracleDriver.ts index 8f33fe9..06ed177 100644 --- a/src/drivers/OracleDriver.ts +++ b/src/drivers/OracleDriver.ts @@ -273,8 +273,9 @@ export class OracleDriver extends AbstractDriver { rels = {}; rels.ownerColumnsNames = []; rels.referencedColumnsNames = []; - rels.actionOnDelete = resp.DELETE_RULE; - rels.actionOnUpdate = "NO ACTION"; + rels.actionOnDelete = + resp.DELETE_RULE == "NO ACTION" ? null : resp.DELETE_RULE; + rels.actionOnUpdate = null; rels.object_id = resp.CONSTRAINT_NAME; rels.ownerTable = resp.OWNER_TABLE_NAME; rels.referencedTable = resp.CHILD_TABLE_NAME; diff --git a/src/drivers/PostgresDriver.ts b/src/drivers/PostgresDriver.ts index d9f243a..cc34598 100644 --- a/src/drivers/PostgresDriver.ts +++ b/src/drivers/PostgresDriver.ts @@ -394,8 +394,8 @@ export class PostgresDriver extends AbstractDriver { att2.attname AS foreignkeycolumn, cl.relname AS tablereferenced, att.attname AS foreignkeycolumnreferenced, - update_rule as ondelete, - delete_rule as onupdate, + delete_rule as ondelete, + update_rule as onupdate, con.conname as object_id FROM ( SELECT @@ -435,8 +435,10 @@ export class PostgresDriver extends AbstractDriver { rels = {}; rels.ownerColumnsNames = []; rels.referencedColumnsNames = []; - rels.actionOnDelete = resp.ondelete; - rels.actionOnUpdate = resp.onupdate; + rels.actionOnDelete = + resp.ondelete == "NO ACTION" ? null : resp.ondelete; + rels.actionOnUpdate = + resp.onupdate == "NO ACTION" ? null : resp.onupdate; rels.object_id = resp.object_id; rels.ownerTable = resp.tablewithforeignkey; rels.referencedTable = resp.tablereferenced; diff --git a/src/entity.mst b/src/entity.mst index 21f0a0f..2c72658 100644 --- a/src/entity.mst +++ b/src/entity.mst @@ -24,7 +24,7 @@ import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, Man }) {{toPropertyName name}}:{{ts_type}}; {{/relations}}{{#relations}} - @{{relationType}}(type=>{{toEntityName relatedTable}}, {{toPropertyName ../name}}=>{{toPropertyName ../name}}.{{#if isOwner}}{{toPropertyName ownerColumn}}{{#../isPrimary}},{primary:true{{^is_nullable}}, nullable:false,{{/is_nullable}} }{{/../isPrimary}}{{else}}{{toPropertyName relatedColumn}}{{/if}}){{#isOwner}} + @{{relationType}}(type=>{{toEntityName relatedTable}}, {{toPropertyName ../name}}=>{{toPropertyName ../name}}.{{#if isOwner}}{{toPropertyName ownerColumn}},{ {{#../isPrimary}}primary:true,{{/../isPrimary}}{{^../is_nullable}} nullable:false,{{/../is_nullable}}{{#actionOnDelete}}onDelete: '{{.}}'{{/actionOnDelete}} }{{else}}{{toPropertyName relatedColumn}}{{#actionOnDelete}},{ onDelete: '{{.}}' }{{/actionOnDelete}}{{/if}}){{#isOwner}} {{#if isManyToMany}}@JoinTable(){{else}}@JoinColumn({ name:'{{ ../name}}'}){{/if}}{{/isOwner}} {{#if (or isOneToMany isManyToMany)}}{{toPropertyName ../name}}:{{toEntityName relatedTable}}[]; {{else}}{{toPropertyName ../name}}:{{toEntityName relatedTable}}; diff --git a/src/models/RelationInfo.ts b/src/models/RelationInfo.ts index 8d895a2..a239d10 100644 --- a/src/models/RelationInfo.ts +++ b/src/models/RelationInfo.ts @@ -7,8 +7,8 @@ export class RelationInfo { relatedColumn: string; ownerTable: string; ownerColumn: string; - actionOnDelete: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION"; - actionOnUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION"; + actionOnDelete: "RESTRICT" | "CASCADE" | "SET NULL" | null; + actionOnUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | null; get isOneToMany(): boolean { return this.relationType == "OneToMany"; diff --git a/src/models/RelationTempInfo.ts b/src/models/RelationTempInfo.ts index ecf657f..1e1063f 100644 --- a/src/models/RelationTempInfo.ts +++ b/src/models/RelationTempInfo.ts @@ -3,7 +3,7 @@ interface RelationTempInfo { ownerColumnsNames: string[]; referencedTable: string; referencedColumnsNames: string[]; - actionOnDelete: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION"; - actionOnUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | "NO ACTION"; + actionOnDelete: "RESTRICT" | "CASCADE" | "SET NULL" | null; + actionOnUpdate: "RESTRICT" | "CASCADE" | "SET NULL" | null; object_id: number | string; } diff --git a/test/integration/examples/sample2-one-to-one/entity/Post.ts b/test/integration/examples/sample2-one-to-one/entity/Post.ts index c68dad6..1fc3dd2 100644 --- a/test/integration/examples/sample2-one-to-one/entity/Post.ts +++ b/test/integration/examples/sample2-one-to-one/entity/Post.ts @@ -21,7 +21,7 @@ export class Post { // post has relation with category, however inverse relation is not set (category does not have relation with post set) @OneToOne(type => PostCategory, { // cascade: true, - // onDelete: 'CASCADE' + onDelete: 'CASCADE' }) @JoinColumn() // @Index({ unique: true }) @@ -30,7 +30,8 @@ export class Post { // post has relation with details. cascade inserts here means if new PostDetails instance will be set to this // relation it will be inserted automatically to the db when you save this Post entity @OneToOne(type => PostDetails, details => details.post, { - // cascade: true + onDelete: 'CASCADE' + // cascade: true }) @JoinColumn() // @Index({ unique: true }) @@ -48,7 +49,7 @@ export class Post { // post has relation with details. cascade update here means if new PostDetail instance will be set to this relation // it will be inserted automatically to the db when you save this Post entity @OneToOne(type => PostMetadata, metadata => metadata.post, { - // onDelete: 'CASCADE' + onDelete: 'CASCADE' }) @JoinColumn() // @Index({ unique: true }) @@ -57,7 +58,7 @@ export class Post { // post has relation with details. full cascades here @OneToOne(type => PostInformation, information => information.post, { // cascade: true, - // onDelete: 'CASCADE' + onDelete: 'CASCADE' }) @JoinColumn() // @Index({ unique: true }) diff --git a/test/integration/examples/sample2-one-to-one/entity/PostDetails.ts b/test/integration/examples/sample2-one-to-one/entity/PostDetails.ts index 0ac9f6a..7433b30 100644 --- a/test/integration/examples/sample2-one-to-one/entity/PostDetails.ts +++ b/test/integration/examples/sample2-one-to-one/entity/PostDetails.ts @@ -18,7 +18,6 @@ export class PostDetails { @OneToOne(type => Post, post => post.details, { // cascade: true, - // onDelete: 'CASCADE' }) post: Post;