From 98d5a5b7a79b15e761769cb8e30963cd5f6aa29d Mon Sep 17 00:00:00 2001
From: vran <vran_dev@foxmail.com>
Date: Thu, 17 Mar 2022 10:59:47 +0800
Subject: [PATCH] feat: ignore sync if without change

---
 .../document/converter/BaseConverter.java     |   9 -
 .../converter/DatabaseMetaConverter.java      |  72 ++++++++
 .../converter/DocumentPojoConverter.java      |   4 +-
 .../document/converter/NullToEmpty.java       |  14 --
 .../document/service/DocumentService.java     |  38 +++-
 .../dao/tables/TableColumnDocument.java       |   2 +-
 .../databasir/dao/tables/TableDocument.java   |   4 +-
 .../dao/tables/TableForeignKeyDocument.java   |  13 +-
 .../pojos/TableForeignKeyDocumentPojo.java    |  19 ++
 .../TableForeignKeyDocumentRecord.java        | 166 +++++++++++-------
 .../main/resources/db/migration/V1__init.sql  |  13 +-
 .../processor/ForeignKeyDiffProcessor.java    |   2 +-
 .../core/meta/data/ForeignKeyMeta.java        |   2 +-
 .../jdbc/JdbcForeignKeyMetaRepository.java    |   4 +-
 .../core/render/markdown/MarkdownRender.java  |   2 +-
 15 files changed, 249 insertions(+), 115 deletions(-)
 delete mode 100644 core/src/main/java/com/databasir/core/domain/document/converter/BaseConverter.java
 create mode 100644 core/src/main/java/com/databasir/core/domain/document/converter/DatabaseMetaConverter.java
 delete mode 100644 core/src/main/java/com/databasir/core/domain/document/converter/NullToEmpty.java

diff --git a/core/src/main/java/com/databasir/core/domain/document/converter/BaseConverter.java b/core/src/main/java/com/databasir/core/domain/document/converter/BaseConverter.java
deleted file mode 100644
index 7190117..0000000
--- a/core/src/main/java/com/databasir/core/domain/document/converter/BaseConverter.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.databasir.core.domain.document.converter;
-
-public interface BaseConverter {
-
-    @NullToEmpty
-    default String nullToEmpty(String s) {
-        return s == null ? "" : s;
-    }
-}
diff --git a/core/src/main/java/com/databasir/core/domain/document/converter/DatabaseMetaConverter.java b/core/src/main/java/com/databasir/core/domain/document/converter/DatabaseMetaConverter.java
new file mode 100644
index 0000000..3f32a8c
--- /dev/null
+++ b/core/src/main/java/com/databasir/core/domain/document/converter/DatabaseMetaConverter.java
@@ -0,0 +1,72 @@
+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.DatabaseMeta;
+import com.databasir.core.meta.data.IndexMeta;
+import com.databasir.core.meta.data.TableMeta;
+import com.databasir.dao.tables.pojos.*;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Mapper(componentModel = "spring", uses = JsonConverter.class)
+public interface DatabaseMetaConverter {
+
+    default DatabaseMeta of(DatabaseDocumentPojo database,
+                            List<TableDocumentPojo> tables,
+                            List<TableColumnDocumentPojo> columns,
+                            List<TableIndexDocumentPojo> indexes,
+                            List<TableTriggerDocumentPojo> triggers,
+                            List<TableForeignKeyDocumentPojo> foreignKeys) {
+        var columnMap = groupBy(columns, TableColumnDocumentPojo::getTableDocumentId);
+        var indexMap = groupBy(indexes, TableIndexDocumentPojo::getTableDocumentId);
+        var triggerMap = groupBy(triggers, TableTriggerDocumentPojo::getTableDocumentId);
+        var fkMap = groupBy(foreignKeys, TableForeignKeyDocumentPojo::getTableDocumentId);
+        return of(database, tables, columnMap, indexMap, triggerMap, fkMap);
+    }
+
+    default <R> Map<Integer, List<R>> groupBy(List<R> content, Function<R, Integer> idMapping) {
+        return content.stream()
+                .collect(Collectors.groupingBy(idMapping));
+    }
+
+    default DatabaseMeta of(DatabaseDocumentPojo database,
+                            List<TableDocumentPojo> tables,
+                            Map<Integer, List<TableColumnDocumentPojo>> columnGroupByTableId,
+                            Map<Integer, List<TableIndexDocumentPojo>> indexGroupByTableId,
+                            Map<Integer, List<TableTriggerDocumentPojo>> triggerGroupByTableId,
+                            Map<Integer, List<TableForeignKeyDocumentPojo>> fkGroupByTableId) {
+        List<TableMeta> tableMetas = tables.stream()
+                .map(table -> {
+                    Integer id = table.getId();
+                    var columns = columnGroupByTableId.getOrDefault(id, Collections.emptyList());
+                    var indexes = indexGroupByTableId.getOrDefault(id, Collections.emptyList());
+                    var triggers = triggerGroupByTableId.getOrDefault(id, Collections.emptyList());
+                    var foreignKeys = fkGroupByTableId.getOrDefault(id, Collections.emptyList());
+                    return of(table, columns, indexes, triggers, foreignKeys);
+                })
+                .collect(Collectors.toList());
+        return of(database, tableMetas);
+    }
+
+    DatabaseMeta of(DatabaseDocumentPojo database, List<TableMeta> tables);
+
+    TableMeta of(TableDocumentPojo table,
+                 List<TableColumnDocumentPojo> columns,
+                 List<TableIndexDocumentPojo> indexes,
+                 List<TableTriggerDocumentPojo> triggers,
+                 List<TableForeignKeyDocumentPojo> foreignKeys);
+
+    ColumnMeta of(TableColumnDocumentPojo pojo);
+
+    @Mapping(target = "isUniqueKey", source = "pojo.isUnique")
+    @Mapping(target = "columnNames", source = "pojo.columnNameArray")
+    IndexMeta of(TableIndexDocumentPojo pojo);
+
+}
diff --git a/core/src/main/java/com/databasir/core/domain/document/converter/DocumentPojoConverter.java b/core/src/main/java/com/databasir/core/domain/document/converter/DocumentPojoConverter.java
index b5d74c2..9d35e98 100644
--- a/core/src/main/java/com/databasir/core/domain/document/converter/DocumentPojoConverter.java
+++ b/core/src/main/java/com/databasir/core/domain/document/converter/DocumentPojoConverter.java
@@ -14,7 +14,7 @@ import java.util.List;
 import java.util.stream.Collectors;
 
 @Mapper(componentModel = "spring", uses = JsonConverter.class, unmappedTargetPolicy = ReportingPolicy.WARN)
-public interface DocumentPojoConverter extends BaseConverter {
+public interface DocumentPojoConverter {
 
     @Mapping(target = "databaseName", source = "meta.databaseName")
     @Mapping(target = "schemaName", source = "meta.schemaName")
@@ -23,7 +23,6 @@ public interface DocumentPojoConverter extends BaseConverter {
                                         com.databasir.core.meta.data.DatabaseMeta meta,
                                         Long version);
 
-    @Mapping(target = "comment", qualifiedBy = NullToEmpty.class)
     TableDocumentPojo toTablePojo(Integer databaseDocumentId,
                                   com.databasir.core.meta.data.TableMeta meta);
 
@@ -35,7 +34,6 @@ public interface DocumentPojoConverter extends BaseConverter {
                 .collect(Collectors.toList());
     }
 
-    @Mapping(target = "comment", qualifiedBy = NullToEmpty.class)
     TableColumnDocumentPojo toColumnPojo(Integer databaseDocumentId,
                                          Integer tableDocumentId,
                                          ColumnMeta meta);
diff --git a/core/src/main/java/com/databasir/core/domain/document/converter/NullToEmpty.java b/core/src/main/java/com/databasir/core/domain/document/converter/NullToEmpty.java
deleted file mode 100644
index e0eaa6e..0000000
--- a/core/src/main/java/com/databasir/core/domain/document/converter/NullToEmpty.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.databasir.core.domain.document.converter;
-
-import org.mapstruct.Qualifier;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Qualifier
-@Target(ElementType.METHOD)
-@Retention(RetentionPolicy.CLASS)
-public @interface NullToEmpty {
-}
diff --git a/core/src/main/java/com/databasir/core/domain/document/service/DocumentService.java b/core/src/main/java/com/databasir/core/domain/document/service/DocumentService.java
index 2af3c1b..c7f1dd2 100644
--- a/core/src/main/java/com/databasir/core/domain/document/service/DocumentService.java
+++ b/core/src/main/java/com/databasir/core/domain/document/service/DocumentService.java
@@ -2,7 +2,11 @@ package com.databasir.core.domain.document.service;
 
 import com.databasir.core.Databasir;
 import com.databasir.core.DatabasirConfig;
+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;
@@ -74,6 +78,8 @@ public class DocumentService {
 
     private final DocumentSimpleResponseConverter documentSimpleResponseConverter;
 
+    private final DatabaseMetaConverter databaseMetaConverter;
+
     private final JsonConverter jsonConverter;
 
     private final List<DocumentFileGenerator> documentFileGenerators;
@@ -82,19 +88,37 @@ public class DocumentService {
     public void syncByProjectId(Integer projectId) {
         projectDao.selectOptionalById(projectId)
                 .orElseThrow(DomainErrors.PROJECT_NOT_FOUND::exception);
-        DatabaseMeta meta = retrieveDatabaseMeta(projectId);
-        Optional<DatabaseDocumentPojo> latestDocumentOpt = databaseDocumentDao.selectNotArchivedByProjectId(projectId);
-        if (latestDocumentOpt.isPresent()) {
-            DatabaseDocumentPojo latestDocument = latestDocumentOpt.get();
-            Integer previousDocumentId = latestDocument.getId();
+        DatabaseMeta current = retrieveDatabaseMeta(projectId);
+        Optional<DatabaseDocumentPojo> originalOption = databaseDocumentDao.selectNotArchivedByProjectId(projectId);
+        if (originalOption.isPresent()) {
+            DatabaseDocumentPojo original = originalOption.get();
+            DatabaseMeta originalMeta = retrieveOriginalDatabaseMeta(original);
+            RootDiff diff = Diffs.diff(originalMeta, current);
+            if (diff.getDiffType() == DiffType.NONE) {
+                log.info("ignore project {} {} sync data, because without change",
+                        projectId,
+                        original.getDatabaseName());
+                return;
+            }
+            Integer previousDocumentId = original.getId();
             // archive old version
             databaseDocumentDao.updateIsArchiveById(previousDocumentId, true);
-            saveNewDocument(meta, latestDocument.getVersion() + 1, latestDocument.getProjectId());
+            saveNewDocument(current, original.getVersion() + 1, original.getProjectId());
         } else {
-            saveNewDocument(meta, 1L, projectId);
+            saveNewDocument(current, 1L, projectId);
         }
     }
 
+    private DatabaseMeta retrieveOriginalDatabaseMeta(DatabaseDocumentPojo original) {
+        Integer docId = original.getId();
+        List<TableDocumentPojo> tables = tableDocumentDao.selectByDatabaseDocumentId(docId);
+        List<TableColumnDocumentPojo> columns = tableColumnDocumentDao.selectByDatabaseDocumentId(docId);
+        List<TableIndexDocumentPojo> indexes = tableIndexDocumentDao.selectByDatabaseMetaId(docId);
+        List<TableTriggerDocumentPojo> triggers = tableTriggerDocumentDao.selectByDatabaseDocumentId(docId);
+        List<TableForeignKeyDocumentPojo> fks = tableForeignKeyDocumentDao.selectByDatabaseDocumentId(docId);
+        return databaseMetaConverter.of(original, tables, columns, indexes, triggers, fks);
+    }
+
     private DatabaseMeta retrieveDatabaseMeta(Integer projectId) {
         ProjectSyncRulePojo rule = projectSyncRuleDao.selectByProjectId(projectId);
         DataSourcePojo dataSource = dataSourceDao.selectByProjectId(projectId);
diff --git a/dao/generated-src/jooq/main/java/com/databasir/dao/tables/TableColumnDocument.java b/dao/generated-src/jooq/main/java/com/databasir/dao/tables/TableColumnDocument.java
index ea326fe..dfb3cfc 100644
--- a/dao/generated-src/jooq/main/java/com/databasir/dao/tables/TableColumnDocument.java
+++ b/dao/generated-src/jooq/main/java/com/databasir/dao/tables/TableColumnDocument.java
@@ -81,7 +81,7 @@ public class TableColumnDocument extends TableImpl<TableColumnDocumentRecord> {
     /**
      * The column <code>databasir.table_column_document.comment</code>.
      */
-    public final TableField<TableColumnDocumentRecord, String> COMMENT = createField(DSL.name("comment"), SQLDataType.VARCHAR(512).nullable(false), this, "");
+    public final TableField<TableColumnDocumentRecord, String> COMMENT = createField(DSL.name("comment"), SQLDataType.VARCHAR(512), this, "");
 
     /**
      * The column <code>databasir.table_column_document.default_value</code>.
diff --git a/dao/generated-src/jooq/main/java/com/databasir/dao/tables/TableDocument.java b/dao/generated-src/jooq/main/java/com/databasir/dao/tables/TableDocument.java
index 3e38576..c7e1549 100644
--- a/dao/generated-src/jooq/main/java/com/databasir/dao/tables/TableDocument.java
+++ b/dao/generated-src/jooq/main/java/com/databasir/dao/tables/TableDocument.java
@@ -69,12 +69,12 @@ public class TableDocument extends TableImpl<TableDocumentRecord> {
     /**
      * The column <code>databasir.table_document.type</code>.
      */
-    public final TableField<TableDocumentRecord, String> TYPE = createField(DSL.name("type"), SQLDataType.CLOB.nullable(false), this, "");
+    public final TableField<TableDocumentRecord, String> TYPE = createField(DSL.name("type"), SQLDataType.VARCHAR(255).nullable(false), this, "");
 
     /**
      * The column <code>databasir.table_document.comment</code>.
      */
-    public final TableField<TableDocumentRecord, String> COMMENT = createField(DSL.name("comment"), SQLDataType.CLOB.nullable(false), this, "");
+    public final TableField<TableDocumentRecord, String> COMMENT = createField(DSL.name("comment"), SQLDataType.VARCHAR(512), this, "");
 
     /**
      * The column <code>databasir.table_document.create_at</code>.
diff --git a/dao/generated-src/jooq/main/java/com/databasir/dao/tables/TableForeignKeyDocument.java b/dao/generated-src/jooq/main/java/com/databasir/dao/tables/TableForeignKeyDocument.java
index 67f3c18..2dd9be9 100644
--- a/dao/generated-src/jooq/main/java/com/databasir/dao/tables/TableForeignKeyDocument.java
+++ b/dao/generated-src/jooq/main/java/com/databasir/dao/tables/TableForeignKeyDocument.java
@@ -19,7 +19,7 @@ import org.jooq.Identity;
 import org.jooq.Index;
 import org.jooq.Name;
 import org.jooq.Record;
-import org.jooq.Row12;
+import org.jooq.Row13;
 import org.jooq.Schema;
 import org.jooq.Table;
 import org.jooq.TableField;
@@ -69,6 +69,11 @@ public class TableForeignKeyDocument extends TableImpl<TableForeignKeyDocumentRe
      */
     public final TableField<TableForeignKeyDocumentRecord, Integer> DATABASE_DOCUMENT_ID = createField(DSL.name("database_document_id"), SQLDataType.INTEGER.nullable(false), this, "");
 
+    /**
+     * The column <code>databasir.table_foreign_key_document.key_seq</code>.
+     */
+    public final TableField<TableForeignKeyDocumentRecord, Integer> KEY_SEQ = createField(DSL.name("key_seq"), SQLDataType.INTEGER.nullable(false).defaultValue(DSL.inline("0", SQLDataType.INTEGER)), this, "");
+
     /**
      * The column <code>databasir.table_foreign_key_document.fk_name</code>.
      */
@@ -203,11 +208,11 @@ public class TableForeignKeyDocument extends TableImpl<TableForeignKeyDocumentRe
     }
 
     // -------------------------------------------------------------------------
-    // Row12 type methods
+    // Row13 type methods
     // -------------------------------------------------------------------------
 
     @Override
-    public Row12<Integer, Integer, Integer, String, String, String, String, String, String, String, String, LocalDateTime> fieldsRow() {
-        return (Row12) super.fieldsRow();
+    public Row13<Integer, Integer, Integer, Integer, String, String, String, String, String, String, String, String, LocalDateTime> fieldsRow() {
+        return (Row13) super.fieldsRow();
     }
 }
diff --git a/dao/generated-src/jooq/main/java/com/databasir/dao/tables/pojos/TableForeignKeyDocumentPojo.java b/dao/generated-src/jooq/main/java/com/databasir/dao/tables/pojos/TableForeignKeyDocumentPojo.java
index c99c49d..89d7110 100644
--- a/dao/generated-src/jooq/main/java/com/databasir/dao/tables/pojos/TableForeignKeyDocumentPojo.java
+++ b/dao/generated-src/jooq/main/java/com/databasir/dao/tables/pojos/TableForeignKeyDocumentPojo.java
@@ -19,6 +19,7 @@ public class TableForeignKeyDocumentPojo implements Serializable {
     private Integer       id;
     private Integer       tableDocumentId;
     private Integer       databaseDocumentId;
+    private Integer       keySeq;
     private String        fkName;
     private String        fkTableName;
     private String        fkColumnName;
@@ -35,6 +36,7 @@ public class TableForeignKeyDocumentPojo implements Serializable {
         this.id = value.id;
         this.tableDocumentId = value.tableDocumentId;
         this.databaseDocumentId = value.databaseDocumentId;
+        this.keySeq = value.keySeq;
         this.fkName = value.fkName;
         this.fkTableName = value.fkTableName;
         this.fkColumnName = value.fkColumnName;
@@ -50,6 +52,7 @@ public class TableForeignKeyDocumentPojo implements Serializable {
         Integer       id,
         Integer       tableDocumentId,
         Integer       databaseDocumentId,
+        Integer       keySeq,
         String        fkName,
         String        fkTableName,
         String        fkColumnName,
@@ -63,6 +66,7 @@ public class TableForeignKeyDocumentPojo implements Serializable {
         this.id = id;
         this.tableDocumentId = tableDocumentId;
         this.databaseDocumentId = databaseDocumentId;
+        this.keySeq = keySeq;
         this.fkName = fkName;
         this.fkTableName = fkTableName;
         this.fkColumnName = fkColumnName;
@@ -120,6 +124,20 @@ public class TableForeignKeyDocumentPojo implements Serializable {
         this.databaseDocumentId = databaseDocumentId;
     }
 
+    /**
+     * Getter for <code>databasir.table_foreign_key_document.key_seq</code>.
+     */
+    public Integer getKeySeq() {
+        return this.keySeq;
+    }
+
+    /**
+     * Setter for <code>databasir.table_foreign_key_document.key_seq</code>.
+     */
+    public void setKeySeq(Integer keySeq) {
+        this.keySeq = keySeq;
+    }
+
     /**
      * Getter for <code>databasir.table_foreign_key_document.fk_name</code>.
      */
@@ -265,6 +283,7 @@ public class TableForeignKeyDocumentPojo implements Serializable {
         sb.append(id);
         sb.append(", ").append(tableDocumentId);
         sb.append(", ").append(databaseDocumentId);
+        sb.append(", ").append(keySeq);
         sb.append(", ").append(fkName);
         sb.append(", ").append(fkTableName);
         sb.append(", ").append(fkColumnName);
diff --git a/dao/generated-src/jooq/main/java/com/databasir/dao/tables/records/TableForeignKeyDocumentRecord.java b/dao/generated-src/jooq/main/java/com/databasir/dao/tables/records/TableForeignKeyDocumentRecord.java
index 6ec3eaf..d37af29 100644
--- a/dao/generated-src/jooq/main/java/com/databasir/dao/tables/records/TableForeignKeyDocumentRecord.java
+++ b/dao/generated-src/jooq/main/java/com/databasir/dao/tables/records/TableForeignKeyDocumentRecord.java
@@ -11,8 +11,8 @@ import java.time.LocalDateTime;
 
 import org.jooq.Field;
 import org.jooq.Record1;
-import org.jooq.Record12;
-import org.jooq.Row12;
+import org.jooq.Record13;
+import org.jooq.Row13;
 import org.jooq.impl.UpdatableRecordImpl;
 
 
@@ -20,7 +20,7 @@ import org.jooq.impl.UpdatableRecordImpl;
  * This class is generated by jOOQ.
  */
 @SuppressWarnings({ "all", "unchecked", "rawtypes" })
-public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableForeignKeyDocumentRecord> implements Record12<Integer, Integer, Integer, String, String, String, String, String, String, String, String, LocalDateTime> {
+public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableForeignKeyDocumentRecord> implements Record13<Integer, Integer, Integer, Integer, String, String, String, String, String, String, String, String, LocalDateTime> {
 
     private static final long serialVersionUID = 1L;
 
@@ -70,18 +70,32 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
         return (Integer) get(2);
     }
 
+    /**
+     * Setter for <code>databasir.table_foreign_key_document.key_seq</code>.
+     */
+    public void setKeySeq(Integer value) {
+        set(3, value);
+    }
+
+    /**
+     * Getter for <code>databasir.table_foreign_key_document.key_seq</code>.
+     */
+    public Integer getKeySeq() {
+        return (Integer) get(3);
+    }
+
     /**
      * Setter for <code>databasir.table_foreign_key_document.fk_name</code>.
      */
     public void setFkName(String value) {
-        set(3, value);
+        set(4, value);
     }
 
     /**
      * Getter for <code>databasir.table_foreign_key_document.fk_name</code>.
      */
     public String getFkName() {
-        return (String) get(3);
+        return (String) get(4);
     }
 
     /**
@@ -89,7 +103,7 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
      * <code>databasir.table_foreign_key_document.fk_table_name</code>.
      */
     public void setFkTableName(String value) {
-        set(4, value);
+        set(5, value);
     }
 
     /**
@@ -97,7 +111,7 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
      * <code>databasir.table_foreign_key_document.fk_table_name</code>.
      */
     public String getFkTableName() {
-        return (String) get(4);
+        return (String) get(5);
     }
 
     /**
@@ -105,7 +119,7 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
      * <code>databasir.table_foreign_key_document.fk_column_name</code>.
      */
     public void setFkColumnName(String value) {
-        set(5, value);
+        set(6, value);
     }
 
     /**
@@ -113,21 +127,21 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
      * <code>databasir.table_foreign_key_document.fk_column_name</code>.
      */
     public String getFkColumnName() {
-        return (String) get(5);
+        return (String) get(6);
     }
 
     /**
      * Setter for <code>databasir.table_foreign_key_document.pk_name</code>.
      */
     public void setPkName(String value) {
-        set(6, value);
+        set(7, value);
     }
 
     /**
      * Getter for <code>databasir.table_foreign_key_document.pk_name</code>.
      */
     public String getPkName() {
-        return (String) get(6);
+        return (String) get(7);
     }
 
     /**
@@ -135,7 +149,7 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
      * <code>databasir.table_foreign_key_document.pk_table_name</code>.
      */
     public void setPkTableName(String value) {
-        set(7, value);
+        set(8, value);
     }
 
     /**
@@ -143,7 +157,7 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
      * <code>databasir.table_foreign_key_document.pk_table_name</code>.
      */
     public String getPkTableName() {
-        return (String) get(7);
+        return (String) get(8);
     }
 
     /**
@@ -151,7 +165,7 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
      * <code>databasir.table_foreign_key_document.pk_column_name</code>.
      */
     public void setPkColumnName(String value) {
-        set(8, value);
+        set(9, value);
     }
 
     /**
@@ -159,7 +173,7 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
      * <code>databasir.table_foreign_key_document.pk_column_name</code>.
      */
     public String getPkColumnName() {
-        return (String) get(8);
+        return (String) get(9);
     }
 
     /**
@@ -167,7 +181,7 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
      * NO_ACTION, CASCADE, SET_NULL, SET_DEFAULT
      */
     public void setUpdateRule(String value) {
-        set(9, value);
+        set(10, value);
     }
 
     /**
@@ -175,7 +189,7 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
      * NO_ACTION, CASCADE, SET_NULL, SET_DEFAULT
      */
     public String getUpdateRule() {
-        return (String) get(9);
+        return (String) get(10);
     }
 
     /**
@@ -183,7 +197,7 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
      * NO_ACTION, CASCADE, SET_NULL, SET_DEFAULT
      */
     public void setDeleteRule(String value) {
-        set(10, value);
+        set(11, value);
     }
 
     /**
@@ -191,21 +205,21 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
      * NO_ACTION, CASCADE, SET_NULL, SET_DEFAULT
      */
     public String getDeleteRule() {
-        return (String) get(10);
+        return (String) get(11);
     }
 
     /**
      * Setter for <code>databasir.table_foreign_key_document.create_at</code>.
      */
     public void setCreateAt(LocalDateTime value) {
-        set(11, value);
+        set(12, value);
     }
 
     /**
      * Getter for <code>databasir.table_foreign_key_document.create_at</code>.
      */
     public LocalDateTime getCreateAt() {
-        return (LocalDateTime) get(11);
+        return (LocalDateTime) get(12);
     }
 
     // -------------------------------------------------------------------------
@@ -218,17 +232,17 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
     }
 
     // -------------------------------------------------------------------------
-    // Record12 type implementation
+    // Record13 type implementation
     // -------------------------------------------------------------------------
 
     @Override
-    public Row12<Integer, Integer, Integer, String, String, String, String, String, String, String, String, LocalDateTime> fieldsRow() {
-        return (Row12) super.fieldsRow();
+    public Row13<Integer, Integer, Integer, Integer, String, String, String, String, String, String, String, String, LocalDateTime> fieldsRow() {
+        return (Row13) super.fieldsRow();
     }
 
     @Override
-    public Row12<Integer, Integer, Integer, String, String, String, String, String, String, String, String, LocalDateTime> valuesRow() {
-        return (Row12) super.valuesRow();
+    public Row13<Integer, Integer, Integer, Integer, String, String, String, String, String, String, String, String, LocalDateTime> valuesRow() {
+        return (Row13) super.valuesRow();
     }
 
     @Override
@@ -247,47 +261,52 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
     }
 
     @Override
-    public Field<String> field4() {
-        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.FK_NAME;
+    public Field<Integer> field4() {
+        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.KEY_SEQ;
     }
 
     @Override
     public Field<String> field5() {
-        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.FK_TABLE_NAME;
+        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.FK_NAME;
     }
 
     @Override
     public Field<String> field6() {
-        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.FK_COLUMN_NAME;
+        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.FK_TABLE_NAME;
     }
 
     @Override
     public Field<String> field7() {
-        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.PK_NAME;
+        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.FK_COLUMN_NAME;
     }
 
     @Override
     public Field<String> field8() {
-        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.PK_TABLE_NAME;
+        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.PK_NAME;
     }
 
     @Override
     public Field<String> field9() {
-        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.PK_COLUMN_NAME;
+        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.PK_TABLE_NAME;
     }
 
     @Override
     public Field<String> field10() {
-        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.UPDATE_RULE;
+        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.PK_COLUMN_NAME;
     }
 
     @Override
     public Field<String> field11() {
+        return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.UPDATE_RULE;
+    }
+
+    @Override
+    public Field<String> field12() {
         return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.DELETE_RULE;
     }
 
     @Override
-    public Field<LocalDateTime> field12() {
+    public Field<LocalDateTime> field13() {
         return TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT.CREATE_AT;
     }
 
@@ -307,47 +326,52 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
     }
 
     @Override
-    public String component4() {
-        return getFkName();
+    public Integer component4() {
+        return getKeySeq();
     }
 
     @Override
     public String component5() {
-        return getFkTableName();
+        return getFkName();
     }
 
     @Override
     public String component6() {
-        return getFkColumnName();
+        return getFkTableName();
     }
 
     @Override
     public String component7() {
-        return getPkName();
+        return getFkColumnName();
     }
 
     @Override
     public String component8() {
-        return getPkTableName();
+        return getPkName();
     }
 
     @Override
     public String component9() {
-        return getPkColumnName();
+        return getPkTableName();
     }
 
     @Override
     public String component10() {
-        return getUpdateRule();
+        return getPkColumnName();
     }
 
     @Override
     public String component11() {
+        return getUpdateRule();
+    }
+
+    @Override
+    public String component12() {
         return getDeleteRule();
     }
 
     @Override
-    public LocalDateTime component12() {
+    public LocalDateTime component13() {
         return getCreateAt();
     }
 
@@ -367,47 +391,52 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
     }
 
     @Override
-    public String value4() {
-        return getFkName();
+    public Integer value4() {
+        return getKeySeq();
     }
 
     @Override
     public String value5() {
-        return getFkTableName();
+        return getFkName();
     }
 
     @Override
     public String value6() {
-        return getFkColumnName();
+        return getFkTableName();
     }
 
     @Override
     public String value7() {
-        return getPkName();
+        return getFkColumnName();
     }
 
     @Override
     public String value8() {
-        return getPkTableName();
+        return getPkName();
     }
 
     @Override
     public String value9() {
-        return getPkColumnName();
+        return getPkTableName();
     }
 
     @Override
     public String value10() {
-        return getUpdateRule();
+        return getPkColumnName();
     }
 
     @Override
     public String value11() {
+        return getUpdateRule();
+    }
+
+    @Override
+    public String value12() {
         return getDeleteRule();
     }
 
     @Override
-    public LocalDateTime value12() {
+    public LocalDateTime value13() {
         return getCreateAt();
     }
 
@@ -430,61 +459,67 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
     }
 
     @Override
-    public TableForeignKeyDocumentRecord value4(String value) {
-        setFkName(value);
+    public TableForeignKeyDocumentRecord value4(Integer value) {
+        setKeySeq(value);
         return this;
     }
 
     @Override
     public TableForeignKeyDocumentRecord value5(String value) {
-        setFkTableName(value);
+        setFkName(value);
         return this;
     }
 
     @Override
     public TableForeignKeyDocumentRecord value6(String value) {
-        setFkColumnName(value);
+        setFkTableName(value);
         return this;
     }
 
     @Override
     public TableForeignKeyDocumentRecord value7(String value) {
-        setPkName(value);
+        setFkColumnName(value);
         return this;
     }
 
     @Override
     public TableForeignKeyDocumentRecord value8(String value) {
-        setPkTableName(value);
+        setPkName(value);
         return this;
     }
 
     @Override
     public TableForeignKeyDocumentRecord value9(String value) {
-        setPkColumnName(value);
+        setPkTableName(value);
         return this;
     }
 
     @Override
     public TableForeignKeyDocumentRecord value10(String value) {
-        setUpdateRule(value);
+        setPkColumnName(value);
         return this;
     }
 
     @Override
     public TableForeignKeyDocumentRecord value11(String value) {
+        setUpdateRule(value);
+        return this;
+    }
+
+    @Override
+    public TableForeignKeyDocumentRecord value12(String value) {
         setDeleteRule(value);
         return this;
     }
 
     @Override
-    public TableForeignKeyDocumentRecord value12(LocalDateTime value) {
+    public TableForeignKeyDocumentRecord value13(LocalDateTime value) {
         setCreateAt(value);
         return this;
     }
 
     @Override
-    public TableForeignKeyDocumentRecord values(Integer value1, Integer value2, Integer value3, String value4, String value5, String value6, String value7, String value8, String value9, String value10, String value11, LocalDateTime value12) {
+    public TableForeignKeyDocumentRecord values(Integer value1, Integer value2, Integer value3, Integer value4, String value5, String value6, String value7, String value8, String value9, String value10, String value11, String value12, LocalDateTime value13) {
         value1(value1);
         value2(value2);
         value3(value3);
@@ -497,6 +532,7 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
         value10(value10);
         value11(value11);
         value12(value12);
+        value13(value13);
         return this;
     }
 
@@ -514,12 +550,13 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
     /**
      * Create a detached, initialised TableForeignKeyDocumentRecord
      */
-    public TableForeignKeyDocumentRecord(Integer id, Integer tableDocumentId, Integer databaseDocumentId, String fkName, String fkTableName, String fkColumnName, String pkName, String pkTableName, String pkColumnName, String updateRule, String deleteRule, LocalDateTime createAt) {
+    public TableForeignKeyDocumentRecord(Integer id, Integer tableDocumentId, Integer databaseDocumentId, Integer keySeq, String fkName, String fkTableName, String fkColumnName, String pkName, String pkTableName, String pkColumnName, String updateRule, String deleteRule, LocalDateTime createAt) {
         super(TableForeignKeyDocument.TABLE_FOREIGN_KEY_DOCUMENT);
 
         setId(id);
         setTableDocumentId(tableDocumentId);
         setDatabaseDocumentId(databaseDocumentId);
+        setKeySeq(keySeq);
         setFkName(fkName);
         setFkTableName(fkTableName);
         setFkColumnName(fkColumnName);
@@ -541,6 +578,7 @@ public class TableForeignKeyDocumentRecord extends UpdatableRecordImpl<TableFore
             setId(value.getId());
             setTableDocumentId(value.getTableDocumentId());
             setDatabaseDocumentId(value.getDatabaseDocumentId());
+            setKeySeq(value.getKeySeq());
             setFkName(value.getFkName());
             setFkTableName(value.getFkTableName());
             setFkColumnName(value.getFkColumnName());
diff --git a/dao/src/main/resources/db/migration/V1__init.sql b/dao/src/main/resources/db/migration/V1__init.sql
index e50d9da..1db5027 100644
--- a/dao/src/main/resources/db/migration/V1__init.sql
+++ b/dao/src/main/resources/db/migration/V1__init.sql
@@ -136,11 +136,11 @@ CREATE TABLE IF NOT EXISTS table_document
 (
 
     id                   INT PRIMARY KEY AUTO_INCREMENT,
-    database_document_id INT       NOT NULL,
-    name                 TEXT      NOT NULL,
-    type                 TEXT      NOT NULL,
-    comment              TEXT      NOT NULL,
-    create_at            TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    database_document_id INT          NOT NULL,
+    name                 TEXT         NOT NULL,
+    type                 VARCHAR(255) NOT NULL,
+    comment              VARCHAR(512)          DEFAULT NULL,
+    create_at            TIMESTAMP    NOT NULL DEFAULT CURRENT_TIMESTAMP,
     INDEX idx_database_document_id (database_document_id)
 ) CHARSET utf8mb4
   COLLATE utf8mb4_unicode_ci;
@@ -153,7 +153,7 @@ CREATE TABLE IF NOT EXISTS table_column_document
     database_document_id INT          NOT NULL,
     name                 TEXT         NOT NULL,
     type                 VARCHAR(255) NOT NULL,
-    comment              VARCHAR(512) NOT NULL,
+    comment              VARCHAR(512)          DEFAULT NULL,
     default_value        VARCHAR(512)          DEFAULT NULL,
     size                 INT          NOT NULL,
     decimal_digits       INT                   DEFAULT NULL,
@@ -171,6 +171,7 @@ CREATE TABLE IF NOT EXISTS table_foreign_key_document
     id                   INT PRIMARY KEY AUTO_INCREMENT,
     table_document_id    INT          NOT NULL,
     database_document_id INT          NOT NULL,
+    key_seq              INT          NOT NULL DEFAULT 0,
     fk_name              VARCHAR(255)          DEFAULT NULL,
     fk_table_name        VARCHAR(512) NOT NULL,
     fk_column_name       VARCHAR(512) NOT NULL,
diff --git a/plugin/src/main/java/com/databasir/core/diff/processor/ForeignKeyDiffProcessor.java b/plugin/src/main/java/com/databasir/core/diff/processor/ForeignKeyDiffProcessor.java
index 59f2d1a..8d8e537 100644
--- a/plugin/src/main/java/com/databasir/core/diff/processor/ForeignKeyDiffProcessor.java
+++ b/plugin/src/main/java/com/databasir/core/diff/processor/ForeignKeyDiffProcessor.java
@@ -15,7 +15,7 @@ public class ForeignKeyDiffProcessor implements DiffProcessor<ForeignKeyMeta> {
                 "foreignKeys",
                 fk -> {
                     if (fk.getFkName() == null) {
-                        return fk.getFkTableName() + "." + fk.getFkColumnName() + "." + fk.getKeySql();
+                        return fk.getFkTableName() + "." + fk.getFkColumnName() + "." + fk.getKeySeq();
                     } else {
                         return fk.getFkName();
                     }
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
index 65a4307..5a025d2 100644
--- a/plugin/src/main/java/com/databasir/core/meta/data/ForeignKeyMeta.java
+++ b/plugin/src/main/java/com/databasir/core/meta/data/ForeignKeyMeta.java
@@ -11,7 +11,7 @@ import lombok.NoArgsConstructor;
 @AllArgsConstructor
 public class ForeignKeyMeta {
 
-    private Integer keySql;
+    private Integer keySeq;
 
     /**
      * may null
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
index 7c51ecd..dea1089 100644
--- 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
@@ -41,10 +41,10 @@ public class JdbcForeignKeyMetaRepository implements ForeignKeyMetaRepository {
                 String pkColumnName = keyResult.getString("PKCOLUMN_NAME");
                 String pkName = keyResult.getString("PK_NAME");
                 int updateRule = keyResult.getInt("UPDATE_RULE");
-                int keySql = keyResult.getInt("KEY_SEQ");
+                int keySeq = keyResult.getInt("KEY_SEQ");
                 int deleteRule = keyResult.getInt("DELETE_RULE");
                 ForeignKeyMeta meta = ForeignKeyMeta.builder()
-                        .keySql(keySql)
+                        .keySeq(keySeq)
                         .fkTableName(fkTableName)
                         .fkColumnName(fkColumnName)
                         .fkName(fkName)
diff --git a/plugin/src/main/java/com/databasir/core/render/markdown/MarkdownRender.java b/plugin/src/main/java/com/databasir/core/render/markdown/MarkdownRender.java
index 7e90dda..c968fe6 100644
--- a/plugin/src/main/java/com/databasir/core/render/markdown/MarkdownRender.java
+++ b/plugin/src/main/java/com/databasir/core/render/markdown/MarkdownRender.java
@@ -51,7 +51,7 @@ public class MarkdownRender implements Render {
 
     private void buildTableName(MarkdownBuilder contentBuilder, TableMeta table) {
         String tableName;
-        if (table.getComment() == null || table.getComment().trim().isEmpty()) {
+        if (table.getComment().isEmpty()) {
             tableName = table.getName();
         } else {
             tableName = table.getName() + "(" + table.getComment() + ")";