From 410f0a1253ceaf05b55daa4b371c3a6f2ad37315 Mon Sep 17 00:00:00 2001 From: vran Date: Tue, 15 Mar 2022 09:35:03 +0800 Subject: [PATCH] feat: support resolve foreign key --- .../java/com/databasir/core/Databasir.java | 12 ++- .../com/databasir/core/DatabasirConfig.java | 2 + .../core/meta/data/ForeignKeyMeta.java | 37 ++++++++ .../databasir/core/meta/data/TableMeta.java | 3 + .../repository/ForeignKeyMetaRepository.java | 13 +++ .../jdbc/JdbcForeignKeyMetaRepository.java | 90 +++++++++++++++++++ .../impl/jdbc/JdbcTableMetaRepository.java | 8 +- 7 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 plugin/src/main/java/com/databasir/core/meta/data/ForeignKeyMeta.java create mode 100644 plugin/src/main/java/com/databasir/core/meta/repository/ForeignKeyMetaRepository.java create mode 100644 plugin/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcForeignKeyMetaRepository.java diff --git a/plugin/src/main/java/com/databasir/core/Databasir.java b/plugin/src/main/java/com/databasir/core/Databasir.java index a30bb38..d1a4426 100644 --- a/plugin/src/main/java/com/databasir/core/Databasir.java +++ b/plugin/src/main/java/com/databasir/core/Databasir.java @@ -55,10 +55,18 @@ public class Databasir { if (columnMetaRepository == null) { columnMetaRepository = new JdbcColumnMetaRepository(); } + ForeignKeyMetaRepository foreignKeyMetaRepository = config.getForeignKeyMetaRepository(); + if (foreignKeyMetaRepository == null) { + foreignKeyMetaRepository = new JdbcForeignKeyMetaRepository(); + } TableMetaRepository tableMetaRepository = config.getTableMetaRepository(); if (tableMetaRepository == null) { - tableMetaRepository = - new JdbcTableMetaRepository(columnMetaRepository, indexMetaRepository, triggerMetaRepository); + tableMetaRepository = new JdbcTableMetaRepository( + columnMetaRepository, + indexMetaRepository, + triggerMetaRepository, + foreignKeyMetaRepository + ); } DatabaseMetaRepository databaseMetaRepository = config.getDatabaseMetaRepository(); if (databaseMetaRepository == null) { diff --git a/plugin/src/main/java/com/databasir/core/DatabasirConfig.java b/plugin/src/main/java/com/databasir/core/DatabasirConfig.java index 74a58bb..744d0a0 100644 --- a/plugin/src/main/java/com/databasir/core/DatabasirConfig.java +++ b/plugin/src/main/java/com/databasir/core/DatabasirConfig.java @@ -17,6 +17,8 @@ public class DatabasirConfig { private ColumnMetaRepository columnMetaRepository; + private ForeignKeyMetaRepository foreignKeyMetaRepository; + private TableMetaRepository tableMetaRepository; private DatabaseMetaRepository databaseMetaRepository; diff --git a/plugin/src/main/java/com/databasir/core/meta/data/ForeignKeyMeta.java b/plugin/src/main/java/com/databasir/core/meta/data/ForeignKeyMeta.java new file mode 100644 index 0000000..2122f29 --- /dev/null +++ b/plugin/src/main/java/com/databasir/core/meta/data/ForeignKeyMeta.java @@ -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; +} diff --git a/plugin/src/main/java/com/databasir/core/meta/data/TableMeta.java b/plugin/src/main/java/com/databasir/core/meta/data/TableMeta.java index 04c3d07..0023fe7 100644 --- a/plugin/src/main/java/com/databasir/core/meta/data/TableMeta.java +++ b/plugin/src/main/java/com/databasir/core/meta/data/TableMeta.java @@ -25,5 +25,8 @@ public class TableMeta { @Builder.Default private List indexes = Collections.emptyList(); + @Builder.Default + private List foreignKeys = Collections.emptyList(); + private String remark; } diff --git a/plugin/src/main/java/com/databasir/core/meta/repository/ForeignKeyMetaRepository.java b/plugin/src/main/java/com/databasir/core/meta/repository/ForeignKeyMetaRepository.java new file mode 100644 index 0000000..42f0f5f --- /dev/null +++ b/plugin/src/main/java/com/databasir/core/meta/repository/ForeignKeyMetaRepository.java @@ -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 selectForeignKeys(Connection connection, TableCondition condition); + +} diff --git a/plugin/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcForeignKeyMetaRepository.java b/plugin/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcForeignKeyMetaRepository.java new file mode 100644 index 0000000..0e0790a --- /dev/null +++ b/plugin/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcForeignKeyMetaRepository.java @@ -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 selectForeignKeys(Connection connection, TableCondition condition) { + String databaseName = condition.getDatabaseName(); + String schemaName = condition.getSchemaName(); + String tableName = condition.getTableName(); + List 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 ""; + } +} diff --git a/plugin/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcTableMetaRepository.java b/plugin/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcTableMetaRepository.java index fe96cad..6b44af2 100644 --- a/plugin/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcTableMetaRepository.java +++ b/plugin/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcTableMetaRepository.java @@ -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.TableMeta; -import com.databasir.core.meta.repository.ColumnMetaRepository; -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.*; import com.databasir.core.meta.repository.condition.Condition; import com.databasir.core.meta.repository.condition.TableCondition; import lombok.RequiredArgsConstructor; @@ -27,6 +24,8 @@ public class JdbcTableMetaRepository implements TableMetaRepository { private final TriggerMetaRepository triggerMetaRepository; + private final ForeignKeyMetaRepository foreignKeyMetaRepository; + @Override public List selectTables(Connection connection, Condition condition) { try { @@ -63,6 +62,7 @@ public class JdbcTableMetaRepository implements TableMetaRepository { .type(tableType) .comment(tableComment) .columns(columns) + .foreignKeys(foreignKeyMetaRepository.selectForeignKeys(connection, tableCondition)) .indexes(indexMetaRepository.selectIndexes(connection, tableCondition)) .triggers(triggerMetaRepository.selectTriggers(connection, tableCondition)) .build();