move migration creator to seperate module
This commit is contained in:
27
migration-creator/pom.xml
Normal file
27
migration-creator/pom.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>jef</artifactId>
|
||||
<groupId>jef</groupId>
|
||||
<version>0.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>migration-creator</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>jef</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,196 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.constraints.ForeignKeyConstraint;
|
||||
import jef.model.migration.Migration;
|
||||
import jef.model.migration.MigrationBuilder;
|
||||
import jef.model.migration.operation.AddFieldOperation;
|
||||
import jef.model.migration.operation.AddForeignKeyOperation;
|
||||
import jef.model.migration.operation.AddIndexOperation;
|
||||
import jef.model.migration.operation.AddKeyOperation;
|
||||
import jef.model.migration.operation.AddPrimaryKeyOperation;
|
||||
import jef.model.migration.operation.AddTableOperation;
|
||||
import jef.model.migration.operation.AddUniqueKeyOperation;
|
||||
import jef.model.migration.operation.DropConstraintOperation;
|
||||
import jef.model.migration.operation.DropFieldOperation;
|
||||
import jef.model.migration.operation.DropTableOperation;
|
||||
import jef.model.migration.operation.MigrationOperation;
|
||||
import jef.model.migration.operation.RenameFieldOperation;
|
||||
import jef.model.migration.operation.RenameTableOperation;
|
||||
import jef.model.migration.operation.UpdateFieldOperation;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class MigrationBuilderGenerator {
|
||||
private final List<MigrationOperation> opsUp;
|
||||
private final List<MigrationOperation> opsDown;
|
||||
private final String name;
|
||||
private final String packageName;
|
||||
|
||||
private final Set<Class<?>> imports = new HashSet<>();
|
||||
@Getter
|
||||
private String java = null;
|
||||
|
||||
public MigrationBuilderGenerator generate() {
|
||||
if (java == null) {
|
||||
java = generateMigrationBuilderJava();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private String generateMigrationBuilderJava() {
|
||||
imports.add(Migration.class);
|
||||
imports.add(MigrationBuilder.class);
|
||||
|
||||
//generate java for migration step and concat
|
||||
var migrationUp = String.join("\n\n", opsUp.stream().map(this::getMigrationJava).toList());
|
||||
var migrationDown = String.join("\n\n", opsDown.stream().map(this::getMigrationJava).toList());
|
||||
|
||||
//generate migration class file
|
||||
var normalImports = imports.stream().filter(e -> !e.getName().startsWith("java")).sorted(Comparator.comparing(Class::getName, String.CASE_INSENSITIVE_ORDER)).toList();
|
||||
var javaImports = imports.stream().filter(e -> e.getName().startsWith("java")).sorted(Comparator.comparing(Class::getName, String.CASE_INSENSITIVE_ORDER)).toList();
|
||||
var normalImportsString = normalImports.stream().map(e -> "import " + e.getName().replace("$", ".") + ";").collect(Collectors.joining("\n"));
|
||||
var javaImportsString = javaImports.stream().map(e -> "import " + e.getName().replace("$", ".") + ";").collect(Collectors.joining("\n"));
|
||||
|
||||
var java = (packageName != null ? "package " + packageName + ";\n\n" : "")
|
||||
+ normalImportsString + (normalImportsString.length() > 0 ? "\n\n" : "")
|
||||
+ javaImportsString + (javaImportsString.length() > 0 ? "\n\n" : "")
|
||||
+ "public class " + name + " implements Migration {\n"
|
||||
+ " public void up(MigrationBuilder mb) {\n"
|
||||
+ " " + migrationUp.replace("\n", "\n ") + "\n"
|
||||
+ " }\n"
|
||||
+ "\n"
|
||||
+ " public void down(MigrationBuilder mb) {\n"
|
||||
+ " " + migrationDown.replace("\n", "\n ") + "\n"
|
||||
+ " }\n"
|
||||
+ "}\n";
|
||||
return java;
|
||||
}
|
||||
|
||||
//mapper stuff
|
||||
private final Map<Class<? extends MigrationOperation>, Function<? extends MigrationOperation, String>> OP_TO_STRING_MAPPERS = initMapper();
|
||||
private final Function<MigrationOperation, String> UNSUPPORTED_MIGRATION_OPERATION_FUNCTION = (MigrationOperation i) -> {
|
||||
throw new RuntimeException(new UnsupportedOperationException("Unsupported migration operation: " + i.getClass().getSimpleName()));
|
||||
};
|
||||
|
||||
private Map<Class<? extends MigrationOperation>, Function<? extends MigrationOperation, String>> initMapper() {
|
||||
Map<Class<? extends MigrationOperation>, Function<? extends MigrationOperation, String>> map = new HashMap<>();
|
||||
map.put(AddFieldOperation.class, (AddFieldOperation op) -> addFieldOp(op));
|
||||
map.put(AddForeignKeyOperation.class, (AddForeignKeyOperation op) -> addForeignKeyOp(op));
|
||||
map.put(AddIndexOperation.class, (AddIndexOperation op) -> addIndexOp(op));
|
||||
map.put(AddKeyOperation.class, (AddKeyOperation op) -> addKeyOp(op));
|
||||
map.put(AddPrimaryKeyOperation.class, (AddPrimaryKeyOperation op) -> addPrimaryKeyOp(op));
|
||||
map.put(AddTableOperation.class, (AddTableOperation op) -> addTableOp(op));
|
||||
map.put(AddUniqueKeyOperation.class, (AddUniqueKeyOperation op) -> addUniqueKeyOp(op));
|
||||
map.put(DropConstraintOperation.class, (DropConstraintOperation op) -> dropConstraintOp(op));
|
||||
map.put(DropFieldOperation.class, (DropFieldOperation op) -> dropFieldOp(op));
|
||||
map.put(DropTableOperation.class, (DropTableOperation op) -> dropTableOp(op));
|
||||
map.put(RenameFieldOperation.class, (RenameFieldOperation op) -> renameFieldOp(op));
|
||||
map.put(RenameTableOperation.class, (RenameTableOperation op) -> renameTableOp(op));
|
||||
map.put(UpdateFieldOperation.class, (UpdateFieldOperation op) -> updateField(op));
|
||||
return map;
|
||||
}
|
||||
|
||||
private String getMigrationJava(MigrationOperation migrationOperation) {
|
||||
var mapper = (Function<MigrationOperation, String>) OP_TO_STRING_MAPPERS.getOrDefault(migrationOperation.getClass(), UNSUPPORTED_MIGRATION_OPERATION_FUNCTION);
|
||||
return mapper.apply(migrationOperation);
|
||||
}
|
||||
|
||||
private String addFieldOp(AddFieldOperation op) {
|
||||
return "mb.addField(\"" + op.getTable() + "\", \"" + op.getField() + "\")" + addFieldOpOptional(op) + ";";
|
||||
}
|
||||
|
||||
private String addFieldOpOptional(AddFieldOperation op) {
|
||||
return "\n"
|
||||
+ " .notNull(" + op.isNotNull() + ")\n"
|
||||
+ " .sqlType(\"" + op.getSqlType() + "\")";
|
||||
}
|
||||
|
||||
private String addForeignKeyOp(AddForeignKeyOperation op) {
|
||||
imports.add(List.class);
|
||||
imports.add(ForeignKeyConstraint.class);
|
||||
imports.add(ForeignKeyConstraint.Action.class);
|
||||
return "mb.addForeignKey(\"" + op.getName() + "\",\n"
|
||||
+ " \"" + op.getTable() + "\",\n"
|
||||
+ " List.of(" + op.getFields().stream().map(e -> "\"" + e + "\"").collect(Collectors.joining(", ")) + "),\n"
|
||||
+ " \"" + op.getReferencedTable() + "\",\n"
|
||||
+ " List.of(" + op.getReferencedFields().stream().map(e -> "\"" + e + "\"").collect(Collectors.joining(", ")) + "),\n"
|
||||
+ " ForeignKeyConstraint.Action." + op.getOnUpdate().name() + ",\n"
|
||||
+ " ForeignKeyConstraint.Action." + op.getOnDelete().name() + ");";
|
||||
}
|
||||
|
||||
private String addIndexOp(AddIndexOperation op) {
|
||||
imports.add(List.class);
|
||||
return "mb.addIndex(\"" + op.getName() + "\",\n"
|
||||
+ " \"" + op.getTable() + "\",\n"
|
||||
+ " List.of(" + op.getFields().stream().map(e -> "\"" + e + "\"").collect(Collectors.joining(", ")) + "));";
|
||||
}
|
||||
|
||||
private String addKeyOp(AddKeyOperation op) {
|
||||
imports.add(List.class);
|
||||
return "mb.addKey(\"" + op.getName() + "\",\n"
|
||||
+ " \"" + op.getTable() + "\",\n"
|
||||
+ " List.of(" + op.getFields().stream().map(e -> "\"" + e + "\"").collect(Collectors.joining(", ")) + "));";
|
||||
}
|
||||
|
||||
private String addPrimaryKeyOp(AddPrimaryKeyOperation op) {
|
||||
imports.add(List.class);
|
||||
return "mb.addPrimaryKey(\"" + op.getName() + "\",\n"
|
||||
+ " \"" + op.getTable() + "\",\n"
|
||||
+ " List.of(" + op.getFields().stream().map(e -> "\"" + e + "\"").collect(Collectors.joining(", ")) + "));";
|
||||
}
|
||||
|
||||
private String addTableOp(AddTableOperation op) {
|
||||
imports.add(List.class);
|
||||
imports.add(AddFieldOperation.class);
|
||||
imports.add(AddFieldOperation.Builder.class);
|
||||
return "mb.addTable(\"" + op.getTable() + "\", List.of(\n"
|
||||
+ op.getFields().stream()
|
||||
/**/.map(f -> " new AddFieldOperation.Builder(\"" + op.getTable() + "\", \"" + f.build().getField() + "\")" + addFieldOpOptional(f.build()).replace("\n", "\n "))
|
||||
/**/.collect(Collectors.joining(",\n")) + "\n"
|
||||
+ "));";
|
||||
}
|
||||
|
||||
private String addUniqueKeyOp(AddUniqueKeyOperation op) {
|
||||
imports.add(List.class);
|
||||
return "mb.addUniqueKey(\"" + op.getName() + "\",\n"
|
||||
+ " \"" + op.getTable() + "\",\n"
|
||||
+ " List.of(" + op.getFields().stream().map(e -> "\"" + e + "\"").collect(Collectors.joining(", ")) + "));";
|
||||
}
|
||||
|
||||
private String dropConstraintOp(DropConstraintOperation op) {
|
||||
return "mb.dropConstraint(\"" + op.getTable() + "\", \"" + op.getName() + "\");";
|
||||
}
|
||||
|
||||
private String dropFieldOp(DropFieldOperation op) {
|
||||
return "mb.dropField(\"" + op.getTable() + "\", \"" + op.getField() + "\");";
|
||||
}
|
||||
|
||||
private String dropTableOp(DropTableOperation op) {
|
||||
return "mb.dropTable(\"" + op.getTable() + "\");";
|
||||
}
|
||||
|
||||
private String renameFieldOp(RenameFieldOperation op) {
|
||||
return "mb.renameField(\"" + op.getTable() + "\", \"" + op.getOldName() + "\", \"" + op.getNewName() + "\");";
|
||||
}
|
||||
|
||||
private String renameTableOp(RenameTableOperation op) {
|
||||
return "mb.renameTable(\"" + op.getOldName() + "\", \"" + op.getNewName() + "\");";
|
||||
}
|
||||
|
||||
private String updateField(UpdateFieldOperation op) {
|
||||
return "mb.updateField(\"" + op.getTable() + "\", \"" + op.getField() + "\")\n"
|
||||
+ (op.getNewName() != null ? " .newName(\"" + op.getNewName() + "\")\n" : "")
|
||||
+ " .notNull(" + op.isNotNull() + ")\n"
|
||||
+ " .sqlType(" + op.getSqlType() + ");";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,478 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.DbField;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.SqlTypeMapper;
|
||||
import jef.model.constraints.ForeignKeyConstraint;
|
||||
import jef.model.constraints.IndexConstraint;
|
||||
import jef.model.constraints.KeyConstraint;
|
||||
import jef.model.constraints.UniqueKeyConstraint;
|
||||
import jef.model.migration.operation.AddFieldOperation;
|
||||
import jef.model.migration.operation.AddForeignKeyOperation;
|
||||
import jef.model.migration.operation.AddIndexOperation;
|
||||
import jef.model.migration.operation.AddKeyOperation;
|
||||
import jef.model.migration.operation.AddPrimaryKeyOperation;
|
||||
import jef.model.migration.operation.AddTableOperation;
|
||||
import jef.model.migration.operation.AddUniqueKeyOperation;
|
||||
import jef.model.migration.operation.DropConstraintOperation;
|
||||
import jef.model.migration.operation.DropFieldOperation;
|
||||
import jef.model.migration.operation.DropTableOperation;
|
||||
import jef.model.migration.operation.MigrationOperation;
|
||||
import jef.model.migration.operation.RenameFieldOperation;
|
||||
import jef.model.migration.operation.RenameTableOperation;
|
||||
import jef.model.migration.operation.UpdateFieldOperation;
|
||||
import jef.util.Check;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MigrationCreator {
|
||||
public Result createMigration(ModelBuilder from, ModelBuilder to, String name, String packageName, String currentSnapshotJava) {
|
||||
var result = new Result();
|
||||
|
||||
//create pre-migration model snapshot class
|
||||
result = generatePreMigrationSnapshot(name, packageName, currentSnapshotJava, result);
|
||||
|
||||
//create migration
|
||||
result = generateMigration(from, to, name, packageName, result);
|
||||
|
||||
//create current model snapshot class
|
||||
result = generatePostMigrationSnapshot(to, packageName, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private Result generatePreMigrationSnapshot(String name, String packageName, String currentSnapshotJava, Result result) {
|
||||
String preMigrationSnapshot;
|
||||
if (currentSnapshotJava == null || currentSnapshotJava.isBlank()) {
|
||||
preMigrationSnapshot = generateModelBuilderJava(new ModelBuilder(), name, packageName);
|
||||
} else {
|
||||
preMigrationSnapshot = currentSnapshotJava.replace("CurrentSnapshot", name + "Snapshot");
|
||||
}
|
||||
result.setMigrationSnapshot(preMigrationSnapshot);
|
||||
return result;
|
||||
}
|
||||
|
||||
private Result generatePostMigrationSnapshot(ModelBuilder to, String packageName, Result result) {
|
||||
result.setCurrentSnapshot(generateModelBuilderJava(to, "Current", packageName));
|
||||
return result;
|
||||
}
|
||||
|
||||
private String generateModelBuilderJava(ModelBuilder mb, String name, String packageName) {
|
||||
return new ModelBuilderGenerator(mb, name, packageName, new SqlTypeMapper()).generate().getJava();//TODO mapper
|
||||
}
|
||||
|
||||
private Result generateMigration(ModelBuilder from, ModelBuilder to, String name, String packageName, Result result) {
|
||||
//reduce model builders to changes
|
||||
var mcd = new ModelChangeDetector(from, to).detect();
|
||||
var fromReduced = mcd.getFrom();
|
||||
var toReduced = mcd.getTo();
|
||||
|
||||
//create migration steps
|
||||
var migrationUpOps = new ArrayList<MigrationOperation.Builder>();
|
||||
var migrationDownOps = new ArrayList<MigrationOperation.Builder>();
|
||||
|
||||
generateMigrationSteps(fromReduced, toReduced, from, to, migrationUpOps);
|
||||
generateMigrationSteps(toReduced, fromReduced, to, from, migrationDownOps);
|
||||
|
||||
var builtUpOps = migrationUpOps.stream().map(e -> e.build()).toList();
|
||||
var builtDownOps = migrationDownOps.stream().map(e -> e.build()).toList();
|
||||
|
||||
result.setMigration(new MigrationBuilderGenerator(builtUpOps, builtDownOps, name, packageName).generate().getJava());
|
||||
result.setStepsUp(builtUpOps);
|
||||
result.setStepsDown(builtDownOps);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void generateMigrationSteps(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
//key drop
|
||||
addForeignKeyDropGeneration(fromReduced, toReduced, from, to, steps);
|
||||
addPrimaryKeyDropGeneration(fromReduced, toReduced, from, to, steps);
|
||||
addUniqueKeyDropGeneration(fromReduced, toReduced, from, to, steps);
|
||||
addKeyDropGeneration(fromReduced, toReduced, from, to, steps);
|
||||
addIndexDropGeneration(fromReduced, toReduced, from, to, steps);
|
||||
|
||||
//table
|
||||
addTableDropGeneration(fromReduced, toReduced, from, to, steps);
|
||||
addTableRenameGeneration(fromReduced, toReduced, from, to, steps);
|
||||
addTableAddGeneration(fromReduced, toReduced, from, to, steps);
|
||||
|
||||
//fields
|
||||
addFieldAddRenameUpdateDropGeneration(fromReduced, toReduced, from, to, steps);
|
||||
|
||||
//key add
|
||||
addPrimaryKeyAddGeneration(fromReduced, toReduced, from, to, steps);
|
||||
addForeignKeyAddGeneration(fromReduced, toReduced, from, to, steps);
|
||||
addUniqueKeyAddGeneration(fromReduced, toReduced, from, to, steps);
|
||||
addKeyAddGeneration(fromReduced, toReduced, from, to, steps);
|
||||
addIndexAddGeneration(fromReduced, toReduced, from, to, steps);
|
||||
}
|
||||
|
||||
private void addTableAddGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var toEntity : toReduced.getEntities()) {
|
||||
var fromEntity = fromReduced.getEntity(toEntity.getTypeName());
|
||||
|
||||
//new entity
|
||||
if (fromEntity == null) {
|
||||
steps.add(new AddTableOperation.Builder(
|
||||
toEntity.getName(),
|
||||
toEntity.getFields().stream()
|
||||
.filter(DbField::isDatabaseField)
|
||||
.map(e -> new AddFieldOperation.Builder(toEntity.getName(), e.getName())
|
||||
.notNull(e.isNotNull())
|
||||
.sqlType(getSqlType(e)))
|
||||
.toList()
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getSqlType(DbField<?> e) {
|
||||
return Optional.ofNullable(e.getSqlType()).or(() -> new SqlTypeMapper().map(e.getTypeName())).orElse(null);
|
||||
}
|
||||
|
||||
private void addTableRenameGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var toEntity : toReduced.getEntities()) {
|
||||
var fromEntity = fromReduced.getEntity(toEntity.getTypeName());
|
||||
// entity added
|
||||
if (fromEntity == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//entity rename
|
||||
if (!fromEntity.getName().equals(toEntity.getName())) {
|
||||
steps.add(new RenameTableOperation.Builder(fromEntity.getName(), toEntity.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addTableDropGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var fromEntity : fromReduced.getEntities()) {
|
||||
var toEntity = toReduced.getEntity(fromEntity.getTypeName());
|
||||
if (toEntity == null) {
|
||||
steps.add(new DropTableOperation.Builder(fromEntity.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addFieldAddRenameUpdateDropGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var toEntity : toReduced.getEntities()) {
|
||||
var fromEntity = fromReduced.getEntities().stream().filter(e -> e.getName().equals(toEntity.getName())).findFirst().orElse(null);
|
||||
|
||||
//entity added -> nothing to do here
|
||||
if (fromEntity == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var remainingFromFields = new ArrayList<>(fromEntity.getFields());
|
||||
var remainingToFields = new ArrayList<>(toEntity.getFields());
|
||||
|
||||
var handledFrom = new ArrayList<DbField<?>>();
|
||||
var handledTo = new ArrayList<DbField<?>>();
|
||||
|
||||
//fields with same name but different type parameters
|
||||
for (DbField<?> toField : toEntity.getFields()) {
|
||||
var fromField = fromEntity.getFields().stream().filter(e -> e.getName().equals(toField.getName())).findFirst().orElse(null);
|
||||
if (fromField != null) {
|
||||
handledFrom.add(fromField);
|
||||
handledTo.add(toField);
|
||||
//this assumes the reduced ModelBuilders exclude exactly matching entities
|
||||
steps.add(new UpdateFieldOperation.Builder(toField.getEntity().getName(), toField.getName())
|
||||
.notNull(toField.isNotNull()));
|
||||
}
|
||||
}
|
||||
|
||||
//fields with different name but same type parameters
|
||||
remainingFromFields.removeAll(handledFrom);
|
||||
remainingToFields.removeAll(handledTo);
|
||||
|
||||
var map = new ArrayList<FieldCompare>();
|
||||
for (DbField<?> toField : remainingToFields) {
|
||||
for (DbField<?> FromField : remainingFromFields) {
|
||||
map.add(new FieldCompare(FromField, toField));
|
||||
}
|
||||
}
|
||||
map.removeIf(e -> e.getSimilarity() <= 0);
|
||||
map.sort(Comparator.comparingInt(FieldCompare::getSimilarity).reversed());
|
||||
|
||||
for (FieldCompare compare : map) {
|
||||
var toField = compare.getTo();
|
||||
var fromField = compare.getFrom();
|
||||
if (handledFrom.contains(fromField) || handledTo.contains(toField)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
handledFrom.add(fromField);
|
||||
handledTo.add(toField);
|
||||
steps.add(new RenameFieldOperation.Builder(toField.getEntity().getName(), fromField.getName(), toField.getName()));
|
||||
}
|
||||
|
||||
//drop
|
||||
remainingFromFields.removeAll(handledFrom);
|
||||
remainingToFields.removeAll(handledTo);
|
||||
for (DbField<?> fromField : remainingFromFields) {
|
||||
var toField = remainingToFields.stream().filter(e -> e.getName().equals(fromField.getName())).findFirst().orElse(null);
|
||||
if (toField == null) {
|
||||
handledFrom.add(fromField);
|
||||
steps.add(new DropFieldOperation.Builder(fromField.getEntity().getName(), fromField.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
//add
|
||||
remainingFromFields.removeAll(handledFrom);
|
||||
remainingToFields.removeAll(handledTo);
|
||||
for (DbField<?> toField : remainingToFields) {
|
||||
var fromField = remainingFromFields.stream().filter(e -> e.getName().equals(toField.getName())).findFirst().orElse(null);
|
||||
if (fromField == null) {
|
||||
handledTo.add(toField);
|
||||
steps.add(new AddFieldOperation.Builder(toField.getEntity().getName(), toField.getName())
|
||||
.notNull(toField.isNotNull()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addPrimaryKeyAddGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var toEntity : toReduced.getEntities()) {
|
||||
var originalEntity = to.getEntities().stream().filter(e -> e.getName().equals(toEntity.getName())).findFirst().orElse(null);
|
||||
Check.notNull(originalEntity, "originalEntity"); //may never be null
|
||||
var involvedFields = toEntity.getFields();
|
||||
var involvedForeignKeys = originalEntity.getPrimaryKey() != null
|
||||
&& originalEntity.getPrimaryKey().getFields().stream().anyMatch(involvedFields::contains);
|
||||
if (involvedForeignKeys) {
|
||||
steps.add(new AddPrimaryKeyOperation.Builder(
|
||||
originalEntity.getPrimaryKey().getName(),
|
||||
originalEntity.getPrimaryKey().getEntity().getName(),
|
||||
originalEntity.getPrimaryKey().getFields().stream().map(DbField::getName).collect(Collectors.toList())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addForeignKeyAddGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var toEntity : toReduced.getEntities()) {
|
||||
var originalEntity = to.getEntities().stream().filter(e -> e.getName().equals(toEntity.getName())).findFirst().orElse(null);
|
||||
Check.notNull(originalEntity, "originalEntity"); //may never be null
|
||||
var involvedFields = toEntity.getFields();
|
||||
var involvedForeignKeys = originalEntity.getForeignKeys().stream()
|
||||
.filter(e -> e.getFields().stream().anyMatch(involvedFields::contains) || toEntity.getForeignKeys().contains(e))
|
||||
.toList();
|
||||
for (ForeignKeyConstraint foreignKey : involvedForeignKeys) {
|
||||
steps.add(new AddForeignKeyOperation.Builder(
|
||||
foreignKey.getName(),
|
||||
foreignKey.getEntity().getName(),
|
||||
foreignKey.getFields().stream().map(DbField::getName).collect(Collectors.toList()),
|
||||
foreignKey.getReferencedEntity().getName(),
|
||||
foreignKey.getReferencedFields().stream().map(DbField::getName).collect(Collectors.toList()),
|
||||
foreignKey.getOnUpdate(), foreignKey.getOnDelete()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addUniqueKeyAddGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var toEntity : toReduced.getEntities()) {
|
||||
var originalEntity = to.getEntities().stream().filter(e -> e.getName().equals(toEntity.getName())).findFirst().orElse(null);
|
||||
Check.notNull(originalEntity, "originalEntity"); //may never be null
|
||||
var involvedFields = toEntity.getFields();
|
||||
var involvedUniqueKeys = originalEntity.getUniqueKeys().stream()
|
||||
.filter(e -> e.getFields().stream().anyMatch(involvedFields::contains) || toEntity.getUniqueKeys().contains(e))
|
||||
.toList();
|
||||
for (UniqueKeyConstraint uniqueKey : involvedUniqueKeys) {
|
||||
steps.add(new AddUniqueKeyOperation.Builder(
|
||||
uniqueKey.getName(),
|
||||
uniqueKey.getEntity().getName(),
|
||||
uniqueKey.getFields().stream().map(DbField::getName).collect(Collectors.toList())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addKeyAddGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var toEntity : toReduced.getEntities()) {
|
||||
var originalEntity = to.getEntities().stream().filter(e -> e.getName().equals(toEntity.getName())).findFirst().orElse(null);
|
||||
Check.notNull(originalEntity, "originalEntity"); //may never be null
|
||||
var involvedFields = toEntity.getFields();
|
||||
var involvedKeys = originalEntity.getKeys().stream()
|
||||
.filter(e -> e.getFields().stream().anyMatch(involvedFields::contains) || toEntity.getKeys().contains(e))
|
||||
.toList();
|
||||
for (KeyConstraint key : involvedKeys) {
|
||||
steps.add(new AddKeyOperation.Builder(
|
||||
key.getName(),
|
||||
key.getEntity().getName(),
|
||||
key.getFields().stream().map(DbField::getName).collect(Collectors.toList())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addIndexAddGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var toEntity : toReduced.getEntities()) {
|
||||
var originalEntity = to.getEntities().stream().filter(e -> e.getName().equals(toEntity.getName())).findFirst().orElse(null);
|
||||
Check.notNull(originalEntity, "originalEntity"); //may never be null
|
||||
var involvedFields = toEntity.getFields();
|
||||
var involvedIndexes = originalEntity.getIndexes().stream()
|
||||
.filter(e -> e.getFields().stream().anyMatch(involvedFields::contains) || toEntity.getIndexes().contains(e))
|
||||
.toList();
|
||||
for (IndexConstraint index : involvedIndexes) {
|
||||
steps.add(new AddIndexOperation.Builder(
|
||||
index.getName(),
|
||||
index.getEntity().getName(),
|
||||
index.getFields().stream().map(DbField::getName).collect(Collectors.toList())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addPrimaryKeyDropGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var fromEntity : fromReduced.getEntities()) {
|
||||
var originalEntity = from.getEntities().stream().filter(e -> e.getName().equals(fromEntity.getName())).findFirst().orElse(null);
|
||||
Check.notNull(originalEntity, "originalEntity"); //may never be null
|
||||
var involvedFields = fromEntity.getFields();
|
||||
if (originalEntity.getPrimaryKey() == null) {
|
||||
continue;
|
||||
}
|
||||
var isPrimaryKeyInvolved = originalEntity.getPrimaryKey().getFields().stream().anyMatch(involvedFields::contains);
|
||||
if (isPrimaryKeyInvolved) {
|
||||
//drop all referencing foreign keys
|
||||
from.getEntities().stream().flatMap(e -> e.getForeignKeys().stream())
|
||||
.filter(foreignKey -> foreignKey.getReferencedEntity() == fromEntity
|
||||
&& foreignKey.getReferencedFields().stream().anyMatch(involvedFields::contains))
|
||||
.forEach(foreignKey -> steps.add(new DropConstraintOperation.Builder(foreignKey.getName(), fromEntity.getName())));
|
||||
|
||||
//drop primary
|
||||
steps.add(new DropConstraintOperation.Builder(originalEntity.getPrimaryKey().getName(), fromEntity.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addForeignKeyDropGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var fromEntity : fromReduced.getEntities()) {
|
||||
var originalEntity = from.getEntities().stream().filter(e -> e.getName().equals(fromEntity.getName())).findFirst().orElse(null);
|
||||
Check.notNull(originalEntity, "originalEntity"); //may never be null
|
||||
var involvedFields = fromEntity.getFields();
|
||||
var involvedForeignKeys = originalEntity.getForeignKeys().stream()
|
||||
.filter(e -> e.getFields().stream().anyMatch(involvedFields::contains) || fromEntity.getForeignKeys().contains(e))
|
||||
.toList();
|
||||
for (ForeignKeyConstraint foreignKey : involvedForeignKeys) {
|
||||
steps.add(new DropConstraintOperation.Builder(foreignKey.getName(), fromEntity.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
// for (var fromEntity : from.getEntities()) {
|
||||
// var toEntity = to.getEntity(fromEntity.getType());
|
||||
//
|
||||
// //foreign keys
|
||||
// for (var foreignKey : fromEntity.getForeignKeys()) {
|
||||
// if (toEntity == null || toEntity.getForeignKeys().stream().noneMatch(fk -> compareForeignKey(foreignKey, fk))) {
|
||||
// migrationUpOps.add(new DropConstraintOperation.Builder(foreignKey.getName(), fromEntity.getName()));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private void addUniqueKeyDropGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var fromEntity : fromReduced.getEntities()) {
|
||||
var originalEntity = from.getEntities().stream().filter(e -> e.getName().equals(fromEntity.getName())).findFirst().orElse(null);
|
||||
Check.notNull(originalEntity, "originalEntity"); //may never be null
|
||||
var involvedFields = fromEntity.getFields();
|
||||
var involvedForeignKeys = originalEntity.getUniqueKeys().stream()
|
||||
.filter(e -> e.getFields().stream().anyMatch(involvedFields::contains) || fromEntity.getUniqueKeys().contains(e))
|
||||
.toList();
|
||||
for (UniqueKeyConstraint uniqueKey : involvedForeignKeys) {
|
||||
steps.add(new DropConstraintOperation.Builder(uniqueKey.getName(), fromEntity.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
// for (var fromEntity : from.getEntities()) {
|
||||
// var toEntity = to.getEntity(fromEntity.getType());
|
||||
//
|
||||
// //unique keys
|
||||
// for (var uniqueKey : fromEntity.getUniqueKeys()) {
|
||||
// if (toEntity == null || toEntity.getUniqueKeys().stream().noneMatch(uk -> compareConstraint(uniqueKey, uk))) {
|
||||
// steps.add(new DropConstraintOperation.Builder(uniqueKey.getName(), fromEntity.getName()));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private void addKeyDropGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var fromEntity : fromReduced.getEntities()) {
|
||||
var originalEntity = from.getEntities().stream().filter(e -> e.getName().equals(fromEntity.getName())).findFirst().orElse(null);
|
||||
Check.notNull(originalEntity, "originalEntity"); //may never be null
|
||||
var involvedFields = fromEntity.getFields();
|
||||
var involvedForeignKeys = originalEntity.getKeys().stream()
|
||||
.filter(e -> e.getFields().stream().anyMatch(involvedFields::contains) || fromEntity.getKeys().contains(e))
|
||||
.toList();
|
||||
for (KeyConstraint key : involvedForeignKeys) {
|
||||
steps.add(new DropConstraintOperation.Builder(key.getName(), fromEntity.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
// for (var fromEntity : from.getEntities()) {
|
||||
// var toEntity = to.getEntity(fromEntity.getType());
|
||||
//
|
||||
// //keys
|
||||
// for (var key : fromEntity.getKeys()) {
|
||||
// if (toEntity == null || toEntity.getKeys().stream().noneMatch(k -> compareConstraint(key, k))) {
|
||||
// migrationUpOps.add(new DropConstraintOperation.Builder(key.getName(), fromEntity.getName()));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private void addIndexDropGeneration(ModelBuilder fromReduced, ModelBuilder toReduced, ModelBuilder from, ModelBuilder to, List<MigrationOperation.Builder> steps) {
|
||||
for (var fromEntity : fromReduced.getEntities()) {
|
||||
var originalEntity = from.getEntities().stream().filter(e -> e.getName().equals(fromEntity.getName())).findFirst().orElse(null);
|
||||
Check.notNull(originalEntity, "originalEntity"); //may never be null
|
||||
var involvedFields = fromEntity.getFields();
|
||||
var involvedForeignKeys = originalEntity.getIndexes().stream()
|
||||
.filter(e -> e.getFields().stream().anyMatch(involvedFields::contains) || fromEntity.getIndexes().contains(e))
|
||||
.toList();
|
||||
for (IndexConstraint foreignKey : involvedForeignKeys) {
|
||||
steps.add(new DropConstraintOperation.Builder(foreignKey.getName(), fromEntity.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
// for (var fromEntity : from.getEntities()) {
|
||||
// var toEntity = to.getEntity(fromEntity.getType());
|
||||
//
|
||||
// //indexes
|
||||
// for (var index : fromEntity.getIndexes()) {
|
||||
// if (toEntity == null || toEntity.getIndexes().stream().noneMatch(i -> compareConstraint(index, i))) {
|
||||
// steps.add(new DropConstraintOperation.Builder(index.getName(), fromEntity.getName()));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
@NoArgsConstructor(access = AccessLevel.PACKAGE)
|
||||
public static class Result {
|
||||
private List<MigrationOperation> stepsUp = new ArrayList<>();
|
||||
private List<MigrationOperation> stepsDown = new ArrayList<>();
|
||||
private String migration = "";
|
||||
private String migrationSnapshot = "";
|
||||
private String currentSnapshot = "";
|
||||
}
|
||||
|
||||
@Getter
|
||||
private class FieldCompare {
|
||||
private final DbField<?> from;
|
||||
private final DbField<?> to;
|
||||
private final int similarity;
|
||||
|
||||
public FieldCompare(DbField<?> from, DbField<?> to) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.similarity = compute();
|
||||
}
|
||||
|
||||
private int compute() {
|
||||
return from.equalsExceptName(to) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.DbContext;
|
||||
import jef.model.DbEntity;
|
||||
import jef.model.DbEntityBuilder;
|
||||
import jef.model.DbField;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.SqlTypeMapper;
|
||||
import jef.model.constraints.ForeignKeyConstraint;
|
||||
import jef.model.constraints.IndexConstraint;
|
||||
import jef.model.constraints.KeyConstraint;
|
||||
import jef.model.constraints.PrimaryKeyConstraint;
|
||||
import jef.model.constraints.UniqueKeyConstraint;
|
||||
import jef.serializable.SerializableObject;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ModelBuilderGenerator {
|
||||
private final ModelBuilder mb;
|
||||
private final String name;
|
||||
private final String packageName;
|
||||
private final SqlTypeMapper sqlTypeMapper;
|
||||
|
||||
private final Set<Class<?>> imports = new HashSet<>();
|
||||
@Getter
|
||||
private String java = null;
|
||||
|
||||
public ModelBuilderGenerator generate() {
|
||||
if (java == null) {
|
||||
java = generateModelBuilderJava();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private String generateModelBuilderJava() {
|
||||
var indent = " ";
|
||||
imports.add(DbContext.class);
|
||||
imports.add(ModelBuilder.class);
|
||||
imports.add(DbEntityBuilder.class);
|
||||
var java = ""
|
||||
+ "public class " + name + "Snapshot extends DbContext {\n"
|
||||
+ " @Override\n"
|
||||
+ " public void onModelCreate(ModelBuilder mb) {\n"
|
||||
+ indent + "DbEntityBuilder entity;\n"
|
||||
+ indent + "DbEntityBuilder referencedEntity;\n";
|
||||
for (DbEntity<? extends SerializableObject> entity : mb.getEntities()) {
|
||||
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
|
||||
+ indent + " .name(\"" + entity.getName() + "\");\n";
|
||||
for (DbField<?> field : entity.getFields()) {
|
||||
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
|
||||
+ indent + " .field(\"" + field.getName() + "\", \"" + field.getTypeName() + "\")"
|
||||
+ "\n" + indent + " .sqlType(" + getSqlType(field) + ")"
|
||||
+ (field.isNotNull() ? "\n" + indent + " .isNotNull()" : "")
|
||||
+ "\n" + indent + " .isDatabaseField(" + field.isDatabaseField() + ")"
|
||||
+ "\n" + indent + " .isModelField(" + field.isModelField() + ");\n";
|
||||
}
|
||||
if (entity.getPrimaryKey() != null) {
|
||||
imports.add(List.class);
|
||||
imports.add(PrimaryKeyConstraint.class);
|
||||
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
|
||||
+ indent + " .hasOne(" + entity.getPrimaryKey().getFields().stream().map(f -> "\"" + f.getName() + "\"").collect(Collectors.joining(", ")) + ")\n"
|
||||
+ indent + " .isPrimaryKey();\n";
|
||||
}
|
||||
java += "\n";
|
||||
}
|
||||
for (DbEntity<? extends SerializableObject> entity : mb.getEntities()) {
|
||||
if (entity.getForeignKeys().isEmpty() && entity.getForeignKeys().isEmpty() && entity.getForeignKeys().isEmpty() && entity.getForeignKeys().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (ForeignKeyConstraint foreignKey : entity.getForeignKeys()) {
|
||||
imports.add(ForeignKeyConstraint.class);
|
||||
//TODO hasOne/hasMany/withOne/WithMany
|
||||
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
|
||||
+ indent + " .hasOne(" + foreignKey.getFields().stream().map(f -> "\"" + f.getName() + "\"").collect(Collectors.joining(", " + indent)) + ")\n"
|
||||
+ indent + " .withOne(\"" + foreignKey.getReferencedEntity().getTypeName() + "\", " + foreignKey.getReferencedFields().stream().map(f -> "\"" + f.getName() + "\"").collect(Collectors.joining(", ")) + ")\n"
|
||||
+ indent + " .onUpdate(ForeignKeyConstraint.Action." + foreignKey.getOnUpdate().name() + ")\n"
|
||||
+ indent + " .onDelete(ForeignKeyConstraint.Action." + foreignKey.getOnDelete().name() + ");\n";
|
||||
}
|
||||
for (UniqueKeyConstraint uniqueKey : entity.getUniqueKeys()) {
|
||||
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
|
||||
+ indent + " .hasOne(" + uniqueKey.getFields().stream().map(f -> "\"" + f.getName() + "\"").collect(Collectors.joining(", ")) + ")\n"
|
||||
+ indent + " .isUnique();\n";
|
||||
}
|
||||
for (KeyConstraint key : entity.getKeys()) {
|
||||
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
|
||||
+ indent + " .hasOne(" + key.getFields().stream().map(f -> "\"" + f.getName() + "\"").collect(Collectors.joining(", ")) + ")\n"
|
||||
+ indent + " .isKey();\n";
|
||||
}
|
||||
for (IndexConstraint index : entity.getIndexes()) {
|
||||
java += indent + "mb.entity(\"" + entity.getTypeName() + "\")\n"
|
||||
+ indent + " .hasOne(" + index.getFields().stream().map(f -> "\"" + f.getName() + "\"").collect(Collectors.joining(", ")) + ")\n"
|
||||
+ indent + " .isIndex();\n";
|
||||
}
|
||||
}
|
||||
java += " }\n"
|
||||
+ "}\n";
|
||||
|
||||
//imports
|
||||
var normalImports = imports.stream().filter(e -> !e.getName().startsWith("java")).sorted(Comparator.comparing(Class::getName, String.CASE_INSENSITIVE_ORDER)).toList();
|
||||
var javaImports = imports.stream().filter(e -> e.getName().startsWith("java")).sorted(Comparator.comparing(Class::getName, String.CASE_INSENSITIVE_ORDER)).toList();
|
||||
|
||||
//finalize
|
||||
java = (packageName != null ? "package " + packageName + ";\n\n" : "")
|
||||
+ normalImports.stream().map(e -> "import " + e.getName().replace("$", ".") + ";").collect(Collectors.joining("\n")) + "\n\n"
|
||||
+ javaImports.stream().map(e -> "import " + e.getName().replace("$", ".") + ";").collect(Collectors.joining("\n")) + "\n\n"
|
||||
+ java;
|
||||
return java;
|
||||
}
|
||||
|
||||
private String getSqlType(DbField<?> f) {
|
||||
return Optional.ofNullable(f.getSqlType()).or(() -> sqlTypeMapper.map(f.getTypeName())).map(e -> "\"" + e + "\"").orElse(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.util.Check;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Getter
|
||||
public class ModelChangeDetector {
|
||||
private final ModelBuilder from;
|
||||
private final ModelBuilder to;
|
||||
|
||||
public ModelChangeDetector(ModelBuilder from, ModelBuilder to) {
|
||||
this.from = Check.notNull(from, "from").clone();
|
||||
this.to = Check.notNull(to, "to").clone();
|
||||
}
|
||||
|
||||
public ModelChangeDetector detect() {
|
||||
extractChanges();
|
||||
return this;
|
||||
}
|
||||
|
||||
private void extractChanges() {
|
||||
extractChangesFromTo(from, to);
|
||||
extractChangesFromTo(to, from);
|
||||
|
||||
for (int i = 0; i < to.getEntities().size(); i++) {
|
||||
var toEntity = to.getEntities().get(i);
|
||||
var fromEntity = from.getEntities().stream().filter(e -> e.getTypeName().equals(toEntity.getTypeName())).findFirst().orElse(null);
|
||||
if (fromEntity != null) {
|
||||
//entity empty
|
||||
if (toEntity.getName().equals(fromEntity.getName())
|
||||
&& toEntity.getFields().isEmpty()
|
||||
&& toEntity.getPrimaryKey() == null
|
||||
&& toEntity.getForeignKeys().isEmpty()
|
||||
&& toEntity.getUniqueKeys().isEmpty()
|
||||
&& toEntity.getKeys().isEmpty()
|
||||
&& toEntity.getIndexes().isEmpty()
|
||||
&& fromEntity.getFields().isEmpty()
|
||||
&& fromEntity.getPrimaryKey() == null
|
||||
&& fromEntity.getForeignKeys().isEmpty()
|
||||
&& fromEntity.getUniqueKeys().isEmpty()
|
||||
&& fromEntity.getKeys().isEmpty()
|
||||
&& fromEntity.getIndexes().isEmpty()) {
|
||||
to.dropEntity(toEntity);
|
||||
from.dropEntity(fromEntity);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void extractChangesFromTo(ModelBuilder from, ModelBuilder to) {
|
||||
for (int i = 0; i < to.getEntities().size(); i++) {
|
||||
var toEntity = to.getEntities().get(i);
|
||||
var fromEntity = from.getEntities().stream().filter(e -> e.getTypeName().equals(toEntity.getTypeName())).findFirst().orElse(null);
|
||||
if (fromEntity != null) {
|
||||
for (int j = 0; j < toEntity.getFields().size(); j++) {
|
||||
var toField = toEntity.getFields().get(j);
|
||||
var fromField = fromEntity.getFields().stream().filter(e -> e.equals(toField)).findFirst().orElse(null);
|
||||
if (fromField != null) {
|
||||
toEntity.dropField(toField);
|
||||
fromEntity.dropField(fromField);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
if (Objects.equals(fromEntity.getPrimaryKey(), toEntity.getPrimaryKey())) {
|
||||
fromEntity.setPrimaryKey(null);
|
||||
toEntity.setPrimaryKey(null);
|
||||
}
|
||||
|
||||
for (int j = 0; j < toEntity.getForeignKeys().size(); j++) {
|
||||
var toFk = toEntity.getForeignKeys().get(j);
|
||||
var fromFk = fromEntity.getForeignKeys().stream().filter(e -> e.equals(toFk)).findFirst().orElse(null);
|
||||
if (fromFk != null) {
|
||||
toEntity.dropForeignKey(toFk);
|
||||
fromEntity.dropForeignKey(fromFk);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < toEntity.getUniqueKeys().size(); j++) {
|
||||
var toUnique = toEntity.getUniqueKeys().get(j);
|
||||
var fromUnique = fromEntity.getUniqueKeys().stream().filter(e -> e.equals(toUnique)).findFirst().orElse(null);
|
||||
if (fromUnique != null) {
|
||||
toEntity.dropUniqueKey(toUnique);
|
||||
fromEntity.dropUniqueKey(fromUnique);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < toEntity.getKeys().size(); j++) {
|
||||
var toKey = toEntity.getKeys().get(j);
|
||||
var fromKey = fromEntity.getKeys().stream().filter(e -> e.equals(toKey)).findFirst().orElse(null);
|
||||
if (fromKey != null) {
|
||||
toEntity.dropKey(toKey);
|
||||
fromEntity.dropKey(fromKey);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < toEntity.getIndexes().size(); j++) {
|
||||
var toIx = toEntity.getIndexes().get(j);
|
||||
var fromIx = fromEntity.getIndexes().stream().filter(e -> e.equals(toIx)).findFirst().orElse(null);
|
||||
if (fromIx != null) {
|
||||
toEntity.dropIndex(toIx);
|
||||
fromEntity.dropIndex(fromIx);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.DbSet;
|
||||
import jef.model.DbContext;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.SqlTypeMapper;
|
||||
import jef.model.annotations.Clazz;
|
||||
import jef.model.annotations.Id;
|
||||
import jef.model.constraints.ForeignKeyConstraint;
|
||||
import jef.model.constraints.PrimaryKeyConstraint;
|
||||
import jef.model.migration.operation.AddForeignKeyOperation;
|
||||
import jef.model.migration.operation.AddPrimaryKeyOperation;
|
||||
import jef.model.migration.operation.AddTableOperation;
|
||||
import jef.model.migration.operation.DropConstraintOperation;
|
||||
import jef.model.migration.operation.DropTableOperation;
|
||||
import jef.serializable.SerializableObject;
|
||||
import lombok.Getter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class MigrationCreatorAddEntityTest extends MigrationCreatorTestBase {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = ModelBuilder.from(Ctx.class);
|
||||
var to = ModelBuilder.from(Ctx.class);
|
||||
var ent = to.entity("AddedEntity");
|
||||
ent.field("id", int.class.getName());
|
||||
ent.field("addedField", int.class.getName());
|
||||
to.getEntity("AddedEntity").setPrimaryKey(new PrimaryKeyConstraint(to.getEntity("AddedEntity"), List.of(to.getEntity("AddedEntity").getField("id"))));
|
||||
to.getEntity("AddedEntity").addForeignKey(new ForeignKeyConstraint(to.getEntity("AddedEntity"), List.of(to.getEntity("AddedEntity").getField("addedField")), to.getEntity("AddedEntity"), List.of(to.getEntity("AddedEntity").getField("id")), ForeignKeyConstraint.Action.CASCADE, ForeignKeyConstraint.Action.CASCADE));
|
||||
var mc = new MigrationCreator();
|
||||
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test", new SqlTypeMapper()).generate().getJava());//TODO mapper
|
||||
try {
|
||||
validateUp(res);
|
||||
validateDown(res);
|
||||
} catch (Throwable t) {
|
||||
System.out.println(res.getMigration());
|
||||
throw t;
|
||||
}
|
||||
validateMigration(res, from, to);
|
||||
}
|
||||
|
||||
private void validateUp(MigrationCreator.Result res) {
|
||||
assertEquals(3, res.getStepsUp().size());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddTableOperation o
|
||||
&& o.getTable().equals("AddedEntity")
|
||||
&& o.getFields().size() == 2
|
||||
&& o.getFields().stream().filter(f -> f.build().getField().equals("id")).count() == 1
|
||||
&& o.getFields().stream().filter(f -> f.build().getField().equals("addedField")).count() == 1)
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddPrimaryKeyOperation o
|
||||
&& o.getTable().equals("AddedEntity")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("id"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddForeignKeyOperation o
|
||||
&& o.getTable().equals("AddedEntity")
|
||||
&& o.getReferencedTable().equals("AddedEntity")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("addedField")
|
||||
&& o.getReferencedFields().size() == 1
|
||||
&& o.getReferencedFields().get(0).equals("id"))
|
||||
.count());
|
||||
}
|
||||
|
||||
private void validateDown(MigrationCreator.Result res) {
|
||||
assertEquals(3, res.getStepsDown().size());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("AddedEntity")
|
||||
&& o.getName().equals("FK_AddedEntity_AddedEntity_addedField"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("AddedEntity")
|
||||
&& o.getName().equals("PRIMARY"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropTableOperation o
|
||||
&& o.getTable().equals("AddedEntity"))
|
||||
.count());
|
||||
}
|
||||
|
||||
public static class Ctx extends DbContext {
|
||||
@Clazz(TestClass2.class)
|
||||
private DbSet<TestClass2> objects1;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass2 extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
@Clazz(TestClass.class)
|
||||
public List<TestClass> nested;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
public Object o = new Object();
|
||||
public double d;
|
||||
public float f;
|
||||
public long l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.DbSet;
|
||||
import jef.model.DbContext;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.SqlTypeMapper;
|
||||
import jef.model.annotations.Clazz;
|
||||
import jef.model.annotations.Id;
|
||||
import jef.model.constraints.ForeignKeyConstraint;
|
||||
import jef.model.migration.operation.AddFieldOperation;
|
||||
import jef.model.migration.operation.AddForeignKeyOperation;
|
||||
import jef.model.migration.operation.DropConstraintOperation;
|
||||
import jef.model.migration.operation.DropFieldOperation;
|
||||
import jef.serializable.SerializableObject;
|
||||
import lombok.Getter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class MigrationCreatorAddFieldTest extends MigrationCreatorTestBase{
|
||||
@Test
|
||||
public void test() {
|
||||
var from = ModelBuilder.from(Ctx.class);
|
||||
var to = ModelBuilder.from(Ctx.class);
|
||||
var ent = to.getEntity(TestClass2.class);
|
||||
ent.getOrCreateField("addedField", int.class.getName());
|
||||
ent.addForeignKey(new ForeignKeyConstraint(ent, List.of(ent.getField("addedField")), ent, List.of(ent.getField("i")), ForeignKeyConstraint.Action.CASCADE, ForeignKeyConstraint.Action.CASCADE));
|
||||
var mc = new MigrationCreator();
|
||||
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test", new SqlTypeMapper()).generate().getJava());//TODO mapper
|
||||
try {
|
||||
validateUp(res);
|
||||
validateDown(res);
|
||||
} catch (Throwable t) {
|
||||
System.out.println(res.getMigration());
|
||||
throw t;
|
||||
}
|
||||
validateMigration(res, from, to);
|
||||
}
|
||||
|
||||
private void validateUp(MigrationCreator.Result res) {
|
||||
assertEquals(2, res.getStepsUp().size());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddFieldOperation o
|
||||
&& o.getTable().equals("objects1")
|
||||
&& o.getField().equals("addedField"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddForeignKeyOperation o
|
||||
&& o.getTable().equals("objects1")
|
||||
&& o.getReferencedTable().equals("objects1")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("addedField")
|
||||
&& o.getReferencedFields().size() == 1
|
||||
&& o.getReferencedFields().get(0).equals("i"))
|
||||
.count());
|
||||
}
|
||||
|
||||
private void validateDown(MigrationCreator.Result res) {
|
||||
assertEquals(2, res.getStepsDown().size());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("objects1")
|
||||
&& o.getName().equals("FK_objects1_objects1_addedField"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropFieldOperation o
|
||||
&& o.getTable().equals("objects1")
|
||||
&& o.getField().equals("addedField"))
|
||||
.count());
|
||||
}
|
||||
|
||||
public static class Ctx extends DbContext {
|
||||
@Clazz(TestClass2.class)
|
||||
private DbSet<TestClass2> objects1;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass2 extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
@Clazz(TestClass.class)
|
||||
public List<TestClass> nested;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
public Object o = new Object();
|
||||
public double d;
|
||||
public float f;
|
||||
public long l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.DbSet;
|
||||
import jef.model.DbContext;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.SqlTypeMapper;
|
||||
import jef.model.annotations.Clazz;
|
||||
import jef.model.annotations.Id;
|
||||
import jef.model.constraints.ForeignKeyConstraint;
|
||||
import jef.model.migration.operation.AddForeignKeyOperation;
|
||||
import jef.model.migration.operation.DropConstraintOperation;
|
||||
import jef.serializable.SerializableObject;
|
||||
import lombok.Getter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class MigrationCreatorAddForeignKeyTest extends MigrationCreatorTestBase {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = ModelBuilder.from(Ctx.class);
|
||||
var to = ModelBuilder.from(Ctx.class);
|
||||
var ent = to.getEntity(TestClass.class);
|
||||
ent.addForeignKey(new ForeignKeyConstraint(ent, List.of(ent.getField("i2")), ent, List.of(ent.getField("i")), ForeignKeyConstraint.Action.CASCADE, ForeignKeyConstraint.Action.CASCADE));
|
||||
var mc = new MigrationCreator();
|
||||
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test", new SqlTypeMapper()).generate().getJava());//TODO mapper
|
||||
try {
|
||||
validateUp(res);
|
||||
validateDown(res);
|
||||
} catch (Throwable t) {
|
||||
System.out.println(res.getMigration());
|
||||
throw t;
|
||||
}
|
||||
validateMigration(res, from, to);
|
||||
}
|
||||
|
||||
private void validateUp(MigrationCreator.Result res) {
|
||||
assertEquals(1, res.getStepsUp().size());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddForeignKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getReferencedTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("i2")
|
||||
&& o.getReferencedFields().size() == 1
|
||||
&& o.getReferencedFields().get(0).equals("i"))
|
||||
.count());
|
||||
}
|
||||
|
||||
private void validateDown(MigrationCreator.Result res) {
|
||||
assertEquals(1, res.getStepsDown().size());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("FK_TestClass_TestClass_i2"))
|
||||
.count());
|
||||
}
|
||||
|
||||
public static class Ctx extends DbContext {
|
||||
@Clazz(TestClass2.class)
|
||||
private DbSet<TestClass2> objects1;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass2 extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
@Clazz(TestClass.class)
|
||||
public List<TestClass> nested;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
public int i2 = 1;
|
||||
public Object o = new Object();
|
||||
public double d;
|
||||
public float f;
|
||||
public long l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.DbSet;
|
||||
import jef.model.DbContext;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.SqlTypeMapper;
|
||||
import jef.model.annotations.Clazz;
|
||||
import jef.model.annotations.Id;
|
||||
import jef.model.migration.operation.AddIndexOperation;
|
||||
import jef.model.migration.operation.DropConstraintOperation;
|
||||
import jef.serializable.SerializableObject;
|
||||
import lombok.Getter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class MigrationCreatorAddIndexTest extends MigrationCreatorTestBase{
|
||||
@Test
|
||||
public void test() {
|
||||
var from = ModelBuilder.from(Ctx.class);
|
||||
var to = ModelBuilder.from(Ctx.class);
|
||||
var ent = to.entity(TestClass.class);
|
||||
ent.field("d", double.class.getName()).isIndex(true);
|
||||
var mc = new MigrationCreator();
|
||||
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test", new SqlTypeMapper()).generate().getJava());//TODO mapper
|
||||
try {
|
||||
validateUp(res);
|
||||
validateDown(res);
|
||||
} catch (Throwable t) {
|
||||
System.out.println(res.getMigration());
|
||||
throw t;
|
||||
}
|
||||
validateMigration(res, from, to);
|
||||
}
|
||||
|
||||
private void validateUp(MigrationCreator.Result res) {
|
||||
assertEquals(1, res.getStepsUp().size());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddIndexOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("d"))
|
||||
.count());
|
||||
}
|
||||
|
||||
private void validateDown(MigrationCreator.Result res) {
|
||||
assertEquals(1, res.getStepsDown().size());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("I_TestClass_d"))
|
||||
.count());
|
||||
}
|
||||
|
||||
public static class Ctx extends DbContext {
|
||||
@Clazz(TestClass2.class)
|
||||
private DbSet<TestClass2> objects1;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass2 extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
@Clazz(TestClass.class)
|
||||
public List<TestClass> nested;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
public Object o = new Object();
|
||||
public double d;
|
||||
public float f;
|
||||
public long l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.DbSet;
|
||||
import jef.model.DbContext;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.SqlTypeMapper;
|
||||
import jef.model.annotations.Clazz;
|
||||
import jef.model.annotations.Id;
|
||||
import jef.model.migration.operation.AddKeyOperation;
|
||||
import jef.model.migration.operation.DropConstraintOperation;
|
||||
import jef.serializable.SerializableObject;
|
||||
import lombok.Getter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class MigrationCreatorAddKeyTest extends MigrationCreatorTestBase{
|
||||
@Test
|
||||
public void test() {
|
||||
var from = ModelBuilder.from(Ctx.class);
|
||||
var to = ModelBuilder.from(Ctx.class);
|
||||
var ent = to.entity(TestClass.class);
|
||||
ent.field("d", double.class.getName()).isKey(true);
|
||||
var mc = new MigrationCreator();
|
||||
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test", new SqlTypeMapper()).generate().getJava());//TODO mapper
|
||||
try {
|
||||
validateUp(res);
|
||||
validateDown(res);
|
||||
} catch (Throwable t) {
|
||||
System.out.println(res.getMigration());
|
||||
throw t;
|
||||
}
|
||||
validateMigration(res, from, to);
|
||||
}
|
||||
|
||||
private void validateUp(MigrationCreator.Result res) {
|
||||
assertEquals(1, res.getStepsUp().size());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("d"))
|
||||
.count());
|
||||
}
|
||||
|
||||
private void validateDown(MigrationCreator.Result res) {
|
||||
assertEquals(1, res.getStepsDown().size());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("K_TestClass_d"))
|
||||
.count());
|
||||
}
|
||||
|
||||
public static class Ctx extends DbContext {
|
||||
@Clazz(TestClass2.class)
|
||||
private DbSet<TestClass2> objects1;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass2 extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
@Clazz(TestClass.class)
|
||||
public List<TestClass> nested;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
public Object o = new Object();
|
||||
public double d;
|
||||
public float f;
|
||||
public long l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.DbSet;
|
||||
import jef.model.DbContext;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.SqlTypeMapper;
|
||||
import jef.model.annotations.Clazz;
|
||||
import jef.model.annotations.Id;
|
||||
import jef.model.migration.operation.AddUniqueKeyOperation;
|
||||
import jef.model.migration.operation.DropConstraintOperation;
|
||||
import jef.serializable.SerializableObject;
|
||||
import lombok.Getter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class MigrationCreatorAddUniqueTest extends MigrationCreatorTestBase{
|
||||
@Test
|
||||
public void test() {
|
||||
var from = ModelBuilder.from(Ctx.class);
|
||||
var to = ModelBuilder.from(Ctx.class);
|
||||
var ent = to.entity(TestClass.class);
|
||||
ent.field("d", double.class.getName()).isUnique(true);
|
||||
var mc = new MigrationCreator();
|
||||
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test", new SqlTypeMapper()).generate().getJava());//TODO mapper
|
||||
try {
|
||||
validateUp(res);
|
||||
validateDown(res);
|
||||
} catch (Throwable t) {
|
||||
System.out.println(res.getMigration());
|
||||
throw t;
|
||||
}
|
||||
validateMigration(res, from, to);
|
||||
}
|
||||
|
||||
private void validateUp(MigrationCreator.Result res) {
|
||||
assertEquals(1, res.getStepsUp().size());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddUniqueKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("d"))
|
||||
.count());
|
||||
}
|
||||
|
||||
private void validateDown(MigrationCreator.Result res) {
|
||||
assertEquals(1, res.getStepsDown().size());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("U_TestClass_d"))
|
||||
.count());
|
||||
}
|
||||
|
||||
public static class Ctx extends DbContext {
|
||||
@Clazz(TestClass2.class)
|
||||
private DbSet<TestClass2> objects1;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass2 extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
@Clazz(TestClass.class)
|
||||
public List<TestClass> nested;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
public Object o = new Object();
|
||||
public double d;
|
||||
public float f;
|
||||
public long l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.DbSet;
|
||||
import jef.model.DbContext;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.SqlTypeMapper;
|
||||
import jef.model.annotations.Clazz;
|
||||
import jef.model.annotations.Id;
|
||||
import jef.model.annotations.Index;
|
||||
import jef.model.annotations.Key;
|
||||
import jef.model.annotations.Unique;
|
||||
import jef.serializable.SerializableObject;
|
||||
import lombok.Getter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class MigrationCreatorEmptyTest extends MigrationCreatorTestBase{
|
||||
@Test
|
||||
public void test() {
|
||||
var from = ModelBuilder.from(Ctx.class);
|
||||
var to = ModelBuilder.from(Ctx.class);
|
||||
var mc = new MigrationCreator();
|
||||
var res = mc.createMigration(from, to, "EmptyMigration", "test",new ModelBuilderGenerator(from, "Current", "test", new SqlTypeMapper()).generate().getJava());//TODO mapper
|
||||
try {
|
||||
assertEquals(0, res.getStepsUp().size());
|
||||
assertEquals(0, res.getStepsDown().size());
|
||||
} catch (Throwable t) {
|
||||
System.out.println(res.getMigration());
|
||||
throw t;
|
||||
}
|
||||
validateMigration(res, from, to);
|
||||
}
|
||||
|
||||
public static class Ctx extends DbContext {
|
||||
@Clazz(TestClass2.class)
|
||||
private DbSet<TestClass2> objects1;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass2 extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
@Clazz(TestClass.class)
|
||||
public List<TestClass> nested;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
public Object o = new Object();
|
||||
@Index
|
||||
public double d;
|
||||
@Unique
|
||||
public float f;
|
||||
@Key
|
||||
public long l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.DbSet;
|
||||
import jef.model.DbContext;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.SqlTypeMapper;
|
||||
import jef.model.annotations.Clazz;
|
||||
import jef.model.annotations.Id;
|
||||
import jef.model.migration.operation.AddForeignKeyOperation;
|
||||
import jef.model.migration.operation.AddPrimaryKeyOperation;
|
||||
import jef.model.migration.operation.AddTableOperation;
|
||||
import jef.model.migration.operation.DropConstraintOperation;
|
||||
import jef.model.migration.operation.DropTableOperation;
|
||||
import jef.serializable.SerializableObject;
|
||||
import lombok.Getter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class MigrationCreatorInitialMigrationTest extends MigrationCreatorTestBase {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = new ModelBuilder(List.of());
|
||||
var to = ModelBuilder.from(Ctx.class);
|
||||
var mc = new MigrationCreator();
|
||||
var res = mc.createMigration(from, to, "InitialMigration", "test", new ModelBuilderGenerator(from, "Current", "test", new SqlTypeMapper()).generate().getJava());//TODO mapper
|
||||
try {
|
||||
validateUp(res);
|
||||
validateDown(res);
|
||||
} catch (Throwable t) {
|
||||
System.out.println(res.getMigration());
|
||||
throw t;
|
||||
}
|
||||
validateMigration(res, from, to);
|
||||
}
|
||||
|
||||
private void validateUp(MigrationCreator.Result res) {
|
||||
assertEquals(5, res.getStepsUp().size());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddTableOperation o
|
||||
&& o.getTable().equals("objects1")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).build().getField().equals("i"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddTableOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 6
|
||||
&& o.getFields().stream().filter(f -> f.build().getField().equals("d")).count() == 1
|
||||
&& o.getFields().stream().filter(f -> f.build().getField().equals("f")).count() == 1
|
||||
&& o.getFields().stream().filter(f -> f.build().getField().equals("i")).count() == 1
|
||||
&& o.getFields().stream().filter(f -> f.build().getField().equals("l")).count() == 1
|
||||
&& o.getFields().stream().filter(f -> f.build().getField().equals("o")).count() == 1
|
||||
&& o.getFields().stream().filter(f -> f.build().getField().equals("nestedI")).count() == 1)
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddPrimaryKeyOperation o
|
||||
&& o.getTable().equals("objects1")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("i"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddPrimaryKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("i"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddForeignKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getReferencedTable().equals("objects1")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("nestedI")
|
||||
&& o.getReferencedFields().size() == 1
|
||||
&& o.getReferencedFields().get(0).equals("i"))
|
||||
.count());
|
||||
}
|
||||
|
||||
private void validateDown(MigrationCreator.Result res) {
|
||||
assertEquals(5, res.getStepsDown().size());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("FK_TestClass_objects1_nestedI"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("PRIMARY"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("objects1")
|
||||
&& o.getName().equals("PRIMARY"))
|
||||
.count());
|
||||
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropTableOperation o
|
||||
&& o.getTable().equals("TestClass"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropTableOperation o
|
||||
&& o.getTable().equals("objects1"))
|
||||
.count());
|
||||
}
|
||||
|
||||
public static class Ctx extends DbContext {
|
||||
@Clazz(TestClass2.class)
|
||||
private DbSet<TestClass2> objects1;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass2 extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
@Clazz(TestClass.class)
|
||||
public List<TestClass> nested;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
public Object o = new Object();
|
||||
public double d;
|
||||
public float f;
|
||||
public long l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.DbSet;
|
||||
import jef.model.DbContext;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.SqlTypeMapper;
|
||||
import jef.model.annotations.Clazz;
|
||||
import jef.model.annotations.Id;
|
||||
import jef.model.migration.operation.AddForeignKeyOperation;
|
||||
import jef.model.migration.operation.AddPrimaryKeyOperation;
|
||||
import jef.model.migration.operation.DropConstraintOperation;
|
||||
import jef.model.migration.operation.RenameTableOperation;
|
||||
import jef.serializable.SerializableObject;
|
||||
import lombok.Getter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class MigrationCreatorRenameEntityTest extends MigrationCreatorTestBase {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = ModelBuilder.from(Ctx.class);
|
||||
var to = ModelBuilder.from(Ctx.class);
|
||||
var ent = to.entity(TestClass.class);
|
||||
ent.name("d2");
|
||||
var mc = new MigrationCreator();
|
||||
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test", new SqlTypeMapper()).generate().getJava());//TODO mapper
|
||||
try {
|
||||
validateUp(res);
|
||||
validateDown(res);
|
||||
} catch (Throwable t) {
|
||||
System.out.println(res.getMigration());
|
||||
throw t;
|
||||
}
|
||||
validateMigration(res, from, to);
|
||||
}
|
||||
|
||||
private void validateUp(MigrationCreator.Result res) {
|
||||
assertEquals(5, res.getStepsUp().size());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("FK_TestClass_objects1_nestedI"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("PRIMARY"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof RenameTableOperation o
|
||||
&& o.getOldName().equals("TestClass")
|
||||
&& o.getNewName().equals("d2"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddPrimaryKeyOperation o
|
||||
&& o.getTable().equals("d2")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("i"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddForeignKeyOperation o
|
||||
&& o.getTable().equals("d2")
|
||||
&& o.getReferencedTable().equals("objects1")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("nestedI")
|
||||
&& o.getReferencedFields().size() == 1
|
||||
&& o.getReferencedFields().get(0).equals("i"))
|
||||
.count());
|
||||
}
|
||||
|
||||
private void validateDown(MigrationCreator.Result res) {
|
||||
assertEquals(5, res.getStepsDown().size());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("d2")
|
||||
&& o.getName().equals("FK_d2_objects1_nestedI"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("d2")
|
||||
&& o.getName().equals("PRIMARY"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof RenameTableOperation o
|
||||
&& o.getOldName().equals("d2")
|
||||
&& o.getNewName().equals("TestClass"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof AddPrimaryKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("i"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof AddForeignKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getReferencedTable().equals("objects1")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("nestedI")
|
||||
&& o.getReferencedFields().size() == 1
|
||||
&& o.getReferencedFields().get(0).equals("i"))
|
||||
.count());
|
||||
}
|
||||
|
||||
public static class Ctx extends DbContext {
|
||||
@Clazz(TestClass2.class)
|
||||
private DbSet<TestClass2> objects1;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass2 extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
@Clazz(TestClass.class)
|
||||
public List<TestClass> nested;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
public Object o = new Object();
|
||||
public double d;
|
||||
public float f;
|
||||
public long l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.DbSet;
|
||||
import jef.model.DbContext;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.SqlTypeMapper;
|
||||
import jef.model.annotations.Clazz;
|
||||
import jef.model.annotations.ForeignKey;
|
||||
import jef.model.annotations.Id;
|
||||
import jef.model.annotations.Index;
|
||||
import jef.model.annotations.Key;
|
||||
import jef.model.annotations.Unique;
|
||||
import jef.model.migration.operation.AddForeignKeyOperation;
|
||||
import jef.model.migration.operation.AddIndexOperation;
|
||||
import jef.model.migration.operation.AddKeyOperation;
|
||||
import jef.model.migration.operation.AddPrimaryKeyOperation;
|
||||
import jef.model.migration.operation.AddUniqueKeyOperation;
|
||||
import jef.model.migration.operation.DropConstraintOperation;
|
||||
import jef.model.migration.operation.RenameFieldOperation;
|
||||
import jef.serializable.SerializableObject;
|
||||
import lombok.Getter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class MigrationCreatorRenameFieldConstraintsTest extends MigrationCreatorTestBase {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = ModelBuilder.from(Ctx.class);
|
||||
var to = ModelBuilder.from(Ctx.class);
|
||||
to.getEntity(TestClass.class).getField("i").setName("i2");
|
||||
var mc = new MigrationCreator();
|
||||
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test", new SqlTypeMapper()).generate().getJava());//TODO mapper
|
||||
try {
|
||||
validateUp(res);
|
||||
validateDown(res);
|
||||
} catch (Throwable t) {
|
||||
System.out.println(res.getMigration());
|
||||
throw t;
|
||||
}
|
||||
validateMigration(res, from, to);
|
||||
}
|
||||
|
||||
private void validateUp(MigrationCreator.Result res) {
|
||||
assertEquals(11, res.getStepsUp().size());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("FK_TestClass_TestClass_iFk"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("PRIMARY"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("U_TestClass_i"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("K_TestClass_i"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("I_TestClass_i"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof RenameFieldOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getOldName().equals("i")
|
||||
&& o.getNewName().equals("i2"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddPrimaryKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("i2"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddForeignKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getReferencedTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("iFk")
|
||||
&& o.getReferencedFields().size() == 1
|
||||
&& o.getReferencedFields().get(0).equals("i2"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddUniqueKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("i2"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("i2"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof AddIndexOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("i2"))
|
||||
.count());
|
||||
}
|
||||
|
||||
private void validateDown(MigrationCreator.Result res) {
|
||||
assertEquals(11, res.getStepsDown().size());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("FK_TestClass_TestClass_iFk"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("PRIMARY"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("U_TestClass_i2"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("K_TestClass_i2"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof DropConstraintOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getName().equals("I_TestClass_i2"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof RenameFieldOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getOldName().equals("i2")
|
||||
&& o.getNewName().equals("i"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof AddPrimaryKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("i"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof AddForeignKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getReferencedTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("iFk")
|
||||
&& o.getReferencedFields().size() == 1
|
||||
&& o.getReferencedFields().get(0).equals("i"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof AddUniqueKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("i"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof AddKeyOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("i"))
|
||||
.count());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof AddIndexOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getFields().size() == 1
|
||||
&& o.getFields().get(0).equals("i"))
|
||||
.count());
|
||||
}
|
||||
|
||||
public static class Ctx extends DbContext {
|
||||
@Clazz(TestClass2.class)
|
||||
private DbSet<TestClass2> objects1;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass2 extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
@Clazz(TestClass.class)
|
||||
public List<TestClass> nested;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass extends SerializableObject {
|
||||
@Id
|
||||
@Index
|
||||
@Unique
|
||||
@Key
|
||||
public int i = 1;
|
||||
@ForeignKey(entity = TestClass.class, getterOrField = "i")
|
||||
public int iFk = 1;
|
||||
public Object o = new Object();
|
||||
public double d;
|
||||
public float f;
|
||||
public long l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.DbSet;
|
||||
import jef.model.DbContext;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.SqlTypeMapper;
|
||||
import jef.model.annotations.Clazz;
|
||||
import jef.model.annotations.Id;
|
||||
import jef.model.migration.operation.RenameFieldOperation;
|
||||
import jef.serializable.SerializableObject;
|
||||
import lombok.Getter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class MigrationCreatorRenameFieldTest extends MigrationCreatorTestBase {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = ModelBuilder.from(Ctx.class);
|
||||
var to = ModelBuilder.from(Ctx.class);
|
||||
var ent = to.entity(TestClass.class);
|
||||
ent.field("d", double.class.getName()).name("d2");
|
||||
var mc = new MigrationCreator();
|
||||
var res = mc.createMigration(from, to, "SomeMigration", "test", new ModelBuilderGenerator(from, "Current", "test", new SqlTypeMapper()).generate().getJava());//TODO mapper
|
||||
try {
|
||||
validateUp(res);
|
||||
validateDown(res);
|
||||
} catch (Throwable t) {
|
||||
System.out.println(res.getMigration());
|
||||
throw t;
|
||||
}
|
||||
validateMigration(res, from, to);
|
||||
}
|
||||
|
||||
private void validateUp(MigrationCreator.Result res) {
|
||||
assertEquals(1, res.getStepsUp().size());
|
||||
assertEquals(1, res.getStepsUp().stream()
|
||||
.filter(e -> e instanceof RenameFieldOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getOldName().equals("d")
|
||||
&& o.getNewName().equals("d2"))
|
||||
.count());
|
||||
}
|
||||
|
||||
private void validateDown(MigrationCreator.Result res) {
|
||||
assertEquals(1, res.getStepsDown().size());
|
||||
assertEquals(1, res.getStepsDown().stream()
|
||||
.filter(e -> e instanceof RenameFieldOperation o
|
||||
&& o.getTable().equals("TestClass")
|
||||
&& o.getOldName().equals("d2")
|
||||
&& o.getNewName().equals("d"))
|
||||
.count());
|
||||
}
|
||||
|
||||
public static class Ctx extends DbContext {
|
||||
@Clazz(TestClass2.class)
|
||||
private DbSet<TestClass2> objects1;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass2 extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
@Clazz(TestClass.class)
|
||||
public List<TestClass> nested;
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class TestClass extends SerializableObject {
|
||||
@Id
|
||||
public int i = 1;
|
||||
public Object o = new Object();
|
||||
public double d;
|
||||
public float f;
|
||||
public long l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.DbContext;
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.ModelBuilderCloneTest;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class MigrationCreatorTestBase {
|
||||
private static final File JAVA_FILES_DIR = new File("target/test-generated-migrations/src");//TODO move tot a TESTUTil class or smth
|
||||
private static final File CLASS_FILES_DIR = new File("target/test-generated-migrations/target");
|
||||
|
||||
public void validateMigration(MigrationCreator.Result result, ModelBuilder from, ModelBuilder to) {
|
||||
validateMigrationJava(result.getMigration());
|
||||
validatePreMigrationSnapshotJava(result.getMigrationSnapshot(), from);
|
||||
validatePostMigrationSnapshotJava(result.getCurrentSnapshot(), to);
|
||||
}
|
||||
|
||||
public void validateMigrationJava(String migrationJava) {
|
||||
try {
|
||||
var packageName = findPackageName(migrationJava);
|
||||
var className = findClassName(migrationJava);
|
||||
compile(packageName, className, migrationJava);
|
||||
var clazz = loadClass(packageName, className);
|
||||
//for migration just test if it's compiling
|
||||
} catch (AssertionError | RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Failed to load generated class", t);
|
||||
}
|
||||
}
|
||||
|
||||
public void validatePreMigrationSnapshotJava(String snapshotJava, ModelBuilder from) {
|
||||
try {
|
||||
var packageName = findPackageName(snapshotJava);
|
||||
var className = findClassName(snapshotJava);
|
||||
compile(packageName, className, snapshotJava);
|
||||
var clazz = (Class<? extends DbContext>) loadClass(packageName, className);
|
||||
var mb = ModelBuilder.from(clazz);
|
||||
ModelBuilderCloneTest.debugHelper(from, mb);
|
||||
assertEquals(from, mb);
|
||||
} catch (AssertionError | RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Failed to load generated class", t);
|
||||
}
|
||||
}
|
||||
|
||||
public void validatePostMigrationSnapshotJava(String snapshotJava, ModelBuilder to) {
|
||||
try {
|
||||
var packageName = findPackageName(snapshotJava);
|
||||
var className = findClassName(snapshotJava);
|
||||
compile(packageName, className, snapshotJava);
|
||||
var clazz = (Class<? extends DbContext>) loadClass(packageName, className);
|
||||
var mb = ModelBuilder.from(clazz);
|
||||
assertEquals(to, mb);
|
||||
} catch (AssertionError | RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Failed to load generated class", t);
|
||||
}
|
||||
}
|
||||
|
||||
private File compile(String packageName, String className, String java) {
|
||||
try {//src
|
||||
File srcdir = new File(getSourcesFilesDir(), packageName.replace(".", File.separator));
|
||||
srcdir.mkdirs();
|
||||
File srcf = new File(srcdir, className + ".java");
|
||||
Files.writeString(srcf.toPath(), java, StandardCharsets.UTF_8,
|
||||
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
|
||||
|
||||
//dest
|
||||
File destdir = getClassFilesDir();
|
||||
|
||||
var javaHome = System.getProperty("java.home");
|
||||
var isWindows = System.getProperty("os.name").toLowerCase(Locale.ROOT).equals("win");
|
||||
var javac = new File(javaHome, "bin/javac" + (isWindows ? ".exe" : ""));
|
||||
var process = new ProcessBuilder()
|
||||
.command(javac.getAbsolutePath(),
|
||||
"-cp", "target/classes" + File.pathSeparator + "target/test-classes",
|
||||
"-encoding", "UTF8",
|
||||
"-g", //debug symbols
|
||||
"-d", destdir.getPath(), //target
|
||||
srcf.getPath()
|
||||
)
|
||||
.inheritIO()
|
||||
.start();
|
||||
process.waitFor(10, TimeUnit.SECONDS);
|
||||
var exitCode = process.exitValue();
|
||||
assertEquals(0, exitCode, "Compilation failed");
|
||||
|
||||
return new File(new File(destdir, packageName.replace(".", File.separator)), srcf.getName().replace(".java", ".class"));
|
||||
} catch (AssertionError | RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Error while compiling generated class", t);
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> loadClass(String packageName, String className) {
|
||||
try {
|
||||
var cl = new URLClassLoader(new URL[]{getClassFilesDir().toURL()});
|
||||
return cl.loadClass(packageName + "." + className);
|
||||
} catch (AssertionError | RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Failed to load generated class", t);
|
||||
}
|
||||
}
|
||||
|
||||
private String findPackageName(String java) {
|
||||
Pattern p = Pattern.compile("package ([^;]+);");
|
||||
Matcher m = p.matcher(java);
|
||||
m.find();
|
||||
return m.group(1);
|
||||
}
|
||||
|
||||
private String findClassName(String java) {
|
||||
Pattern p = Pattern.compile("public class ([^ ]+)");
|
||||
Matcher m = p.matcher(java);
|
||||
m.find();
|
||||
return m.group(1);
|
||||
}
|
||||
|
||||
private File getSourcesFilesDir() {
|
||||
File srcdir = new File(JAVA_FILES_DIR, getClass().getSimpleName());
|
||||
srcdir.mkdirs();
|
||||
return srcdir;
|
||||
}
|
||||
|
||||
private File getClassFilesDir() {
|
||||
File destdir = new File(CLASS_FILES_DIR, getClass().getSimpleName());
|
||||
destdir.mkdirs();
|
||||
return destdir;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ModelChangeDetectorAddEntityTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(0, cd.getFrom().getEntities().size());
|
||||
|
||||
assertEquals(2, cd.getTo().getEntities().size());
|
||||
assertEquals(1, cd.getTo().getEntities().get(0).getFields().size());
|
||||
assertEquals(1, cd.getTo().getEntities().get(1).getFields().size());
|
||||
assertEquals("i2", cd.getTo().getEntities().get(0).getFields().get(0).getName());
|
||||
assertEquals("i3", cd.getTo().getEntities().get(1).getFields().get(0).getName());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass2");
|
||||
mb.entity("TestClass2").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass3");
|
||||
mb.entity("TestClass3").field("i3", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ModelChangeDetectorAddFieldTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(1, cd.getFrom().getEntities().size());
|
||||
assertEquals(0, cd.getFrom().getEntities().get(0).getFields().size());
|
||||
|
||||
assertEquals(1, cd.getTo().getEntities().size());
|
||||
assertEquals(2, cd.getTo().getEntities().get(0).getFields().size());
|
||||
assertEquals("i2", cd.getTo().getEntities().get(0).getFields().get(0).getName());
|
||||
assertEquals("i3", cd.getTo().getEntities().get(0).getFields().get(1).getName());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i3", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.constraints.ForeignKeyConstraint;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ModelChangeDetectorAddForeignKeyTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(1, cd.getFrom().getEntities().size());
|
||||
assertEquals(0, cd.getFrom().getEntities().get(0).getForeignKeys().size());
|
||||
|
||||
assertEquals(1, cd.getTo().getEntities().size());
|
||||
assertEquals(1, cd.getTo().getEntities().get(0).getForeignKeys().size());
|
||||
assertEquals("FK_TestClass_TestClass_i2", cd.getTo().getEntities().get(0).getForeignKeys().get(0).getName());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
var ent = mb.entity("TestClass");
|
||||
ent.field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
ent.field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.getEntity("TestClass").addForeignKey(new ForeignKeyConstraint(mb.getEntity("TestClass"), List.of(mb.getEntity("TestClass").getField("i2")),
|
||||
mb.getEntity("TestClass"), List.of(mb.getEntity("TestClass").getField("i")),
|
||||
ForeignKeyConstraint.Action.CASCADE, ForeignKeyConstraint.Action.CASCADE));
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ModelChangeDetectorAddIndexTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(1, cd.getFrom().getEntities().size());
|
||||
assertEquals(0, cd.getFrom().getEntities().get(0).getIndexes().size());
|
||||
|
||||
assertEquals(1, cd.getTo().getEntities().size());
|
||||
assertEquals(1, cd.getTo().getEntities().get(0).getIndexes().size());
|
||||
assertEquals("I_TestClass_i", cd.getTo().getEntities().get(0).getIndexes().get(0).getName());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i", int.class.getName()).isIndex(true);
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ModelChangeDetectorAddKeyTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(1, cd.getFrom().getEntities().size());
|
||||
assertEquals(0, cd.getFrom().getEntities().get(0).getKeys().size());
|
||||
|
||||
assertEquals(1, cd.getTo().getEntities().size());
|
||||
assertEquals(1, cd.getTo().getEntities().get(0).getKeys().size());
|
||||
assertEquals("K_TestClass_i", cd.getTo().getEntities().get(0).getKeys().get(0).getName());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i", int.class.getName()).isKey(true);
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.constraints.PrimaryKeyConstraint;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
class ModelChangeDetectorAddPrimaryKeyTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(1, cd.getFrom().getEntities().size());
|
||||
assertNull(cd.getFrom().getEntities().get(0).getPrimaryKey());
|
||||
|
||||
assertEquals(1, cd.getTo().getEntities().size());
|
||||
assertNotNull(cd.getTo().getEntities().get(0).getPrimaryKey());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.getEntity("TestClass").setPrimaryKey(new PrimaryKeyConstraint(mb.getEntity("TestClass"),
|
||||
List.of(mb.getEntity("TestClass").getField("i"))));
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ModelChangeDetectorAddUniqueTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(1, cd.getFrom().getEntities().size());
|
||||
assertEquals(0, cd.getFrom().getEntities().get(0).getUniqueKeys().size());
|
||||
|
||||
assertEquals(1, cd.getTo().getEntities().size());
|
||||
assertEquals(1, cd.getTo().getEntities().get(0).getUniqueKeys().size());
|
||||
assertEquals("U_TestClass_i", cd.getTo().getEntities().get(0).getUniqueKeys().get(0).getName());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i", int.class.getName()).isUnique(true);
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ModelChangeDetectorDropEntityTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(2, cd.getFrom().getEntities().size());
|
||||
assertEquals(1, cd.getFrom().getEntities().get(0).getFields().size());
|
||||
assertEquals(1, cd.getFrom().getEntities().get(1).getFields().size());
|
||||
assertEquals("i2", cd.getFrom().getEntities().get(0).getFields().get(0).getName());
|
||||
assertEquals("i3", cd.getFrom().getEntities().get(1).getFields().get(0).getName());
|
||||
|
||||
assertEquals(0, cd.getTo().getEntities().size());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass2");
|
||||
mb.entity("TestClass2").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass3");
|
||||
mb.entity("TestClass3").field("i3", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ModelChangeDetectorDropFieldTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(1, cd.getFrom().getEntities().size());
|
||||
assertEquals(2, cd.getFrom().getEntities().get(0).getFields().size());
|
||||
assertEquals("i2", cd.getFrom().getEntities().get(0).getFields().get(0).getName());
|
||||
assertEquals("i3", cd.getFrom().getEntities().get(0).getFields().get(1).getName());
|
||||
|
||||
assertEquals(1, cd.getTo().getEntities().size());
|
||||
assertEquals(0, cd.getTo().getEntities().get(0).getFields().size());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i3", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.constraints.ForeignKeyConstraint;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ModelChangeDetectorDropForeignKeyTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(1, cd.getFrom().getEntities().size());
|
||||
assertEquals(1, cd.getFrom().getEntities().get(0).getForeignKeys().size());
|
||||
assertEquals("FK_TestClass_TestClass_i2", cd.getFrom().getEntities().get(0).getForeignKeys().get(0).getName());
|
||||
|
||||
assertEquals(1, cd.getTo().getEntities().size());
|
||||
assertEquals(0, cd.getTo().getEntities().get(0).getForeignKeys().size());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
var ent = mb.entity("TestClass");
|
||||
ent.field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
ent.field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.getEntity("TestClass").addForeignKey(new ForeignKeyConstraint(mb.getEntity("TestClass"), List.of(mb.getEntity("TestClass").getField("i2")),
|
||||
mb.getEntity("TestClass"), List.of(mb.getEntity("TestClass").getField("i")),
|
||||
ForeignKeyConstraint.Action.CASCADE, ForeignKeyConstraint.Action.CASCADE));
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ModelChangeDetectorDropIndexTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(1, cd.getFrom().getEntities().size());
|
||||
assertEquals(1, cd.getFrom().getEntities().get(0).getIndexes().size());
|
||||
assertEquals("I_TestClass_i", cd.getFrom().getEntities().get(0).getIndexes().get(0).getName());
|
||||
|
||||
assertEquals(1, cd.getTo().getEntities().size());
|
||||
assertEquals(0, cd.getTo().getEntities().get(0).getIndexes().size());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i", int.class.getName()).isIndex(true);
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ModelChangeDetectorDropKeyTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(1, cd.getFrom().getEntities().size());
|
||||
assertEquals(1, cd.getFrom().getEntities().get(0).getKeys().size());
|
||||
assertEquals("K_TestClass_i", cd.getFrom().getEntities().get(0).getKeys().get(0).getName());
|
||||
|
||||
assertEquals(1, cd.getTo().getEntities().size());
|
||||
assertEquals(0, cd.getTo().getEntities().get(0).getKeys().size());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i", int.class.getName()).isKey(true);
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import jef.model.constraints.PrimaryKeyConstraint;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
class ModelChangeDetectorDropPrimaryKeyTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(1, cd.getFrom().getEntities().size());
|
||||
assertNotNull(cd.getFrom().getEntities().get(0).getPrimaryKey());
|
||||
|
||||
assertEquals(1, cd.getTo().getEntities().size());
|
||||
assertNull(cd.getTo().getEntities().get(0).getPrimaryKey());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.getEntity("TestClass").setPrimaryKey(new PrimaryKeyConstraint(mb.getEntity("TestClass"),
|
||||
List.of(mb.getEntity("TestClass").getField("i"))));
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ModelChangeDetectorDropUniqueTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
|
||||
assertEquals(1, cd.getFrom().getEntities().size());
|
||||
assertEquals(1, cd.getFrom().getEntities().get(0).getUniqueKeys().size());
|
||||
assertEquals("U_TestClass_i", cd.getFrom().getEntities().get(0).getUniqueKeys().get(0).getName());
|
||||
|
||||
assertEquals(1, cd.getTo().getEntities().size());
|
||||
assertEquals(0, cd.getTo().getEntities().get(0).getUniqueKeys().size());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i", int.class.getName()).isUnique(true);
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package jef.model.migration.creator;
|
||||
|
||||
import jef.model.ModelBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class ModelChangeDetectorNoChangeTest {
|
||||
@Test
|
||||
public void test() {
|
||||
var from = createFrom();
|
||||
var to = createTo();
|
||||
var cd = new ModelChangeDetector(from, to).detect();
|
||||
assertTrue(cd.getFrom().getEntities().isEmpty());
|
||||
assertTrue(cd.getTo().getEntities().isEmpty());
|
||||
}
|
||||
|
||||
private ModelBuilder createFrom() {
|
||||
var mb = new ModelBuilder();
|
||||
mb.entity("TestClass");
|
||||
mb.entity("TestClass").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass2");
|
||||
mb.entity("TestClass2").field("i", int.class.getName())
|
||||
.isNotNull(true);
|
||||
mb.entity("TestClass2").field("i2", int.class.getName())
|
||||
.isNotNull(true);
|
||||
return mb;
|
||||
}
|
||||
|
||||
private ModelBuilder createTo() {
|
||||
return createFrom();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user