mirror of
https://github.com/vran-dev/databasir.git
synced 2025-08-08 17:32:14 +08:00
support mock data (#67)
* feat:support generate mock sql * feat: update frontend resources * feat: update readme * fix: check failed
This commit is contained in:
@@ -29,6 +29,7 @@ dependencies {
|
||||
// others
|
||||
implementation 'com.auth0:java-jwt:3.18.3'
|
||||
implementation 'org.commonmark:commonmark:0.18.1'
|
||||
implementation 'com.github.javafaker:javafaker:1.0.2'
|
||||
implementation 'com.alibaba:easyexcel'
|
||||
implementation "org.freemarker:freemarker"
|
||||
|
||||
|
@@ -34,6 +34,14 @@ public enum DomainErrors implements DatabasirErrors {
|
||||
INVALID_DATABASE_TYPE_URL_PATTERN("A_10019", "不合法的 url pattern"),
|
||||
DOCUMENT_VERSION_IS_INVALID("A_10020", "文档版本不合法"),
|
||||
CANNOT_UPDATE_SELF_ENABLED_STATUS("A_10021", "无法对自己执行启用禁用操作"),
|
||||
MOCK_DATA_SCRIPT_MUST_NOT_BE_BLANK("A_10022", "脚本内容不能为空"),
|
||||
TABLE_META_NOT_FOUND("A_10023", "不存在的数据库表"),
|
||||
DEPENDENT_COLUMN_NAME_MUST_NOT_BE_BLANK("A_10024", "必须指定依赖的字段"),
|
||||
DEPENDENT_REF_MUST_NOT_BE_BLANK("A_10025", "请选择关联表和字段"),
|
||||
MUST_NOT_REF_SELF("A_10026", "不能引用自身"),
|
||||
CIRCLE_REFERENCE("A_10027", "检查到循环引用"),
|
||||
DUPLICATE_COLUMN("A_10028", "重复的列"),
|
||||
INVALID_MOCK_DATA_SCRIPT("A_10029", "不合法的表达式"),
|
||||
;
|
||||
|
||||
private final String errCode;
|
||||
|
@@ -0,0 +1,25 @@
|
||||
package com.databasir.core.domain.document.converter;
|
||||
|
||||
import com.databasir.core.domain.document.data.TableResponse;
|
||||
import com.databasir.dao.tables.pojos.TableColumnDocumentPojo;
|
||||
import com.databasir.dao.tables.pojos.TableDocumentPojo;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface TableResponseConverter {
|
||||
|
||||
default List<TableResponse> from(List<TableDocumentPojo> tables,
|
||||
Map<Integer, List<TableColumnDocumentPojo>> columnMapByTableId) {
|
||||
return tables.stream()
|
||||
.map(table -> from(table, columnMapByTableId.get(table.getId())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
TableResponse from(TableDocumentPojo table, List<TableColumnDocumentPojo> columns);
|
||||
|
||||
TableResponse.ColumnResponse from(TableColumnDocumentPojo column);
|
||||
}
|
@@ -16,12 +16,16 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
public class DocumentTemplatePropertiesResponse {
|
||||
|
||||
@Builder.Default
|
||||
private List<DocumentTemplatePropertyResponse> columnFieldNameProperties = Collections.emptyList();
|
||||
|
||||
@Builder.Default
|
||||
private List<DocumentTemplatePropertyResponse> indexFieldNameProperties = Collections.emptyList();
|
||||
|
||||
@Builder.Default
|
||||
private List<DocumentTemplatePropertyResponse> triggerFieldNameProperties = Collections.emptyList();
|
||||
|
||||
@Builder.Default
|
||||
private List<DocumentTemplatePropertyResponse> foreignKeyFieldNameProperties = Collections.emptyList();
|
||||
|
||||
@Data
|
||||
|
@@ -0,0 +1,27 @@
|
||||
package com.databasir.core.domain.document.data;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class TableResponse {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
private List<ColumnResponse> columns = Collections.emptyList();
|
||||
|
||||
@Data
|
||||
public static class ColumnResponse {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String type;
|
||||
|
||||
}
|
||||
}
|
@@ -6,14 +6,8 @@ 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.converter.DatabaseMetaConverter;
|
||||
import com.databasir.core.domain.document.converter.DocumentPojoConverter;
|
||||
import com.databasir.core.domain.document.converter.DocumentResponseConverter;
|
||||
import com.databasir.core.domain.document.converter.DocumentSimpleResponseConverter;
|
||||
import com.databasir.core.domain.document.data.DatabaseDocumentResponse;
|
||||
import com.databasir.core.domain.document.data.DatabaseDocumentSimpleResponse;
|
||||
import com.databasir.core.domain.document.data.DatabaseDocumentVersionResponse;
|
||||
import com.databasir.core.domain.document.data.TableDocumentResponse;
|
||||
import com.databasir.core.domain.document.converter.*;
|
||||
import com.databasir.core.domain.document.data.*;
|
||||
import com.databasir.core.domain.document.event.DocumentUpdated;
|
||||
import com.databasir.core.domain.document.generator.DocumentFileGenerator;
|
||||
import com.databasir.core.domain.document.generator.DocumentFileType;
|
||||
@@ -82,6 +76,8 @@ public class DocumentService {
|
||||
|
||||
private final DatabaseMetaConverter databaseMetaConverter;
|
||||
|
||||
private final TableResponseConverter tableResponseConverter;
|
||||
|
||||
private final JsonConverter jsonConverter;
|
||||
|
||||
private final List<DocumentFileGenerator> documentFileGenerators;
|
||||
@@ -373,4 +369,23 @@ public class DocumentService {
|
||||
DatabaseMeta originalMeta = retrieveOriginalDatabaseMeta(original);
|
||||
return Diffs.diff(originalMeta, currMeta);
|
||||
}
|
||||
|
||||
public List<TableResponse> getTableAndColumns(Integer projectId, Long version) {
|
||||
Optional<DatabaseDocumentPojo> documentOption;
|
||||
if (version == null) {
|
||||
documentOption = databaseDocumentDao.selectNotArchivedByProjectId(projectId);
|
||||
} else {
|
||||
documentOption = databaseDocumentDao.selectOptionalByProjectIdAndVersion(projectId, version);
|
||||
}
|
||||
if (documentOption.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
DatabaseDocumentPojo databaseDoc = documentOption.get();
|
||||
var tables = tableDocumentDao.selectByDatabaseDocumentId(databaseDoc.getId());
|
||||
var columns = tableColumnDocumentDao.selectByDatabaseDocumentId(databaseDoc.getId());
|
||||
var columnMapByTableId = columns.stream()
|
||||
.collect(Collectors.groupingBy(TableColumnDocumentPojo::getTableDocumentId));
|
||||
return tableResponseConverter.from(tables, columnMapByTableId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,96 @@
|
||||
package com.databasir.core.domain.mock;
|
||||
|
||||
import com.databasir.core.domain.mock.converter.MockDataRulePojoConverter;
|
||||
import com.databasir.core.domain.mock.converter.MockDataRuleResponseConverter;
|
||||
import com.databasir.core.domain.mock.data.ColumnMockRuleSaveRequest;
|
||||
import com.databasir.core.domain.mock.data.MockDataGenerateCondition;
|
||||
import com.databasir.core.domain.mock.data.MockDataRuleListCondition;
|
||||
import com.databasir.core.domain.mock.data.MockDataRuleResponse;
|
||||
import com.databasir.core.domain.mock.generator.MockDataGenerator;
|
||||
import com.databasir.core.domain.mock.validator.MockDataSaveValidator;
|
||||
import com.databasir.core.domain.mock.validator.MockDataValidator;
|
||||
import com.databasir.dao.enums.MockDataType;
|
||||
import com.databasir.dao.impl.MockDataRuleDao;
|
||||
import com.databasir.dao.impl.TableColumnDocumentDao;
|
||||
import com.databasir.dao.tables.pojos.DatabaseDocumentPojo;
|
||||
import com.databasir.dao.tables.pojos.MockDataRulePojo;
|
||||
import com.databasir.dao.tables.pojos.TableColumnDocumentPojo;
|
||||
import com.databasir.dao.tables.pojos.TableDocumentPojo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MockDataService {
|
||||
|
||||
private final MockDataGenerator mockDataGenerator;
|
||||
|
||||
private final MockDataRuleDao mockDataRuleDao;
|
||||
|
||||
private final TableColumnDocumentDao tableColumnDocumentDao;
|
||||
|
||||
private final MockDataRulePojoConverter mockDataRulePojoConverter;
|
||||
|
||||
private final MockDataRuleResponseConverter mockDataRuleResponseConverter;
|
||||
|
||||
private final MockDataSaveValidator mockDataSaveValidator;
|
||||
|
||||
private final MockDataValidator mockDataValidator;
|
||||
|
||||
public String generateMockInsertSql(Integer projectId, MockDataGenerateCondition condition) {
|
||||
mockDataValidator.validProject(projectId);
|
||||
DatabaseDocumentPojo databaseDoc =
|
||||
mockDataValidator.validAndGetDatabaseDocumentPojo(projectId, condition.getVersion());
|
||||
TableDocumentPojo tableDoc =
|
||||
mockDataValidator.validAndGetTableDocumentPojo(databaseDoc.getId(), condition.getTableId());
|
||||
return mockDataGenerator.createInsertSql(projectId, databaseDoc.getId(), tableDoc.getName());
|
||||
}
|
||||
|
||||
public void saveMockRules(Integer projectId,
|
||||
Integer tableId,
|
||||
List<ColumnMockRuleSaveRequest> rules) {
|
||||
mockDataValidator.validProject(projectId);
|
||||
DatabaseDocumentPojo doc =
|
||||
mockDataValidator.validAndGetDatabaseDocumentPojo(projectId, null);
|
||||
TableDocumentPojo tableDoc =
|
||||
mockDataValidator.validAndGetTableDocumentPojo(doc.getId(), tableId);
|
||||
List<String> columnNames = rules.stream()
|
||||
.map(ColumnMockRuleSaveRequest::getColumnName)
|
||||
.collect(Collectors.toList());
|
||||
mockDataSaveValidator.validTableColumn(tableDoc.getId(), columnNames);
|
||||
mockDataSaveValidator.validScriptMockType(rules);
|
||||
mockDataSaveValidator.validRefMockType(doc.getId(), rules);
|
||||
// verify
|
||||
mockDataGenerator.createInsertSql(projectId, doc.getId(), tableDoc.getName());
|
||||
|
||||
List<MockDataRulePojo> pojo = mockDataRulePojoConverter.from(projectId, rules);
|
||||
mockDataRuleDao.batchSave(pojo);
|
||||
}
|
||||
|
||||
public List<MockDataRuleResponse> listRules(Integer projectId, MockDataRuleListCondition condition) {
|
||||
mockDataValidator.validProject(projectId);
|
||||
DatabaseDocumentPojo databaseDoc =
|
||||
mockDataValidator.validAndGetDatabaseDocumentPojo(projectId, condition.getVersion());
|
||||
TableDocumentPojo tableDoc =
|
||||
mockDataValidator.validAndGetTableDocumentPojo(databaseDoc.getId(), condition.getTableId());
|
||||
List<TableColumnDocumentPojo> columns =
|
||||
tableColumnDocumentDao.selectByTableDocumentId(condition.getTableId());
|
||||
var ruleMapByColumnName = mockDataRuleDao.selectByProjectIdAndTableName(projectId, tableDoc.getName())
|
||||
.stream()
|
||||
.collect(Collectors.toMap(MockDataRulePojo::getColumnName, Function.identity()));
|
||||
return columns.stream()
|
||||
.map(col -> {
|
||||
if (ruleMapByColumnName.containsKey(col.getName())) {
|
||||
return mockDataRuleResponseConverter.from(ruleMapByColumnName.get(col.getName()), col);
|
||||
} else {
|
||||
return mockDataRuleResponseConverter.from(tableDoc.getName(), MockDataType.AUTO, col);
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package com.databasir.core.domain.mock.converter;
|
||||
|
||||
import com.databasir.core.domain.mock.data.ColumnMockRuleSaveRequest;
|
||||
import com.databasir.dao.tables.pojos.MockDataRulePojo;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface MockDataRulePojoConverter {
|
||||
|
||||
MockDataRulePojo from(Integer projectId, ColumnMockRuleSaveRequest request);
|
||||
|
||||
default List<MockDataRulePojo> from(Integer projectId, List<ColumnMockRuleSaveRequest> request) {
|
||||
return request.stream()
|
||||
.map(rule -> from(projectId, rule))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package com.databasir.core.domain.mock.converter;
|
||||
|
||||
import com.databasir.core.domain.mock.data.MockDataRuleResponse;
|
||||
import com.databasir.dao.enums.MockDataType;
|
||||
import com.databasir.dao.tables.pojos.MockDataRulePojo;
|
||||
import com.databasir.dao.tables.pojos.TableColumnDocumentPojo;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
|
||||
@Mapper(componentModel = "spring")
|
||||
public interface MockDataRuleResponseConverter {
|
||||
|
||||
@Mapping(target = "columnType", source = "column.type")
|
||||
MockDataRuleResponse from(MockDataRulePojo pojo, TableColumnDocumentPojo column);
|
||||
|
||||
@Mapping(target = "columnName", source = "pojo.name")
|
||||
@Mapping(target = "columnType", source = "pojo.type")
|
||||
MockDataRuleResponse from(String tableName, MockDataType mockDataType, TableColumnDocumentPojo pojo);
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
package com.databasir.core.domain.mock.data;
|
||||
|
||||
import com.databasir.dao.enums.MockDataType;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
public class ColumnMockRuleSaveRequest {
|
||||
|
||||
@NotBlank
|
||||
private String tableName;
|
||||
|
||||
@NotBlank
|
||||
private String columnName;
|
||||
|
||||
private String dependentTableName;
|
||||
|
||||
private String dependentColumnName;
|
||||
|
||||
@NotNull
|
||||
private MockDataType mockDataType;
|
||||
|
||||
private String mockDataScript;
|
||||
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
package com.databasir.core.domain.mock.data;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class MockDataGenerateCondition {
|
||||
|
||||
private Long version;
|
||||
|
||||
private Integer tableId;
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
package com.databasir.core.domain.mock.data;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class MockDataRuleListCondition {
|
||||
|
||||
private Long version;
|
||||
|
||||
private Integer tableId;
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package com.databasir.core.domain.mock.data;
|
||||
|
||||
import com.databasir.dao.enums.MockDataType;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class MockDataRuleResponse {
|
||||
|
||||
private String tableName;
|
||||
|
||||
private String columnName;
|
||||
|
||||
private String columnType;
|
||||
|
||||
private String dependentTableName;
|
||||
|
||||
private String dependentColumnName;
|
||||
|
||||
private MockDataType mockDataType;
|
||||
|
||||
private String mockDataScript;
|
||||
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
package com.databasir.core.domain.mock.factory;
|
||||
|
||||
import com.databasir.dao.enums.MockDataType;
|
||||
import com.databasir.dao.impl.TableColumnDocumentDao;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
@Order
|
||||
@RequiredArgsConstructor
|
||||
public class AutoMockDataFactory implements MockDataFactory {
|
||||
|
||||
private final TableColumnDocumentDao tableColumnDocumentDao;
|
||||
|
||||
public static final Map<Integer, String> DATA_TYPE_VALUE_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
DATA_TYPE_VALUE_MAP.put(9999, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.BIT, "1");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.TINYINT, "1");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.SMALLINT, "1");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.INTEGER, "1");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.BIGINT, "1");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.FLOAT, "1.1");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.REAL, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.DOUBLE, "1.2");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.NUMERIC, "1");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.DECIMAL, "1.1");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.CHAR, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.VARCHAR, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.LONGVARCHAR, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.DATE, "'1970-12-31'");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.TIME, "'00:00:00'");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.TIMESTAMP, "'2001-01-01 00:00:00'");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.BINARY, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.VARBINARY, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.LONGVARBINARY, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.NULL, "null");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.OTHER, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.JAVA_OBJECT, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.DISTINCT, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.STRUCT, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.ARRAY, "'{}'");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.BLOB, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.CLOB, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.REF, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.DATALINK, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.BOOLEAN, "true");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.ROWID, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.NCHAR, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.NVARCHAR, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.LONGNVARCHAR, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.NCLOB, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.SQLXML, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.REF_CURSOR, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.TIME_WITH_TIMEZONE, "''");
|
||||
DATA_TYPE_VALUE_MAP.put(Types.TIMESTAMP_WITH_TIMEZONE, "''");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(MockColumnRule rule) {
|
||||
return rule == null || rule.getMockDataType() == MockDataType.AUTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String create(MockColumnRule rule) {
|
||||
return DATA_TYPE_VALUE_MAP.getOrDefault(rule.getDataType(), "''");
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
package com.databasir.core.domain.mock.factory;
|
||||
|
||||
import com.databasir.dao.enums.MockDataType;
|
||||
import com.github.javafaker.Faker;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.StringJoiner;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
@Order(0)
|
||||
public class FakerMockDataFactory implements MockDataFactory {
|
||||
|
||||
@Override
|
||||
public boolean accept(MockColumnRule rule) {
|
||||
return MockDataType.fakerTypes().contains(rule.getMockDataType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String create(MockColumnRule rule) {
|
||||
Faker faker = new Faker();
|
||||
StringJoiner joiner = new StringJoiner("", "'", "'");
|
||||
switch (rule.getMockDataType()) {
|
||||
case FULL_NAME:
|
||||
joiner.add(faker.name().username());
|
||||
return joiner.toString();
|
||||
case PHONE:
|
||||
joiner.add(faker.phoneNumber().cellPhone());
|
||||
return joiner.toString();
|
||||
case FULL_ADDRESS:
|
||||
joiner.add(faker.address().fullAddress());
|
||||
return joiner.toString();
|
||||
case AVATAR_URL:
|
||||
joiner.add(faker.avatar().image());
|
||||
return joiner.toString();
|
||||
case UUID:
|
||||
joiner.add(UUID.randomUUID().toString());
|
||||
return joiner.toString();
|
||||
case EMAIL:
|
||||
joiner.add(faker.name().username() + "@generated" + UUID.randomUUID().toString()
|
||||
.replace("-", "").toString());
|
||||
return joiner.toString();
|
||||
default:
|
||||
return "''";
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
package com.databasir.core.domain.mock.factory;
|
||||
|
||||
import com.databasir.dao.enums.MockDataType;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class MockColumnRule {
|
||||
|
||||
private String tableName;
|
||||
|
||||
private String columnName;
|
||||
|
||||
private String columnType;
|
||||
|
||||
private Integer dataType;
|
||||
|
||||
private MockDataType mockDataType;
|
||||
|
||||
private String mockDataScript;
|
||||
|
||||
public static MockColumnRule auto(String tableName, String columnName) {
|
||||
return MockColumnRule.builder()
|
||||
.tableName(tableName)
|
||||
.columnName(columnName)
|
||||
.mockDataType(MockDataType.AUTO)
|
||||
.build();
|
||||
}
|
||||
|
||||
public Optional<String> getMockDataScript() {
|
||||
return Optional.ofNullable(mockDataScript);
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
package com.databasir.core.domain.mock.factory;
|
||||
|
||||
public interface MockDataFactory {
|
||||
|
||||
boolean accept(MockColumnRule rule);
|
||||
|
||||
String create(MockColumnRule rule);
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package com.databasir.core.domain.mock.factory;
|
||||
|
||||
import com.databasir.core.domain.mock.script.MockScriptEvaluator;
|
||||
import com.databasir.dao.enums.MockDataType;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Order(0)
|
||||
@RequiredArgsConstructor
|
||||
public class ScriptMockDataFactory implements MockDataFactory {
|
||||
|
||||
private final MockScriptEvaluator mockScriptEvaluator;
|
||||
|
||||
@Override
|
||||
public boolean accept(MockColumnRule rule) {
|
||||
return rule.getMockDataType() == MockDataType.SCRIPT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String create(MockColumnRule rule) {
|
||||
return mockScriptEvaluator.evaluate(rule.getMockDataScript().get(), new MockScriptEvaluator.ScriptContext());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
package com.databasir.core.domain.mock.generator;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class ColumnMockData {
|
||||
|
||||
private String columnName;
|
||||
|
||||
private String columnType;
|
||||
|
||||
private String mockData;
|
||||
|
||||
}
|
@@ -0,0 +1,173 @@
|
||||
package com.databasir.core.domain.mock.generator;
|
||||
|
||||
import com.databasir.core.domain.DomainErrors;
|
||||
import com.databasir.dao.exception.DataNotExistsException;
|
||||
import com.databasir.dao.tables.pojos.MockDataRulePojo;
|
||||
import com.databasir.dao.tables.pojos.TableColumnDocumentPojo;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class MockDataContext {
|
||||
|
||||
private Integer projectId;
|
||||
|
||||
private Integer databaseDocumentId;
|
||||
|
||||
@Builder.Default
|
||||
private Map<String, TableMockData> tableMockDataMap = new LinkedHashMap<>();
|
||||
|
||||
@Builder.Default
|
||||
private Map<String, Set<String>> fromReference = new LinkedHashMap<>();
|
||||
|
||||
@Builder.Default
|
||||
private Map<String, Set<String>> toReference = new LinkedHashMap<>();
|
||||
|
||||
@Builder.Default
|
||||
private Map<String, Map<String, MockDataRulePojo>> ruleMap = new LinkedHashMap<>(16);
|
||||
|
||||
@Builder.Default
|
||||
private Map<String, Map<String, TableColumnDocumentPojo>> tableColumnMap = new LinkedHashMap<>(16);
|
||||
|
||||
@Builder.Default
|
||||
private Map<String, Set<String>> mockInProgress = new HashMap<>();
|
||||
|
||||
public void addTableMockRules(String tableName, List<MockDataRulePojo> rules) {
|
||||
var columnRuleMap = rules.stream()
|
||||
.collect(Collectors.toMap(MockDataRulePojo::getColumnName, Function.identity()));
|
||||
this.ruleMap.put(tableName, columnRuleMap);
|
||||
}
|
||||
|
||||
public boolean containMockRule(String tableName) {
|
||||
return ruleMap.containsKey(tableName);
|
||||
}
|
||||
|
||||
public boolean containMockRule(String tableName, String columnName) {
|
||||
if (!ruleMap.containsKey(tableName)) {
|
||||
return false;
|
||||
}
|
||||
return ruleMap.get(tableName).containsKey(columnName);
|
||||
}
|
||||
|
||||
public Optional<MockDataRulePojo> getMockRule(String tableName, String columnName) {
|
||||
if (!ruleMap.containsKey(tableName)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.ofNullable(ruleMap.get(tableName).get(columnName));
|
||||
}
|
||||
|
||||
public void addTableColumns(String tableName, List<TableColumnDocumentPojo> columns) {
|
||||
Map<String, TableColumnDocumentPojo> columnMap = new LinkedHashMap<>();
|
||||
for (TableColumnDocumentPojo column : columns) {
|
||||
columnMap.put(column.getName(), column);
|
||||
}
|
||||
this.tableColumnMap.put(tableName, columnMap);
|
||||
}
|
||||
|
||||
public boolean containsTable(String tableName) {
|
||||
return tableColumnMap.containsKey(tableName);
|
||||
}
|
||||
|
||||
public boolean containsTableColumn(String tableName, String columnName) {
|
||||
if (!tableColumnMap.containsKey(tableName)) {
|
||||
return false;
|
||||
}
|
||||
return tableColumnMap.get(tableName).containsKey(columnName);
|
||||
}
|
||||
|
||||
public TableColumnDocumentPojo getTableColumn(String tableName, String columnName) {
|
||||
if (!tableColumnMap.containsKey(tableName)) {
|
||||
return null;
|
||||
}
|
||||
return tableColumnMap.get(tableName).get(columnName);
|
||||
}
|
||||
|
||||
public boolean containsTableMockData(String tableName) {
|
||||
return tableMockDataMap.containsKey(tableName);
|
||||
}
|
||||
|
||||
public boolean containsColumnMockData(String tableName, String columName) {
|
||||
return tableMockDataMap.containsKey(tableName) && tableMockDataMap.get(tableName).containsColumn(columName);
|
||||
}
|
||||
|
||||
public void addTableMockData(TableMockData tableMockData) {
|
||||
this.tableMockDataMap.put(tableMockData.getTableName(), tableMockData);
|
||||
}
|
||||
|
||||
public TableMockData getTableMockData(String tableName) {
|
||||
return this.tableMockDataMap.get(tableName);
|
||||
}
|
||||
|
||||
public void addColumnMockData(String tableName, ColumnMockData columnMockData) {
|
||||
TableMockData mock =
|
||||
tableMockDataMap.computeIfAbsent(tableName, key -> TableMockData.of(tableName, new ArrayList<>()));
|
||||
mock.addColumnIfNotExists(columnMockData);
|
||||
// sort to last
|
||||
tableMockDataMap.remove(tableName);
|
||||
tableMockDataMap.put(tableName, mock);
|
||||
}
|
||||
|
||||
public String getRawColumnMockData(String tableName, String columnName) {
|
||||
if (!this.containsTableMockData(tableName)) {
|
||||
throw new DataNotExistsException("can't find table mock data by " + tableName);
|
||||
}
|
||||
return getTableMockData(tableName)
|
||||
.getColumnMockData()
|
||||
.stream()
|
||||
.filter(t -> t.getColumnName().equals(columnName))
|
||||
.findFirst()
|
||||
.map(ColumnMockData::getMockData)
|
||||
.orElseThrow(DataNotExistsException::new);
|
||||
}
|
||||
|
||||
public boolean isMockInProgress(String tableName, String columnName) {
|
||||
return this.mockInProgress.containsKey(tableName) && this.mockInProgress.get(tableName).contains(columnName);
|
||||
}
|
||||
|
||||
public void addMockInProgress(String tableName, String columnName) {
|
||||
Set<String> inProgress = this.mockInProgress.computeIfAbsent(tableName, key -> new HashSet<>());
|
||||
inProgress.add(columnName);
|
||||
}
|
||||
|
||||
public void removeMockInProgress(String tableName, String columnName) {
|
||||
Set<String> inProgress = this.mockInProgress.computeIfAbsent(tableName, key -> new HashSet<>());
|
||||
inProgress.remove(columnName);
|
||||
}
|
||||
|
||||
public String toInsertSql() {
|
||||
return tableMockDataMap.entrySet()
|
||||
.stream()
|
||||
.map(entry -> {
|
||||
String tableName = entry.getKey();
|
||||
List<ColumnMockData> columns = entry.getValue().getColumnMockData();
|
||||
String format = "insert into %s (%s)\nvalues\n(%s);";
|
||||
String columnNames = columns.stream()
|
||||
.map(c -> "" + c.getColumnName() + "")
|
||||
.collect(Collectors.joining(", "));
|
||||
String columnValues = columns.stream()
|
||||
.map(ColumnMockData::getMockData)
|
||||
.collect(Collectors.joining(", "));
|
||||
return String.format(format, tableName, columnNames, columnValues);
|
||||
})
|
||||
.collect(Collectors.joining("\n\n"));
|
||||
}
|
||||
|
||||
public void saveReference(String fromTable, String fromColumn, String toTable, String toColumn) {
|
||||
if (toReference.containsKey(fromTable) && toReference.get(fromTable).contains(fromColumn)) {
|
||||
if (fromReference.containsKey(toTable) && fromReference.get(toTable).contains(toColumn)) {
|
||||
String format = "%s 和 %s 出现了循环引用";
|
||||
String message = String.format(format, fromTable + "." + fromColumn, toTable + "." + toColumn);
|
||||
throw DomainErrors.CIRCLE_REFERENCE.exception(message);
|
||||
}
|
||||
}
|
||||
Set<String> fromColumns = this.fromReference.computeIfAbsent(fromTable, key -> new HashSet<>());
|
||||
fromColumns.add(fromColumn);
|
||||
Set<String> toColumns = this.toReference.computeIfAbsent(toTable, key -> new HashSet<>());
|
||||
toColumns.add(toColumn);
|
||||
}
|
||||
}
|
@@ -0,0 +1,129 @@
|
||||
package com.databasir.core.domain.mock.generator;
|
||||
|
||||
import com.databasir.core.domain.DomainErrors;
|
||||
import com.databasir.core.domain.mock.factory.MockColumnRule;
|
||||
import com.databasir.core.domain.mock.factory.MockDataFactory;
|
||||
import com.databasir.dao.enums.MockDataType;
|
||||
import com.databasir.dao.impl.MockDataRuleDao;
|
||||
import com.databasir.dao.impl.ProjectDao;
|
||||
import com.databasir.dao.impl.TableColumnDocumentDao;
|
||||
import com.databasir.dao.impl.TableDocumentDao;
|
||||
import com.databasir.dao.tables.pojos.MockDataRulePojo;
|
||||
import com.databasir.dao.tables.pojos.TableColumnDocumentPojo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class MockDataGenerator {
|
||||
|
||||
private final List<MockDataFactory> mockDataFactories;
|
||||
|
||||
private final MockDataRuleDao mockDataRuleDao;
|
||||
|
||||
private final TableDocumentDao tableDocumentDao;
|
||||
|
||||
private final TableColumnDocumentDao tableColumnDocumentDao;
|
||||
|
||||
private final ProjectDao projectDao;
|
||||
|
||||
public String createInsertSql(Integer projectId,
|
||||
Integer databaseDocId,
|
||||
String tableName) {
|
||||
if (!projectDao.existsById(projectId)) {
|
||||
throw DomainErrors.PROJECT_NOT_FOUND.exception();
|
||||
}
|
||||
MockDataContext context = MockDataContext.builder()
|
||||
.databaseDocumentId(databaseDocId)
|
||||
.projectId(projectId)
|
||||
.build();
|
||||
create(context, tableName);
|
||||
return context.toInsertSql();
|
||||
}
|
||||
|
||||
private void create(MockDataContext context, String tableName) {
|
||||
if (!context.containsTable(tableName)) {
|
||||
var tableOption =
|
||||
tableDocumentDao.selectByDatabaseDocumentIdAndTableName(context.getDatabaseDocumentId(), tableName);
|
||||
if (tableOption.isEmpty()) {
|
||||
log.warn("can not find table => " + tableName);
|
||||
return;
|
||||
}
|
||||
var table = tableOption.get();
|
||||
var columns = tableColumnDocumentDao.selectByTableDocumentId(table.getId());
|
||||
context.addTableColumns(tableName, columns);
|
||||
}
|
||||
if (!context.containMockRule(tableName)) {
|
||||
var columnRules = mockDataRuleDao.selectByProjectIdAndTableName(context.getProjectId(), tableName);
|
||||
context.addTableMockRules(tableName, columnRules);
|
||||
}
|
||||
|
||||
for (TableColumnDocumentPojo column : context.getTableColumnMap().get(tableName).values()) {
|
||||
if (context.containsColumnMockData(tableName, column.getName())
|
||||
|| context.isMockInProgress(tableName, column.getName())) {
|
||||
continue;
|
||||
}
|
||||
create(context, tableName, column.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private void create(MockDataContext context, String tableName, String columnName) {
|
||||
if (context.containsColumnMockData(tableName, columnName)) {
|
||||
return;
|
||||
}
|
||||
TableColumnDocumentPojo column = context.getTableColumn(tableName, columnName);
|
||||
Optional<MockDataRulePojo> ruleOption = context.getMockRule(tableName, columnName);
|
||||
String rawData;
|
||||
if (ruleOption.isPresent()) {
|
||||
MockDataRulePojo rule = ruleOption.get();
|
||||
if (rule.getMockDataType() == MockDataType.REF) {
|
||||
context.addMockInProgress(tableName, columnName);
|
||||
context.saveReference(
|
||||
rule.getTableName(), rule.getColumnName(),
|
||||
rule.getDependentTableName(), rule.getDependentColumnName()
|
||||
);
|
||||
if (context.containsTable(rule.getDependentTableName())) {
|
||||
create(context, rule.getDependentTableName(), rule.getDependentColumnName());
|
||||
} else {
|
||||
create(context, rule.getDependentTableName());
|
||||
}
|
||||
context.removeMockInProgress(tableName, columnName);
|
||||
rawData = context.getRawColumnMockData(rule.getDependentTableName(), rule.getDependentColumnName());
|
||||
} else {
|
||||
rawData = createByFactory(column, rule);
|
||||
}
|
||||
} else {
|
||||
rawData = createByFactory(column, null);
|
||||
}
|
||||
context.addColumnMockData(tableName, toData(rawData, column));
|
||||
}
|
||||
|
||||
private String createByFactory(TableColumnDocumentPojo column, MockDataRulePojo rule) {
|
||||
MockDataType mockType = rule == null ? MockDataType.AUTO : rule.getMockDataType();
|
||||
MockColumnRule colRule = MockColumnRule.builder()
|
||||
.dataType(column.getDataType())
|
||||
.mockDataType(mockType)
|
||||
.mockDataScript(null == rule ? null : rule.getMockDataScript())
|
||||
.columnName(column.getName())
|
||||
.columnType(column.getType())
|
||||
.build();
|
||||
return mockDataFactories.stream()
|
||||
.filter(factory -> factory.accept(colRule))
|
||||
.findFirst()
|
||||
.map(factory -> factory.create(colRule))
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
private ColumnMockData toData(String data, TableColumnDocumentPojo column) {
|
||||
return ColumnMockData.builder()
|
||||
.columnName(column.getName())
|
||||
.columnType(column.getType())
|
||||
.mockData(data)
|
||||
.build();
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package com.databasir.core.domain.mock.generator;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class TableMockData {
|
||||
|
||||
private String tableName;
|
||||
|
||||
private List<ColumnMockData> columnMockData;
|
||||
|
||||
public static TableMockData of(String tableName, List<ColumnMockData> columnMockData) {
|
||||
return new TableMockData(tableName, columnMockData);
|
||||
}
|
||||
|
||||
public void addColumnIfNotExists(ColumnMockData data) {
|
||||
boolean present = columnMockData.stream()
|
||||
.anyMatch(col -> Objects.equals(col.getColumnName(), data.getColumnName()));
|
||||
if (present) {
|
||||
return;
|
||||
}
|
||||
this.columnMockData.add(data);
|
||||
}
|
||||
|
||||
public boolean containsColumn(String columnName) {
|
||||
return columnMockData.stream()
|
||||
.anyMatch(col -> Objects.equals(col.getColumnName(), columnName));
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
package com.databasir.core.domain.mock.script;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
public interface MockScriptEvaluator {
|
||||
|
||||
String evaluate(String script, ScriptContext context);
|
||||
|
||||
@Data
|
||||
class ScriptContext {
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package com.databasir.core.domain.mock.script;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class SpelScriptEvaluator implements MockScriptEvaluator {
|
||||
|
||||
private final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
|
||||
|
||||
@Override
|
||||
public String evaluate(String script, ScriptContext context) {
|
||||
Expression expression = spelExpressionParser.parseExpression(script);
|
||||
StandardEvaluationContext spelContext = new StandardEvaluationContext(context);
|
||||
return expression.getValue(spelContext, String.class);
|
||||
}
|
||||
}
|
@@ -0,0 +1,127 @@
|
||||
package com.databasir.core.domain.mock.validator;
|
||||
|
||||
import com.alibaba.excel.util.StringUtils;
|
||||
import com.databasir.core.domain.DomainErrors;
|
||||
import com.databasir.core.domain.mock.data.ColumnMockRuleSaveRequest;
|
||||
import com.databasir.core.domain.mock.script.MockScriptEvaluator;
|
||||
import com.databasir.core.domain.mock.script.SpelScriptEvaluator;
|
||||
import com.databasir.dao.enums.MockDataType;
|
||||
import com.databasir.dao.impl.TableColumnDocumentDao;
|
||||
import com.databasir.dao.impl.TableDocumentDao;
|
||||
import com.databasir.dao.tables.pojos.TableColumnDocumentPojo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MockDataSaveValidator {
|
||||
|
||||
private final TableDocumentDao tableDocumentDao;
|
||||
|
||||
private final TableColumnDocumentDao tableColumnDocumentDao;
|
||||
|
||||
private final SpelScriptEvaluator spelScriptEvaluator;
|
||||
|
||||
public void validScriptMockType(List<ColumnMockRuleSaveRequest> rules) {
|
||||
for (ColumnMockRuleSaveRequest request : rules) {
|
||||
if (request.getMockDataType() != MockDataType.SCRIPT) {
|
||||
continue;
|
||||
}
|
||||
if (StringUtils.isBlank(request.getMockDataScript())) {
|
||||
throw DomainErrors.MOCK_DATA_SCRIPT_MUST_NOT_BE_BLANK.exception();
|
||||
}
|
||||
try {
|
||||
spelScriptEvaluator.evaluate(request.getMockDataScript(), new MockScriptEvaluator.ScriptContext());
|
||||
} catch (Exception e) {
|
||||
throw DomainErrors.INVALID_MOCK_DATA_SCRIPT.exception(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void validTableColumn(Integer tableDocId, List<String> requestColumnNames) {
|
||||
var existsColumnNames = tableColumnDocumentDao.selectByTableDocumentId(tableDocId)
|
||||
.stream()
|
||||
.map(TableColumnDocumentPojo::getName)
|
||||
.collect(Collectors.toSet());
|
||||
for (String colName : requestColumnNames) {
|
||||
if (!existsColumnNames.contains(colName)) {
|
||||
throw DomainErrors.TABLE_META_NOT_FOUND.exception("column "
|
||||
+ colName
|
||||
+ " not exists in "
|
||||
+ tableDocId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void validRefMockType(Integer databaseDocId,
|
||||
List<ColumnMockRuleSaveRequest> rules) {
|
||||
Map<String, Set<String>> fromTableAndColumn = new HashMap<>();
|
||||
Map<String, Set<String>> toTableAndColumn = new HashMap<>();
|
||||
for (ColumnMockRuleSaveRequest request : rules) {
|
||||
if (request.getMockDataType() != MockDataType.REF) {
|
||||
continue;
|
||||
}
|
||||
forbiddenIfMissRequireParams(request);
|
||||
forbiddenIfSelfReference(request);
|
||||
forbiddenIfCircleReference(request, fromTableAndColumn, toTableAndColumn);
|
||||
forbiddenIfIsInvalidTableOrColumn(databaseDocId, request);
|
||||
}
|
||||
}
|
||||
|
||||
private void forbiddenIfSelfReference(ColumnMockRuleSaveRequest request) {
|
||||
if (!Objects.equals(request.getTableName(), request.getDependentTableName())) {
|
||||
return;
|
||||
}
|
||||
if (!Objects.equals(request.getColumnName(), request.getDependentColumnName())) {
|
||||
return;
|
||||
}
|
||||
throw DomainErrors.MUST_NOT_REF_SELF.exception();
|
||||
}
|
||||
|
||||
private void forbiddenIfMissRequireParams(ColumnMockRuleSaveRequest request) {
|
||||
if (StringUtils.isBlank(request.getDependentTableName())) {
|
||||
throw DomainErrors.DEPENDENT_COLUMN_NAME_MUST_NOT_BE_BLANK.exception();
|
||||
}
|
||||
if (StringUtils.isBlank(request.getDependentColumnName())) {
|
||||
throw DomainErrors.DEPENDENT_COLUMN_NAME_MUST_NOT_BE_BLANK.exception();
|
||||
}
|
||||
}
|
||||
|
||||
private void forbiddenIfIsInvalidTableOrColumn(Integer docId, ColumnMockRuleSaveRequest request) {
|
||||
String dependentTableName = request.getDependentTableName();
|
||||
var dependentTable = tableDocumentDao.selectByDatabaseDocumentIdAndTableName(docId, dependentTableName)
|
||||
.orElseThrow(DomainErrors.TABLE_META_NOT_FOUND::exception);
|
||||
if (!tableColumnDocumentDao.exists(dependentTable.getId(), request.getDependentColumnName())) {
|
||||
throw DomainErrors.TABLE_META_NOT_FOUND.exception("列字段 "
|
||||
+ request.getDependentColumnName()
|
||||
+ "不存在");
|
||||
}
|
||||
}
|
||||
|
||||
private void forbiddenIfCircleReference(ColumnMockRuleSaveRequest request,
|
||||
Map<String, Set<String>> fromTableAndColumn,
|
||||
Map<String, Set<String>> toTableAndColumn) {
|
||||
if (toTableAndColumn.containsKey(request.getTableName())
|
||||
&& toTableAndColumn.get(request.getTableName()).contains(request.getColumnName())) {
|
||||
if (fromTableAndColumn.containsKey(request.getDependentTableName())
|
||||
&& fromTableAndColumn.get(request.getDependentTableName())
|
||||
.contains(request.getDependentColumnName())) {
|
||||
String format = "%s 和 %s 出现了循环引用";
|
||||
String from = request.getTableName() + "." + request.getColumnName();
|
||||
String to = request.getDependentTableName() + "." + request.getDependentColumnName();
|
||||
String message = String.format(format, from, to);
|
||||
throw DomainErrors.CIRCLE_REFERENCE.exception(message);
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> fromColumns =
|
||||
fromTableAndColumn.computeIfAbsent(request.getTableName(), key -> new HashSet<String>());
|
||||
fromColumns.add(request.getColumnName());
|
||||
Set<String> toColumns =
|
||||
toTableAndColumn.computeIfAbsent(request.getDependentTableName(), key -> new HashSet<String>());
|
||||
toColumns.add(request.getDependentColumnName());
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
package com.databasir.core.domain.mock.validator;
|
||||
|
||||
import com.databasir.core.domain.DomainErrors;
|
||||
import com.databasir.dao.impl.DatabaseDocumentDao;
|
||||
import com.databasir.dao.impl.ProjectDao;
|
||||
import com.databasir.dao.impl.TableDocumentDao;
|
||||
import com.databasir.dao.tables.pojos.DatabaseDocumentPojo;
|
||||
import com.databasir.dao.tables.pojos.TableDocumentPojo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MockDataValidator {
|
||||
|
||||
private final ProjectDao projectDao;
|
||||
|
||||
private final DatabaseDocumentDao databaseDocumentDao;
|
||||
|
||||
private final TableDocumentDao tableDocumentDao;
|
||||
|
||||
public void validProject(Integer projectId) {
|
||||
if (!projectDao.existsById(projectId)) {
|
||||
throw DomainErrors.PROJECT_NOT_FOUND.exception();
|
||||
}
|
||||
}
|
||||
|
||||
public DatabaseDocumentPojo validAndGetDatabaseDocumentPojo(Integer projectId, Long version) {
|
||||
Optional<DatabaseDocumentPojo> databaseDoc;
|
||||
if (version == null) {
|
||||
databaseDoc = databaseDocumentDao.selectNotArchivedByProjectId(projectId);
|
||||
} else {
|
||||
databaseDoc = databaseDocumentDao.selectOptionalByProjectIdAndVersion(projectId, version);
|
||||
}
|
||||
if (databaseDoc.isEmpty()) {
|
||||
throw DomainErrors.DATABASE_META_NOT_FOUND.exception();
|
||||
}
|
||||
return databaseDoc.get();
|
||||
}
|
||||
|
||||
public TableDocumentPojo validAndGetTableDocumentPojo(Integer databaseDocId, Integer tableId) {
|
||||
Optional<TableDocumentPojo> tableOption =
|
||||
tableDocumentDao.selectByDatabaseDocumentIdAndId(databaseDocId, tableId);
|
||||
if (tableOption.isEmpty()) {
|
||||
throw DomainErrors.DATABASE_META_NOT_FOUND.exception("表数据不存在");
|
||||
}
|
||||
return tableOption.get();
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user