Skip to content

Commit

Permalink
Clean up simple-team-IT for MS SQL
Browse files Browse the repository at this point in the history
  • Loading branch information
sdbuehlmann committed Feb 20, 2024
1 parent f4664cf commit cce3e9d
Show file tree
Hide file tree
Showing 13 changed files with 371 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
package ch.admin.bar.siard2.cmd.usecases.keys;

import ch.admin.bar.siard2.cmd.SiardFromDb;
import ch.admin.bar.siard2.cmd.utils.CollectionsHelper;
import ch.admin.bar.siard2.cmd.utils.siard.SiardArchivesHandler;
import ch.admin.bar.siard2.cmd.utils.siard.model.header.Metadata;
import ch.admin.bar.siard2.cmd.utils.siard.model.utils.Id;
import ch.admin.bar.siard2.cmd.utils.siard.model.utils.QualifiedColumnId;
import ch.admin.bar.siard2.cmd.utils.siard.model.utils.QualifiedForeignKeyId;
import ch.admin.bar.siard2.cmd.utils.siard.model.utils.QualifiedPrimaryKeyId;
import ch.admin.bar.siard2.cmd.utils.siard.model.utils.QualifiedTableId;
import ch.admin.bar.siard2.cmd.utils.siard.model.utils.StringWrapper;
import lombok.val;
import org.assertj.core.api.Assertions;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.testcontainers.containers.MSSQLServerContainer;
import org.testcontainers.utility.DockerImageName;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Optional;

public class MsSqlDownloadSiardProjectIT {

/**
* +-------------------+ +-------------------+ +---------------------+
* | Schema1 | | Schema2 | | Schema2 |
* +-------------------+ +-------------------+ +---------------------+
* | | | | | |
* | Teams | | Members | | TeamMembers |
* |-------------------| |-------------------| |---------------------|
* | TeamName (PK) | | MemberID (PK) | | TeamMembersID (PK) |
* | Location (PK) | | MemberName | | TeamName (FK) |
* | | | | | Location (FK) |
* | | | | | MemberID (FK) |
* +-------------------+ +-------------------+ +---------------------+
*/
public final static String CREATE_SIMPLE_TEAMS_EXAMPLE = "usecases/keys/create-simple-teams-example_mssql.sql";

public final static Id<Metadata.Schema> SCHEMA_1 = Id.of("Schema1");
public final static Id<Metadata.Schema> SCHEMA_2 = Id.of("Schema2");

public final static Id<Metadata.Table> TABLE_TEAMS = Id.of("Teams");
public final static Id<Metadata.Table> TABLE_MEMBERS = Id.of("Members");
public final static Id<Metadata.Table> TABLE_TEAM_MEMBERS = Id.of("TeamMembers");

public final static Id<Metadata.Column> COLUMN_TEAM_NAME = Id.of("TeamName");
public final static Id<Metadata.Column> COLUMN_LOCATION = Id.of("Location");
public final static Id<Metadata.Column> COLUMN_MEMBER_ID = Id.of("MemberID");
public final static Id<Metadata.Column> COLUMN_MEMBER_NAME = Id.of("MemberName");
public final static Id<Metadata.Column> COLUMN_TEAM_MEMBERS_ID = Id.of("TeamMembersID");



private static final QualifiedTableId TEAM_MEMBERS = QualifiedTableId.builder()
.schemaId(SCHEMA_2)
.tableId(Id.of("TeamMembers"))
.build();

private static final QualifiedTableId TEAMS = QualifiedTableId.builder()
.schemaId(SCHEMA_1)
.tableId(Id.of("Teams"))
.build();

private static final QualifiedTableId MEMBERS = QualifiedTableId.builder()
.schemaId(SCHEMA_2)
.tableId(Id.of("Members"))
.build();

private static final QualifiedForeignKeyId TEAM_MEMBERS_2_TEAMS_FOREIGN_KEY = QualifiedForeignKeyId.builder()
.qualifiedTableId(TEAM_MEMBERS)
.foreignKeyId(Id.of("FK_TeamMembers_TeamID"))
.build();

private static final QualifiedForeignKeyId TEAM_MEMBERS_2_MEMBERS_FOREIGN_KEY = QualifiedForeignKeyId.builder()
.qualifiedTableId(TEAM_MEMBERS)
.foreignKeyId(Id.of("FK_TeamMembers_MemberID"))
.build();

private static final QualifiedPrimaryKeyId TEAMS_PRIMARY_KEY = QualifiedPrimaryKeyId.builder()
.qualifiedTableId(TEAMS)
.primaryKeyId(Id.of("PK_Teams"))
.build();

private static final QualifiedPrimaryKeyId MEMBERS_PRIMARY_KEY = QualifiedPrimaryKeyId.builder()
.qualifiedTableId(MEMBERS)
.primaryKeyId(Id.of("PK_Members"))
.build();

private static final QualifiedPrimaryKeyId TEAM_MEMBERS_PRIMARY_KEY = QualifiedPrimaryKeyId.builder()
.qualifiedTableId(TEAM_MEMBERS)
.primaryKeyId(Id.of("PK_TeamMembers"))
.build();


@Rule
public SiardArchivesHandler siardArchivesHandler = new SiardArchivesHandler();

@Rule
public MSSQLServerContainer<?> db = new MSSQLServerContainer<>(DockerImageName.parse("mcr.microsoft.com/mssql/server:2017-CU12"))
.acceptLicense()
.withInitScript(CREATE_SIMPLE_TEAMS_EXAMPLE);

@Test
public void uploadAndDownload_expectNoExceptions() throws IOException, SQLException, ClassNotFoundException {
// given
val actualArchive = siardArchivesHandler.prepareEmpty();

// when
SiardFromDb siardFromDb = new SiardFromDb(new String[]{
"-o",
"-j:" + db.getJdbcUrl(),
"-u:" + db.getUsername(),
"-p:" + db.getPassword(),
"-s:" + actualArchive.getPathToArchiveFile()
});

// then
Assert.assertEquals(SiardFromDb.iRETURN_OK, siardFromDb.getReturn());

actualArchive.preserveArchive();

val metadataExplorer = actualArchive.exploreMetadata();
metadataExplorer.tryFindByColumnId(QualifiedColumnId.builder()
.schemaId(SCHEMA_1)
.tableId(TABLE_TEAMS)
.columnId(COLUMN_TEAM_NAME)
.build());

Assertions.assertThat(metadataExplorer.tryFindPrimaryKey(TEAMS))
.contains(Metadata.PrimaryKey.builder()
.name(TEAMS_PRIMARY_KEY.getPrimaryKeyId())
.columns(CollectionsHelper.setOf(
COLUMN_LOCATION,
COLUMN_TEAM_NAME
))
.build());

Assertions.assertThat(metadataExplorer.tryFindPrimaryKey(MEMBERS))
.contains(Metadata.PrimaryKey.builder()
.name(MEMBERS_PRIMARY_KEY.getPrimaryKeyId())
.columns(CollectionsHelper.setOf(COLUMN_MEMBER_ID))
.build());

Assertions.assertThat(metadataExplorer.tryFindPrimaryKey(TEAM_MEMBERS))
.contains(Metadata.PrimaryKey.builder()
.name(TEAM_MEMBERS_PRIMARY_KEY.getPrimaryKeyId())
.columns(CollectionsHelper.setOf(COLUMN_TEAM_MEMBERS_ID))
.build());

Assertions.assertThat(metadataExplorer.findForeignKey(TEAM_MEMBERS_2_TEAMS_FOREIGN_KEY))
.isEqualTo(Metadata.ForeignKey.builder()
.name(TEAM_MEMBERS_2_TEAMS_FOREIGN_KEY.getForeignKeyId())
.referencedSchema(TEAMS.getSchemaId())
.referencedTable(TEAMS.getTableId())
.references(CollectionsHelper.setOf(Metadata.Reference.builder()
.column(COLUMN_TEAM_NAME)
.referenced(COLUMN_TEAM_NAME)
.build(),
Metadata.Reference.builder()
.column(COLUMN_LOCATION)
.referenced(COLUMN_LOCATION)
.build()))
.deleteAction(Optional.of(StringWrapper.of("CASCADE")))
.updateAction(Optional.of(StringWrapper.of("CASCADE")))
.build());

Assertions.assertThat(metadataExplorer.findForeignKey(TEAM_MEMBERS_2_MEMBERS_FOREIGN_KEY))
.isEqualTo(Metadata.ForeignKey.builder()
.name(TEAM_MEMBERS_2_MEMBERS_FOREIGN_KEY.getForeignKeyId())
.referencedSchema(MEMBERS.getSchemaId())
.referencedTable(MEMBERS.getTableId())
.references(CollectionsHelper.setOf(Metadata.Reference.builder()
.column(COLUMN_MEMBER_ID)
.referenced(COLUMN_MEMBER_ID)
.build()))
.deleteAction(Optional.of(StringWrapper.of("RESTRICT"))) // FIXME: Should be "NO ACTION" (RESTRICT is unknown in MS SQL)
.updateAction(Optional.of(StringWrapper.of("RESTRICT"))) // FIXME: Should be "NO ACTION" (RESTRICT is unknown in MS SQL)
.build());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package ch.admin.bar.siard2.cmd;
package ch.admin.bar.siard2.cmd.usecases.keys;

import ch.admin.bar.siard2.cmd.SiardFromDb;
import ch.admin.bar.siard2.cmd.SiardToDb;
import ch.admin.bar.siard2.cmd.utils.SiardProjectExamples;
import ch.admin.bar.siard2.cmd.utils.siard.assertions.SiardArchiveAssertions;
import ch.admin.bar.siard2.cmd.utils.siard.SiardArchivesHandler;
Expand All @@ -15,6 +17,12 @@

public class MsSqlUploadDownloadSiardProjectIT {

/**
* Output of {@link MsSqlDownloadSiardProjectIT}
*/
public final static String SIMPLE_TEAMS_EXAMPLE = "usecases/keys/simple-teams-example_mssql.siard";


@Rule
public SiardArchivesHandler siardArchivesHandler = new SiardArchivesHandler();

Expand All @@ -25,7 +33,7 @@ public class MsSqlUploadDownloadSiardProjectIT {
@Test
public void uploadAndDownload_expectNoExceptions() throws IOException, SQLException, ClassNotFoundException {
// given
val expectedArchive = siardArchivesHandler.prepareResource(SiardProjectExamples.SIMPLE_TEAMS_EXAMPLE_MSSQL2017CU12_2_2);
val expectedArchive = siardArchivesHandler.prepareResource(SIMPLE_TEAMS_EXAMPLE);
val actualArchive = siardArchivesHandler.prepareEmpty();

// when
Expand All @@ -52,7 +60,6 @@ public void uploadAndDownload_expectNoExceptions() throws IOException, SQLExcept
.expectedArchive(expectedArchive)
.actualArchive(actualArchive)
.assertionModifier(SiardArchiveAssertions.IGNORE_DBNAME) // FIXME ?
.assertionModifier(SiardArchiveAssertions.IGNORE_PRIMARY_KEY_NAME) // Probably a DB-restriction (primary key names are generated)
.assertEqual();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.jetbrains.annotations.NotNull;
import org.junit.rules.ExternalResource;
Expand Down Expand Up @@ -114,6 +115,7 @@ private SiardArchiveExplorer createExplorer(final File pathToArchive, final File
* Please use the {@link SiardArchivesHandler#prepareResource(String)} or the
* {@link SiardArchivesHandler#prepareEmpty()} method to create a new {@link SiardArchiveExplorer} instance.
*/
@Slf4j
@Builder
@RequiredArgsConstructor
public static class SiardArchiveExplorer {
Expand Down Expand Up @@ -187,6 +189,8 @@ public SiardArchiveExplorer preserveArchive() {
pathToArchiveFile.toPath(),
outputFile.toPath());

log.info("Archive {} preserved at {}", filename, outputFile.getAbsolutePath());

return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ private static List<Qualifier<Metadata.PrimaryKey>> extractQualifiedPrimaryKeys(
table.getName(),
schema.getName(),
primaryKey.getName(),
primaryKey.getColumn()),
primaryKey.getColumns().stream()
.map(columnId -> columnId.getValue().getValue())
.sorted()
.collect(Collectors.joining(";"))),
primaryKey))))
.sorted(Comparator.comparing(Qualifier::getQualifier))
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import ch.admin.bar.siard2.cmd.utils.CastHelper;
import ch.admin.bar.siard2.cmd.utils.siard.SiardArchivesHandler.SiardArchiveExplorer;
import ch.admin.bar.siard2.cmd.utils.siard.model.header.Metadata;
import ch.admin.bar.siard2.cmd.utils.siard.model.utils.Id;
import ch.admin.bar.siard2.cmd.utils.siard.model.utils.StringWrapper;
import ch.admin.bar.siard2.cmd.utils.siard.update.UpdateInstruction;
import ch.admin.bar.siard2.cmd.utils.siard.update.Updater;
Expand Down Expand Up @@ -67,7 +68,7 @@ public class SiardArchiveAssertions {
UpdateInstruction.<Metadata.PrimaryKey>builder()
.clazz(Metadata.PrimaryKey.class)
.updater(primaryKey -> primaryKey.toBuilder()
.name(SiardArchiveAssertions.IGNORED_PLACEHOLDER)
.name(Id.of(SiardArchiveAssertions.IGNORED_PLACEHOLDER))
.build())
.build())
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import ch.admin.bar.siard2.cmd.utils.siard.update.Updatable;
import ch.admin.bar.siard2.cmd.utils.siard.update.Updater;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.Builder;
import lombok.NonNull;
Expand Down Expand Up @@ -148,16 +150,23 @@ public Column applyUpdates(Updater updater) {
@Builder(toBuilder = true)
@Jacksonized
public static class PrimaryKey implements Updatable<PrimaryKey> {
StringWrapper name;
Id<Column> column;
Id<PrimaryKey> name;

@NonNull
@Builder.Default
@JacksonXmlProperty(localName = "column")
@JacksonXmlElementWrapper(useWrapping = false)
Set<Id<Column>> columns = new HashSet<>();

@Override
public PrimaryKey applyUpdates(Updater updater) {
val updatedThis = updater.applyUpdate(this);

return new PrimaryKey(
updatedThis.name.applyUpdates(updater),
updatedThis.column.applyUpdates(updater));
updatedThis.columns.stream()
.map(columnId -> columnId.applyUpdates(updater))
.collect(Collectors.toSet()));
}
}

Expand All @@ -168,7 +177,14 @@ public static class ForeignKey implements Updatable<ForeignKey> {
Id<ForeignKey> name;
Id<Schema> referencedSchema;
Id<Table> referencedTable;
Reference reference; // TODO Probably a embedded set?

@NonNull
@Builder.Default
@JacksonXmlProperty(localName = "reference")
@JacksonXmlElementWrapper(useWrapping = false)
Set<Reference> references = new HashSet<>();


@Builder.Default
Optional<StringWrapper> deleteAction = Optional.empty();
@Builder.Default
Expand All @@ -182,7 +198,9 @@ public ForeignKey applyUpdates(Updater updater) {
updatedThis.name.applyUpdates(updater),
updatedThis.referencedSchema.applyUpdates(updater),
updatedThis.referencedTable.applyUpdates(updater),
updatedThis.reference.applyUpdates(updater),
updatedThis.references.stream()
.map(reference -> reference.applyUpdates(updater))
.collect(Collectors.toSet()),
updatedThis.deleteAction.map(s -> s.applyUpdates(updater)),
updatedThis.updateAction.map(s -> s.applyUpdates(updater)));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package ch.admin.bar.siard2.cmd.utils.siard.model.utils;

import ch.admin.bar.siard2.cmd.utils.siard.model.header.Metadata;
import lombok.Builder;
import lombok.NonNull;
import lombok.Value;

@Value
@Builder
public class QualifiedForeignKeyId {
@NonNull Id<Metadata.Schema> schemaId;
@NonNull Id<Metadata.Table> tableId;
@NonNull Id<Metadata.ForeignKey> foreignKeyId;

public QualifiedTableId getQualifiedTableId() {
return QualifiedTableId.builder()
.schemaId(schemaId)
.tableId(tableId)
.build();
}

public static class QualifiedForeignKeyIdBuilder {
public QualifiedForeignKeyIdBuilder qualifiedTableId(final QualifiedTableId qualifiedTableId) {
schemaId(qualifiedTableId.getSchemaId());
tableId(qualifiedTableId.getTableId());

return this;
}
}
}

0 comments on commit cce3e9d

Please sign in to comment.