From 3d2ba1dd62896feb4c350f83d1df7bc7ba494b63 Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Sun, 29 Sep 2024 21:32:28 +0200 Subject: [PATCH] Fixed mapping problem where UK and FK share columns they are inserted twice --- .../service/SchemaServiceIntegrationTest.java | 1 + .../src/test/resources/init/weather.sql | 2 +- dbrepo-metadata-db/1_setup-schema.sql | 3 +- .../database/table/columns/TableColumn.java | 4 +-- .../table/columns/TableColumnConcept.java | 3 +- .../table/columns/TableColumnUnit.java | 3 +- .../foreignKey/ForeignKeyReference.java | 2 ++ .../constraints/primaryKey/PrimaryKey.java | 4 +-- .../table/constraints/unique/Unique.java | 5 +-- .../java/at/tuwien/mapper/MetadataMapper.java | 1 - .../service/impl/DatabaseServiceImpl.java | 33 +++++++++++++------ 11 files changed, 40 insertions(+), 21 deletions(-) diff --git a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java index 540e17850a..d69ea86e68 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/tuwien/service/SchemaServiceIntegrationTest.java @@ -194,6 +194,7 @@ public class SchemaServiceIntegrationTest extends AbstractUnitTest { assertEquals(1, uniques.size()); final UniqueDto unique0 = uniques.get(0); assertNotNull(unique0.getTable()); + assertEquals("some_constraint", unique0.getName()); assertNull(unique0.getTable().getId()); assertEquals(TABLE_1_INTERNALNAME, unique0.getTable().getName()); assertEquals(TABLE_1_INTERNALNAME, unique0.getTable().getInternalName()); diff --git a/dbrepo-data-service/rest-service/src/test/resources/init/weather.sql b/dbrepo-data-service/rest-service/src/test/resources/init/weather.sql index 7c3ca99ce3..10cbf85565 100644 --- a/dbrepo-data-service/rest-service/src/test/resources/init/weather.sql +++ b/dbrepo-data-service/rest-service/src/test/resources/init/weather.sql @@ -17,7 +17,7 @@ CREATE TABLE weather_aus mintemp DOUBLE PRECISION NULL, rainfall DOUBLE PRECISION NULL, FOREIGN KEY (location) REFERENCES weather_location (location) ON DELETE SET NULL, - UNIQUE (`date`), + CONSTRAINT some_constraint UNIQUE (`date`), CHECK (`mintemp` > 0) ) WITH SYSTEM VERSIONING COMMENT 'Weather in Australia'; diff --git a/dbrepo-metadata-db/1_setup-schema.sql b/dbrepo-metadata-db/1_setup-schema.sql index 47ee3a95e2..9f0f2775cb 100644 --- a/dbrepo-metadata-db/1_setup-schema.sql +++ b/dbrepo-metadata-db/1_setup-schema.sql @@ -176,8 +176,9 @@ CREATE TABLE IF NOT EXISTS `mdb_columns` std_dev Numeric NULL, created timestamp NOT NULL DEFAULT NOW(), last_modified timestamp, + PRIMARY KEY (ID), FOREIGN KEY (tID) REFERENCES mdb_tables (ID) ON DELETE CASCADE, - PRIMARY KEY (ID) + UNIQUE (tID, internal_name) ) WITH SYSTEM VERSIONING; CREATE TABLE IF NOT EXISTS `mdb_columns_enums` diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java index c869e41637..dd59e21003 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java @@ -24,7 +24,7 @@ import java.util.List; @EqualsAndHashCode(onlyExplicitlyIncluded = true) @EntityListeners(AuditingEntityListener.class) @jakarta.persistence.Table(name = "mdb_columns", uniqueConstraints = { - @UniqueConstraint(columnNames = {"tid", "internalName"}) + @UniqueConstraint(columnNames = {"tID", "internal_name"}) }) @NamedQueries({ @NamedQuery(name = "TableColumn.findAllByDatabaseId", query = "select c from TableColumn c where c.table.database.id = ?1"), @@ -56,7 +56,7 @@ public class TableColumn implements Comparable<TableColumn> { @Column(name = "auto_generated", columnDefinition = "BOOLEAN default false") private Boolean autoGenerated; - @Column(nullable = false, columnDefinition = "VARCHAR(64)") + @Column(name = "internal_name", nullable = false, columnDefinition = "VARCHAR(64)") private String internalName; @Column(columnDefinition = "VARCHAR(2048)") diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java index 080abf87cd..e53e69f498 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnConcept.java @@ -50,7 +50,8 @@ public class TableColumnConcept { private Instant created; @ToString.Exclude - @OneToMany(fetch = FetchType.LAZY) + @org.springframework.data.annotation.Transient + @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) @JoinTable(name = "mdb_columns_concepts", inverseJoinColumns = { @JoinColumn(name = "cid", referencedColumnName = "id", insertable = false, updatable = false) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java index 21822c5da7..df3950785e 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumnUnit.java @@ -49,7 +49,8 @@ public class TableColumnUnit { private Instant created; @ToString.Exclude - @OneToMany(fetch = FetchType.LAZY) + @org.springframework.data.annotation.Transient + @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) @JoinTable(name = "mdb_columns_units", inverseJoinColumns = { @JoinColumn(name = "cid", referencedColumnName = "id", insertable = false, updatable = false) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKeyReference.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKeyReference.java index c63cdd22e6..c5f3570099 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKeyReference.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/foreignKey/ForeignKeyReference.java @@ -32,12 +32,14 @@ public class ForeignKeyReference { @JoinColumn(name = "fkid", referencedColumnName = "fkid", nullable = false) private ForeignKey foreignKey; + @org.springframework.data.annotation.Transient @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) @JoinColumns({ @JoinColumn(name = "cid", referencedColumnName = "id", nullable = false) }) private TableColumn column; + @org.springframework.data.annotation.Transient @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) @JoinColumns({ @JoinColumn(name = "rcid", referencedColumnName = "id", nullable = false) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/primaryKey/PrimaryKey.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/primaryKey/PrimaryKey.java index c4ccc379c5..aaa1e5fc8f 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/primaryKey/PrimaryKey.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/primaryKey/PrimaryKey.java @@ -27,7 +27,7 @@ public class PrimaryKey { @ToString.Exclude @org.springframework.data.annotation.Transient - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) + @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) @JoinColumns({ @JoinColumn(name = "tid", referencedColumnName = "id", nullable = false) }) @@ -35,7 +35,7 @@ public class PrimaryKey { @ToString.Exclude @org.springframework.data.annotation.Transient - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) + @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) @JoinColumns({ @JoinColumn(name = "cid", referencedColumnName = "id", nullable = false) }) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/unique/Unique.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/unique/Unique.java index 25ed2eae5d..c49fc48eb6 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/unique/Unique.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/constraints/unique/Unique.java @@ -33,13 +33,14 @@ public class Unique { @ToString.Exclude @org.springframework.data.annotation.Transient - @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) + @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) @JoinColumns({ @JoinColumn(name = "tid", referencedColumnName = "id") }) private Table table; - @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) + @org.springframework.data.annotation.Transient + @ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}) @JoinTable( name = "mdb_constraints_unique_columns", joinColumns = { diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java index a9b04058e2..f6c96f133d 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java @@ -555,7 +555,6 @@ public interface MetadataMapper { ref.getColumn().setDatabaseId(table.getTdbid()); ref.getReferencedColumn().setTableId(fk.getReferencedTable().getId()); ref.getReferencedColumn().setDatabaseId(table.getTdbid()); - log.trace("mapped foreign key part ({}) reference ({})", ref.getColumn().getInternalName(), ref.getReferencedColumn().getInternalName()); }); }); table.getConstraints() diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java index 1c91de7be1..0a962f7d6e 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java @@ -11,9 +11,11 @@ import at.tuwien.entities.container.Container; import at.tuwien.entities.database.*; import at.tuwien.entities.database.table.Table; import at.tuwien.entities.database.table.columns.TableColumn; +import at.tuwien.entities.database.table.constraints.Constraints; import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKey; import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKeyReference; import at.tuwien.entities.database.table.constraints.primaryKey.PrimaryKey; +import at.tuwien.entities.database.table.constraints.unique.Unique; import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.gateway.DataServiceGateway; @@ -212,12 +214,14 @@ public class DatabaseServiceImpl implements DatabaseService { .forEach(column -> { column.setTable(tableEntity); }); + log.trace("mapped unique constraint: {} ({})", tableEntity.getName(), uk.getColumns().stream().map(TableColumn::getInternalName).toList()); }); /* map foreign key constraint(s) */ tableEntity.getConstraints() .getForeignKeys() .forEach(fk -> { fk.setTable(tableEntity); + log.trace("mapped foreign key constraint: {} ({}) -> {} ({})", fk.getTable().getInternalName(), fk.getReferences().stream().map(r -> r.getColumn().getInternalName()).toList(), fk.getReferencedTable().getInternalName(), fk.getReferences().stream().map(r -> r.getReferencedColumn().getInternalName()).toList()); }); /* map primary key constraint */ for (PrimaryKey key : tableEntity.getConstraints().getPrimaryKey()) { @@ -237,7 +241,6 @@ public class DatabaseServiceImpl implements DatabaseService { } /* update referenced tables after they are known to the service */ for (ForeignKey foreignKey : database.getTables().stream().map(t -> t.getConstraints().getForeignKeys()).flatMap(List::stream).toList()) { - log.trace("lookup table {} in tables: {}", foreignKey.getReferencedTable().getInternalName(), database.getTables().stream().map(Table::getInternalName).toList()); final Optional<Table> optional = database.getTables() .stream() .filter(t -> t.getInternalName().equals(foreignKey.getReferencedTable().getInternalName())) @@ -275,15 +278,25 @@ public class DatabaseServiceImpl implements DatabaseService { reference.setReferencedColumn(optional2.get()); } } - database.getTables() - .stream() - .filter(t -> t.getConstraints().getForeignKeys().size() > 0) - .map(t -> t.getConstraints().getForeignKeys()) - .flatMap(List::stream) - .filter(fk -> fk.getReferences().size() > 1) - .forEach(fk -> { - log.debug(""); - }); + /* correct the unique constraint columns */ + for (Table table : database.getTables()) { + for (Unique uniqueConstraint : table.getConstraints().getUniques()) { + uniqueConstraint.setColumns(uniqueConstraint.getColumns() + .stream() + .map(column -> { + final Optional<TableColumn> optional = table.getColumns() + .stream() + .filter(c -> c.getInternalName().equals(column.getInternalName())) + .findFirst(); + if (optional.isEmpty()) { + log.error("Failed to find unique constraint column: {}", column.getInternalName()); + throw new IllegalArgumentException("Failed to find unique constraint column: " + column.getInternalName()); + } + return optional.get(); + }) + .toList()); + } + } /* update in metadata database */ database = databaseRepository.save(database); /* save in search service */ -- GitLab