refactor diff api (#138)

* ref: migrate diff logic to list api

* feat: update frontend resources

* fix: checkstyle
This commit is contained in:
vran
2022-04-30 23:03:20 +08:00
committed by GitHub
parent ba60cf12e1
commit 573a82b96d
39 changed files with 625 additions and 149 deletions

View File

@@ -0,0 +1,15 @@
package com.databasir.core.domain.document.comparator;
import com.databasir.core.diff.data.DiffType;
import lombok.Data;
import lombok.RequiredArgsConstructor;
@Data
@RequiredArgsConstructor
public class DiffResult {
private final String id;
private final DiffType diffType;
}

View File

@@ -0,0 +1,188 @@
package com.databasir.core.domain.document.comparator;
import com.databasir.core.diff.data.DiffType;
import com.databasir.core.meta.data.*;
import lombok.extern.slf4j.Slf4j;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
@Slf4j
public class DocumentDiffs {
public static List<TableDiffResult> tableDiff(DatabaseMeta original, DatabaseMeta current) {
return tableDiff(original.getTables(), current.getTables());
}
public static List<TableDiffResult> tableDiff(List<TableMeta> original, List<TableMeta> current) {
Map<String, TableMeta> originalTablesMap = toMap(original, TableMeta::getName);
Map<String, TableMeta> currentTablesMap = toMap(current, TableMeta::getName);
var added = added(originalTablesMap, currentTablesMap)
.stream()
.map(curr -> {
TableDiffResult result = new TableDiffResult(curr.getName(), DiffType.ADDED);
List<DiffResult> columnDiffs =
doDiff(Collections.emptyList(), curr.getColumns(), ColumnMeta::getName);
List<DiffResult> indexDiffs =
doDiff(Collections.emptyList(), curr.getIndexes(), IndexMeta::getName);
List<DiffResult> triggerDiffs =
doDiff(Collections.emptyList(), curr.getTriggers(), TriggerMeta::getName);
List<DiffResult> fkDiffs =
doDiff(Collections.emptyList(),
curr.getForeignKeys(),
fk -> fk.getFkTableName() + "." + fk.getFkColumnName() + "." + fk.getKeySeq());
result.setColumnDiffResults(columnDiffs);
result.setIndexDiffResults(indexDiffs);
result.setTriggerDiffResults(triggerDiffs);
result.setForeignKeyDiffResults(fkDiffs);
return result;
})
.collect(Collectors.toList());
var removed = removed(originalTablesMap, currentTablesMap)
.stream()
.map(old -> {
TableDiffResult result = new TableDiffResult(old.getName(), DiffType.REMOVED);
List<DiffResult> columnDiffs =
doDiff(old.getColumns(), Collections.emptyList(), ColumnMeta::getName);
List<DiffResult> indexDiffs =
doDiff(old.getIndexes(), Collections.emptyList(), IndexMeta::getName);
List<DiffResult> triggerDiffs =
doDiff(old.getTriggers(), Collections.emptyList(), TriggerMeta::getName);
List<DiffResult> fkDiffs =
doDiff(old.getForeignKeys(),
Collections.emptyList(),
fk -> fk.getFkTableName() + "." + fk.getFkColumnName() + "." + fk.getKeySeq());
result.setColumnDiffResults(columnDiffs);
result.setIndexDiffResults(indexDiffs);
result.setTriggerDiffResults(triggerDiffs);
result.setForeignKeyDiffResults(fkDiffs);
return result;
})
.collect(Collectors.toList());
List<TableDiffResult> sameOrModified = currentTablesMap.entrySet()
.stream()
.filter(entry -> originalTablesMap.containsKey(entry.getKey()))
.map(entry -> {
String tableName = entry.getKey();
TableMeta currentTable = entry.getValue();
TableMeta originalTable = originalTablesMap.get(tableName);
List<DiffResult> columnDiffs =
doDiff(originalTable.getColumns(), currentTable.getColumns(), ColumnMeta::getName);
List<DiffResult> indexDiffs =
doDiff(originalTable.getIndexes(), currentTable.getIndexes(), IndexMeta::getName);
List<DiffResult> triggerDiffs =
doDiff(originalTable.getTriggers(), currentTable.getTriggers(), TriggerMeta::getName);
List<DiffResult> fkDiffs =
doDiff(originalTable.getForeignKeys(),
currentTable.getForeignKeys(),
fk -> fk.getFkTableName() + "." + fk.getFkColumnName() + "." + fk.getKeySeq());
DiffType diffType = Objects.equals(currentTable, originalTable) ? DiffType.NONE : DiffType.MODIFIED;
TableDiffResult diffResult = new TableDiffResult(tableName, diffType);
diffResult.setColumnDiffResults(columnDiffs);
diffResult.setIndexDiffResults(indexDiffs);
diffResult.setTriggerDiffResults(triggerDiffs);
diffResult.setForeignKeyDiffResults(fkDiffs);
return diffResult;
})
.collect(Collectors.toList());
List<TableDiffResult> all = new ArrayList<>(16);
all.addAll(sameOrModified);
all.addAll(added);
all.addAll(removed);
return all;
}
private static <T> List<DiffResult> doDiff(List<T> original, List<T> current, Function<T, String> idMapping) {
Map<String, T> originalColumnMap = toMap(original, idMapping);
Map<String, T> currentColumnMap = toMap(current, idMapping);
BiFunction<T, DiffType, DiffResult> mapping = (meta, diffType) -> {
return new DiffResult(idMapping.apply(meta), diffType);
};
List<DiffResult> added = added(originalColumnMap, currentColumnMap)
.stream()
.map(col -> mapping.apply(col, DiffType.ADDED))
.collect(Collectors.toList());
List<DiffResult> removed = removed(originalColumnMap, currentColumnMap)
.stream()
.map(col -> mapping.apply(col, DiffType.REMOVED))
.collect(Collectors.toList());
List<DiffResult> modified = modified(originalColumnMap, currentColumnMap)
.stream()
.map(col -> mapping.apply(col, DiffType.MODIFIED))
.collect(Collectors.toList());
List<DiffResult> same = same(originalColumnMap, currentColumnMap)
.stream()
.map(col -> mapping.apply(col, DiffType.NONE))
.collect(Collectors.toList());
List<DiffResult> columnResults = new ArrayList<>();
columnResults.addAll(same);
columnResults.addAll(added);
columnResults.addAll(modified);
columnResults.addAll(removed);
return columnResults;
}
private static <T> Map<String, T> toMap(List<T> content, Function<T, String> idMapping) {
return content
.stream()
.collect(Collectors.toMap(idMapping, Function.identity(), (a, b) -> {
log.warn("Duplicate key, origin = {}, current = {}", a, b);
return a;
}));
}
private static <T> List<T> added(Map<String, T> originalMapById,
Map<String, T> currentMapById) {
return currentMapById.entrySet()
.stream()
.filter(entry -> !originalMapById.containsKey(entry.getKey()))
.map(Map.Entry::getValue)
.collect(Collectors.toList());
}
private static <T> List<T> removed(Map<String, T> originalMapById,
Map<String, T> currentMapById) {
return originalMapById.entrySet()
.stream()
.filter(entry -> !currentMapById.containsKey(entry.getKey()))
.map(Map.Entry::getValue)
.collect(Collectors.toList());
}
private static <T> List<T> modified(Map<String, T> originalMapById,
Map<String, T> currentMapById) {
return modified(originalMapById, currentMapById, Objects::equals);
}
private static <T> List<T> modified(Map<String, T> originalMapById,
Map<String, T> currentMapById,
BiFunction<T, T, Boolean> sameFunction) {
return currentMapById.entrySet()
.stream()
.filter(entry -> originalMapById.containsKey(entry.getKey()))
.filter(entry -> !sameFunction.apply(entry.getValue(), originalMapById.get(entry.getKey())))
.map(Map.Entry::getValue)
.collect(Collectors.toList());
}
private static <T> List<T> same(Map<String, T> originalMapById,
Map<String, T> currentMapById) {
return same(originalMapById, currentMapById, Objects::equals);
}
private static <T> List<T> same(Map<String, T> originalMapById,
Map<String, T> currentMapById,
BiFunction<T, T, Boolean> sameFunction) {
return currentMapById.entrySet()
.stream()
.filter(entry -> originalMapById.containsKey(entry.getKey()))
.filter(entry -> sameFunction.apply(entry.getValue(), originalMapById.get(entry.getKey())))
.map(Map.Entry::getValue)
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,25 @@
package com.databasir.core.domain.document.comparator;
import com.databasir.core.diff.data.DiffType;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import java.util.Collection;
import java.util.Collections;
@Data
@RequiredArgsConstructor
public class TableDiffResult {
private final String id;
private final DiffType diffType;
private Collection<DiffResult> columnDiffResults = Collections.emptyList();
private Collection<DiffResult> indexDiffResults = Collections.emptyList();
private Collection<DiffResult> triggerDiffResults = Collections.emptyList();
private Collection<DiffResult> foreignKeyDiffResults = Collections.emptyList();
}

View File

@@ -1,5 +1,6 @@
package com.databasir.core.domain.document.converter;
import com.databasir.core.domain.document.data.TableDocumentResponse;
import com.databasir.core.infrastructure.converter.JsonConverter;
import com.databasir.core.meta.data.ColumnMeta;
import com.databasir.core.meta.data.DatabaseMeta;
@@ -64,6 +65,10 @@ public interface DatabaseMetaConverter {
@Mapping(target = "columnNames", source = "pojo.columnNameArray")
IndexMeta of(TableIndexDocumentPojo pojo);
List<TableMeta> of(List<TableDocumentResponse> table);
TableMeta of(TableDocumentResponse table);
default <R> Map<Integer, List<R>> groupBy(List<R> content, Function<R, Integer> idMapping) {
return content.stream()
.collect(Collectors.groupingBy(idMapping));

View File

@@ -1,10 +1,7 @@
package com.databasir.core.domain.document.converter;
import com.databasir.core.infrastructure.converter.JsonConverter;
import com.databasir.core.meta.data.ColumnMeta;
import com.databasir.core.meta.data.ForeignKeyMeta;
import com.databasir.core.meta.data.IndexMeta;
import com.databasir.core.meta.data.TriggerMeta;
import com.databasir.core.meta.data.*;
import com.databasir.dao.tables.pojos.*;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@@ -20,7 +17,7 @@ public interface DocumentPojoConverter {
@Mapping(target = "schemaName", source = "meta.schemaName")
@Mapping(target = "isArchive", constant = "false")
DatabaseDocumentPojo toDatabasePojo(Integer projectId,
com.databasir.core.meta.data.DatabaseMeta meta,
DatabaseMeta meta,
Long version);
TableDocumentPojo toTablePojo(Integer databaseDocumentId,

View File

@@ -1,5 +1,6 @@
package com.databasir.core.domain.document.converter;
import com.databasir.core.diff.data.DiffType;
import com.databasir.core.domain.document.data.DatabaseDocumentSimpleResponse;
import com.databasir.core.infrastructure.converter.JsonConverter;
import com.databasir.dao.tables.pojos.DatabaseDocumentPojo;
@@ -19,7 +20,8 @@ public interface DocumentSimpleResponseConverter {
@Mapping(target = "createAt", source = "databaseDocument.createAt")
@Mapping(target = "documentVersion", source = "databaseDocument.version")
DatabaseDocumentSimpleResponse of(DatabaseDocumentPojo databaseDocument,
List<DatabaseDocumentSimpleResponse.TableData> tables);
List<DatabaseDocumentSimpleResponse.TableData> tables,
DiffType diffType);
DatabaseDocumentSimpleResponse.TableData of(TableDocumentPojo tables,
Integer discussionCount,

View File

@@ -1,5 +1,6 @@
package com.databasir.core.domain.document.data;
import com.databasir.core.diff.data.DiffType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -32,4 +33,6 @@ public class DatabaseDocumentResponse {
private LocalDateTime createAt;
private DiffType diffType;
}

View File

@@ -1,5 +1,6 @@
package com.databasir.core.domain.document.data;
import com.databasir.core.diff.data.DiffType;
import lombok.Data;
import java.time.LocalDateTime;
@@ -25,8 +26,10 @@ public class DatabaseDocumentSimpleResponse {
private LocalDateTime createAt;
private DiffType diffType;
@Data
public static class TableData {
public static class TableData implements DiffAble<TableData> {
private Integer id;
@@ -39,5 +42,9 @@ public class DatabaseDocumentSimpleResponse {
private Integer discussionCount;
private String description;
private DiffType diffType;
private TableData original;
}
}

View File

@@ -0,0 +1,11 @@
package com.databasir.core.domain.document.data;
import com.databasir.core.diff.data.DiffType;
public interface DiffAble<T> {
void setDiffType(DiffType diffType);
void setOriginal(T t);
}

View File

@@ -0,0 +1,16 @@
package com.databasir.core.domain.document.data;
import lombok.Data;
import java.util.Collection;
import java.util.Collections;
@Data
public class TableDocumentRequest {
private Collection<Integer> tableIds = Collections.emptyList();
private Long originalVersion;
private Long currentVersion;
}

View File

@@ -1,5 +1,6 @@
package com.databasir.core.domain.document.data;
import com.databasir.core.diff.data.DiffType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -13,7 +14,7 @@ import java.util.List;
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class TableDocumentResponse {
public class TableDocumentResponse implements DiffAble<TableDocumentResponse> {
private Integer id;
@@ -41,11 +42,15 @@ public class TableDocumentResponse {
private LocalDateTime createAt;
private DiffType diffType;
private TableDocumentResponse original;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class ColumnDocumentResponse {
public static class ColumnDocumentResponse implements DiffAble<ColumnDocumentResponse> {
private Integer id;
private String name;
@@ -71,13 +76,17 @@ public class TableDocumentResponse {
private Integer discussionCount;
private LocalDateTime createAt;
private DiffType diffType;
private ColumnDocumentResponse original;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class IndexDocumentResponse {
public static class IndexDocumentResponse implements DiffAble<IndexDocumentResponse> {
private Integer id;
@@ -89,13 +98,17 @@ public class TableDocumentResponse {
private List<String> columnNames = new ArrayList<>();
private LocalDateTime createAt;
private DiffType diffType;
private IndexDocumentResponse original;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class ForeignKeyDocumentResponse {
public static class ForeignKeyDocumentResponse implements DiffAble<ForeignKeyDocumentResponse> {
private Integer id;
@@ -105,6 +118,8 @@ public class TableDocumentResponse {
private String fkColumnName;
private Integer keySeq;
private String pkName;
private String pkTableName;
@@ -116,13 +131,17 @@ public class TableDocumentResponse {
private String deleteRule;
private LocalDateTime createAt;
private DiffType diffType;
private ForeignKeyDocumentResponse original;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class TriggerDocumentResponse {
public static class TriggerDocumentResponse implements DiffAble<TriggerDocumentResponse> {
private Integer id;
@@ -137,5 +156,9 @@ public class TableDocumentResponse {
private String triggerCreateAt;
private LocalDateTime createAt;
private DiffType diffType;
private TriggerDocumentResponse original;
}
}

View File

@@ -7,8 +7,12 @@ import com.databasir.core.diff.Diffs;
import com.databasir.core.diff.data.DiffType;
import com.databasir.core.diff.data.RootDiff;
import com.databasir.core.domain.DomainErrors;
import com.databasir.core.domain.document.comparator.DiffResult;
import com.databasir.core.domain.document.comparator.DocumentDiffs;
import com.databasir.core.domain.document.comparator.TableDiffResult;
import com.databasir.core.domain.document.converter.*;
import com.databasir.core.domain.document.data.*;
import com.databasir.core.domain.document.data.TableDocumentResponse.ForeignKeyDocumentResponse;
import com.databasir.core.domain.document.event.DocumentUpdated;
import com.databasir.core.domain.document.generator.DocumentFileGenerator;
import com.databasir.core.domain.document.generator.DocumentFileType;
@@ -16,6 +20,7 @@ import com.databasir.core.infrastructure.connection.DatabaseConnectionService;
import com.databasir.core.infrastructure.converter.JsonConverter;
import com.databasir.core.infrastructure.event.EventPublisher;
import com.databasir.core.meta.data.DatabaseMeta;
import com.databasir.core.meta.data.TableMeta;
import com.databasir.dao.impl.*;
import com.databasir.dao.tables.pojos.*;
import com.databasir.dao.value.DocumentDiscussionCountPojo;
@@ -32,12 +37,12 @@ import org.springframework.util.CollectionUtils;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static java.util.Collections.emptyList;
@Service
@RequiredArgsConstructor
@Slf4j
@@ -51,8 +56,6 @@ public class DocumentService {
private final DataSourcePropertyDao dataSourcePropertyDao;
private final SysKeyDao sysKeyDao;
private final DatabaseConnectionService databaseConnectionService;
private final DatabaseDocumentDao databaseDocumentDao;
@@ -199,13 +202,16 @@ public class DocumentService {
projectId, meta.getDatabaseName(), version);
}
public Optional<DatabaseDocumentSimpleResponse> getSimpleOneByProjectId(Integer projectId, Long version) {
public Optional<DatabaseDocumentSimpleResponse> getSimpleOneByProjectId(Integer projectId,
Long version,
Long originalVersion) {
Optional<DatabaseDocumentPojo> documentOption;
if (version == null) {
documentOption = databaseDocumentDao.selectNotArchivedByProjectId(projectId);
} else {
documentOption = databaseDocumentDao.selectOptionalByProjectIdAndVersion(projectId, version);
}
return documentOption.map(document -> {
Integer id = document.getId();
var tables = tableDocumentDao.selectByDatabaseDocumentId(id);
@@ -213,7 +219,7 @@ public class DocumentService {
documentDiscussionDao.selectTableDiscussionCount(projectId)
.stream()
.collect(Collectors.toMap(d -> d.getTableName(), d -> d.getCount(), (a, b) -> a));
Map<String, String> descriptionMapByTableName =
var descriptionMapByTableName =
documentDescriptionDao.selectTableDescriptionByProjectId(projectId)
.stream()
.collect(Collectors.toMap(d -> d.getTableName(), d -> d.getContent(), (a, b) -> a));
@@ -222,10 +228,70 @@ public class DocumentService {
discussionCountMapByTableName,
descriptionMapByTableName
);
return documentSimpleResponseConverter.of(document, tableMetas);
// if original version is not null mean version diff enabled
if (originalVersion != null) {
var originalDocument =
databaseDocumentDao.selectOptionalByProjectIdAndVersion(projectId, originalVersion)
.orElseThrow(DomainErrors.DOCUMENT_VERSION_IS_INVALID::exception);
var originalTables = tableDocumentDao.selectByDatabaseDocumentId(originalDocument.getId());
var originalTableMetas = documentSimpleResponseConverter.of(
originalTables,
discussionCountMapByTableName,
descriptionMapByTableName
);
var originalMap = originalTableMetas.stream()
.collect(Collectors.toMap(t -> t.getName(), Function.identity(), (a, b) -> a));
var currentMap = tableMetas.stream()
.collect(Collectors.toMap(t -> t.getName(), Function.identity(), (a, b) -> a));
List<TableDiffResult> diffResults = tableDiffs(projectId, originalVersion, version);
List<DatabaseDocumentSimpleResponse.TableData> result = new ArrayList<>();
for (TableDiffResult diffResult : diffResults) {
var cur = currentMap.get(diffResult.getId());
var org = originalMap.get(diffResult.getId());
if (diffResult.getDiffType() == DiffType.ADDED) {
cur.setDiffType(DiffType.ADDED);
result.add(cur);
} else if (diffResult.getDiffType() == DiffType.MODIFIED) {
cur.setDiffType(DiffType.MODIFIED);
cur.setOriginal(org);
result.add(cur);
} else if (diffResult.getDiffType() == DiffType.REMOVED) {
org.setDiffType(DiffType.REMOVED);
result.add(org);
} else {
cur.setDiffType(DiffType.NONE);
result.add(cur);
}
}
result.sort(Comparator.comparing(DatabaseDocumentSimpleResponse.TableData::getName));
DiffType diffType = result.stream()
.anyMatch(t -> t.getDiffType() == DiffType.MODIFIED) ? DiffType.MODIFIED : DiffType.NONE;
return documentSimpleResponseConverter.of(document, result, diffType);
} else {
tableMetas.sort(Comparator.comparing(DatabaseDocumentSimpleResponse.TableData::getName));
return documentSimpleResponseConverter.of(document, tableMetas, DiffType.NONE);
}
});
}
public List<TableDiffResult> tableDiffs(Integer projectId, Long originalVersion, Long currentVersion) {
var original = databaseDocumentDao.selectOptionalByProjectIdAndVersion(projectId, originalVersion)
.orElseThrow(DomainErrors.DOCUMENT_VERSION_IS_INVALID::exception);
DatabaseDocumentPojo current;
if (currentVersion == null) {
current = databaseDocumentDao.selectNotArchivedByProjectId(projectId)
.orElseThrow(DomainErrors.DOCUMENT_VERSION_IS_INVALID::exception);
} else {
current = databaseDocumentDao.selectOptionalByProjectIdAndVersion(projectId, currentVersion)
.orElseThrow(DomainErrors.DOCUMENT_VERSION_IS_INVALID::exception);
}
DatabaseMeta currMeta = retrieveOriginalDatabaseMeta(current);
DatabaseMeta originalMeta = retrieveOriginalDatabaseMeta(original);
return DocumentDiffs.tableDiff(originalMeta, currMeta);
}
public Optional<DatabaseDocumentResponse> getOneByProjectId(Integer projectId, Long version) {
Optional<DatabaseDocumentPojo> documentOption;
@@ -252,11 +318,11 @@ public class DocumentService {
var tableDocumentResponseList = tables.stream()
.map(table -> {
Integer tableId = table.getId();
var subColumns = columnsGroupByTableMetaId.getOrDefault(tableId, Collections.emptyList());
var subIndexes = indexesGroupByTableMetaId.getOrDefault(tableId, Collections.emptyList());
var subTriggers = triggersGroupByTableMetaId.getOrDefault(tableId, Collections.emptyList());
var subColumns = columnsGroupByTableMetaId.getOrDefault(tableId, emptyList());
var subIndexes = indexesGroupByTableMetaId.getOrDefault(tableId, emptyList());
var subTriggers = triggersGroupByTableMetaId.getOrDefault(tableId, emptyList());
var subForeignKeys =
foreignKeysGroupByTableMetaId.getOrDefault(tableId, Collections.emptyList());
foreignKeysGroupByTableMetaId.getOrDefault(tableId, emptyList());
return documentResponseConverter.of(
table,
subColumns,
@@ -284,10 +350,10 @@ public class DocumentService {
public List<TableDocumentResponse> getTableDetails(Integer projectId,
Integer databaseDocumentId,
List<Integer> tableIds) {
Collection<Integer> tableIds) {
// maybe deleted
if (CollectionUtils.isEmpty(tableIds) || !projectDao.existsById(projectId)) {
return Collections.emptyList();
return emptyList();
}
var tables =
tableDocumentDao.selectByDatabaseDocumentIdAndIdIn(databaseDocumentId, tableIds);
@@ -338,10 +404,10 @@ public class DocumentService {
return tables.stream()
.map(table -> {
Integer tableId = table.getId();
var subColumns = columnsGroupByTableMetaId.getOrDefault(tableId, Collections.emptyList());
var subIndexes = indexesGroupByTableMetaId.getOrDefault(tableId, Collections.emptyList());
var subForeignKeys = foreignKeysGroupByTableMetaId.getOrDefault(tableId, Collections.emptyList());
var subTriggers = triggersGroupByTableMetaId.getOrDefault(tableId, Collections.emptyList());
var subColumns = columnsGroupByTableMetaId.getOrDefault(tableId, emptyList());
var subIndexes = indexesGroupByTableMetaId.getOrDefault(tableId, emptyList());
var subForeignKeys = foreignKeysGroupByTableMetaId.getOrDefault(tableId, emptyList());
var subTriggers = triggersGroupByTableMetaId.getOrDefault(tableId, emptyList());
var discussionCount = discussionCountMapByJoinName.get(table.getName());
var description = descriptionMapByJoinName.get(table.getName());
var columnResponses = documentResponseConverter.of(
@@ -362,6 +428,87 @@ public class DocumentService {
.collect(Collectors.toList());
}
public List<TableDocumentResponse> getTableDetails(Integer projectId,
Integer databaseDocumentId,
TableDocumentRequest request) {
// maybe deleted
if (CollectionUtils.isEmpty(request.getTableIds()) || !projectDao.existsById(projectId)) {
return emptyList();
}
var current = this.getTableDetails(projectId, databaseDocumentId, request.getTableIds());
if (request.getOriginalVersion() != null) {
DatabaseDocumentPojo doc =
databaseDocumentDao.selectOptionalByProjectIdAndVersion(projectId, request.getOriginalVersion())
.orElseThrow(DomainErrors.DOCUMENT_VERSION_IS_INVALID::exception);
List<String> tableNames = current.stream().map(t -> t.getName()).distinct().collect(Collectors.toList());
List<Integer> originalTableIds =
tableDocumentDao.selectTableIdsByDatabaseDocumentIdAndTableNameIn(doc.getId(), tableNames);
var original = this.getTableDetails(projectId, doc.getId(), originalTableIds);
Map<String, TableDocumentResponse> currentMapByName = current.stream()
.collect(Collectors.toMap(TableDocumentResponse::getName, Function.identity(), (a, b) -> a));
Map<String, TableDocumentResponse> originalMapByName = original.stream()
.collect(Collectors.toMap(TableDocumentResponse::getName, Function.identity(), (a, b) -> a));
List<TableMeta> currentMeta = databaseMetaConverter.of(current);
List<TableMeta> originalMeta = databaseMetaConverter.of(original);
List<TableDiffResult> diffs = DocumentDiffs.tableDiff(originalMeta, currentMeta);
return diffs.stream()
.map(diff -> {
if (diff.getDiffType() == DiffType.ADDED) {
TableDocumentResponse c = currentMapByName.get(diff.getId());
c.setDiffType(DiffType.ADDED);
var cols =
diff(diff.getColumnDiffResults(), emptyList(), c.getColumns(), i -> i.getName());
c.setColumns(cols);
var indexes =
diff(diff.getIndexDiffResults(), emptyList(), c.getIndexes(), i -> i.getName());
c.setIndexes(indexes);
var foreignKeys = foreignKeyDiff(diff.getForeignKeyDiffResults(),
emptyList(), c.getForeignKeys());
c.setForeignKeys(foreignKeys);
var triggers =
diff(diff.getTriggerDiffResults(), emptyList(), c.getTriggers(), t -> t.getName());
c.setTriggers(triggers);
return c;
}
if (diff.getDiffType() == DiffType.REMOVED) {
TableDocumentResponse t = originalMapByName.get(diff.getId());
t.setDiffType(DiffType.REMOVED);
return t;
}
if (diff.getDiffType() == DiffType.MODIFIED) {
TableDocumentResponse c = currentMapByName.get(diff.getId());
TableDocumentResponse o = originalMapByName.get(diff.getId());
c.setDiffType(DiffType.MODIFIED);
c.setOriginal(o);
var cols =
diff(diff.getColumnDiffResults(), o.getColumns(), c.getColumns(),
col -> col.getName());
c.setColumns(cols);
var indexes =
diff(diff.getIndexDiffResults(), o.getIndexes(), c.getIndexes(), i -> i.getName());
c.setIndexes(indexes);
var foreignKeys = foreignKeyDiff(diff.getForeignKeyDiffResults(),
o.getForeignKeys(), c.getForeignKeys());
c.setForeignKeys(foreignKeys);
var triggers =
diff(diff.getTriggerDiffResults(), o.getTriggers(), c.getTriggers(),
t -> t.getName());
c.setTriggers(triggers);
return c;
}
TableDocumentResponse t = currentMapByName.get(diff.getId());
t.setDiffType(DiffType.NONE);
return t;
})
.sorted(Comparator.comparing(TableDocumentResponse::getName))
.collect(Collectors.toList());
} else {
current.sort(Comparator.comparing(TableDocumentResponse::getName));
return current;
}
}
public void export(Integer projectId,
Long version,
DocumentFileType type,
@@ -379,22 +526,6 @@ public class DocumentService {
});
}
public RootDiff diff(Integer projectId, Long originalVersion, Long currentVersion) {
var original = databaseDocumentDao.selectOptionalByProjectIdAndVersion(projectId, originalVersion)
.orElseThrow(DomainErrors.DOCUMENT_VERSION_IS_INVALID::exception);
DatabaseDocumentPojo current;
if (currentVersion == null) {
current = databaseDocumentDao.selectNotArchivedByProjectId(projectId)
.orElseThrow(DomainErrors.DOCUMENT_VERSION_IS_INVALID::exception);
} else {
current = databaseDocumentDao.selectOptionalByProjectIdAndVersion(projectId, currentVersion)
.orElseThrow(DomainErrors.DOCUMENT_VERSION_IS_INVALID::exception);
}
DatabaseMeta currMeta = retrieveOriginalDatabaseMeta(current);
DatabaseMeta originalMeta = retrieveOriginalDatabaseMeta(original);
return Diffs.diff(originalMeta, currMeta);
}
public List<TableResponse> getTableAndColumns(Integer projectId, Long version) {
Optional<DatabaseDocumentPojo> documentOption;
if (version == null) {
@@ -403,7 +534,7 @@ public class DocumentService {
documentOption = databaseDocumentDao.selectOptionalByProjectIdAndVersion(projectId, version);
}
if (documentOption.isEmpty()) {
return Collections.emptyList();
return emptyList();
} else {
DatabaseDocumentPojo databaseDoc = documentOption.get();
var tables = tableDocumentDao.selectByDatabaseDocumentId(databaseDoc.getId());
@@ -413,4 +544,46 @@ public class DocumentService {
return tableResponseConverter.from(tables, columnMapByTableId);
}
}
private <T extends DiffAble> List<T> diff(Collection<DiffResult> diffs,
Collection<T> original,
Collection<T> current,
Function<T, String> idMapping) {
var currentMapByName = current.stream()
.collect(Collectors.toMap(idMapping, Function.identity(), (a, b) -> a));
var originalMapByName = original.stream()
.collect(Collectors.toMap(idMapping, Function.identity(), (a, b) -> a));
return diffs.stream().map(diff -> {
if (diff.getDiffType() == DiffType.ADDED) {
var t = currentMapByName.get(diff.getId());
t.setDiffType(DiffType.ADDED);
return t;
}
if (diff.getDiffType() == DiffType.REMOVED) {
var t = originalMapByName.get(diff.getId());
t.setDiffType(DiffType.REMOVED);
return t;
}
if (diff.getDiffType() == DiffType.MODIFIED) {
var c = currentMapByName.get(diff.getId());
var o = originalMapByName.get(diff.getId());
c.setDiffType(DiffType.MODIFIED);
c.setOriginal(o);
return c;
}
var t = currentMapByName.get(diff.getId());
t.setDiffType(DiffType.NONE);
return t;
})
.collect(Collectors.toList());
}
private List<ForeignKeyDocumentResponse> foreignKeyDiff(Collection<DiffResult> diffs,
Collection<ForeignKeyDocumentResponse> original,
Collection<ForeignKeyDocumentResponse> current) {
Function<ForeignKeyDocumentResponse, String> idMapping = fk -> {
return fk.getFkTableName() + "." + fk.getFkColumnName() + "." + fk.getKeySeq();
};
return diff(diffs, original, current, idMapping);
}
}

View File

@@ -61,7 +61,7 @@ public class SystemStartedEventSubscriber {
DocumentTemplatePropertyPojo pojo = new DocumentTemplatePropertyPojo();
pojo.setType(type);
pojo.setKey(key);
pojo.setDefaultValue(fieldChineseMap.get(key));
pojo.setDefaultValue(fieldChineseMap.getOrDefault(key, def));
return pojo;
};
// table field name;