Browse Source

feature: code redesign

master
vran 3 years ago
parent
commit
29b9e8e50f
  1. 62
      README.md
  2. 2
      build.gradle
  3. 46
      core/src/main/java/com/databasir/core/Databasir.java
  4. 39
      core/src/main/java/com/databasir/core/DatabasirConfig.java
  5. 49
      core/src/main/java/com/databasir/core/doc/factory/DatabaseDocConfig.java
  6. 11
      core/src/main/java/com/databasir/core/doc/factory/DatabaseDocFactory.java
  7. 16
      core/src/main/java/com/databasir/core/doc/factory/Sortable.java
  8. 12
      core/src/main/java/com/databasir/core/doc/factory/TableColumnDocFactory.java
  9. 12
      core/src/main/java/com/databasir/core/doc/factory/TableDocFactory.java
  10. 12
      core/src/main/java/com/databasir/core/doc/factory/TableIndexDocFactory.java
  11. 11
      core/src/main/java/com/databasir/core/doc/factory/TableTriggerDocFactory.java
  12. 45
      core/src/main/java/com/databasir/core/doc/factory/jdbc/JdbcDatabaseDocFactory.java
  13. 59
      core/src/main/java/com/databasir/core/doc/factory/jdbc/JdbcTableDocFactory.java
  14. 64
      core/src/main/java/com/databasir/core/doc/factory/jdbc/JdbcTableIndexDocFactory.java
  15. 18
      core/src/main/java/com/databasir/core/doc/factory/jdbc/JdbcTableTriggerDocFactory.java
  16. 16
      core/src/main/java/com/databasir/core/doc/render/Render.java
  17. 0
      core/src/main/java/com/databasir/core/doc/render/pdf/.gitkeep
  18. 4
      core/src/main/java/com/databasir/core/meta/pojo/ColumnMeta.java
  19. 21
      core/src/main/java/com/databasir/core/meta/pojo/DatabaseMeta.java
  20. 4
      core/src/main/java/com/databasir/core/meta/pojo/IndexMeta.java
  21. 10
      core/src/main/java/com/databasir/core/meta/pojo/TableMeta.java
  22. 4
      core/src/main/java/com/databasir/core/meta/pojo/TriggerMeta.java
  23. 80
      core/src/main/java/com/databasir/core/meta/provider/SqlProvider.java
  24. 13
      core/src/main/java/com/databasir/core/meta/repository/ColumnMetaRepository.java
  25. 13
      core/src/main/java/com/databasir/core/meta/repository/DatabaseMetaRepository.java
  26. 12
      core/src/main/java/com/databasir/core/meta/repository/IndexMetaRepository.java
  27. 13
      core/src/main/java/com/databasir/core/meta/repository/TableMetaRepository.java
  28. 13
      core/src/main/java/com/databasir/core/meta/repository/TriggerMetaRepository.java
  29. 32
      core/src/main/java/com/databasir/core/meta/repository/condition/Condition.java
  30. 24
      core/src/main/java/com/databasir/core/meta/repository/condition/TableCondition.java
  31. 29
      core/src/main/java/com/databasir/core/meta/repository/impl/extension/MysqlTableTriggerMetaRepository.java
  32. 40
      core/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcColumnMetaRepository.java
  33. 47
      core/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcDatabaseMetaRepository.java
  34. 59
      core/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcIndexMetaRepository.java
  35. 66
      core/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcTableMetaRepository.java
  36. 18
      core/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcTriggerMetaRepository.java
  37. 16
      core/src/main/java/com/databasir/core/render/Render.java
  38. 36
      core/src/main/java/com/databasir/core/render/RenderConfig.java
  39. 0
      core/src/main/java/com/databasir/core/render/html/.gitkeep
  40. 2
      core/src/main/java/com/databasir/core/render/markdown/MarkdownBuilder.java
  41. 28
      core/src/main/java/com/databasir/core/render/markdown/MarkdownRender.java
  42. 0
      core/src/main/java/com/databasir/core/render/pdf/.gitkeep
  43. 41
      core/src/test/java/App.java

62
README.md

@ -10,30 +10,23 @@ you could use `databasir` to generate database meta model, or render it as markd
```java ```java
java.sql.Connection connection=...; java.sql.Connection connection=...;
DatabaseDocConfig config = DatabaseDocConfig.builder() DatabaseMeta meta=Databasir.of().get(connection,"user").orElseThrow();
.databaseName("Demo")
.connection(connection)
.build();
DatabaseDoc doc = JdbcDatabaseDocFactory.of().create(config).orElseThrow();
``` ```
## Render as Markdown ## Render as Markdown
```java ```java
try(FileOutputStream out=new FileOutputStream("user.md")){
java.sql.Connection connection=...; java.sql.Connection connection=...;
DatabaseDocConfig config = DatabaseDocConfig.builder() Databasir databasir=Databasir.of();
.databaseName("Demo") DatabaseMeta meta=databasir.get(connection,"user").orElseThrow();
.connection(connection) databasir.renderAsMarkdown(doc,out);
.build();
DatabaseDoc doc = JdbcDatabaseDocFactory.of().create(config).orElseThrow();
try (FileOutputStream out = new FileOutputStream("doc.md")) {
RenderConfig renderConfig = new RenderConfig();
Render.markdownRender(renderConfig).rendering(doc, out);
}catch(IOException e){ }catch(IOException e){
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
``` ```
- Example - Markdown Example
![](README/table-doc.png) ![](README/table-doc.png)
@ -44,36 +37,31 @@ support regex pattern to ignore table or column
```java ```java
java.sql.Connection connection=...; java.sql.Connection connection=...;
DatabaseDocConfig config = DatabaseDocConfig.builder() DatabasirConfig config=new DatabasirConfig();
.databaseName("Demo") config.ignoreColumn("id*");
.connection(connection) config.ignoreTable("flyway.*");
.ignoreTableRegexes(Arrays.asList("mysql_*")) DatabaseMeta meta=Databasir.of(config).get(connection,"user").orElseThrow();
.ignoreColumnRegexes(Arrays.asList("id"))
.build();
DatabaseDoc doc = JdbcDatabaseDocFactory.of().create(config).orElseThrow();
``` ```
## Extension ## Extension
Default factory
- tableDocFactory -> `com.databasir.core.doc.factory.jdbc.JdbcTableDocFactory`
- columnDocFactory -> `com.databasir.core.doc.factory.jdbc.JdbcTableColumnDocFactory`
- indexDocFactory -> `com.databasir.core.doc.factory.jdbc.JdbcTableIndexDocFactory`
- triggerDocFactory -> `com.databasir.core.doc.factory.jdbc.JdbcTableTriggerDocFactory`
Custom configuration Custom configuration
```java ```java
java.sql.Connection connection=...; java.sql.Connection connection=...;
DatabaseDocConfig config = DatabaseDocConfig.builder() DatabasirConfig config=new DatabasirConfig();
.databaseName("Demo") config.setDatabaseMetaRepository(...); // your custom repository
.connection(connection) config.setTableMetaRepository(...); // your custom repository
.tableDocFactory(...) // your custom table doc factory config.setColumnMetaRepository(...); // your custom repository
.tableColumnDocFactory(...) // your custom column doc factory config.setTriggerMetaRepository(...); // your custom repository
.tableIndexDocFactory(...) // your custom index doc factory config.setIndexMetaRepository(...); // your custom repository
.tableTriggerDocFactory(...) // your custom trigger doc factory DatabaseMeta meta=Databasir.of().get(connection,"user").orElseThrow();
.build();
DatabaseDoc doc = JdbcDatabaseDocFactory.of().create(config).orElseThrow();
``` ```
Default Repository Is
- com.databasir.core.meta.repository.impl.jdbc.JdbcDatabaseMetaRepository
- com.databasir.core.meta.repository.impl.jdbc.JdbcTableMetaRepository
- com.databasir.core.meta.repository.impl.jdbc.JdbcColumnMetaRepository
- com.databasir.core.meta.repository.impl.jdbc.JdbcIndexMetaRepository
- com.databasir.core.meta.repository.impl.jdbc.JdbcTriggerMetaRepository

2
build.gradle

@ -6,7 +6,7 @@ subprojects {
apply plugin: 'java' apply plugin: 'java'
group 'cc.cc1234' group 'com.databasir'
version '1.0-SNAPSHOT' version '1.0-SNAPSHOT'
repositories { repositories {

46
core/src/main/java/com/databasir/core/Databasir.java

@ -0,0 +1,46 @@
package com.databasir.core;
import com.databasir.core.meta.pojo.DatabaseMeta;
import com.databasir.core.meta.repository.condition.Condition;
import com.databasir.core.render.Render;
import com.databasir.core.render.RenderConfig;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.Connection;
import java.util.Optional;
@RequiredArgsConstructor
@Getter
public class Databasir {
private final DatabasirConfig config;
public Optional<DatabaseMeta> get(Connection connection, String databaseName) {
Condition condition = Condition.builder()
.databaseName(databaseName)
.ignoreTableNameRegex(config.getIgnoreTableNameRegex())
.ignoreTableColumnNameRegex(config.getIgnoreTableColumnNameRegex())
.build();
return config.getDatabaseMetaRepository().select(connection, condition);
}
public void renderAsMarkdown(DatabaseMeta meta, OutputStream out) throws IOException {
renderAsMarkdown(new RenderConfig(), meta, out);
}
public void renderAsMarkdown(RenderConfig config, DatabaseMeta meta, OutputStream stream) throws IOException {
Render.markdownRender(config).rendering(meta, stream);
}
public static Databasir of() {
return of(new DatabasirConfig());
}
public static Databasir of(DatabasirConfig config) {
return new Databasir(config);
}
}

39
core/src/main/java/com/databasir/core/DatabasirConfig.java

@ -0,0 +1,39 @@
package com.databasir.core;
import com.databasir.core.meta.repository.*;
import com.databasir.core.meta.repository.impl.jdbc.*;
import lombok.Getter;
import lombok.Setter;
import java.util.Collection;
import java.util.HashSet;
@Getter
@Setter
public class DatabasirConfig {
private IndexMetaRepository indexMetaRepository = new JdbcIndexMetaRepository();
private TriggerMetaRepository triggerMetaRepository = new JdbcTriggerMetaRepository();
private ColumnMetaRepository columnMetaRepository = new JdbcColumnMetaRepository();
private TableMetaRepository tableMetaRepository =
new JdbcTableMetaRepository(columnMetaRepository, indexMetaRepository, triggerMetaRepository);
private DatabaseMetaRepository databaseMetaRepository = new JdbcDatabaseMetaRepository(tableMetaRepository);
private Collection<String> ignoreTableNameRegex = new HashSet<>();
private Collection<String> ignoreTableColumnNameRegex = new HashSet<>();
public DatabasirConfig ignoreTable(String tableNameRegex) {
ignoreTableNameRegex.add(tableNameRegex);
return this;
}
public DatabasirConfig ignoreColumn(String columnNameRegex) {
ignoreTableColumnNameRegex.add(columnNameRegex);
return this;
}
}

49
core/src/main/java/com/databasir/core/doc/factory/DatabaseDocConfig.java

@ -1,49 +0,0 @@
package com.databasir.core.doc.factory;
import com.databasir.core.doc.factory.jdbc.*;
import lombok.Builder;
import lombok.Getter;
import lombok.NonNull;
import java.sql.Connection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
@Builder
@Getter
public class DatabaseDocConfig {
@NonNull
private String databaseName;
@NonNull
private Connection connection;
@Builder.Default
private List<String> ignoreTableRegexes = Collections.emptyList();
@Builder.Default
private List<String> ignoreColumnRegexes = Collections.emptyList();
@Builder.Default
private TableDocFactory tableDocFactory = new JdbcTableDocFactory();
@Builder.Default
private TableIndexDocFactory tableIndexDocFactory = new JdbcTableIndexDocFactory();
@Builder.Default
private TableTriggerDocFactory tableTriggerDocFactory = new JdbcTableTriggerDocFactory();
@Builder.Default
private TableColumnDocFactory tableColumnDocFactory = new JdbcTableColumnDocFactory();
public boolean tableIsIgnored(String tableName) {
return ignoreTableRegexes.stream().anyMatch(regex -> Pattern.matches(regex, tableName));
}
public boolean columnIsIgnored(String column) {
return ignoreColumnRegexes.stream().anyMatch(regex -> Pattern.matches(regex, column));
}
}

11
core/src/main/java/com/databasir/core/doc/factory/DatabaseDocFactory.java

@ -1,11 +0,0 @@
package com.databasir.core.doc.factory;
import com.databasir.core.doc.model.DatabaseDoc;
import java.util.Optional;
public interface DatabaseDocFactory extends Sortable<DatabaseDocFactory> {
Optional<DatabaseDoc> create(DatabaseDocConfig configuration);
}

16
core/src/main/java/com/databasir/core/doc/factory/Sortable.java

@ -1,16 +0,0 @@
package com.databasir.core.doc.factory;
public interface Sortable<T extends Sortable<?>> extends Comparable<T> {
/**
* @return priority, min -> max means low -> high
*/
default int order() {
return Integer.MIN_VALUE;
}
@Override
default int compareTo(T o) {
return Integer.compare(this.order(), o.order());
}
}

12
core/src/main/java/com/databasir/core/doc/factory/TableColumnDocFactory.java

@ -1,12 +0,0 @@
package com.databasir.core.doc.factory;
import com.databasir.core.doc.model.ColumnDoc;
import java.sql.DatabaseMetaData;
import java.util.List;
public interface TableColumnDocFactory extends Sortable<TableColumnDocFactory> {
List<ColumnDoc> create(String tableName, DatabaseMetaData metaData, DatabaseDocConfig configuration);
}

12
core/src/main/java/com/databasir/core/doc/factory/TableDocFactory.java

@ -1,12 +0,0 @@
package com.databasir.core.doc.factory;
import com.databasir.core.doc.model.TableDoc;
import java.sql.DatabaseMetaData;
import java.util.List;
public interface TableDocFactory extends Sortable<TableDocFactory> {
List<TableDoc> create(DatabaseMetaData metaData, DatabaseDocConfig configuration);
}

12
core/src/main/java/com/databasir/core/doc/factory/TableIndexDocFactory.java

@ -1,12 +0,0 @@
package com.databasir.core.doc.factory;
import com.databasir.core.doc.model.IndexDoc;
import java.sql.DatabaseMetaData;
import java.util.List;
public interface TableIndexDocFactory extends Sortable<TableIndexDocFactory> {
List<IndexDoc> create(String tableName, DatabaseMetaData metaData, DatabaseDocConfig configuration);
}

11
core/src/main/java/com/databasir/core/doc/factory/TableTriggerDocFactory.java

@ -1,11 +0,0 @@
package com.databasir.core.doc.factory;
import com.databasir.core.doc.model.TriggerDoc;
import java.sql.DatabaseMetaData;
import java.util.List;
public interface TableTriggerDocFactory extends Sortable<TableTriggerDocFactory> {
List<TriggerDoc> create(String tableName, DatabaseMetaData metaData, DatabaseDocConfig configuration);
}

45
core/src/main/java/com/databasir/core/doc/factory/jdbc/JdbcDatabaseDocFactory.java

@ -1,45 +0,0 @@
package com.databasir.core.doc.factory.jdbc;
import com.databasir.core.doc.factory.DatabaseDocConfig;
import com.databasir.core.doc.factory.*;
import com.databasir.core.doc.model.DatabaseDoc;
import com.databasir.core.doc.model.TableDoc;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
public class JdbcDatabaseDocFactory implements DatabaseDocFactory {
public static JdbcDatabaseDocFactory of() {
return new JdbcDatabaseDocFactory();
}
@Override
public Optional<DatabaseDoc> create(DatabaseDocConfig configuration) {
try {
DatabaseMetaData metaData = configuration.getConnection().getMetaData();
ResultSet catalogs = metaData.getCatalogs();
while (catalogs.next()) {
String catalogName = catalogs.getString("TABLE_CAT");
if (Objects.equals(configuration.getDatabaseName(), catalogName)) {
TableDocFactory tableDocFactory = configuration.getTableDocFactory();
List<TableDoc> tableDocs = tableDocFactory.create(metaData, configuration);
DatabaseDoc databaseDoc = DatabaseDoc.builder()
.productName(metaData.getDatabaseProductName())
.productVersion(metaData.getDatabaseProductVersion())
.databaseName(catalogName)
.tables(tableDocs)
.build();
return Optional.of(databaseDoc);
}
}
return Optional.empty();
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}
}

59
core/src/main/java/com/databasir/core/doc/factory/jdbc/JdbcTableDocFactory.java

@ -1,59 +0,0 @@
package com.databasir.core.doc.factory.jdbc;
import com.databasir.core.doc.factory.DatabaseDocConfig;
import com.databasir.core.doc.factory.*;
import com.databasir.core.doc.model.TableDoc;
import lombok.extern.slf4j.Slf4j;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class JdbcTableDocFactory implements TableDocFactory {
@Override
public List<TableDoc> create(DatabaseMetaData metaData,
DatabaseDocConfig configuration) {
try {
return doCreateTableDoc(metaData, configuration);
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}
private List<TableDoc> doCreateTableDoc(DatabaseMetaData metaData,
DatabaseDocConfig configuration) throws SQLException {
List<TableDoc> tableDocs = new ArrayList<>();
if (metaData == null) {
return tableDocs;
}
String databaseName = configuration.getDatabaseName();
ResultSet tablesResult = metaData.getTables(databaseName, null, null, null);
while (tablesResult.next()) {
String tableName = tablesResult.getString("TABLE_NAME");
if (configuration.tableIsIgnored(tableName)) {
if (log.isWarnEnabled()) {
log.warn("ignore table: " + configuration.getDatabaseName() + "." + tableName);
}
} else {
String tableType = tablesResult.getString("TABLE_TYPE");
String tableComment = tablesResult.getString("REMARKS");
TableDoc tableDoc = TableDoc.builder()
.tableName(tableName)
.tableType(tableType)
.tableComment(tableComment)
.columns(configuration.getTableColumnDocFactory().create(tableName, metaData, configuration))
.indexes(configuration.getTableIndexDocFactory().create(tableName, metaData, configuration))
.triggers(configuration.getTableTriggerDocFactory().create(tableName, metaData, configuration))
.build();
tableDocs.add(tableDoc);
}
}
return tableDocs;
}
}

64
core/src/main/java/com/databasir/core/doc/factory/jdbc/JdbcTableIndexDocFactory.java

@ -1,64 +0,0 @@
package com.databasir.core.doc.factory.jdbc;
import com.databasir.core.doc.factory.DatabaseDocConfig;
import com.databasir.core.doc.factory.TableIndexDocFactory;
import com.databasir.core.doc.model.IndexDoc;
import lombok.extern.slf4j.Slf4j;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
@Slf4j
public class JdbcTableIndexDocFactory implements TableIndexDocFactory {
@Override
public List<IndexDoc> create(String tableName, DatabaseMetaData metaData, DatabaseDocConfig configuration) {
try {
return doCreateIndexDocs(tableName, metaData, configuration);
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}
private List<IndexDoc> doCreateIndexDocs(String tableName,
DatabaseMetaData metaData,
DatabaseDocConfig configuration)
throws SQLException {
List<IndexDoc> indexDocs = new ArrayList<>();
String databaseName = configuration.getDatabaseName();
if (tableName == null || metaData == null) {
return indexDocs;
}
ResultSet indexResults;
try {
indexResults = metaData.getIndexInfo(databaseName, null, tableName, false, false);
} catch (SQLException e) {
log.warn("warn: ignore " + databaseName + "." + tableName);
return indexDocs;
}
Map<String, IndexDoc> docsGroupByName = new HashMap<>();
while (indexResults.next()) {
Boolean nonUnique = indexResults.getBoolean("NON_UNIQUE");
String indexName = indexResults.getString("INDEX_NAME");
String columnName = indexResults.getString("COLUMN_NAME");
if (docsGroupByName.containsKey(indexName)) {
docsGroupByName.get(indexName).getColumnNames().add(columnName);
} else {
List<String> columns = new ArrayList<>();
columns.add(columnName);
IndexDoc columnDoc = IndexDoc.builder()
.indexName(indexName)
.columnNames(columns)
.isPrimaryKey(Objects.equals("PRIMARY", indexName))
.isUniqueKey(Objects.equals(nonUnique, false))
.build();
docsGroupByName.put(indexName, columnDoc);
}
}
return new ArrayList<>(docsGroupByName.values());
}
}

18
core/src/main/java/com/databasir/core/doc/factory/jdbc/JdbcTableTriggerDocFactory.java

@ -1,18 +0,0 @@
package com.databasir.core.doc.factory.jdbc;
import com.databasir.core.doc.factory.DatabaseDocConfig;
import com.databasir.core.doc.factory.TableTriggerDocFactory;
import com.databasir.core.doc.model.TriggerDoc;
import java.sql.DatabaseMetaData;
import java.util.Collections;
import java.util.List;
public class JdbcTableTriggerDocFactory implements TableTriggerDocFactory {
@Override
public List<TriggerDoc> create(String tableName, DatabaseMetaData metaData, DatabaseDocConfig configuration) {
// note: jdbc not support get triggers
return Collections.emptyList();
}
}

16
core/src/main/java/com/databasir/core/doc/render/Render.java

@ -1,16 +0,0 @@
package com.databasir.core.doc.render;
import com.databasir.core.doc.model.DatabaseDoc;
import com.databasir.core.doc.render.markdown.MarkdownRender;
import java.io.IOException;
import java.io.OutputStream;
public interface Render {
void rendering(DatabaseDoc doc, OutputStream outputStream) throws IOException;
static Render markdownRender(RenderConfig configuration) {
return MarkdownRender.of(configuration);
}
}

0
core/src/main/java/com/databasir/core/doc/render/pdf/.gitkeep

4
core/src/main/java/com/databasir/core/doc/model/ColumnDoc.java → core/src/main/java/com/databasir/core/meta/pojo/ColumnMeta.java

@ -1,11 +1,11 @@
package com.databasir.core.doc.model; package com.databasir.core.meta.pojo;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
@Data @Data
@Builder @Builder
public class ColumnDoc { public class ColumnMeta {
private String name; private String name;

21
core/src/main/java/com/databasir/core/doc/model/DatabaseDoc.java → core/src/main/java/com/databasir/core/meta/pojo/DatabaseMeta.java

@ -1,4 +1,4 @@
package com.databasir.core.doc.model; package com.databasir.core.meta.pojo;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
@ -8,21 +8,36 @@ import java.util.List;
@Data @Data
@Builder @Builder
public class DatabaseDoc { public class DatabaseMeta {
/**
* product_name
*/
private String productName; private String productName;
/**
* product_version
*/
private String productVersion; private String productVersion;
/**
* driver_name
*/
private String driverName; private String driverName;
/**
* driver_version
*/
private String driverVersion; private String driverVersion;
/**
* database_name
*/
private String databaseName; private String databaseName;
private String remark; private String remark;
@Builder.Default @Builder.Default
private List<TableDoc> tables = Collections.emptyList(); private List<TableMeta> tables = Collections.emptyList();
} }

4
core/src/main/java/com/databasir/core/doc/model/IndexDoc.java → core/src/main/java/com/databasir/core/meta/pojo/IndexMeta.java

@ -1,4 +1,4 @@
package com.databasir.core.doc.model; package com.databasir.core.meta.pojo;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
@ -8,7 +8,7 @@ import java.util.List;
@Data @Data
@Builder @Builder
public class IndexDoc { public class IndexMeta {
private String indexName; private String indexName;

10
core/src/main/java/com/databasir/core/doc/model/TableDoc.java → core/src/main/java/com/databasir/core/meta/pojo/TableMeta.java

@ -1,4 +1,4 @@
package com.databasir.core.doc.model; package com.databasir.core.meta.pojo;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
@ -8,7 +8,7 @@ import java.util.List;
@Data @Data
@Builder @Builder
public class TableDoc { public class TableMeta {
private String tableName; private String tableName;
@ -17,13 +17,13 @@ public class TableDoc {
private String tableComment; private String tableComment;
@Builder.Default @Builder.Default
private List<ColumnDoc> columns = Collections.emptyList(); private List<ColumnMeta> columns = Collections.emptyList();
@Builder.Default @Builder.Default
private List<TriggerDoc> triggers = Collections.emptyList(); private List<TriggerMeta> triggers = Collections.emptyList();
@Builder.Default @Builder.Default
private List<IndexDoc> indexes = Collections.emptyList(); private List<IndexMeta> indexes = Collections.emptyList();
private String remark; private String remark;
} }

4
core/src/main/java/com/databasir/core/doc/model/TriggerDoc.java → core/src/main/java/com/databasir/core/meta/pojo/TriggerMeta.java

@ -1,4 +1,4 @@
package com.databasir.core.doc.model; package com.databasir.core.meta.pojo;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
@ -8,7 +8,7 @@ import lombok.Data;
*/ */
@Data @Data
@Builder @Builder
public class TriggerDoc { public class TriggerMeta {
private String name; private String name;

80
core/src/main/java/com/databasir/core/meta/provider/SqlProvider.java

@ -0,0 +1,80 @@
package com.databasir.core.meta.provider;
import java.util.Optional;
/**
* TODO use to extension repository
*/
public interface SqlProvider {
Default DEFAULT = new Default();
/**
* <p>
* generate sql to select database information, should return the follow columns
* </p>
*
* <table>
* <tr>
* <th> column name </th>
* <th> column type </th>
* <th> description </th>
* <th> nullable </th>
* </tr>
* <tr>
* <td> TABLE_CAT </td>
* <td> String </td>
* <td> catalog name </td>
* <td> NO </td>
* </tr>
* </table>
* <br>
*
* @param databaseName
* @return
*/
default Optional<String> databaseMetaSql(String databaseName) {
return Optional.empty();
}
/**
* generate sql to select table information, should return the follow columns
* <table>
* <tr>
* <th> column name </th>
* <th> column type </th>
* <th> description </th>
* <th> nullable </th>
* </tr>
* <tr>
* <td> TABLE_CAT </td>
* <td> String </td>
* <td> catalog name </td>
* <td> NO </td>
* </tr>
* </table>
*
* @param databaseName
* @param tableName
* @return
*/
default Optional<String> tableMetaSql(String databaseName, String tableName) {
return Optional.empty();
}
default Optional<String> tableColumnMetaSql(String databaseName, String tableName) {
return Optional.empty();
}
default Optional<String> tableIndexMetaSql(String databaseName, String tableName) {
return Optional.empty();
}
default Optional<String> tableTriggerMetaSql(String databaseName, String tableName) {
return Optional.empty();
}
class Default implements SqlProvider {
}
}

13
core/src/main/java/com/databasir/core/meta/repository/ColumnMetaRepository.java

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

13
core/src/main/java/com/databasir/core/meta/repository/DatabaseMetaRepository.java

@ -0,0 +1,13 @@
package com.databasir.core.meta.repository;
import com.databasir.core.meta.pojo.DatabaseMeta;
import com.databasir.core.meta.repository.condition.Condition;
import java.sql.Connection;
import java.util.Optional;
public interface DatabaseMetaRepository {
Optional<DatabaseMeta> select(Connection connection, Condition condition);
}

12
core/src/main/java/com/databasir/core/meta/repository/IndexMetaRepository.java

@ -0,0 +1,12 @@
package com.databasir.core.meta.repository;
import com.databasir.core.meta.pojo.IndexMeta;
import com.databasir.core.meta.repository.condition.TableCondition;
import java.sql.Connection;
import java.util.List;
public interface IndexMetaRepository {
List<IndexMeta> selectIndexes(Connection connection, TableCondition condition);
}

13
core/src/main/java/com/databasir/core/meta/repository/TableMetaRepository.java

@ -0,0 +1,13 @@
package com.databasir.core.meta.repository;
import com.databasir.core.meta.pojo.TableMeta;
import com.databasir.core.meta.repository.condition.Condition;
import java.sql.Connection;
import java.util.List;
public interface TableMetaRepository {
List<TableMeta> selectTables(Connection connection, Condition condition);
}

13
core/src/main/java/com/databasir/core/meta/repository/TriggerMetaRepository.java

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

32
core/src/main/java/com/databasir/core/meta/repository/condition/Condition.java

@ -0,0 +1,32 @@
package com.databasir.core.meta.repository.condition;
import lombok.Builder;
import lombok.Getter;
import lombok.NonNull;
import lombok.experimental.SuperBuilder;
import java.util.Collection;
import java.util.Collections;
import java.util.regex.Pattern;
@SuperBuilder
@Getter
public class Condition {
@NonNull
private String databaseName;
@Builder.Default
private Collection<String> ignoreTableNameRegex = Collections.emptyList();
@Builder.Default
private Collection<String> ignoreTableColumnNameRegex = Collections.emptyList();
public boolean tableIsIgnored(String tableName) {
return ignoreTableNameRegex.stream().anyMatch(regex -> Pattern.matches(regex, tableName));
}
public boolean columnIsIgnored(String column) {
return ignoreTableColumnNameRegex.stream().anyMatch(regex -> Pattern.matches(regex, column));
}
}

24
core/src/main/java/com/databasir/core/meta/repository/condition/TableCondition.java

@ -0,0 +1,24 @@
package com.databasir.core.meta.repository.condition;
import lombok.Getter;
import lombok.NonNull;
import lombok.experimental.SuperBuilder;
@SuperBuilder
@Getter
public class TableCondition extends Condition {
@NonNull
private String tableName;
public static TableCondition of(Condition condition, String tableName) {
return TableCondition.builder()
.databaseName(condition.getDatabaseName())
.tableName(tableName)
.ignoreTableNameRegex(condition.getIgnoreTableNameRegex())
.ignoreTableColumnNameRegex(condition.getIgnoreTableColumnNameRegex())
.build();
}
}

29
core/src/main/java/com/databasir/core/doc/factory/extension/mysql/MysqlTableTriggerDocFactory.java → core/src/main/java/com/databasir/core/meta/repository/impl/extension/MysqlTableTriggerMetaRepository.java

@ -1,11 +1,11 @@
package com.databasir.core.doc.factory.extension.mysql; package com.databasir.core.meta.repository.impl.extension;
import com.databasir.core.doc.factory.DatabaseDocConfig; import com.databasir.core.meta.pojo.TriggerMeta;
import com.databasir.core.doc.factory.TableTriggerDocFactory; import com.databasir.core.meta.repository.TriggerMetaRepository;
import com.databasir.core.doc.model.TriggerDoc; import com.databasir.core.meta.repository.condition.TableCondition;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.sql.DatabaseMetaData; import java.sql.Connection;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
@ -14,12 +14,10 @@ import java.util.Collections;
import java.util.List; import java.util.List;
@Slf4j @Slf4j
public class MysqlTableTriggerDocFactory implements TableTriggerDocFactory { public class MysqlTableTriggerMetaRepository implements TriggerMetaRepository {
@Override @Override
public List<TriggerDoc> create(String tableName, public List<TriggerMeta> selectTriggers(Connection connection, TableCondition condition) {
DatabaseMetaData metaData,
DatabaseDocConfig configuration) {
String sql = "SELECT TRIGGER_CATALOG,\n" + String sql = "SELECT TRIGGER_CATALOG,\n" +
" TRIGGER_SCHEMA,\n" + " TRIGGER_SCHEMA,\n" +
" TRIGGER_NAME,\n" + " TRIGGER_NAME,\n" +
@ -41,26 +39,25 @@ public class MysqlTableTriggerDocFactory implements TableTriggerDocFactory {
" DEFINER\n " + " DEFINER\n " +
"FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA = ? AND EVENT_OBJECT_TABLE = ?"; "FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA = ? AND EVENT_OBJECT_TABLE = ?";
try { try {
PreparedStatement preparedStatement = configuration.getConnection() PreparedStatement preparedStatement = connection.prepareStatement(sql);
.prepareStatement(sql); preparedStatement.setObject(1, condition.getDatabaseName());
preparedStatement.setObject(1, configuration.getDatabaseName()); preparedStatement.setObject(2, condition.getTableName());
preparedStatement.setObject(2, tableName);
ResultSet results = preparedStatement.executeQuery(); ResultSet results = preparedStatement.executeQuery();
List<TriggerDoc> triggers = new ArrayList<>(); List<TriggerMeta> triggers = new ArrayList<>();
while (results.next()) { while (results.next()) {
String name = results.getString("TRIGGER_NAME"); String name = results.getString("TRIGGER_NAME");
String statement = results.getString("ACTION_STATEMENT"); String statement = results.getString("ACTION_STATEMENT");
String timing = results.getString("ACTION_TIMING"); String timing = results.getString("ACTION_TIMING");
String manipulation = results.getString("EVENT_MANIPULATION"); String manipulation = results.getString("EVENT_MANIPULATION");
String created = results.getString("CREATED"); String created = results.getString("CREATED");
TriggerDoc doc = TriggerDoc.builder() TriggerMeta meta = TriggerMeta.builder()
.name(name) .name(name)
.manipulation(manipulation) .manipulation(manipulation)
.timing(timing) .timing(timing)
.statement(statement) .statement(statement)
.createAt(created) .createAt(created)
.build(); .build();
triggers.add(doc); triggers.add(meta);
} }
return triggers; return triggers;
} catch (SQLException e) { } catch (SQLException e) {

40
core/src/main/java/com/databasir/core/doc/factory/jdbc/JdbcTableColumnDocFactory.java → core/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcColumnMetaRepository.java

@ -1,11 +1,12 @@
package com.databasir.core.doc.factory.jdbc; package com.databasir.core.meta.repository.impl.jdbc;
import com.databasir.core.doc.factory.DatabaseDocConfig; import com.databasir.core.meta.pojo.ColumnMeta;
import com.databasir.core.doc.factory.TableColumnDocFactory; import com.databasir.core.meta.repository.ColumnMetaRepository;
import com.databasir.core.doc.model.ColumnDoc; import com.databasir.core.meta.repository.condition.TableCondition;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.sql.DatabaseMetaData; import java.sql.Connection;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
@ -13,34 +14,32 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
@Slf4j @Slf4j
public class JdbcTableColumnDocFactory implements TableColumnDocFactory { @RequiredArgsConstructor
public class JdbcColumnMetaRepository implements ColumnMetaRepository {
@Override @Override
public List<ColumnDoc> create(String tableName, public List<ColumnMeta> selectColumns(Connection connection, TableCondition tableCondition) {
DatabaseMetaData metaData,
DatabaseDocConfig configuration) {
try { try {
return doCreate(tableName, metaData, configuration); return doSelect(connection, tableCondition);
} catch (SQLException e) { } catch (SQLException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
} }
private List<ColumnDoc> doCreate(String tableName, private List<ColumnMeta> doSelect(Connection connection, TableCondition tableCondition) throws SQLException {
DatabaseMetaData metaData, List<ColumnMeta> columnDocs = new ArrayList<>();
DatabaseDocConfig configuration) throws SQLException { String databaseName = tableCondition.getDatabaseName();
List<ColumnDoc> columnDocs = new ArrayList<>(); String tableName = tableCondition.getTableName();
String database = configuration.getDatabaseName();
ResultSet columnsResult; ResultSet columnsResult;
try { try {
columnsResult = metaData.getColumns(database, null, tableName, null); columnsResult = connection.getMetaData().getColumns(databaseName, null, tableName, null);
} catch (SQLException e) { } catch (SQLException e) {
log.warn("warn: ignore columns in " + database + "." + tableName); log.warn("warn: ignore columns in " + databaseName + "." + tableName);
return columnDocs; return columnDocs;
} }
while (columnsResult.next()) { while (columnsResult.next()) {
String columnName = columnsResult.getString("COLUMN_NAME"); String columnName = columnsResult.getString("COLUMN_NAME");
if (configuration.columnIsIgnored(columnName)) { if (tableCondition.columnIsIgnored(columnName)) {
if (log.isWarnEnabled()) { if (log.isWarnEnabled()) {
log.warn("ignore column: " + columnName); log.warn("ignore column: " + columnName);
} }
@ -52,7 +51,7 @@ public class JdbcTableColumnDocFactory implements TableColumnDocFactory {
boolean isNullable = Objects.equals("YES", columnsResult.getString("IS_NULLABLE")); boolean isNullable = Objects.equals("YES", columnsResult.getString("IS_NULLABLE"));
boolean isAutoIncrement = Objects.equals("YES", columnsResult.getString("IS_AUTOINCREMENT")); boolean isAutoIncrement = Objects.equals("YES", columnsResult.getString("IS_AUTOINCREMENT"));
String columnComment = columnsResult.getString("REMARKS"); String columnComment = columnsResult.getString("REMARKS");
ColumnDoc columnDoc = ColumnDoc.builder() ColumnMeta columnMeta = ColumnMeta.builder()
.name(columnName) .name(columnName)
.type(columnType) .type(columnType)
.size(columnSize) .size(columnSize)
@ -62,11 +61,10 @@ public class JdbcTableColumnDocFactory implements TableColumnDocFactory {
.comment(columnComment) .comment(columnComment)
.defaultValue(defaultValue) .defaultValue(defaultValue)
.build(); .build();
columnDocs.add(columnDoc); columnDocs.add(columnMeta);
} }
} }
return columnDocs; return columnDocs;
} }
} }

47
core/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcDatabaseMetaRepository.java

@ -0,0 +1,47 @@
package com.databasir.core.meta.repository.impl.jdbc;
import com.databasir.core.meta.pojo.DatabaseMeta;
import com.databasir.core.meta.pojo.TableMeta;
import com.databasir.core.meta.repository.DatabaseMetaRepository;
import com.databasir.core.meta.repository.TableMetaRepository;
import com.databasir.core.meta.repository.condition.Condition;
import lombok.RequiredArgsConstructor;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@RequiredArgsConstructor
public class JdbcDatabaseMetaRepository implements DatabaseMetaRepository {
private final TableMetaRepository tableMetaRepository;
@Override
public Optional<DatabaseMeta> select(Connection connection, Condition condition) {
try {
DatabaseMetaData metaData = connection.getMetaData();
ResultSet catalogs = metaData.getCatalogs();
while (catalogs.next()) {
String catalogName = catalogs.getString("TABLE_CAT");
if (Objects.equals(condition.getDatabaseName(), catalogName)) {
List<TableMeta> tableDocs = tableMetaRepository.selectTables(connection, condition);
DatabaseMeta meta = DatabaseMeta.builder()
.productName(metaData.getDatabaseProductName())
.productVersion(metaData.getDatabaseProductVersion())
.databaseName(catalogName)
.tables(tableDocs)
.build();
return Optional.of(meta);
}
}
return Optional.empty();
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}
}

59
core/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcIndexMetaRepository.java

@ -0,0 +1,59 @@
package com.databasir.core.meta.repository.impl.jdbc;
import com.databasir.core.meta.pojo.IndexMeta;
import com.databasir.core.meta.repository.IndexMetaRepository;
import com.databasir.core.meta.repository.condition.TableCondition;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
@Slf4j
public class JdbcIndexMetaRepository implements IndexMetaRepository {
@Override
public List<IndexMeta> selectIndexes(Connection connection, TableCondition condition) {
try {
return doCreateIndexDocs(connection, condition);
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}
private List<IndexMeta> doCreateIndexDocs(Connection connection, TableCondition condition)
throws SQLException {
String databaseName = condition.getDatabaseName();
String tableName = condition.getTableName();
List<IndexMeta> indexMetas = new ArrayList<>();
ResultSet indexResults;
try {
indexResults = connection.getMetaData().getIndexInfo(databaseName, null, tableName, false, false);
} catch (SQLException e) {
log.warn("warn: ignore " + databaseName + "." + tableName);
return indexMetas;
}
Map<String, IndexMeta> pojoGroupByName = new HashMap<>();
while (indexResults.next()) {
Boolean nonUnique = indexResults.getBoolean("NON_UNIQUE");
String indexName = indexResults.getString("INDEX_NAME");
String columnName = indexResults.getString("COLUMN_NAME");
if (pojoGroupByName.containsKey(indexName)) {
pojoGroupByName.get(indexName).getColumnNames().add(columnName);
} else {
List<String> columns = new ArrayList<>();
columns.add(columnName);
IndexMeta indexMeta = IndexMeta.builder()
.indexName(indexName)
.columnNames(columns)
.isPrimaryKey(Objects.equals("PRIMARY", indexName))
.isUniqueKey(Objects.equals(nonUnique, false))
.build();
pojoGroupByName.put(indexName, indexMeta);
}
}
return new ArrayList<>(pojoGroupByName.values());
}
}

66
core/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcTableMetaRepository.java

@ -0,0 +1,66 @@
package com.databasir.core.meta.repository.impl.jdbc;
import com.databasir.core.meta.pojo.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.condition.Condition;
import com.databasir.core.meta.repository.condition.TableCondition;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
@RequiredArgsConstructor
@Slf4j
public class JdbcTableMetaRepository implements TableMetaRepository {
private final ColumnMetaRepository columnMetaRepository;
private final IndexMetaRepository indexMetaRepository;
private final TriggerMetaRepository triggerMetaRepository;
@Override
public List<TableMeta> selectTables(Connection connection, Condition condition) {
try {
return doSelect(connection, condition);
} catch (SQLException e) {
throw new IllegalStateException(e);
}
}
private List<TableMeta> doSelect(Connection connection, Condition condition) throws SQLException {
List<TableMeta> tableMetas = new ArrayList<>();
String databaseName = condition.getDatabaseName();
ResultSet tablesResult = connection.getMetaData().getTables(databaseName, null, null, null);
while (tablesResult.next()) {
String tableName = tablesResult.getString("TABLE_NAME");
if (condition.tableIsIgnored(tableName)) {
if (log.isWarnEnabled()) {
log.warn("ignored table: " + databaseName + "." + tableName);
}
} else {
String tableType = tablesResult.getString("TABLE_TYPE");
String tableComment = tablesResult.getString("REMARKS");
TableCondition tableCondition = TableCondition.of(condition, tableName);
TableMeta tableMeta = TableMeta.builder()
.tableName(tableName)
.tableType(tableType)
.tableComment(tableComment)
.columns(columnMetaRepository.selectColumns(connection, tableCondition))
.indexes(indexMetaRepository.selectIndexes(connection, tableCondition))
.triggers(triggerMetaRepository.selectTriggers(connection, tableCondition))
.build();
tableMetas.add(tableMeta);
}
}
return tableMetas;
}
}

18
core/src/main/java/com/databasir/core/meta/repository/impl/jdbc/JdbcTriggerMetaRepository.java

@ -0,0 +1,18 @@
package com.databasir.core.meta.repository.impl.jdbc;
import com.databasir.core.meta.pojo.TriggerMeta;
import com.databasir.core.meta.repository.TriggerMetaRepository;
import com.databasir.core.meta.repository.condition.TableCondition;
import java.sql.Connection;
import java.util.Collections;
import java.util.List;
public class JdbcTriggerMetaRepository implements TriggerMetaRepository {
@Override
public List<TriggerMeta> selectTriggers(Connection connection, TableCondition condition) {
// note: jdbc not support get triggers
return Collections.emptyList();
}
}

16
core/src/main/java/com/databasir/core/render/Render.java

@ -0,0 +1,16 @@
package com.databasir.core.render;
import com.databasir.core.meta.pojo.DatabaseMeta;
import com.databasir.core.render.markdown.MarkdownRender;
import java.io.IOException;
import java.io.OutputStream;
public interface Render {
void rendering(DatabaseMeta meta, OutputStream outputStream) throws IOException;
static Render markdownRender(RenderConfig configuration) {
return MarkdownRender.of(configuration);
}
}

36
core/src/main/java/com/databasir/core/doc/render/RenderConfig.java → core/src/main/java/com/databasir/core/render/RenderConfig.java

@ -1,8 +1,8 @@
package com.databasir.core.doc.render; package com.databasir.core.render;
import com.databasir.core.doc.model.ColumnDoc; import com.databasir.core.meta.pojo.ColumnMeta;
import com.databasir.core.doc.model.IndexDoc; import com.databasir.core.meta.pojo.IndexMeta;
import com.databasir.core.doc.model.TriggerDoc; import com.databasir.core.meta.pojo.TriggerMeta;
import lombok.Data; import lombok.Data;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -19,15 +19,15 @@ public class RenderConfig {
private Boolean renderTriggers = true; private Boolean renderTriggers = true;
private LinkedHashMap<String, Function<ColumnDoc, String>> columnTitleAndValueMapping = columnTitleAndValueMapping(); private LinkedHashMap<String, Function<ColumnMeta, String>> columnTitleAndValueMapping = columnTitleAndValueMapping();
private LinkedHashMap<String, Function<IndexDoc, String>> indexTitleAndValueMapping = indexTitleAndValueMapping(); private LinkedHashMap<String, Function<IndexMeta, String>> indexTitleAndValueMapping = indexTitleAndValueMapping();
private LinkedHashMap<String, Function<TriggerDoc, String>> triggerTitleAndValueMapping = triggerTitleAndValueMapping(); private LinkedHashMap<String, Function<TriggerMeta, String>> triggerTitleAndValueMapping = triggerTitleAndValueMapping();
protected LinkedHashMap<String, Function<ColumnDoc, String>> columnTitleAndValueMapping() { protected LinkedHashMap<String, Function<ColumnMeta, String>> columnTitleAndValueMapping() {
LinkedHashMap<String, Function<ColumnDoc, String>> mapping = new LinkedHashMap<>(); LinkedHashMap<String, Function<ColumnMeta, String>> mapping = new LinkedHashMap<>();
mapping.put("Name", ColumnDoc::getName); mapping.put("Name", ColumnMeta::getName);
mapping.put("Type", column -> { mapping.put("Type", column -> {
String type; String type;
if (column.getDecimalDigits() == null || column.getDecimalDigits().equals(0)) { if (column.getDecimalDigits() == null || column.getDecimalDigits().equals(0)) {
@ -50,26 +50,26 @@ public class RenderConfig {
} }
return column.getDefaultValue(); return column.getDefaultValue();
}); });
mapping.put("Comment", ColumnDoc::getComment); mapping.put("Comment", ColumnMeta::getComment);
return mapping; return mapping;
} }
protected LinkedHashMap<String, Function<IndexDoc, String>> indexTitleAndValueMapping() { protected LinkedHashMap<String, Function<IndexMeta, String>> indexTitleAndValueMapping() {
LinkedHashMap<String, Function<IndexDoc, String>> mapping = new LinkedHashMap<>(); LinkedHashMap<String, Function<IndexMeta, String>> mapping = new LinkedHashMap<>();
mapping.put("Name", IndexDoc::getIndexName); mapping.put("Name", IndexMeta::getIndexName);
mapping.put("IsPrimary", index -> index.getIsPrimaryKey() ? "YES" : ""); mapping.put("IsPrimary", index -> index.getIsPrimaryKey() ? "YES" : "");
mapping.put("IsUnique", index -> index.getIsUniqueKey() ? "YES" : ""); mapping.put("IsUnique", index -> index.getIsUniqueKey() ? "YES" : "");
mapping.put("Columns", index -> String.join(", ", index.getColumnNames())); mapping.put("Columns", index -> String.join(", ", index.getColumnNames()));
return mapping; return mapping;
} }
protected LinkedHashMap<String, Function<TriggerDoc, String>> triggerTitleAndValueMapping() { protected LinkedHashMap<String, Function<TriggerMeta, String>> triggerTitleAndValueMapping() {
LinkedHashMap<String, Function<TriggerDoc, String>> mapping = new LinkedHashMap<>(); LinkedHashMap<String, Function<TriggerMeta, String>> mapping = new LinkedHashMap<>();
mapping.put("Name", TriggerDoc::getName); mapping.put("Name", TriggerMeta::getName);
mapping.put("Timing", trigger -> trigger.getTiming() + " " + trigger.getManipulation()); mapping.put("Timing", trigger -> trigger.getTiming() + " " + trigger.getManipulation());
mapping.put("Statement", trigger -> trigger.getStatement().replace("\n", " ") mapping.put("Statement", trigger -> trigger.getStatement().replace("\n", " ")
.replace("\r", " ")); .replace("\r", " "));
mapping.put("Create At", TriggerDoc::getCreateAt); mapping.put("Create At", TriggerMeta::getCreateAt);
return mapping; return mapping;
} }
} }

0
core/src/main/java/com/databasir/core/doc/factory/extension/postgresql/.gitkeep → core/src/main/java/com/databasir/core/render/html/.gitkeep

2
core/src/main/java/com/databasir/core/doc/render/markdown/MarkdownBuilder.java → core/src/main/java/com/databasir/core/render/markdown/MarkdownBuilder.java

@ -1,4 +1,4 @@
package com.databasir.core.doc.render.markdown; package com.databasir.core.render.markdown;
import java.util.List; import java.util.List;

28
core/src/main/java/com/databasir/core/doc/render/markdown/MarkdownRender.java → core/src/main/java/com/databasir/core/render/markdown/MarkdownRender.java

@ -1,15 +1,17 @@
package com.databasir.core.doc.render.markdown; package com.databasir.core.render.markdown;
import com.databasir.core.doc.model.DatabaseDoc; import com.databasir.core.meta.pojo.DatabaseMeta;
import com.databasir.core.doc.model.TableDoc; import com.databasir.core.meta.pojo.TableMeta;
import com.databasir.core.doc.render.Render; import com.databasir.core.render.Render;
import com.databasir.core.doc.render.RenderConfig; import com.databasir.core.render.RenderConfig;
import lombok.Getter; import lombok.Getter;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class MarkdownRender implements Render { public class MarkdownRender implements Render {
@ -26,12 +28,12 @@ public class MarkdownRender implements Render {
} }
@Override @Override
public void rendering(DatabaseDoc doc, public void rendering(DatabaseMeta meta,
OutputStream outputStream) throws IOException { OutputStream outputStream) throws IOException {
MarkdownBuilder contentBuilder = MarkdownBuilder.builder(); MarkdownBuilder contentBuilder = MarkdownBuilder.builder();
contentBuilder.primaryTitle(doc.getDatabaseName()); contentBuilder.primaryTitle(meta.getDatabaseName());
if (config.getRenderTables()) { if (config.getRenderTables()) {
for (TableDoc table : doc.getTables()) { for (TableMeta table : meta.getTables()) {
buildTableName(contentBuilder, table); buildTableName(contentBuilder, table);
if (config.getRenderColumns()) { if (config.getRenderColumns()) {
buildColumns(contentBuilder, table); buildColumns(contentBuilder, table);
@ -47,7 +49,7 @@ public class MarkdownRender implements Render {
outputStream.write(contentBuilder.build().getBytes(StandardCharsets.UTF_8)); outputStream.write(contentBuilder.build().getBytes(StandardCharsets.UTF_8));
} }
private void buildTableName(MarkdownBuilder contentBuilder, TableDoc table) { private void buildTableName(MarkdownBuilder contentBuilder, TableMeta table) {
String tableName; String tableName;
if (table.getTableComment() == null || table.getTableComment().trim().isEmpty()) { if (table.getTableComment() == null || table.getTableComment().trim().isEmpty()) {
tableName = table.getTableName(); tableName = table.getTableName();
@ -57,7 +59,7 @@ public class MarkdownRender implements Render {
contentBuilder.secondTitle(tableName); contentBuilder.secondTitle(tableName);
} }
private void buildColumns(MarkdownBuilder contentBuilder, TableDoc table) { private void buildColumns(MarkdownBuilder contentBuilder, TableMeta table) {
contentBuilder.unorderedList(Collections.singletonList("columns")); contentBuilder.unorderedList(Collections.singletonList("columns"));
List<List<String>> allColumnRows = table.getColumns() List<List<String>> allColumnRows = table.getColumns()
.stream() .stream()
@ -70,7 +72,7 @@ public class MarkdownRender implements Render {
contentBuilder.table(tableTitles(), allColumnRows); contentBuilder.table(tableTitles(), allColumnRows);
} }
private void buildIndexes(MarkdownBuilder contentBuilder, TableDoc table) { private void buildIndexes(MarkdownBuilder contentBuilder, TableMeta table) {
contentBuilder.unorderedList(Collections.singletonList("indexes")); contentBuilder.unorderedList(Collections.singletonList("indexes"));
List<List<String>> allIndexRows = table.getIndexes().stream() List<List<String>> allIndexRows = table.getIndexes().stream()
.map(index -> config.getIndexTitleAndValueMapping() .map(index -> config.getIndexTitleAndValueMapping()
@ -82,7 +84,7 @@ public class MarkdownRender implements Render {
contentBuilder.table(indexTitles(), allIndexRows); contentBuilder.table(indexTitles(), allIndexRows);
} }
private void buildTriggers(MarkdownBuilder contentBuilder, TableDoc table) { private void buildTriggers(MarkdownBuilder contentBuilder, TableMeta table) {
if (table.getTriggers() == null || table.getTriggers().isEmpty()) { if (table.getTriggers() == null || table.getTriggers().isEmpty()) {
return; return;
} }

0
core/src/main/java/com/databasir/core/doc/render/html/.gitkeep → core/src/main/java/com/databasir/core/render/pdf/.gitkeep

41
core/src/test/java/App.java

@ -1,43 +1,36 @@
import com.databasir.core.doc.factory.DatabaseDocConfig; import com.databasir.core.Databasir;
import com.databasir.core.doc.factory.extension.mysql.MysqlTableTriggerDocFactory; import com.databasir.core.meta.pojo.DatabaseMeta;
import com.databasir.core.doc.factory.jdbc.JdbcDatabaseDocFactory;
import com.databasir.core.doc.model.DatabaseDoc;
import com.databasir.core.doc.render.Render;
import com.databasir.core.doc.render.RenderConfig;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Properties; import java.util.Properties;
public class App { public class App {
public static void main(String[] args) throws SQLException, ClassNotFoundException { public static void main(String[] args) throws SQLException, ClassNotFoundException {
try (FileOutputStream out = new FileOutputStream("user.md")) {
Connection connection = getJdbcConnection();
Databasir databasir = Databasir.of();
DatabaseMeta doc = databasir.get(connection, "user").orElseThrow();
databasir.renderAsMarkdown(doc, out);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
private static Connection getJdbcConnection() throws SQLException, ClassNotFoundException {
// get database connection // get database connection
Class.forName("com.mysql.cj.jdbc.Driver"); Class.forName("com.mysql.cj.jdbc.Driver");
Properties info = new Properties(); Properties info = new Properties();
info.put("user", "root"); info.put("user", "root");
info.put("password", "123456"); info.put("password", "123456");
// this config is used by mysql // this config is used by mysql
info.put("useInformationSchema", "true"); info.put("useInformationSchema", "true");
String url = "jdbc:mysql://localhost:3306/patient?useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true";
var connection = DriverManager.getConnection(url, info);
// generate doc model
var config = DatabaseDocConfig.builder()
.databaseName("user")
.connection(connection)
.tableTriggerDocFactory(new MysqlTableTriggerDocFactory())
.build();
DatabaseDoc doc = JdbcDatabaseDocFactory.of().create(config).orElseThrow();
// render as markdown String url = "jdbc:mysql://localhost:3306/patient?useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true";
try (FileOutputStream out = new FileOutputStream("user.md")) { return DriverManager.getConnection(url, info);
RenderConfig renderConfig = new RenderConfig();
renderConfig.setRenderTriggers(true);
Render.markdownRender(renderConfig).rendering(doc, out);
} catch (IOException e) {
throw new IllegalStateException(e);
}
} }
} }

Loading…
Cancel
Save