Browse Source

feature: support export document (#11)

* feat: add document export api

* feat: update frontend resource
master
vran 3 years ago
committed by GitHub
parent
commit
ffc8850eb1
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 37
      api/src/main/java/com/databasir/api/DocumentController.java
  2. 2
      api/src/main/java/com/databasir/api/Routes.java
  3. 0
      api/src/main/resources/static/css/chunk-26c477fb.e722c805.css
  4. 0
      api/src/main/resources/static/css/chunk-588dbed6.ab54ac4c.css
  5. 2
      api/src/main/resources/static/index.html
  6. 4
      api/src/main/resources/static/js/app.58300ce2.js
  7. 2
      api/src/main/resources/static/js/app.58300ce2.js.map
  8. 2
      api/src/main/resources/static/js/chunk-26c477fb.72a77fcd.js
  9. 1
      api/src/main/resources/static/js/chunk-26c477fb.72a77fcd.js.map
  10. 2
      api/src/main/resources/static/js/chunk-4935816e.627c0115.js
  11. 1
      api/src/main/resources/static/js/chunk-4935816e.627c0115.js.map
  12. 4
      api/src/main/resources/static/js/chunk-588dbed6.576f3300.js
  13. 2
      api/src/main/resources/static/js/chunk-588dbed6.576f3300.js.map
  14. 2
      api/src/main/resources/static/js/chunk-vendors.8b5336af.js
  15. 1
      api/src/main/resources/static/js/chunk-vendors.8b5336af.js.map
  16. 1
      api/src/main/resources/static/js/chunk-vendors.ebe2dc88.js.map
  17. 84
      core/src/main/java/com/databasir/core/domain/document/service/DocumentService.java
  18. 37
      plugin/src/main/resources/template/render/markdown/markdown.ftlh
  19. 4
      plugin/src/test/java/App.java

37
api/src/main/java/com/databasir/api/DocumentController.java

@ -1,6 +1,7 @@
package com.databasir.api;
import com.databasir.common.JsonData;
import com.databasir.common.SystemException;
import com.databasir.core.domain.document.data.DatabaseDocumentResponse;
import com.databasir.core.domain.document.data.DatabaseDocumentVersionResponse;
import com.databasir.core.domain.document.service.DocumentService;
@ -9,13 +10,24 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
@RestController
@RequiredArgsConstructor
@Validated
@RestController
public class DocumentController {
private final DocumentService documentService;
@ -41,4 +53,25 @@ public class DocumentController {
return JsonData.ok(documentService.getVersionsBySchemaSourceId(projectId, page));
}
@GetMapping(Routes.Document.EXPORT)
public ResponseEntity<StreamingResponseBody> getDocumentFiles(@PathVariable Integer projectId,
@RequestParam(required = false) Long version) {
String data = documentService.toMarkdown(projectId, version).get();
try {
Path path = Files.writeString(Paths.get(UUID.randomUUID().toString() + ".md"), data, StandardCharsets.UTF_8);
HttpHeaders headers = new HttpHeaders();
headers.setContentDisposition(ContentDisposition.attachment()
.filename("demo.md", StandardCharsets.UTF_8)
.build());
byte[] bytes = Files.readAllBytes(path);
Files.deleteIfExists(path);
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return ResponseEntity.ok()
.headers(headers)
.body(out -> out.write(bytes));
} catch (IOException e) {
throw new SystemException("System error");
}
}
}

2
api/src/main/java/com/databasir/api/Routes.java

@ -68,6 +68,8 @@ public interface Routes {
String SYNC_ONE = BASE + "/projects/{projectId}/documents";
String LIST_VERSIONS = BASE + "/projects/{projectId}/document_versions";
String EXPORT = BASE + "/projects/{projectId}/document_files";
}
interface DocumentRemark {

0
api/src/main/resources/static/css/chunk-4935816e.e722c805.css → api/src/main/resources/static/css/chunk-26c477fb.e722c805.css

0
api/src/main/resources/static/css/chunk-bf93911a.ab54ac4c.css → api/src/main/resources/static/css/chunk-588dbed6.ab54ac4c.css

2
api/src/main/resources/static/index.html

@ -1 +1 @@
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>databasir-frontend</title><link href="/css/chunk-1b2e2587.a5b9f9ad.css" rel="prefetch"><link href="/css/chunk-4935816e.e722c805.css" rel="prefetch"><link href="/css/chunk-7efe8be4.a5cbc9e6.css" rel="prefetch"><link href="/css/chunk-bf93911a.ab54ac4c.css" rel="prefetch"><link href="/js/chunk-1b2e2587.2a26d5cb.js" rel="prefetch"><link href="/js/chunk-2d0cc811.feb081c8.js" rel="prefetch"><link href="/js/chunk-48cebeac.b43a95b4.js" rel="prefetch"><link href="/js/chunk-4935816e.627c0115.js" rel="prefetch"><link href="/js/chunk-7efe8be4.e8bbd745.js" rel="prefetch"><link href="/js/chunk-9622a6d8.c20b1f79.js" rel="prefetch"><link href="/js/chunk-abb10c56.4c323350.js" rel="prefetch"><link href="/js/chunk-bf93911a.d40185ff.js" rel="prefetch"><link href="/js/chunk-fffb1b64.df1e960f.js" rel="prefetch"><link href="/css/app.56c172b4.css" rel="preload" as="style"><link href="/css/chunk-vendors.d4aa889d.css" rel="preload" as="style"><link href="/js/app.51f76bee.js" rel="preload" as="script"><link href="/js/chunk-vendors.ebe2dc88.js" rel="preload" as="script"><link href="/css/chunk-vendors.d4aa889d.css" rel="stylesheet"><link href="/css/app.56c172b4.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but databasir-frontend doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/js/chunk-vendors.ebe2dc88.js"></script><script src="/js/app.51f76bee.js"></script></body></html>
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>databasir-frontend</title><link href="/css/chunk-1b2e2587.a5b9f9ad.css" rel="prefetch"><link href="/css/chunk-26c477fb.e722c805.css" rel="prefetch"><link href="/css/chunk-588dbed6.ab54ac4c.css" rel="prefetch"><link href="/css/chunk-7efe8be4.a5cbc9e6.css" rel="prefetch"><link href="/js/chunk-1b2e2587.2a26d5cb.js" rel="prefetch"><link href="/js/chunk-26c477fb.72a77fcd.js" rel="prefetch"><link href="/js/chunk-2d0cc811.feb081c8.js" rel="prefetch"><link href="/js/chunk-48cebeac.b43a95b4.js" rel="prefetch"><link href="/js/chunk-588dbed6.576f3300.js" rel="prefetch"><link href="/js/chunk-7efe8be4.e8bbd745.js" rel="prefetch"><link href="/js/chunk-9622a6d8.c20b1f79.js" rel="prefetch"><link href="/js/chunk-abb10c56.4c323350.js" rel="prefetch"><link href="/js/chunk-fffb1b64.df1e960f.js" rel="prefetch"><link href="/css/app.56c172b4.css" rel="preload" as="style"><link href="/css/chunk-vendors.d4aa889d.css" rel="preload" as="style"><link href="/js/app.58300ce2.js" rel="preload" as="script"><link href="/js/chunk-vendors.8b5336af.js" rel="preload" as="script"><link href="/css/chunk-vendors.d4aa889d.css" rel="stylesheet"><link href="/css/app.56c172b4.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but databasir-frontend doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/js/chunk-vendors.8b5336af.js"></script><script src="/js/app.58300ce2.js"></script></body></html>

4
api/src/main/resources/static/js/app.51f76bee.js → api/src/main/resources/static/js/app.58300ce2.js

File diff suppressed because one or more lines are too long

2
api/src/main/resources/static/js/app.51f76bee.js.map → api/src/main/resources/static/js/app.58300ce2.js.map

File diff suppressed because one or more lines are too long

2
api/src/main/resources/static/js/chunk-26c477fb.72a77fcd.js

File diff suppressed because one or more lines are too long

1
api/src/main/resources/static/js/chunk-26c477fb.72a77fcd.js.map

File diff suppressed because one or more lines are too long

2
api/src/main/resources/static/js/chunk-4935816e.627c0115.js

File diff suppressed because one or more lines are too long

1
api/src/main/resources/static/js/chunk-4935816e.627c0115.js.map

File diff suppressed because one or more lines are too long

4
api/src/main/resources/static/js/chunk-bf93911a.d40185ff.js → api/src/main/resources/static/js/chunk-588dbed6.576f3300.js

@ -1,2 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-bf93911a"],{"4dd4":function(e,t,n){},a1af:function(e,t,n){"use strict";n("4dd4")},a55b:function(e,t,n){"use strict";n.r(t);var r=n("7a23"),o={class:"login-card"},c=Object(r["createElementVNode"])("h1",null,"Databasir",-1),a=Object(r["createTextVNode"])(" 登录 "),u=Object(r["createTextVNode"])(" 忘记密码? ");function l(e,t,n,l,i,d){var s=Object(r["resolveComponent"])("el-header"),f=Object(r["resolveComponent"])("el-link"),b=Object(r["resolveComponent"])("el-divider"),m=Object(r["resolveComponent"])("el-form-item"),p=Object(r["resolveComponent"])("el-button"),j=Object(r["resolveComponent"])("el-space"),O=Object(r["resolveComponent"])("el-form"),h=Object(r["resolveComponent"])("el-main"),w=Object(r["resolveComponent"])("el-footer"),C=Object(r["resolveComponent"])("el-container");return Object(r["openBlock"])(),Object(r["createBlock"])(C,null,{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(s),Object(r["createVNode"])(h,{class:"login-main"},{default:Object(r["withCtx"])((function(){return[Object(r["createElementVNode"])("div",o,[Object(r["createVNode"])(O,{ref:"formRef",rules:i.formRule,model:i.form,style:{border:"none"}},{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(m,null,{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(b,{"content-position":"left"},{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(f,{href:"https://github.com/vran-dev/databasir",target:"_blank",underline:!1,type:"info"},{default:Object(r["withCtx"])((function(){return[c]})),_:1})]})),_:1})]})),_:1}),Object(r["createVNode"])(m,{prop:"username"},{default:Object(r["withCtx"])((function(){return[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"text",class:"login-input",placeholder:"用户名或邮箱","onUpdate:modelValue":t[0]||(t[0]=function(e){return i.form.username=e})},null,512),[[r["vModelText"],i.form.username]])]})),_:1}),Object(r["createVNode"])(m,{prop:"password"},{default:Object(r["withCtx"])((function(){return[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"password",class:"login-input",placeholder:"密码","onUpdate:modelValue":t[1]||(t[1]=function(e){return i.form.password=e})},null,512),[[r["vModelText"],i.form.password]])]})),_:1}),Object(r["createVNode"])(m,null,{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(j,{size:32},{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(p,{style:{width:"120px","margin-top":"10px"},color:"#000",onClick:t[2]||(t[2]=function(e){return d.onLogin("formRef")}),plain:"",round:""},{default:Object(r["withCtx"])((function(){return[a]})),_:1}),Object(r["createVNode"])(f,{href:"#",target:"_blank",underline:!1,type:"info"},{default:Object(r["withCtx"])((function(){return[u]})),_:1})]})),_:1})]})),_:1})]})),_:1},8,["rules","model"])])]})),_:1}),Object(r["createVNode"])(w,null,{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(j)]})),_:1})]})),_:1})}var i=n("b0af"),d=n("5f87"),s={data:function(){return{form:{username:null,password:null},formRule:{username:[{required:!0,message:"请输入用户名或邮箱",trigger:"blur"}],password:[{required:!0,message:"请输入密码",trigger:"blur"}]}}},methods:{toIndexPage:function(){this.$router.push({path:"/groups"})},onLogin:function(){var e=this;this.$refs.formRef.validate((function(t){t&&Object(i["a"])(e.form).then((function(t){t.errCode||(d["b"].saveUserLoginData(t.data),e.$store.commit("userUpdate",{nickname:t.data.nickname,username:t.data.username,email:t.data.email}),e.toIndexPage())}))}))}}},f=(n("a1af"),n("6b0d")),b=n.n(f);const m=b()(s,[["render",l]]);t["default"]=m}}]);
//# sourceMappingURL=chunk-bf93911a.d40185ff.js.map
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-588dbed6"],{"4dd4":function(e,t,n){},a1af:function(e,t,n){"use strict";n("4dd4")},a55b:function(e,t,n){"use strict";n.r(t);var r=n("7a23"),o={class:"login-card"},c=Object(r["createElementVNode"])("h1",null,"Databasir",-1),a=Object(r["createTextVNode"])(" 登录 "),u=Object(r["createTextVNode"])(" 忘记密码? ");function l(e,t,n,l,i,d){var s=Object(r["resolveComponent"])("el-header"),f=Object(r["resolveComponent"])("el-link"),b=Object(r["resolveComponent"])("el-divider"),m=Object(r["resolveComponent"])("el-form-item"),p=Object(r["resolveComponent"])("el-button"),j=Object(r["resolveComponent"])("el-space"),O=Object(r["resolveComponent"])("el-form"),h=Object(r["resolveComponent"])("el-main"),w=Object(r["resolveComponent"])("el-footer"),C=Object(r["resolveComponent"])("el-container");return Object(r["openBlock"])(),Object(r["createBlock"])(C,null,{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(s),Object(r["createVNode"])(h,{class:"login-main"},{default:Object(r["withCtx"])((function(){return[Object(r["createElementVNode"])("div",o,[Object(r["createVNode"])(O,{ref:"formRef",rules:i.formRule,model:i.form,style:{border:"none"}},{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(m,null,{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(b,{"content-position":"left"},{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(f,{href:"https://github.com/vran-dev/databasir",target:"_blank",underline:!1,type:"info"},{default:Object(r["withCtx"])((function(){return[c]})),_:1})]})),_:1})]})),_:1}),Object(r["createVNode"])(m,{prop:"username"},{default:Object(r["withCtx"])((function(){return[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"text",class:"login-input",placeholder:"用户名或邮箱","onUpdate:modelValue":t[0]||(t[0]=function(e){return i.form.username=e})},null,512),[[r["vModelText"],i.form.username]])]})),_:1}),Object(r["createVNode"])(m,{prop:"password"},{default:Object(r["withCtx"])((function(){return[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"password",class:"login-input",placeholder:"密码","onUpdate:modelValue":t[1]||(t[1]=function(e){return i.form.password=e})},null,512),[[r["vModelText"],i.form.password]])]})),_:1}),Object(r["createVNode"])(m,null,{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(j,{size:32},{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(p,{style:{width:"120px","margin-top":"10px"},color:"#000",onClick:t[2]||(t[2]=function(e){return d.onLogin("formRef")}),plain:"",round:""},{default:Object(r["withCtx"])((function(){return[a]})),_:1}),Object(r["createVNode"])(f,{href:"#",target:"_blank",underline:!1,type:"info"},{default:Object(r["withCtx"])((function(){return[u]})),_:1})]})),_:1})]})),_:1})]})),_:1},8,["rules","model"])])]})),_:1}),Object(r["createVNode"])(w,null,{default:Object(r["withCtx"])((function(){return[Object(r["createVNode"])(j)]})),_:1})]})),_:1})}var i=n("b0af"),d=n("5f87"),s={data:function(){return{form:{username:null,password:null},formRule:{username:[{required:!0,message:"请输入用户名或邮箱",trigger:"blur"}],password:[{required:!0,message:"请输入密码",trigger:"blur"}]}}},methods:{toIndexPage:function(){this.$router.push({path:"/groups"})},onLogin:function(){var e=this;this.$refs.formRef.validate((function(t){t&&Object(i["a"])(e.form).then((function(t){t.errCode||(d["b"].saveUserLoginData(t.data),e.$store.commit("userUpdate",{nickname:t.data.nickname,username:t.data.username,email:t.data.email}),e.toIndexPage())}))}))}}},f=(n("a1af"),n("6b0d")),b=n.n(f);const m=b()(s,[["render",l]]);t["default"]=m}}]);
//# sourceMappingURL=chunk-588dbed6.576f3300.js.map

2
api/src/main/resources/static/js/chunk-bf93911a.d40185ff.js.map → api/src/main/resources/static/js/chunk-588dbed6.576f3300.js.map

File diff suppressed because one or more lines are too long

2
api/src/main/resources/static/js/chunk-vendors.ebe2dc88.js → api/src/main/resources/static/js/chunk-vendors.8b5336af.js

File diff suppressed because one or more lines are too long

1
api/src/main/resources/static/js/chunk-vendors.8b5336af.js.map

File diff suppressed because one or more lines are too long

1
api/src/main/resources/static/js/chunk-vendors.ebe2dc88.js.map

File diff suppressed because one or more lines are too long

84
core/src/main/java/com/databasir/core/domain/document/service/DocumentService.java

@ -11,6 +11,7 @@ import com.databasir.core.domain.document.data.DatabaseDocumentVersionResponse;
import com.databasir.core.infrastructure.connection.DatabaseConnectionService;
import com.databasir.core.infrastructure.converter.JsonConverter;
import com.databasir.core.meta.data.DatabaseMeta;
import com.databasir.core.render.markdown.MarkdownBuilder;
import com.databasir.dao.impl.*;
import com.databasir.dao.tables.pojos.*;
import lombok.RequiredArgsConstructor;
@ -21,10 +22,8 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.sql.Connection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@Service
@ -183,4 +182,81 @@ public class DocumentService {
.build()))
.orElseGet(Page::empty);
}
public Optional<String> toMarkdown(Integer projectId, Long version) {
return getOneByProjectId(projectId, version)
.map(doc -> {
MarkdownBuilder builder = MarkdownBuilder.builder();
builder.primaryTitle(doc.getDatabaseName());
// overview
builder.secondTitle("overview");
List<List<String>> overviewContent = new ArrayList<>();
for (int i = 0; i < doc.getTables().size(); i++) {
DatabaseDocumentResponse.TableDocumentResponse table = doc.getTables().get(i);
overviewContent.add(List.of((i + 1) + "", table.getName(), table.getType(), table.getComment()));
}
builder.table(List.of("", "表名", "类型", "备注"), overviewContent);
Function<DatabaseDocumentResponse.TableDocumentResponse.ColumnDocumentResponse, String> columnDefaultValueMapping = column -> {
if (Objects.equals(column.getNullable(), "YES")) {
return Objects.requireNonNullElse(column.getDefaultValue(), "null");
} else {
return Objects.requireNonNullElse(column.getDefaultValue(), "");
}
};
// tables
doc.getTables().forEach(table -> {
builder.secondTitle(table.getName());
// columns
List<List<String>> columnContent = new ArrayList<>();
for (int i = 0; i < table.getColumns().size(); i++) {
var column = table.getColumns().get(i);
String type;
if (column.getDecimalDigits() == null || column.getDecimalDigits() == 0) {
type = table.getType() + "(" + column.getSize() + ")";
} else {
type = table.getType() + "(" + column.getSize() + "," + column.getDecimalDigits() + ")";
}
columnContent.add(List.of((i + 1) + "",
column.getName(),
type,
column.getIsPrimaryKey() ? "YES" : "NO",
column.getNullable(),
column.getAutoIncrement(),
columnDefaultValueMapping.apply(column),
column.getComment()));
}
builder.thirdTitle("columns");
builder.table(List.of("", "名称", "类型", "是否为主键", "可为空", "自增", "默认值", "备注"),
columnContent);
// indexes
List<List<String>> indexContent = new ArrayList<>();
for (int i = 0; i < table.getIndexes().size(); i++) {
var index = table.getIndexes().get(i);
String columnNames = String.join(", ", index.getColumnNames());
String isUnique = index.getIsUnique() ? "YES" : "NO";
indexContent.add(List.of((i + 1) + "", index.getName(), isUnique, columnNames));
}
builder.thirdTitle("indexes");
builder.table(List.of("", "名称", "是否唯一", "关联列"), indexContent);
if (!table.getTriggers().isEmpty()) {
List<List<String>> triggerContent = new ArrayList<>();
for (int i = 0; i < table.getTriggers().size(); i++) {
var trigger = table.getTriggers().get(i);
triggerContent.add(List.of((i + 1) + "",
trigger.getName(),
trigger.getTiming(),
trigger.getManipulation(),
trigger.getStatement()));
}
builder.thirdTitle("triggers");
builder.table(List.of("", "名称", "timing", "manipulation", "statement"), triggerContent);
}
});
return builder.build();
});
}
}

37
plugin/src/main/resources/template/render/markdown/markdown.ftlh

@ -1,40 +1,45 @@
# ${meta.databaseName}
| seq | name | comment |
| ---- | --------------- | ------ |
| | |
| --------------- | ---- |
| Database name | |
| Product name | |
| Product version | |
## Overview
| | name | type | comment |
| ---- | --------------- | ------ | ------ |
<#list meta.tables as table>
| ${table_index+1} | [${table.name}](#${table.name}) | ${table.comment!'N/A'} |
| ${table_index+1} | [${table.name}](#${table.name}) | ${table.type} | ${table.comment!'N/A'} |
</#list>
<#if config.renderTables>
<#list meta.tables as table>
## ${table.name}
## ${table.name}
<#if config.renderColumns>
### Columns
### Columns
| seq | name | type | nullable | auto increment| default | comment |
| ---- | ------ | ------ | ------ | -------- | ------ | ------ |
| | name | type | primary Key | nullable | auto increment| default | comment |
| --- | ---- | ---- | ----------- | -------- | ------------- | ------- | ------- |
<#list table.columns as column>
| ${column_index+1} | ${column.name} | ${column.type} | ${column.isNullable?then('YES','NO')} | ${column.isAutoIncrement?then('YES', 'NO')} | ${column.isNullable?then(column.defaultValue!'NULL', column.defaultValue!'')} | ${column.comment!''} |
| ${column_index+1} | ${column.name} | ${column.type} | ${column.isPrimaryKey?then('YES','NO')} | ${column.nullable } | ${column.autoIncrement} | ${column.defaultValue!'NULL'} | ${column.comment!''} |
</#list>
</#if>
<#if config.renderIndexes>
<#if config.renderIndexes>
### Indexes
| seq | name | unique | primary key | columns |
| ---- | ---- | -------- | -------- | ------ |
| | name | unique | columns |
| --- | ---- | ------ | ------- |
<#list table.indexes as index>
| ${index_index+1} | ${index.name} | ${index.isUniqueKey?then('YES', 'NO')} | ${index.isPrimaryKey?then('YES','NO')} | ${index.columnNames?join(', ')} |
| ${index_index+1} | ${index.name} | ${index.isUniqueKey?then('YES', 'NO')} | ${index.columnNames?join(', ')} |
</#list>
</#if>
<#if config.renderTriggers>
### Triggers
| seq | name | timing | statement | created |
| ---- | ---- | -------- | --------- | -------- |
| | name | timing | statement | created |
| --- | ---- | ------ | --------- | ------- |
<#list table.triggers as trigger>
| ${trigger_index} | ${trigger.name} | ${trigger.timing + " " + trigger.manipulation } | ${trigger.statement?replace("\n", "<br>")?replace("\r", " ")} | ${trigger.createAt} |
</#list>

4
plugin/src/test/java/App.java

@ -13,10 +13,10 @@ public class App {
@Test
public void testRenderAsMarkdown() throws SQLException, ClassNotFoundException {
try (FileOutputStream out = new FileOutputStream("user.md")) {
try (FileOutputStream out = new FileOutputStream("demo.md")) {
Connection connection = getJdbcConnection();
Databasir databasir = Databasir.of();
DatabaseMeta doc = databasir.get(connection, "user").orElseThrow();
DatabaseMeta doc = databasir.get(connection, "demo").orElseThrow();
databasir.renderAsMarkdown(doc, out);
} catch (IOException e) {
throw new IllegalStateException(e);

Loading…
Cancel
Save