feat: support resolve foreign key

This commit is contained in:
vran 2022-03-15 09:35:03 +08:00
parent 020671ef8a
commit 410f0a1253
7 changed files with 159 additions and 6 deletions

View File

@ -55,10 +55,18 @@ public class Databasir {
if (columnMetaRepository == null) { if (columnMetaRepository == null) {
columnMetaRepository = new JdbcColumnMetaRepository(); columnMetaRepository = new JdbcColumnMetaRepository();
} }
ForeignKeyMetaRepository foreignKeyMetaRepository = config.getForeignKeyMetaRepository();
if (foreignKeyMetaRepository == null) {
foreignKeyMetaRepository = new JdbcForeignKeyMetaRepository();
}
TableMetaRepository tableMetaRepository = config.getTableMetaRepository(); TableMetaRepository tableMetaRepository = config.getTableMetaRepository();
if (tableMetaRepository == null) { if (tableMetaRepository == null) {
tableMetaRepository = tableMetaRepository = new JdbcTableMetaRepository(
new JdbcTableMetaRepository(columnMetaRepository, indexMetaRepository, triggerMetaRepository); columnMetaRepository,
indexMetaRepository,
triggerMetaRepository,
foreignKeyMetaRepository
);
} }
DatabaseMetaRepository databaseMetaRepository = config.getDatabaseMetaRepository(); DatabaseMetaRepository databaseMetaRepository = config.getDatabaseMetaRepository();
if (databaseMetaRepository == null) { if (databaseMetaRepository == null) {

View File

@ -17,6 +17,8 @@ public class DatabasirConfig {
private ColumnMetaRepository columnMetaRepository; private ColumnMetaRepository columnMetaRepository;
private ForeignKeyMetaRepository foreignKeyMetaRepository;
private TableMetaRepository tableMetaRepository; private TableMetaRepository tableMetaRepository;
private DatabaseMetaRepository databaseMetaRepository; private DatabaseMetaRepository databaseMetaRepository;

View File

@ -0,0 +1,37 @@
package com.databasir.core.meta.data;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class ForeignKeyMeta {
/**
* may null
*/
private String pkName;
private String pkTableName;
private String pkColumnName;
/**
* may null
*/
private String fkName;
private String fkTableName;
private String fkColumnName;
/**
* NO_ACTION \ CASCADE \ SET_NULL \ SET_DEFAULT
*/
private String updateRule;
/**
* NO_ACTION \ CASCADE \ SET_NULL \ SET_DEFAULT
*/
private String deleteRule;
}

View File

@ -25,5 +25,8 @@ public class TableMeta {
@Builder.Default @Builder.Default
private List<IndexMeta> indexes = Collections.emptyList(); private List<IndexMeta> indexes = Collections.emptyList();
@Builder.Default
private List<ForeignKeyMeta> foreignKeys = Collections.emptyList();
private String remark; private String remark;
} }

View File

@ -0,0 +1,13 @@
package com.databasir.core.meta.repository;
import com.databasir.core.meta.data.ForeignKeyMeta;
import com.databasir.core.meta.repository.condition.TableCondition;
import java.sql.Connection;
import java.util.List;
public interface ForeignKeyMetaRepository {
List<ForeignKeyMeta> selectForeignKeys(Connection connection, TableCondition condition);
}

View File

@ -0,0 +1,90 @@
package com.databasir.core.meta.repository.impl.jdbc;
import com.databasir.core.meta.data.ForeignKeyMeta;
import com.databasir.core.meta.repository.ForeignKeyMetaRepository;
import com.databasir.core.meta.repository.condition.TableCondition;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class JdbcForeignKeyMetaRepository implements ForeignKeyMetaRepository {
@Override
public List<ForeignKeyMeta> selectForeignKeys(Connection connection, TableCondition condition) {
String databaseName = condition.getDatabaseName();
String schemaName = condition.getSchemaName();
String tableName = condition.getTableName();
List<ForeignKeyMeta> foreignKeys = new ArrayList<>();
ResultSet keyResult = null;
try {
keyResult = connection.getMetaData().getImportedKeys(databaseName, schemaName, tableName);
} catch (SQLException e) {
log.warn("warn: ignore foreign keys in " + databaseName + "." + tableName + ", " + e.getMessage());
return foreignKeys;
}
try {
keyResult = connection.getMetaData()
.getImportedKeys(databaseName, schemaName, tableName);
while (keyResult.next()) {
String fkTableName = keyResult.getString("FKTABLE_NAME");
String fkColumnName = keyResult.getString("FKCOLUMN_NAME");
String fkName = keyResult.getString("FK_NAME");
String pkTableName = keyResult.getString("PKTABLE_NAME");
String pkColumnName = keyResult.getString("PKCOLUMN_NAME");
String pkName = keyResult.getString("PK_NAME");
int updateRule = keyResult.getInt("UPDATE_RULE");
int deleteRule = keyResult.getInt("DELETE_RULE");
ForeignKeyMeta meta = ForeignKeyMeta.builder()
.fkTableName(fkTableName)
.fkColumnName(fkColumnName)
.fkName(fkName)
.pkTableName(pkTableName)
.pkColumnName(pkColumnName)
.pkName(pkName)
.updateRule(updateRuleConvert(updateRule))
.deleteRule(deleteRuleConvert(deleteRule))
.build();
foreignKeys.add(meta);
}
} catch (SQLException e) {
log.warn("warn: ignore foreign keys in " + databaseName + "." + tableName + ", " + e.getMessage());
}
return foreignKeys;
}
private String updateRuleConvert(int updateRule) {
return doMapping(updateRule, "update");
}
private String deleteRuleConvert(int deleteRule) {
return doMapping(deleteRule, "delete");
}
private String doMapping(int rule, String type) {
if (rule == DatabaseMetaData.importedKeyCascade) {
return "CASCADE";
}
if (rule == DatabaseMetaData.importedKeyRestrict) {
return "CASCADE";
}
if (rule == DatabaseMetaData.importedKeyNoAction) {
return "RESTRICT";
}
if (rule == DatabaseMetaData.importedKeySetNull) {
return "SET_NULL";
}
if (rule == DatabaseMetaData.importedKeySetDefault) {
return "SET_DEFAULT";
}
log.warn("can not map foreign key " + type + " rule = " + rule);
return "";
}
}

View File

@ -2,10 +2,7 @@ package com.databasir.core.meta.repository.impl.jdbc;
import com.databasir.core.meta.data.ColumnMeta; import com.databasir.core.meta.data.ColumnMeta;
import com.databasir.core.meta.data.TableMeta; import com.databasir.core.meta.data.TableMeta;
import com.databasir.core.meta.repository.ColumnMetaRepository; import com.databasir.core.meta.repository.*;
import com.databasir.core.meta.repository.IndexMetaRepository;
import com.databasir.core.meta.repository.TableMetaRepository;
import com.databasir.core.meta.repository.TriggerMetaRepository;
import com.databasir.core.meta.repository.condition.Condition; import com.databasir.core.meta.repository.condition.Condition;
import com.databasir.core.meta.repository.condition.TableCondition; import com.databasir.core.meta.repository.condition.TableCondition;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -27,6 +24,8 @@ public class JdbcTableMetaRepository implements TableMetaRepository {
private final TriggerMetaRepository triggerMetaRepository; private final TriggerMetaRepository triggerMetaRepository;
private final ForeignKeyMetaRepository foreignKeyMetaRepository;
@Override @Override
public List<TableMeta> selectTables(Connection connection, Condition condition) { public List<TableMeta> selectTables(Connection connection, Condition condition) {
try { try {
@ -63,6 +62,7 @@ public class JdbcTableMetaRepository implements TableMetaRepository {
.type(tableType) .type(tableType)
.comment(tableComment) .comment(tableComment)
.columns(columns) .columns(columns)
.foreignKeys(foreignKeyMetaRepository.selectForeignKeys(connection, tableCondition))
.indexes(indexMetaRepository.selectIndexes(connection, tableCondition)) .indexes(indexMetaRepository.selectIndexes(connection, tableCondition))
.triggers(triggerMetaRepository.selectTriggers(connection, tableCondition)) .triggers(triggerMetaRepository.selectTriggers(connection, tableCondition))
.build(); .build();