feat: support version diff (#52)

* feat: implementation diff processor

* fix: checkstyle

* feat: ignore sync if without change

* fix: checkstyle

* feat:add databasir diff api

* feat:update frontend resources
This commit is contained in:
vran 2022-03-19 15:01:15 +08:00 committed by GitHub
parent 64df3d028c
commit 747ae14da2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
113 changed files with 9668 additions and 274 deletions

View File

@ -1,6 +1,7 @@
package com.databasir.api;
import com.databasir.common.JsonData;
import com.databasir.core.diff.data.RootDiff;
import com.databasir.core.domain.document.data.DatabaseDocumentResponse;
import com.databasir.core.domain.document.data.DatabaseDocumentSimpleResponse;
import com.databasir.core.domain.document.data.DatabaseDocumentVersionResponse;
@ -39,6 +40,13 @@ public class DocumentController {
return JsonData.ok();
}
@GetMapping(Routes.Document.DIFF)
public JsonData<RootDiff> diff(@PathVariable Integer projectId,
@RequestParam(name = "originalVersion") Long originalVersion,
@RequestParam(required = false) Long currentVersion) {
return JsonData.ok(documentService.diff(projectId, originalVersion, currentVersion));
}
@GetMapping(Routes.Document.GET_ONE)
public JsonData<DatabaseDocumentResponse> getByProjectId(@PathVariable Integer projectId,
@RequestParam(required = false) Long version) {

View File

@ -82,6 +82,8 @@ public interface Routes {
String GET_TABLE_DETAIL = BASE + "/projects/{projectId}/documents/{documentId}/table_documents";
String DIFF = BASE + "/projects/{projectId}/diff_documents";
String EXPORT = BASE + "/projects/{projectId}/document_files";
}

View File

@ -0,0 +1 @@
@-webkit-keyframes running-line{to{stroke-dashoffset:-1000}}@keyframes running-line{to{stroke-dashoffset:-1000}}.text{font-size:14px;line-height:1.3rem}.item{margin-top:10px;margin-right:40px}.remark-card{margin-bottom:30px}.remark-header{display:flex;justify-content:space-between;align-items:center}.remark-header .remark-user{color:#6d6d6d}.remark-header .remark-time{color:#6d6d6d;font-size:.8rem;margin-left:10px}.remark-content{white-space:pre-wrap;text-align:left}.badge-item{margin-top:18px;margin-bottom:6px}.h2{font-size:24px;color:#606266;margin-top:13px;margin-bottom:13px}.h2,.h3{font-family:Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,,Arial,sans-serif}.h3{font-size:20px;color:#909399;margin-top:18px;margin-bottom:18px}.removed-item{background-color:#fef0f0!important;color:#f56c6c}.added-item{background-color:#f0f9eb!important;color:#67c23a}.modified-item{background-color:#fdf6ec!important;color:#e6a23c}.modified-original-item{background-color:#fdf6ec!important;color:#a8abb2}.span-ellipsis{width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;flex:1;display:flex;align-items:left;justify-content:space-between;font-size:14px}.doc-toc-aside{overflow-wrap:break-word;text-overflow:ellipsis;bottom:0;top:100px;position:fixed;overflow-y:hidden;overflow-x:hidden;max-width:var(--el-aside-width);width:var(--el-aside-width);border-width:0 1px 0 0;border-color:#ddd;border-style:solid}.doc-toc-aside:hover{overflow-y:auto;scrollbar-width:thin}

View File

@ -1 +0,0 @@
@-webkit-keyframes running-line{to{stroke-dashoffset:-1000}}@keyframes running-line{to{stroke-dashoffset:-1000}}.text{font-size:14px;line-height:1.3rem}.item{margin-top:10px;margin-right:40px}.remark-card{margin-bottom:30px}.remark-header{display:flex;justify-content:space-between;align-items:center}.remark-header .remark-user{color:#6d6d6d}.remark-header .remark-time{color:#6d6d6d;font-size:.8rem;margin-left:10px}.remark-content{white-space:pre-wrap;text-align:left}.span-ellipsis{width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;flex:1;display:flex;align-items:left;justify-content:space-between;font-size:14px}.doc-toc-aside{overflow-wrap:break-word;text-overflow:ellipsis;bottom:0;top:100px;position:fixed;overflow-y:hidden;overflow-x:hidden;max-width:var(--el-aside-width);width:var(--el-aside-width);border-width:0 1px 0 0;border-color:#ddd;border-style:solid}.doc-toc-aside:hover{overflow-y:auto;scrollbar-width:thin}

View File

@ -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><script defer="defer" type="module" src="/js/chunk-vendors.45746587.js"></script><script defer="defer" type="module" src="/js/app.e0747db1.js"></script><link href="/css/chunk-vendors.8e1003a6.css" rel="stylesheet"><link href="/css/app.757c1ef3.css" rel="stylesheet"><script defer="defer" src="/js/chunk-vendors-legacy.54c3660b.js" nomodule></script><script defer="defer" src="/js/app-legacy.e6a59dc2.js" nomodule></script></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></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><script defer="defer" type="module" src="/js/chunk-vendors.45746587.js"></script><script defer="defer" type="module" src="/js/app.08e3c996.js"></script><link href="/css/chunk-vendors.8e1003a6.css" rel="stylesheet"><link href="/css/app.757c1ef3.css" rel="stylesheet"><script defer="defer" src="/js/chunk-vendors-legacy.54c3660b.js" nomodule></script><script defer="defer" src="/js/app-legacy.3d5e4b5d.js" nomodule></script></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></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
"use strict";(self["webpackChunkdatabasir_frontend"]=self["webpackChunkdatabasir_frontend"]||[]).push([[596],{2631:function(e,t,n){n.r(t),n.d(t,{default:function(){return _}});var r=n(6252),u=(0,r.Uk)(" 系统邮箱设置 "),o=(0,r.Uk)(" : "),l=(0,r.Uk)("保存"),a=(0,r.Uk)("重置");function s(e,t,n,s,i,m){var f=(0,r.up)("box"),d=(0,r.up)("el-icon"),c=(0,r.up)("el-divider"),p=(0,r.up)("el-input"),w=(0,r.up)("el-form-item"),h=(0,r.up)("el-col"),g=(0,r.up)("el-button"),_=(0,r.up)("el-form"),W=(0,r.up)("el-card"),V=(0,r.up)("el-main"),b=(0,r.up)("el-container");return(0,r.wg)(),(0,r.j4)(b,null,{default:(0,r.w5)((function(){return[(0,r.Wm)(V,null,{default:(0,r.w5)((function(){return[(0,r.Wm)(W,{shadow:"hover",style:{"max-width":"600px"}},{default:(0,r.w5)((function(){return[(0,r.Wm)(c,null,{default:(0,r.w5)((function(){return[(0,r.Wm)(d,null,{default:(0,r.w5)((function(){return[(0,r.Wm)(f)]})),_:1}),u]})),_:1}),(0,r.Wm)(_,{model:i.form,"label-position":"top",rules:i.formRule,ref:"formRef",style:{"max-width":"900px"}},{default:(0,r.w5)((function(){return[(0,r.Wm)(w,{label:"邮箱账号",prop:"username"},{default:(0,r.w5)((function(){return[(0,r.Wm)(p,{modelValue:i.form.username,"onUpdate:modelValue":t[0]||(t[0]=function(e){return i.form.username=e}),placeholder:"请输入邮箱账号"},null,8,["modelValue"])]})),_:1}),(0,r.Wm)(w,{label:"邮箱密码",prop:"password"},{default:(0,r.w5)((function(){return[(0,r.Wm)(p,{modelValue:i.form.password,"onUpdate:modelValue":t[1]||(t[1]=function(e){return i.form.password=e}),type:"password",placeholder:"请输入密码","show-password":""},null,8,["modelValue"])]})),_:1}),(0,r.Wm)(w,{label:"SMTP",prop:"smtpHost"},{default:(0,r.w5)((function(){return[(0,r.Wm)(h,{span:12},{default:(0,r.w5)((function(){return[(0,r.Wm)(p,{modelValue:i.form.smtpHost,"onUpdate:modelValue":t[2]||(t[2]=function(e){return i.form.smtpHost=e}),placeholder:"SMTP Host"},null,8,["modelValue"])]})),_:1}),(0,r.Wm)(h,{span:1,style:{"text-align":"center"}},{default:(0,r.w5)((function(){return[o]})),_:1}),(0,r.Wm)(h,{span:6},{default:(0,r.w5)((function(){return[(0,r.Wm)(p,{modelValue:i.form.smtpPort,"onUpdate:modelValue":t[3]||(t[3]=function(e){return i.form.smtpPort=e}),placeholder:"SMTP Port"},null,8,["modelValue"])]})),_:1})]})),_:1}),(0,r.Wm)(w,{style:{"margin-top":"38px"}},{default:(0,r.w5)((function(){return[(0,r.Wm)(g,{type:"primary",onClick:t[4]||(t[4]=function(e){return m.onSubmit("formRef")})},{default:(0,r.w5)((function(){return[l]})),_:1}),(0,r.Wm)(g,{type:"danger",onClick:t[5]||(t[5]=function(e){return m.onReset()})},{default:(0,r.w5)((function(){return[a]})),_:1})]})),_:1})]})),_:1},8,["model","rules"])]})),_:1})]})),_:1})]})),_:1})}var i=n(8534),m=(n(5666),n(3872)),f="/api/v1.0/settings",d=function(){return m.Z.get(f+"/sys_email")},c=function(e){return m.Z.post(f+"/sys_email",e)},p=function(){return m.Z["delete"](f+"/sys_email")},w={data:function(){return{form:{smtpHost:null,smtpPort:null,username:null,password:null},formRule:{username:[this.requiredInputValidRule("请输入邮箱账号"),{type:"email",message:"邮箱格式不正确",trigger:"blur"}],password:[this.requiredInputValidRule("请输入邮箱密码")],smtpHost:[this.requiredInputValidRule("请输入 SMTP 地址")],smtpPort:[this.requiredInputValidRule("请输入 SMTP 端口"),{min:1,max:65535,message:"端口有效值为 1~65535",trigger:"blur"}]}}},mounted:function(){this.fetchSysMail()},methods:{requiredInputValidRule:function(e){return{required:!0,message:e,trigger:"blur"}},fetchSysMail:function(){var e=this;return(0,i.Z)(regeneratorRuntime.mark((function t(){var n;return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:return t.next=2,d().then((function(e){return e.data}));case 2:n=t.sent,n&&(e.form=n);case 4:case"end":return t.stop()}}),t)})))()},onSubmit:function(){var e=this;this.$refs.formRef.validate((function(t){return t?(c(e.form).then((function(t){t.errCode||e.$message.success("更新成功")})),!0):(e.$message.error("请完善表单相关信息!"),!1)}))},onReset:function(){var e=this;this.$confirm("确认重置系统邮件吗?删除后数据将无法恢复","警告",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}).then((function(){p().then((function(t){t.errCode||(e.form={},e.$message.success("重置成功"))}))}))}}},h=n(3744);const g=(0,h.Z)(w,[["render",s]]);var _=g}}]);
//# sourceMappingURL=596-legacy.d38041af.js.map
//# sourceMappingURL=596-legacy.d1261d0e.js.map

View File

@ -1,2 +1,2 @@
"use strict";(self["webpackChunkdatabasir_frontend"]=self["webpackChunkdatabasir_frontend"]||[]).push([[596],{2631:function(e,l,t){t.r(l),t.d(l,{default:function(){return _}});var r=t(6252);const a=(0,r.Uk)(" 系统邮箱设置 "),s=(0,r.Uk)(" : "),o=(0,r.Uk)("保存"),u=(0,r.Uk)("重置");function m(e,l,t,m,n,d){const p=(0,r.up)("box"),i=(0,r.up)("el-icon"),f=(0,r.up)("el-divider"),c=(0,r.up)("el-input"),h=(0,r.up)("el-form-item"),w=(0,r.up)("el-col"),_=(0,r.up)("el-button"),g=(0,r.up)("el-form"),W=(0,r.up)("el-card"),V=(0,r.up)("el-main"),y=(0,r.up)("el-container");return(0,r.wg)(),(0,r.j4)(y,null,{default:(0,r.w5)((()=>[(0,r.Wm)(V,null,{default:(0,r.w5)((()=>[(0,r.Wm)(W,{shadow:"hover",style:{"max-width":"600px"}},{default:(0,r.w5)((()=>[(0,r.Wm)(f,null,{default:(0,r.w5)((()=>[(0,r.Wm)(i,null,{default:(0,r.w5)((()=>[(0,r.Wm)(p)])),_:1}),a])),_:1}),(0,r.Wm)(g,{model:n.form,"label-position":"top",rules:n.formRule,ref:"formRef",style:{"max-width":"900px"}},{default:(0,r.w5)((()=>[(0,r.Wm)(h,{label:"邮箱账号",prop:"username"},{default:(0,r.w5)((()=>[(0,r.Wm)(c,{modelValue:n.form.username,"onUpdate:modelValue":l[0]||(l[0]=e=>n.form.username=e),placeholder:"请输入邮箱账号"},null,8,["modelValue"])])),_:1}),(0,r.Wm)(h,{label:"邮箱密码",prop:"password"},{default:(0,r.w5)((()=>[(0,r.Wm)(c,{modelValue:n.form.password,"onUpdate:modelValue":l[1]||(l[1]=e=>n.form.password=e),type:"password",placeholder:"请输入密码","show-password":""},null,8,["modelValue"])])),_:1}),(0,r.Wm)(h,{label:"SMTP",prop:"smtpHost"},{default:(0,r.w5)((()=>[(0,r.Wm)(w,{span:12},{default:(0,r.w5)((()=>[(0,r.Wm)(c,{modelValue:n.form.smtpHost,"onUpdate:modelValue":l[2]||(l[2]=e=>n.form.smtpHost=e),placeholder:"SMTP Host"},null,8,["modelValue"])])),_:1}),(0,r.Wm)(w,{span:1,style:{"text-align":"center"}},{default:(0,r.w5)((()=>[s])),_:1}),(0,r.Wm)(w,{span:6},{default:(0,r.w5)((()=>[(0,r.Wm)(c,{modelValue:n.form.smtpPort,"onUpdate:modelValue":l[3]||(l[3]=e=>n.form.smtpPort=e),placeholder:"SMTP Port"},null,8,["modelValue"])])),_:1})])),_:1}),(0,r.Wm)(h,{style:{"margin-top":"38px"}},{default:(0,r.w5)((()=>[(0,r.Wm)(_,{type:"primary",onClick:l[4]||(l[4]=e=>d.onSubmit("formRef"))},{default:(0,r.w5)((()=>[o])),_:1}),(0,r.Wm)(_,{type:"danger",onClick:l[5]||(l[5]=e=>d.onReset())},{default:(0,r.w5)((()=>[u])),_:1})])),_:1})])),_:1},8,["model","rules"])])),_:1})])),_:1})])),_:1})}var n=t(3872);const d="/api/v1.0/settings",p=()=>n.Z.get(d+"/sys_email"),i=e=>n.Z.post(d+"/sys_email",e),f=()=>n.Z["delete"](d+"/sys_email");var c={data(){return{form:{smtpHost:null,smtpPort:null,username:null,password:null},formRule:{username:[this.requiredInputValidRule("请输入邮箱账号"),{type:"email",message:"邮箱格式不正确",trigger:"blur"}],password:[this.requiredInputValidRule("请输入邮箱密码")],smtpHost:[this.requiredInputValidRule("请输入 SMTP 地址")],smtpPort:[this.requiredInputValidRule("请输入 SMTP 端口"),{min:1,max:65535,message:"端口有效值为 1~65535",trigger:"blur"}]}}},mounted(){this.fetchSysMail()},methods:{requiredInputValidRule(e){return{required:!0,message:e,trigger:"blur"}},async fetchSysMail(){const e=await p().then((e=>e.data));e&&(this.form=e)},onSubmit(){this.$refs.formRef.validate((e=>e?(i(this.form).then((e=>{e.errCode||this.$message.success("更新成功")})),!0):(this.$message.error("请完善表单相关信息!"),!1)))},onReset(){this.$confirm("确认重置系统邮件吗?删除后数据将无法恢复","警告",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}).then((()=>{f().then((e=>{e.errCode||(this.form={},this.$message.success("重置成功"))}))}))}}},h=t(3744);const w=(0,h.Z)(c,[["render",m]]);var _=w}}]);
//# sourceMappingURL=596.e58d33aa.js.map
//# sourceMappingURL=596.eb4080a7.js.map

View File

@ -1,2 +1,2 @@
"use strict";(self["webpackChunkdatabasir_frontend"]=self["webpackChunkdatabasir_frontend"]||[]).push([[865],{8865:function(t,n,e){e.r(n),e.d(n,{default:function(){return f}});var i=e(6252),r=e(9963),a=(0,i.Uk)("立即跳转");function o(t,n,e,o,u,l){var s=(0,i.up)("el-button"),c=(0,i.up)("el-result"),d=(0,i.up)("el-main"),f=(0,i.up)("el-container"),g=(0,i.Q2)("loading");return(0,i.wg)(),(0,i.j4)(f,null,{default:(0,i.w5)((function(){return[(0,i.wy)(((0,i.wg)(),(0,i.j4)(d,{class:"login-main"},{default:(0,i.w5)((function(){return[(0,i.wy)((0,i.Wm)(c,{icon:u.icon,title:u.title,"sub-title":u.subTitle},{extra:(0,i.w5)((function(){return[(0,i.Wm)(s,{type:"primary",onClick:n[0]||(n[0]=function(t){return l.toIndexPage()})},{default:(0,i.w5)((function(){return[a]})),_:1})]})),_:1},8,["icon","title","sub-title"]),[[r.F8,!u.loading]])]})),_:1})),[[g,u.loading]])]})),_:1})}var u=e(152),l=e(1836),s={data:function(){return{registrationId:null,icon:"",title:"",subTitle:"",loading:!0}},created:function(){this.registrationId=this.$route.params.id,this.login()},methods:{login:function(){var t=this,n=window.location.href,e=this.$route.query;e.redirect_uri=n,(0,u.rd)(this.registrationId,e).then((function(n){n.errCode?(t.title=n.errMessage,t.icon="error"):(l.E.saveUserLoginData(n.data),t.$store.commit("userUpdate",{nickname:n.data.nickname,username:n.data.username,email:n.data.email,avatar:n.data.avatar}),t.icon="success",t.$router.push({path:"/groups"})),t.loading=!1})).catch((function(n){console.log("login failed: "+n),t.icon="error",t.title="登陆失败,请重试",t.loading=!1}))},toIndexPage:function(){this.$router.push({path:"/"})}}},c=e(3744);const d=(0,c.Z)(s,[["render",o]]);var f=d}}]);
//# sourceMappingURL=865-legacy.3c829294.js.map
//# sourceMappingURL=865-legacy.fc2fd7b3.js.map

View File

@ -1 +1 @@
{"version":3,"file":"js/865-legacy.3c829294.js","mappings":"mNAUiE,Q,qKAT7DA,EAAAA,EAAAA,IAaeC,EAAA,M,kBAZX,iBAWU,uBAXVD,EAAAA,EAAAA,IAWUE,EAAA,CAXmBC,MAAM,cAAY,C,kBAC3C,iBASY,WATZC,EAAAA,EAAAA,IASYC,EAAA,CARPC,KAAMC,EAAAA,KACNC,MAAOD,EAAAA,MACP,YAAWA,EAAAA,UAHhB,CAMeE,OAAK,SAChB,iBAAiE,EAAjEL,EAAAA,EAAAA,IAAiEM,EAAA,CAAtDC,KAAK,UAAWC,QAAK,+BAAEC,EAAAA,iBAAlC,C,kBAAiD,iBAAI,O,eAPzD,wCAIaN,EAAAA,e,OALjB,IAAoBA,EAAAA,e,6BA2B5B,GACIO,KADW,WAEP,MAAO,CACHC,eAAgB,KAChBT,KAAM,GACNE,MAAO,GACPQ,SAAU,GACVC,SAAS,IAIjBC,QAXW,WAYPC,KAAKJ,eAAiBI,KAAKC,OAAOC,OAAOC,GACzCH,KAAKI,SAGTC,QAAS,CACJD,MADI,WACI,WACCE,EAAcC,OAAOC,SAASC,KAC9BP,EAASF,KAAKC,OAAOS,MAC3BR,EAAOS,aAAeL,GACtBM,EAAAA,EAAAA,IAAYZ,KAAKJ,eAAgBM,GAAQW,MAAK,SAAAC,GACrCA,EAAKC,SAWN,EAAK1B,MAAQyB,EAAKE,WAClB,EAAK7B,KAAO,UAXZ8B,EAAAA,EAAAA,kBAAuBH,EAAKnB,MAC5B,EAAKuB,OAAOC,OAAO,aAAc,CAC7BC,SAAUN,EAAKnB,KAAKyB,SACpBC,SAAUP,EAAKnB,KAAK0B,SACpBC,MAAOR,EAAKnB,KAAK2B,MACjBC,OAAQT,EAAKnB,KAAK4B,SAEtB,EAAKpC,KAAK,UACV,EAAKqC,QAAQC,KAAK,CAACC,KAAM,aAK7B,EAAK5B,SAAU,KAChB6B,OAAM,SAAAC,GACLC,QAAQC,IAAI,iBAAiBF,GAC7B,EAAKzC,KAAO,QACZ,EAAKE,MAAQ,WACb,EAAKS,SAAU,MAIvBiC,YA7BK,WA8BD/B,KAAKwB,QAAQC,KAAK,CAACC,KAAM,S,UCpErC,MAAMM,GAA2B,OAAgB,EAAQ,CAAC,CAAC,SAASC,KAEpE","sources":["webpack://databasir-frontend/./src/views/OAuth2Login.vue","webpack://databasir-frontend/./src/views/OAuth2Login.vue?b6ea"],"sourcesContent":["<template>\r\n <el-container>\r\n <el-main v-loading=\"loading\" class=\"login-main\">\r\n <el-result\r\n :icon=\"icon\"\r\n :title=\"title\"\r\n :sub-title=\"subTitle\"\r\n v-show=\"!loading\"\r\n >\r\n <template #extra>\r\n <el-button type=\"primary\" @click=\"toIndexPage()\">立即跳转</el-button>\r\n </template>\r\n </el-result>\r\n </el-main>\r\n </el-container>\r\n</template>\r\n\r\n<style>\r\n.login-main {\r\n margin: 0 auto;\r\n margin-top: 200px;\r\n}\r\n\r\n</style>\r\n<script>\r\nimport { oauth2Login } from \"../api/Login\"\r\nimport { user } from \"../utils/auth\"\r\n\r\n\r\nexport default {\r\n data() {\r\n return {\r\n registrationId: null,\r\n icon: '',\r\n title: '',\r\n subTitle: '',\r\n loading: true,\r\n }\r\n },\r\n\r\n created() {\r\n this.registrationId = this.$route.params.id\r\n this.login()\r\n },\r\n\r\n methods: {\r\n login() {\r\n const redirectUri = window.location.href\r\n const params = this.$route.query\r\n params.redirect_uri = redirectUri\r\n oauth2Login(this.registrationId, params).then(resp => {\r\n if (!resp.errCode) {\r\n user.saveUserLoginData(resp.data)\r\n this.$store.commit('userUpdate', {\r\n nickname: resp.data.nickname,\r\n username: resp.data.username,\r\n email: resp.data.email,\r\n avatar: resp.data.avatar\r\n })\r\n this.icon='success'\r\n this.$router.push({path: '/groups'})\r\n } else {\r\n this.title = resp.errMessage\r\n this.icon = 'error'\r\n }\r\n this.loading = false\r\n }).catch(err => {\r\n console.log('login failed: '+err)\r\n this.icon = 'error'\r\n this.title = '登陆失败,请重试'\r\n this.loading = false\r\n })\r\n },\r\n\r\n toIndexPage() {\r\n this.$router.push({path: '/'})\r\n }\r\n }\r\n}\r\n</script>","import { render } from \"./OAuth2Login.vue?vue&type=template&id=65bc9922\"\nimport script from \"./OAuth2Login.vue?vue&type=script&lang=js\"\nexport * from \"./OAuth2Login.vue?vue&type=script&lang=js\"\n\nimport \"./OAuth2Login.vue?vue&type=style&index=0&id=65bc9922&lang=css\"\n\nimport exportComponent from \"E:\\\\git_workspace\\\\databasir-frontend\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render]])\n\nexport default __exports__"],"names":["_createBlock","_component_el_container","_component_el_main","class","_createVNode","_component_el_result","icon","$data","title","extra","_component_el_button","type","onClick","$options","data","registrationId","subTitle","loading","created","this","$route","params","id","login","methods","redirectUri","window","location","href","query","redirect_uri","oauth2Login","then","resp","errCode","errMessage","user","$store","commit","nickname","username","email","avatar","$router","push","path","catch","err","console","log","toIndexPage","__exports__","render"],"sourceRoot":""}
{"version":3,"file":"js/865-legacy.fc2fd7b3.js","mappings":"mNAUiE,Q,qKAT7DA,EAAAA,EAAAA,IAaeC,EAAA,M,kBAZX,iBAWU,uBAXVD,EAAAA,EAAAA,IAWUE,EAAA,CAXmBC,MAAM,cAAY,C,kBAC3C,iBASY,WATZC,EAAAA,EAAAA,IASYC,EAAA,CARPC,KAAMC,EAAAA,KACNC,MAAOD,EAAAA,MACP,YAAWA,EAAAA,UAHhB,CAMeE,OAAK,SAChB,iBAAiE,EAAjEL,EAAAA,EAAAA,IAAiEM,EAAA,CAAtDC,KAAK,UAAWC,QAAK,+BAAEC,EAAAA,iBAAlC,C,kBAAiD,iBAAI,O,eAPzD,wCAIaN,EAAAA,e,OALjB,IAAoBA,EAAAA,e,6BA2B5B,GACIO,KADW,WAEP,MAAO,CACHC,eAAgB,KAChBT,KAAM,GACNE,MAAO,GACPQ,SAAU,GACVC,SAAS,IAIjBC,QAXW,WAYPC,KAAKJ,eAAiBI,KAAKC,OAAOC,OAAOC,GACzCH,KAAKI,SAGTC,QAAS,CACJD,MADI,WACI,WACCE,EAAcC,OAAOC,SAASC,KAC9BP,EAASF,KAAKC,OAAOS,MAC3BR,EAAOS,aAAeL,GACtBM,EAAAA,EAAAA,IAAYZ,KAAKJ,eAAgBM,GAAQW,MAAK,SAAAC,GACrCA,EAAKC,SAWN,EAAK1B,MAAQyB,EAAKE,WAClB,EAAK7B,KAAO,UAXZ8B,EAAAA,EAAAA,kBAAuBH,EAAKnB,MAC5B,EAAKuB,OAAOC,OAAO,aAAc,CAC7BC,SAAUN,EAAKnB,KAAKyB,SACpBC,SAAUP,EAAKnB,KAAK0B,SACpBC,MAAOR,EAAKnB,KAAK2B,MACjBC,OAAQT,EAAKnB,KAAK4B,SAEtB,EAAKpC,KAAK,UACV,EAAKqC,QAAQC,KAAK,CAACC,KAAM,aAK7B,EAAK5B,SAAU,KAChB6B,OAAM,SAAAC,GACLC,QAAQC,IAAI,iBAAiBF,GAC7B,EAAKzC,KAAO,QACZ,EAAKE,MAAQ,WACb,EAAKS,SAAU,MAIvBiC,YA7BK,WA8BD/B,KAAKwB,QAAQC,KAAK,CAACC,KAAM,S,UCpErC,MAAMM,GAA2B,OAAgB,EAAQ,CAAC,CAAC,SAASC,KAEpE","sources":["webpack://databasir-frontend/./src/views/OAuth2Login.vue","webpack://databasir-frontend/./src/views/OAuth2Login.vue?b6ea"],"sourcesContent":["<template>\r\n <el-container>\r\n <el-main v-loading=\"loading\" class=\"login-main\">\r\n <el-result\r\n :icon=\"icon\"\r\n :title=\"title\"\r\n :sub-title=\"subTitle\"\r\n v-show=\"!loading\"\r\n >\r\n <template #extra>\r\n <el-button type=\"primary\" @click=\"toIndexPage()\">立即跳转</el-button>\r\n </template>\r\n </el-result>\r\n </el-main>\r\n </el-container>\r\n</template>\r\n\r\n<style>\r\n.login-main {\r\n margin: 0 auto;\r\n margin-top: 200px;\r\n}\r\n\r\n</style>\r\n<script>\r\nimport { oauth2Login } from \"../api/Login\"\r\nimport { user } from \"../utils/auth\"\r\n\r\n\r\nexport default {\r\n data() {\r\n return {\r\n registrationId: null,\r\n icon: '',\r\n title: '',\r\n subTitle: '',\r\n loading: true,\r\n }\r\n },\r\n\r\n created() {\r\n this.registrationId = this.$route.params.id\r\n this.login()\r\n },\r\n\r\n methods: {\r\n login() {\r\n const redirectUri = window.location.href\r\n const params = this.$route.query\r\n params.redirect_uri = redirectUri\r\n oauth2Login(this.registrationId, params).then(resp => {\r\n if (!resp.errCode) {\r\n user.saveUserLoginData(resp.data)\r\n this.$store.commit('userUpdate', {\r\n nickname: resp.data.nickname,\r\n username: resp.data.username,\r\n email: resp.data.email,\r\n avatar: resp.data.avatar\r\n })\r\n this.icon='success'\r\n this.$router.push({path: '/groups'})\r\n } else {\r\n this.title = resp.errMessage\r\n this.icon = 'error'\r\n }\r\n this.loading = false\r\n }).catch(err => {\r\n console.log('login failed: '+err)\r\n this.icon = 'error'\r\n this.title = '登陆失败,请重试'\r\n this.loading = false\r\n })\r\n },\r\n\r\n toIndexPage() {\r\n this.$router.push({path: '/'})\r\n }\r\n }\r\n}\r\n</script>","import { render } from \"./OAuth2Login.vue?vue&type=template&id=65bc9922\"\nimport script from \"./OAuth2Login.vue?vue&type=script&lang=js\"\nexport * from \"./OAuth2Login.vue?vue&type=script&lang=js\"\n\nimport \"./OAuth2Login.vue?vue&type=style&index=0&id=65bc9922&lang=css\"\n\nimport exportComponent from \"E:\\\\git_workspace\\\\databasir-frontend\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render]])\n\nexport default __exports__"],"names":["_createBlock","_component_el_container","_component_el_main","class","_createVNode","_component_el_result","icon","$data","title","extra","_component_el_button","type","onClick","$options","data","registrationId","subTitle","loading","created","this","$route","params","id","login","methods","redirectUri","window","location","href","query","redirect_uri","oauth2Login","then","resp","errCode","errMessage","user","$store","commit","nickname","username","email","avatar","$router","push","path","catch","err","console","log","toIndexPage","__exports__","render"],"sourceRoot":""}

View File

@ -1,2 +1,2 @@
"use strict";(self["webpackChunkdatabasir_frontend"]=self["webpackChunkdatabasir_frontend"]||[]).push([[865],{8865:function(t,e,i){i.r(e),i.d(e,{default:function(){return h}});var a=i(6252),n=i(9963);const r=(0,a.Uk)("立即跳转");function s(t,e,i,s,o,l){const u=(0,a.up)("el-button"),d=(0,a.up)("el-result"),c=(0,a.up)("el-main"),h=(0,a.up)("el-container"),g=(0,a.Q2)("loading");return(0,a.wg)(),(0,a.j4)(h,null,{default:(0,a.w5)((()=>[(0,a.wy)(((0,a.wg)(),(0,a.j4)(c,{class:"login-main"},{default:(0,a.w5)((()=>[(0,a.wy)((0,a.Wm)(d,{icon:o.icon,title:o.title,"sub-title":o.subTitle},{extra:(0,a.w5)((()=>[(0,a.Wm)(u,{type:"primary",onClick:e[0]||(e[0]=t=>l.toIndexPage())},{default:(0,a.w5)((()=>[r])),_:1})])),_:1},8,["icon","title","sub-title"]),[[n.F8,!o.loading]])])),_:1})),[[g,o.loading]])])),_:1})}var o=i(152),l=i(1836),u={data(){return{registrationId:null,icon:"",title:"",subTitle:"",loading:!0}},created(){this.registrationId=this.$route.params.id,this.login()},methods:{login(){const t=window.location.href,e=this.$route.query;e.redirect_uri=t,(0,o.rd)(this.registrationId,e).then((t=>{t.errCode?(this.title=t.errMessage,this.icon="error"):(l.E.saveUserLoginData(t.data),this.$store.commit("userUpdate",{nickname:t.data.nickname,username:t.data.username,email:t.data.email,avatar:t.data.avatar}),this.icon="success",this.$router.push({path:"/groups"})),this.loading=!1})).catch((t=>{console.log("login failed: "+t),this.icon="error",this.title="登陆失败,请重试",this.loading=!1}))},toIndexPage(){this.$router.push({path:"/"})}}},d=i(3744);const c=(0,d.Z)(u,[["render",s]]);var h=c}}]);
//# sourceMappingURL=865.ef6dc5a3.js.map
//# sourceMappingURL=865.ebbb1893.js.map

View File

@ -1 +1 @@
{"version":3,"file":"js/865.ef6dc5a3.js","mappings":"yNAUiE,Q,uKAT7DA,EAAAA,EAAAA,IAaeC,EAAA,M,kBAZX,IAWU,uBAXVD,EAAAA,EAAAA,IAWUE,EAAA,CAXmBC,MAAM,cAAY,C,kBAC3C,IASY,WATZC,EAAAA,EAAAA,IASYC,EAAA,CARPC,KAAMC,EAAAA,KACNC,MAAOD,EAAAA,MACP,YAAWA,EAAAA,UAHhB,CAMeE,OAAK,SAChB,IAAiE,EAAjEL,EAAAA,EAAAA,IAAiEM,EAAA,CAAtDC,KAAK,UAAWC,QAAK,eAAEC,EAAAA,gBAAlC,C,kBAAiD,IAAI,M,cAPzD,wCAIaN,EAAAA,c,OALjB,IAAoBA,EAAAA,c,6BA2B5B,GACIO,OACI,MAAO,CACHC,eAAgB,KAChBT,KAAM,GACNE,MAAO,GACPQ,SAAU,GACVC,SAAS,IAIjBC,UACIC,KAAKJ,eAAiBI,KAAKC,OAAOC,OAAOC,GACzCH,KAAKI,SAGTC,QAAS,CACJD,QACG,MAAME,EAAcC,OAAOC,SAASC,KAC9BP,EAASF,KAAKC,OAAOS,MAC3BR,EAAOS,aAAeL,GACtBM,EAAAA,EAAAA,IAAYZ,KAAKJ,eAAgBM,GAAQW,MAAKC,IACrCA,EAAKC,SAWNf,KAAKX,MAAQyB,EAAKE,WAClBhB,KAAKb,KAAO,UAXZ8B,EAAAA,EAAAA,kBAAuBH,EAAKnB,MAC5BK,KAAKkB,OAAOC,OAAO,aAAc,CAC7BC,SAAUN,EAAKnB,KAAKyB,SACpBC,SAAUP,EAAKnB,KAAK0B,SACpBC,MAAOR,EAAKnB,KAAK2B,MACjBC,OAAQT,EAAKnB,KAAK4B,SAEtBvB,KAAKb,KAAK,UACVa,KAAKwB,QAAQC,KAAK,CAACC,KAAM,aAK7B1B,KAAKF,SAAU,KAChB6B,OAAMC,IACLC,QAAQC,IAAI,iBAAiBF,GAC7B5B,KAAKb,KAAO,QACZa,KAAKX,MAAQ,WACbW,KAAKF,SAAU,MAIvBiC,cACI/B,KAAKwB,QAAQC,KAAK,CAACC,KAAM,S,UCpErC,MAAMM,GAA2B,OAAgB,EAAQ,CAAC,CAAC,SAASC,KAEpE","sources":["webpack://databasir-frontend/./src/views/OAuth2Login.vue","webpack://databasir-frontend/./src/views/OAuth2Login.vue?b6ea"],"sourcesContent":["<template>\r\n <el-container>\r\n <el-main v-loading=\"loading\" class=\"login-main\">\r\n <el-result\r\n :icon=\"icon\"\r\n :title=\"title\"\r\n :sub-title=\"subTitle\"\r\n v-show=\"!loading\"\r\n >\r\n <template #extra>\r\n <el-button type=\"primary\" @click=\"toIndexPage()\">立即跳转</el-button>\r\n </template>\r\n </el-result>\r\n </el-main>\r\n </el-container>\r\n</template>\r\n\r\n<style>\r\n.login-main {\r\n margin: 0 auto;\r\n margin-top: 200px;\r\n}\r\n\r\n</style>\r\n<script>\r\nimport { oauth2Login } from \"../api/Login\"\r\nimport { user } from \"../utils/auth\"\r\n\r\n\r\nexport default {\r\n data() {\r\n return {\r\n registrationId: null,\r\n icon: '',\r\n title: '',\r\n subTitle: '',\r\n loading: true,\r\n }\r\n },\r\n\r\n created() {\r\n this.registrationId = this.$route.params.id\r\n this.login()\r\n },\r\n\r\n methods: {\r\n login() {\r\n const redirectUri = window.location.href\r\n const params = this.$route.query\r\n params.redirect_uri = redirectUri\r\n oauth2Login(this.registrationId, params).then(resp => {\r\n if (!resp.errCode) {\r\n user.saveUserLoginData(resp.data)\r\n this.$store.commit('userUpdate', {\r\n nickname: resp.data.nickname,\r\n username: resp.data.username,\r\n email: resp.data.email,\r\n avatar: resp.data.avatar\r\n })\r\n this.icon='success'\r\n this.$router.push({path: '/groups'})\r\n } else {\r\n this.title = resp.errMessage\r\n this.icon = 'error'\r\n }\r\n this.loading = false\r\n }).catch(err => {\r\n console.log('login failed: '+err)\r\n this.icon = 'error'\r\n this.title = '登陆失败,请重试'\r\n this.loading = false\r\n })\r\n },\r\n\r\n toIndexPage() {\r\n this.$router.push({path: '/'})\r\n }\r\n }\r\n}\r\n</script>","import { render } from \"./OAuth2Login.vue?vue&type=template&id=65bc9922\"\nimport script from \"./OAuth2Login.vue?vue&type=script&lang=js\"\nexport * from \"./OAuth2Login.vue?vue&type=script&lang=js\"\n\nimport \"./OAuth2Login.vue?vue&type=style&index=0&id=65bc9922&lang=css\"\n\nimport exportComponent from \"E:\\\\git_workspace\\\\databasir-frontend\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render]])\n\nexport default __exports__"],"names":["_createBlock","_component_el_container","_component_el_main","class","_createVNode","_component_el_result","icon","$data","title","extra","_component_el_button","type","onClick","$options","data","registrationId","subTitle","loading","created","this","$route","params","id","login","methods","redirectUri","window","location","href","query","redirect_uri","oauth2Login","then","resp","errCode","errMessage","user","$store","commit","nickname","username","email","avatar","$router","push","path","catch","err","console","log","toIndexPage","__exports__","render"],"sourceRoot":""}
{"version":3,"file":"js/865.ebbb1893.js","mappings":"yNAUiE,Q,uKAT7DA,EAAAA,EAAAA,IAaeC,EAAA,M,kBAZX,IAWU,uBAXVD,EAAAA,EAAAA,IAWUE,EAAA,CAXmBC,MAAM,cAAY,C,kBAC3C,IASY,WATZC,EAAAA,EAAAA,IASYC,EAAA,CARPC,KAAMC,EAAAA,KACNC,MAAOD,EAAAA,MACP,YAAWA,EAAAA,UAHhB,CAMeE,OAAK,SAChB,IAAiE,EAAjEL,EAAAA,EAAAA,IAAiEM,EAAA,CAAtDC,KAAK,UAAWC,QAAK,eAAEC,EAAAA,gBAAlC,C,kBAAiD,IAAI,M,cAPzD,wCAIaN,EAAAA,c,OALjB,IAAoBA,EAAAA,c,6BA2B5B,GACIO,OACI,MAAO,CACHC,eAAgB,KAChBT,KAAM,GACNE,MAAO,GACPQ,SAAU,GACVC,SAAS,IAIjBC,UACIC,KAAKJ,eAAiBI,KAAKC,OAAOC,OAAOC,GACzCH,KAAKI,SAGTC,QAAS,CACJD,QACG,MAAME,EAAcC,OAAOC,SAASC,KAC9BP,EAASF,KAAKC,OAAOS,MAC3BR,EAAOS,aAAeL,GACtBM,EAAAA,EAAAA,IAAYZ,KAAKJ,eAAgBM,GAAQW,MAAKC,IACrCA,EAAKC,SAWNf,KAAKX,MAAQyB,EAAKE,WAClBhB,KAAKb,KAAO,UAXZ8B,EAAAA,EAAAA,kBAAuBH,EAAKnB,MAC5BK,KAAKkB,OAAOC,OAAO,aAAc,CAC7BC,SAAUN,EAAKnB,KAAKyB,SACpBC,SAAUP,EAAKnB,KAAK0B,SACpBC,MAAOR,EAAKnB,KAAK2B,MACjBC,OAAQT,EAAKnB,KAAK4B,SAEtBvB,KAAKb,KAAK,UACVa,KAAKwB,QAAQC,KAAK,CAACC,KAAM,aAK7B1B,KAAKF,SAAU,KAChB6B,OAAMC,IACLC,QAAQC,IAAI,iBAAiBF,GAC7B5B,KAAKb,KAAO,QACZa,KAAKX,MAAQ,WACbW,KAAKF,SAAU,MAIvBiC,cACI/B,KAAKwB,QAAQC,KAAK,CAACC,KAAM,S,UCpErC,MAAMM,GAA2B,OAAgB,EAAQ,CAAC,CAAC,SAASC,KAEpE","sources":["webpack://databasir-frontend/./src/views/OAuth2Login.vue","webpack://databasir-frontend/./src/views/OAuth2Login.vue?b6ea"],"sourcesContent":["<template>\r\n <el-container>\r\n <el-main v-loading=\"loading\" class=\"login-main\">\r\n <el-result\r\n :icon=\"icon\"\r\n :title=\"title\"\r\n :sub-title=\"subTitle\"\r\n v-show=\"!loading\"\r\n >\r\n <template #extra>\r\n <el-button type=\"primary\" @click=\"toIndexPage()\">立即跳转</el-button>\r\n </template>\r\n </el-result>\r\n </el-main>\r\n </el-container>\r\n</template>\r\n\r\n<style>\r\n.login-main {\r\n margin: 0 auto;\r\n margin-top: 200px;\r\n}\r\n\r\n</style>\r\n<script>\r\nimport { oauth2Login } from \"../api/Login\"\r\nimport { user } from \"../utils/auth\"\r\n\r\n\r\nexport default {\r\n data() {\r\n return {\r\n registrationId: null,\r\n icon: '',\r\n title: '',\r\n subTitle: '',\r\n loading: true,\r\n }\r\n },\r\n\r\n created() {\r\n this.registrationId = this.$route.params.id\r\n this.login()\r\n },\r\n\r\n methods: {\r\n login() {\r\n const redirectUri = window.location.href\r\n const params = this.$route.query\r\n params.redirect_uri = redirectUri\r\n oauth2Login(this.registrationId, params).then(resp => {\r\n if (!resp.errCode) {\r\n user.saveUserLoginData(resp.data)\r\n this.$store.commit('userUpdate', {\r\n nickname: resp.data.nickname,\r\n username: resp.data.username,\r\n email: resp.data.email,\r\n avatar: resp.data.avatar\r\n })\r\n this.icon='success'\r\n this.$router.push({path: '/groups'})\r\n } else {\r\n this.title = resp.errMessage\r\n this.icon = 'error'\r\n }\r\n this.loading = false\r\n }).catch(err => {\r\n console.log('login failed: '+err)\r\n this.icon = 'error'\r\n this.title = '登陆失败,请重试'\r\n this.loading = false\r\n })\r\n },\r\n\r\n toIndexPage() {\r\n this.$router.push({path: '/'})\r\n }\r\n }\r\n}\r\n</script>","import { render } from \"./OAuth2Login.vue?vue&type=template&id=65bc9922\"\nimport script from \"./OAuth2Login.vue?vue&type=script&lang=js\"\nexport * from \"./OAuth2Login.vue?vue&type=script&lang=js\"\n\nimport \"./OAuth2Login.vue?vue&type=style&index=0&id=65bc9922&lang=css\"\n\nimport exportComponent from \"E:\\\\git_workspace\\\\databasir-frontend\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render]])\n\nexport default __exports__"],"names":["_createBlock","_component_el_container","_component_el_main","class","_createVNode","_component_el_result","icon","$data","title","extra","_component_el_button","type","onClick","$options","data","registrationId","subTitle","loading","created","this","$route","params","id","login","methods","redirectUri","window","location","href","query","redirect_uri","oauth2Login","then","resp","errCode","errMessage","user","$store","commit","nickname","username","email","avatar","$router","push","path","catch","err","console","log","toIndexPage","__exports__","render"],"sourceRoot":""}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
"use strict";(self["webpackChunkdatabasir_frontend"]=self["webpackChunkdatabasir_frontend"]||[]).push([[99],{5430:function(e,t,a){a.d(t,{v:function(){return r}});var n=a(3872),o="/api/v1.0/operation_logs",r=function(e){return n.Z.get(o,{params:e})}},2099:function(e,t,a){a.r(t),a.d(t,{default:function(){return h}});a(8309);var n=a(6252),o=a(3577),r={key:0},u=(0,n.Uk)("成功"),l={key:1},i=(0,n.Uk)("失败"),p={key:0},c={key:1},g={key:1},s={key:1},d={key:1};function f(e,t,a,f,w,m){var P=(0,n.up)("el-table-column"),j=(0,n.up)("el-option"),h=(0,n.up)("el-select"),v=(0,n.up)("el-tag"),y=(0,n.up)("el-link"),b=(0,n.up)("el-table"),k=(0,n.up)("el-main"),L=(0,n.up)("el-pagination"),O=(0,n.up)("el-footer"),D=(0,n.up)("el-container");return(0,n.wg)(),(0,n.j4)(D,null,{default:(0,n.w5)((function(){return[(0,n.Wm)(k,null,{default:(0,n.w5)((function(){return[(0,n.Wm)(b,{data:w.projectOperationLogPageData.data},{default:(0,n.w5)((function(){return[(0,n.Wm)(P,{prop:"id",label:""}),(0,n.Wm)(P,{prop:"operationModule",label:"系统模块"}),(0,n.Wm)(P,{prop:"operatorNickname",label:"操作人"}),(0,n.Wm)(P,{prop:"operationName",label:"操作"}),(0,n.Wm)(P,{label:"状态"},{header:(0,n.w5)((function(){return[(0,n.Wm)(h,{modelValue:w.projectOperationLogPageQuery.isSuccess,"onUpdate:modelValue":t[0]||(t[0]=function(e){return w.projectOperationLogPageQuery.isSuccess=e}),placeholder:"状态",onChange:m.onQuery,clearable:"",size:"small","tag-type":"success"},{default:(0,n.w5)((function(){return[((0,n.wg)(),(0,n.iD)(n.HY,null,(0,n.Ko)([!0,!1],(function(e){return(0,n.Wm)(j,{key:e,label:e?"成功":"失败",value:e},null,8,["label","value"])})),64))]})),_:1},8,["modelValue","onChange"])]})),default:(0,n.w5)((function(e){return[e.row.isSuccess?((0,n.wg)(),(0,n.iD)("span",r,[(0,n.Wm)(v,{type:"success"},{default:(0,n.w5)((function(){return[u]})),_:1})])):((0,n.wg)(),(0,n.iD)("span",l,[(0,n.Wm)(v,{type:"danger"},{default:(0,n.w5)((function(){return[i]})),_:1})]))]})),_:1}),(0,n.Wm)(P,{label:"错误信息"},{default:(0,n.w5)((function(e){return[e.row.isSuccess?((0,n.wg)(),(0,n.iD)("span",p)):((0,n.wg)(),(0,n.iD)("span",c,(0,o.zw)(e.row.operationResponse.errMessage),1))]})),_:1}),(0,n.Wm)(P,{label:"涉及分组"},{default:(0,n.w5)((function(e){return[e.row.involvedGroup?((0,n.wg)(),(0,n.j4)(y,{key:0},{default:(0,n.w5)((function(){return[(0,n.Uk)((0,o.zw)(e.row.involvedGroup.name),1)]})),_:2},1024)):((0,n.wg)(),(0,n.iD)("span",g," - "))]})),_:1}),(0,n.Wm)(P,{label:"涉及项目"},{default:(0,n.w5)((function(e){return[e.row.involvedProject?((0,n.wg)(),(0,n.j4)(y,{key:0},{default:(0,n.w5)((function(){return[(0,n.Uk)((0,o.zw)(e.row.involvedProject.name),1)]})),_:2},1024)):((0,n.wg)(),(0,n.iD)("span",s," - "))]})),_:1}),(0,n.Wm)(P,{label:"涉及用户"},{default:(0,n.w5)((function(e){return[e.row.involvedUser?((0,n.wg)(),(0,n.j4)(y,{key:0},{default:(0,n.w5)((function(){return[(0,n.Uk)((0,o.zw)(e.row.involvedUser.nickname),1)]})),_:2},1024)):((0,n.wg)(),(0,n.iD)("span",d," - "))]})),_:1}),(0,n.Wm)(P,{prop:"createAt",label:"记录时间"})]})),_:1},8,["data"])]})),_:1}),(0,n.Wm)(O,null,{default:(0,n.w5)((function(){return[(0,n.Wm)(L,{layout:"prev, pager, next","hide-on-single-page":!1,currentPage:w.projectOperationLogPageData.number,"page-size":w.projectOperationLogPageData.size,"page-count":w.projectOperationLogPageData.totalPages,onCurrentChange:m.onProjectOperationLogCurrentPageChange},null,8,["currentPage","page-size","page-count","onCurrentChange"])]})),_:1})]})),_:1})}var w=a(5430),m={data:function(){return{projectOperationLogPageData:{data:[],number:1,size:10,totalElements:0,totalPages:1},projectOperationLogPageQuery:{page:0,size:10,isSuccess:null,involveProjectId:null,module:null}}},created:function(){this.fetchProjectOperationLogs()},methods:{fetchProjectOperationLogs:function(e){var t=this;this.projectOperationLogPageQuery.page=e?e-1:null,(0,w.v)(this.projectOperationLogPageQuery).then((function(e){e.errCode||(t.projectOperationLogPageData.data=e.data.content,t.projectOperationLogPageData.number=e.data.number+1,t.projectOperationLogPageData.size=e.data.size,t.projectOperationLogPageData.totalPages=e.data.totalPages,t.projectOperationLogPageData.totalElements=e.data.totalElements)}))},onProjectOperationLogCurrentPageChange:function(e){e&&e-1!=this.projectOperationLogPageQuery.page&&(this.projectOperationLogPageQuery.page=e-1,this.fetchProjectOperationLogs(e))},onQuery:function(){this.fetchProjectOperationLogs()}}},P=a(3744);const j=(0,P.Z)(m,[["render",f]]);var h=j}}]);
//# sourceMappingURL=99-legacy.618121ce.js.map
//# sourceMappingURL=99-legacy.6cfcb3aa.js.map

View File

@ -1,2 +1,2 @@
"use strict";(self["webpackChunkdatabasir_frontend"]=self["webpackChunkdatabasir_frontend"]||[]).push([[99],{5430:function(e,a,t){t.d(a,{v:function(){return n}});var o=t(3872);const r="/api/v1.0/operation_logs",n=e=>o.Z.get(r,{params:e})},2099:function(e,a,t){t.r(a),t.d(a,{default:function(){return j}});var o=t(6252),r=t(3577);const n={key:0},l=(0,o.Uk)("成功"),p={key:1},u=(0,o.Uk)("失败"),i={key:0},g={key:1},s={key:1},c={key:1},d={key:1};function w(e,a,t,w,m,P){const f=(0,o.up)("el-table-column"),h=(0,o.up)("el-option"),j=(0,o.up)("el-select"),v=(0,o.up)("el-tag"),y=(0,o.up)("el-link"),b=(0,o.up)("el-table"),k=(0,o.up)("el-main"),L=(0,o.up)("el-pagination"),O=(0,o.up)("el-footer"),D=(0,o.up)("el-container");return(0,o.wg)(),(0,o.j4)(D,null,{default:(0,o.w5)((()=>[(0,o.Wm)(k,null,{default:(0,o.w5)((()=>[(0,o.Wm)(b,{data:m.projectOperationLogPageData.data},{default:(0,o.w5)((()=>[(0,o.Wm)(f,{prop:"id",label:""}),(0,o.Wm)(f,{prop:"operationModule",label:"系统模块"}),(0,o.Wm)(f,{prop:"operatorNickname",label:"操作人"}),(0,o.Wm)(f,{prop:"operationName",label:"操作"}),(0,o.Wm)(f,{label:"状态"},{header:(0,o.w5)((()=>[(0,o.Wm)(j,{modelValue:m.projectOperationLogPageQuery.isSuccess,"onUpdate:modelValue":a[0]||(a[0]=e=>m.projectOperationLogPageQuery.isSuccess=e),placeholder:"状态",onChange:P.onQuery,clearable:"",size:"small","tag-type":"success"},{default:(0,o.w5)((()=>[((0,o.wg)(),(0,o.iD)(o.HY,null,(0,o.Ko)([!0,!1],(e=>(0,o.Wm)(h,{key:e,label:e?"成功":"失败",value:e},null,8,["label","value"]))),64))])),_:1},8,["modelValue","onChange"])])),default:(0,o.w5)((e=>[e.row.isSuccess?((0,o.wg)(),(0,o.iD)("span",n,[(0,o.Wm)(v,{type:"success"},{default:(0,o.w5)((()=>[l])),_:1})])):((0,o.wg)(),(0,o.iD)("span",p,[(0,o.Wm)(v,{type:"danger"},{default:(0,o.w5)((()=>[u])),_:1})]))])),_:1}),(0,o.Wm)(f,{label:"错误信息"},{default:(0,o.w5)((e=>[e.row.isSuccess?((0,o.wg)(),(0,o.iD)("span",i)):((0,o.wg)(),(0,o.iD)("span",g,(0,r.zw)(e.row.operationResponse.errMessage),1))])),_:1}),(0,o.Wm)(f,{label:"涉及分组"},{default:(0,o.w5)((e=>[e.row.involvedGroup?((0,o.wg)(),(0,o.j4)(y,{key:0},{default:(0,o.w5)((()=>[(0,o.Uk)((0,r.zw)(e.row.involvedGroup.name),1)])),_:2},1024)):((0,o.wg)(),(0,o.iD)("span",s," - "))])),_:1}),(0,o.Wm)(f,{label:"涉及项目"},{default:(0,o.w5)((e=>[e.row.involvedProject?((0,o.wg)(),(0,o.j4)(y,{key:0},{default:(0,o.w5)((()=>[(0,o.Uk)((0,r.zw)(e.row.involvedProject.name),1)])),_:2},1024)):((0,o.wg)(),(0,o.iD)("span",c," - "))])),_:1}),(0,o.Wm)(f,{label:"涉及用户"},{default:(0,o.w5)((e=>[e.row.involvedUser?((0,o.wg)(),(0,o.j4)(y,{key:0},{default:(0,o.w5)((()=>[(0,o.Uk)((0,r.zw)(e.row.involvedUser.nickname),1)])),_:2},1024)):((0,o.wg)(),(0,o.iD)("span",d," - "))])),_:1}),(0,o.Wm)(f,{prop:"createAt",label:"记录时间"})])),_:1},8,["data"])])),_:1}),(0,o.Wm)(O,null,{default:(0,o.w5)((()=>[(0,o.Wm)(L,{layout:"prev, pager, next","hide-on-single-page":!1,currentPage:m.projectOperationLogPageData.number,"page-size":m.projectOperationLogPageData.size,"page-count":m.projectOperationLogPageData.totalPages,onCurrentChange:P.onProjectOperationLogCurrentPageChange},null,8,["currentPage","page-size","page-count","onCurrentChange"])])),_:1})])),_:1})}var m=t(5430),P={data(){return{projectOperationLogPageData:{data:[],number:1,size:10,totalElements:0,totalPages:1},projectOperationLogPageQuery:{page:0,size:10,isSuccess:null,involveProjectId:null,module:null}}},created(){this.fetchProjectOperationLogs()},methods:{fetchProjectOperationLogs(e){this.projectOperationLogPageQuery.page=e?e-1:null,(0,m.v)(this.projectOperationLogPageQuery).then((e=>{e.errCode||(this.projectOperationLogPageData.data=e.data.content,this.projectOperationLogPageData.number=e.data.number+1,this.projectOperationLogPageData.size=e.data.size,this.projectOperationLogPageData.totalPages=e.data.totalPages,this.projectOperationLogPageData.totalElements=e.data.totalElements)}))},onProjectOperationLogCurrentPageChange(e){e&&e-1!=this.projectOperationLogPageQuery.page&&(this.projectOperationLogPageQuery.page=e-1,this.fetchProjectOperationLogs(e))},onQuery(){this.fetchProjectOperationLogs()}}},f=t(3744);const h=(0,f.Z)(P,[["render",w]]);var j=h}}]);
//# sourceMappingURL=99.c134b829.js.map
//# sourceMappingURL=99.79a6a4f8.js.map

View File

@ -32,6 +32,7 @@ public enum DomainErrors implements DatabasirErrors {
MUST_NOT_MODIFY_SYSTEM_DEFAULT_DATABASE_TYPE("A_10017", "禁止修改系统默认数据库类型"),
DOWNLOAD_DRIVER_ERROR("A_10018", "驱动下载失败"),
INVALID_DATABASE_TYPE_URL_PATTERN("A_10019", "不合法的 url pattern"),
DOCUMENT_VERSION_IS_INVALID("A_10020", "文档版本不合法"),
;
private final String errCode;

View File

@ -1,9 +0,0 @@
package com.databasir.core.domain.document.converter;
public interface BaseConverter {
@NullToEmpty
default String nullToEmpty(String s) {
return s == null ? "" : s;
}
}

View File

@ -0,0 +1,71 @@
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 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);
default <R> Map<Integer, List<R>> groupBy(List<R> content, Function<R, Integer> idMapping) {
return content.stream()
.collect(Collectors.groupingBy(idMapping));
}
}

View File

@ -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);

View File

@ -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 {
}

View File

@ -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);
@ -325,4 +349,20 @@ public class DocumentService {
.ifPresent(generator -> generator.generate(context, out));
});
}
public RootDiff diff(Integer projectId, Long originalVersion, Long currentVersion) {
var original = databaseDocumentDao.selectOptionalByProjectIdAndVersion(projectId, originalVersion)
.orElseThrow(DomainErrors.DOCUMENT_VERSION_IS_INVALID::exception);
DatabaseDocumentPojo current;
if (currentVersion == null) {
current = databaseDocumentDao.selectNotArchivedByProjectId(projectId)
.orElseThrow(DomainErrors.DOCUMENT_VERSION_IS_INVALID::exception);
} else {
current = databaseDocumentDao.selectOptionalByProjectIdAndVersion(projectId, currentVersion)
.orElseThrow(DomainErrors.DOCUMENT_VERSION_IS_INVALID::exception);
}
DatabaseMeta currMeta = retrieveOriginalDatabaseMeta(current);
DatabaseMeta originalMeta = retrieveOriginalDatabaseMeta(original);
return Diffs.diff(originalMeta, currMeta);
}
}

View File

@ -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>.

View File

@ -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>.

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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());

View File

@ -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,

View File

@ -2,4 +2,6 @@ dependencies {
testImplementation 'mysql:mysql-connector-java:8.0.27'
implementation 'org.commonmark:commonmark:0.18.1'
implementation 'org.freemarker:freemarker:2.3.31'
testImplementation "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}"
testImplementation "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}"
}

View File

@ -0,0 +1,17 @@
package com.databasir.core.diff;
import com.databasir.core.diff.data.RootDiff;
import com.databasir.core.diff.processor.DatabaseDiffProcessor;
import com.databasir.core.meta.data.DatabaseMeta;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Diffs {
private static final DatabaseDiffProcessor databaseDiffProcessor = new DatabaseDiffProcessor();
public static RootDiff diff(DatabaseMeta original, DatabaseMeta current) {
return databaseDiffProcessor.process(original, current);
}
}

View File

@ -0,0 +1,11 @@
package com.databasir.core.diff.data;
public interface Diff {
DiffType getDiffType();
Object getOriginal();
Object getCurrent();
}

View File

@ -0,0 +1,9 @@
package com.databasir.core.diff.data;
public enum DiffType {
NONE, ADDED, REMOVED, MODIFIED;
public static boolean isModified(DiffType type) {
return type != null && type != NONE;
}
}

View File

@ -0,0 +1,24 @@
package com.databasir.core.diff.data;
import lombok.Builder;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
@Builder
public class FieldDiff implements Diff {
private String fieldName;
private DiffType diffType;
private Object original;
private Object current;
@Builder.Default
private List<FieldDiff> fields = new ArrayList<>();
}

View File

@ -0,0 +1,15 @@
package com.databasir.core.diff.data;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class RootDiff {
private DiffType diffType;
private List<FieldDiff> fields = new ArrayList<>();
}

View File

@ -0,0 +1,14 @@
package com.databasir.core.diff.processor;
import com.databasir.core.diff.data.FieldDiff;
import com.databasir.core.meta.data.ColumnMeta;
import java.util.List;
public class ColumnDiffProcessor implements DiffProcessor<ColumnMeta> {
@Override
public FieldDiff process(String fieldName, List<ColumnMeta> original, List<ColumnMeta> current) {
return diffTableField(original, current, fieldName, ColumnMeta::getName);
}
}

View File

@ -0,0 +1,81 @@
package com.databasir.core.diff.processor;
import com.databasir.core.diff.data.DiffType;
import com.databasir.core.diff.data.FieldDiff;
import com.databasir.core.diff.data.RootDiff;
import com.databasir.core.meta.data.DatabaseMeta;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@Slf4j
public class DatabaseDiffProcessor {
private final TableDiffProcessor tableDiffProcessor = new TableDiffProcessor();
private static final DatabaseMeta EMPTY = DatabaseMeta.builder().build();
public RootDiff process(DatabaseMeta original, DatabaseMeta current) {
DiffType diffType = null;
if (original == null && current != null) {
diffType = DiffType.ADDED;
}
if (original != null && current == null) {
diffType = DiffType.REMOVED;
}
List<FieldDiff> fields = diffDatabaseFields(
Objects.requireNonNullElse(original, EMPTY),
Objects.requireNonNullElse(current, EMPTY)
);
boolean isModified = fields.stream().anyMatch(f -> DiffType.isModified(f.getDiffType()));
if (diffType == null) {
diffType = isModified ? DiffType.MODIFIED : DiffType.NONE;
}
RootDiff diff = new RootDiff();
diff.setFields(fields);
diff.setDiffType(diffType);
return diff;
}
private List<FieldDiff> diffDatabaseFields(DatabaseMeta original, DatabaseMeta current) {
Class<DatabaseMeta> clazz = DatabaseMeta.class;
Field[] fields = clazz.getDeclaredFields();
List<FieldDiff> diffs = new ArrayList<>(32);
// ignore tables diff
Arrays.stream(fields)
.filter(field -> !Objects.equals(field.getName(), "tables"))
.forEach(field -> {
try {
field.setAccessible(true);
Object originalValue = original == null ? null : field.get(original);
Object currentValue = current == null ? null : field.get(current);
if (!Objects.equals(originalValue, currentValue)) {
DiffType diffType;
if (originalValue == null) {
diffType = DiffType.ADDED;
} else if (currentValue == null) {
diffType = DiffType.REMOVED;
} else {
diffType = DiffType.MODIFIED;
}
diffs.add(FieldDiff.builder()
.diffType(diffType)
.fieldName(field.getName())
.original(originalValue)
.current(currentValue)
.build());
}
} catch (IllegalAccessException e) {
log.error("diff field failed", e);
}
});
FieldDiff tablesField = tableDiffProcessor.process("tables", original.getTables(), current.getTables());
diffs.add(tablesField);
return diffs;
}
}

View File

@ -0,0 +1,94 @@
package com.databasir.core.diff.processor;
import com.databasir.core.diff.data.DiffType;
import com.databasir.core.diff.data.FieldDiff;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
public interface DiffProcessor<T> {
FieldDiff process(String fieldName, List<T> original, List<T> current);
default FieldDiff diffTableField(List<T> original,
List<T> current,
String fieldName,
Function<T, String> identity) {
Map<String, T> originalMap = toMap(original, identity);
Map<String, T> currentMap = toMap(current, identity);
List<FieldDiff> columnFieldDiffs = new ArrayList<>(32);
// removed
List<FieldDiff> removedFields = originalRemovedField(originalMap, currentMap);
columnFieldDiffs.addAll(removedFields);
// added
List<FieldDiff> addedFields = currentAddedField(originalMap, currentMap);
columnFieldDiffs.addAll(addedFields);
// modified
List<FieldDiff> modifiedFields = modifiedField(originalMap, currentMap);
columnFieldDiffs.addAll(modifiedFields);
return FieldDiff.builder()
.fieldName(fieldName)
.diffType(columnFieldDiffs.isEmpty() ? DiffType.NONE : DiffType.MODIFIED)
.fields(columnFieldDiffs)
.build();
}
default Map<String, T> toMap(List<T> content, Function<T, String> idMapping) {
return content
.stream()
.collect(Collectors.toMap(idMapping, Function.identity()));
}
default List<FieldDiff> originalRemovedField(Map<String, T> originalMapById,
Map<String, T> currentMapById) {
return originalMapById.entrySet()
.stream()
.filter(entry -> !currentMapById.containsKey(entry.getKey()))
.map(entry -> FieldDiff.builder()
.fieldName(entry.getKey())
.original(entry.getValue())
.diffType(DiffType.REMOVED)
.build())
.collect(Collectors.toList());
}
default List<FieldDiff> currentAddedField(Map<String, T> originalMapById,
Map<String, T> currentMapById) {
return currentMapById.entrySet()
.stream()
.filter(entry -> !originalMapById.containsKey(entry.getKey()))
.map(entry -> FieldDiff.builder()
.fieldName(entry.getKey())
.current(entry.getValue())
.diffType(DiffType.ADDED)
.build())
.collect(Collectors.toList());
}
default List<FieldDiff> modifiedField(Map<String, T> original,
Map<String, T> current) {
List<FieldDiff> diff = new ArrayList<>();
original.entrySet()
.stream()
.filter(entry -> current.containsKey(entry.getKey()))
.forEach(entry -> {
T originalValue = entry.getValue();
T currentValue = current.get(entry.getKey());
if (!Objects.equals(originalValue, currentValue)) {
FieldDiff fieldDiff = FieldDiff.builder()
.fieldName(entry.getKey())
.original(originalValue)
.current(currentValue)
.diffType(DiffType.MODIFIED)
.build();
diff.add(fieldDiff);
}
});
return diff;
}
}

View File

@ -0,0 +1,24 @@
package com.databasir.core.diff.processor;
import com.databasir.core.diff.data.FieldDiff;
import com.databasir.core.meta.data.ForeignKeyMeta;
import java.util.List;
public class ForeignKeyDiffProcessor implements DiffProcessor<ForeignKeyMeta> {
@Override
public FieldDiff process(String fieldName, List<ForeignKeyMeta> original, List<ForeignKeyMeta> current) {
return diffTableField(
original,
current,
"foreignKeys",
fk -> {
if (fk.getFkName() == null) {
return fk.getFkTableName() + "." + fk.getFkColumnName() + "." + fk.getKeySeq();
} else {
return fk.getFkName();
}
});
}
}

View File

@ -0,0 +1,14 @@
package com.databasir.core.diff.processor;
import com.databasir.core.diff.data.FieldDiff;
import com.databasir.core.meta.data.IndexMeta;
import java.util.List;
public class IndexDiffProcessor implements DiffProcessor<IndexMeta> {
@Override
public FieldDiff process(String fieldName, List<IndexMeta> original, List<IndexMeta> current) {
return diffTableField(original, current, fieldName, IndexMeta::getName);
}
}

View File

@ -0,0 +1,158 @@
package com.databasir.core.diff.processor;
import com.databasir.core.diff.data.DiffType;
import com.databasir.core.diff.data.FieldDiff;
import com.databasir.core.meta.data.TableMeta;
import lombok.extern.slf4j.Slf4j;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
public class TableDiffProcessor implements DiffProcessor<TableMeta> {
private final IndexDiffProcessor indexDiffProcessor = new IndexDiffProcessor();
private final ColumnDiffProcessor columnDiffProcessor = new ColumnDiffProcessor();
private final TriggerDiffProcessor triggerDiffProcessor = new TriggerDiffProcessor();
private final ForeignKeyDiffProcessor foreignKeyDiffProcessor = new ForeignKeyDiffProcessor();
private static final TableMeta EMPTY = new TableMeta();
@Override
public FieldDiff process(String fieldName, List<TableMeta> original, List<TableMeta> current) {
// diff tables field
Map<String, TableMeta> originalMap = toMap(original, TableMeta::getName);
Map<String, TableMeta> currentMap = toMap(current, TableMeta::getName);
List<FieldDiff> tables = new ArrayList<>();
List<TableMeta> added = added(originalMap, currentMap);
List<TableMeta> removed = removed(originalMap, currentMap);
// added
List<FieldDiff> addedFields = added.stream()
.map(table -> diffTableField(EMPTY, table))
.collect(Collectors.toList());
tables.addAll(addedFields);
// removed
List<FieldDiff> removedFields = removed.stream()
.map(table -> diffTableField(table, EMPTY))
.collect(Collectors.toList());
tables.addAll(removedFields);
// modified
List<FieldDiff> modified = originalMap.entrySet()
.stream()
.filter(entry -> currentMap.containsKey(entry.getKey()))
.filter(entry -> !Objects.equals(entry.getValue(), currentMap.get(entry.getKey())))
.map(entry -> {
TableMeta originalValue = entry.getValue();
TableMeta currentValue = currentMap.get(entry.getKey());
return diffTableField(originalValue, currentValue);
})
.collect(Collectors.toList());
tables.addAll(modified);
DiffType tablesDiffType;
if (!modified.isEmpty()) {
tablesDiffType = DiffType.MODIFIED;
} else if (!addedFields.isEmpty()) {
tablesDiffType = DiffType.ADDED;
} else if (!removedFields.isEmpty()) {
tablesDiffType = DiffType.REMOVED;
} else {
tablesDiffType = DiffType.NONE;
}
FieldDiff tablesField = FieldDiff.builder()
.diffType(tablesDiffType)
.fieldName(fieldName)
.fields(tables)
.build();
return tablesField;
}
private List<TableMeta> added(Map<String, TableMeta> originalMap,
Map<String, TableMeta> currentMap) {
return currentMap.entrySet()
.stream()
.filter(entry -> !originalMap.containsKey(entry.getKey()))
.map(Map.Entry::getValue)
.collect(Collectors.toList());
}
private List<TableMeta> removed(Map<String, TableMeta> originalMap,
Map<String, TableMeta> currentMap) {
return originalMap.entrySet()
.stream()
.filter(entry -> !currentMap.containsKey(entry.getKey()))
.map(Map.Entry::getValue)
.collect(Collectors.toList());
}
private FieldDiff diffTableField(TableMeta original, TableMeta current) {
FieldDiff columns =
columnDiffProcessor.process("columns", original.getColumns(), current.getColumns());
FieldDiff indexes =
indexDiffProcessor.process("indexes", original.getIndexes(), current.getIndexes());
FieldDiff triggers =
triggerDiffProcessor.process("triggers", original.getTriggers(), current.getTriggers());
FieldDiff foreignKeys =
foreignKeyDiffProcessor.process("foreignKeys", original.getForeignKeys(), current.getForeignKeys());
List<FieldDiff> otherFields = fields(original, current);
List<FieldDiff> fields = new ArrayList<>();
fields.add(columns);
fields.add(indexes);
fields.add(foreignKeys);
fields.add(triggers);
fields.addAll(otherFields);
DiffType diffType;
if (original == EMPTY) {
diffType = DiffType.ADDED;
} else if (current == EMPTY) {
diffType = DiffType.REMOVED;
} else {
diffType = DiffType.MODIFIED;
}
return FieldDiff.builder()
.diffType(diffType)
.fieldName(original == EMPTY ? current.getName() : original.getName())
.original(current == EMPTY ? original : null)
.current(original == EMPTY ? current : null)
.fields(fields)
.build();
}
private List<FieldDiff> fields(TableMeta original, TableMeta current) {
List<FieldDiff> fields = new ArrayList<>();
// ignore tables diff
Class<TableMeta> clazz = TableMeta.class;
List<String> ignoredFields = List.of("columns", "indexes", "triggers", "foreignKeys");
Arrays.stream(clazz.getDeclaredFields())
.filter(field -> !ignoredFields.contains(field.getName()))
.forEach(field -> {
try {
field.setAccessible(true);
Object originalValue = original == null ? null : field.get(original);
Object currentValue = current == null ? null : field.get(current);
if (!Objects.equals(originalValue, currentValue)) {
DiffType diffType;
if (originalValue == null) {
diffType = DiffType.ADDED;
} else if (currentValue == null) {
diffType = DiffType.REMOVED;
} else {
diffType = DiffType.MODIFIED;
}
fields.add(FieldDiff.builder()
.diffType(diffType)
.fieldName(field.getName())
.original(originalValue)
.current(currentValue)
.build());
}
} catch (IllegalAccessException e) {
log.error("diff field failed", e);
}
});
return fields;
}
}

View File

@ -0,0 +1,14 @@
package com.databasir.core.diff.processor;
import com.databasir.core.diff.data.FieldDiff;
import com.databasir.core.meta.data.TriggerMeta;
import java.util.List;
public class TriggerDiffProcessor implements DiffProcessor<TriggerMeta> {
@Override
public FieldDiff process(String fieldName, List<TriggerMeta> original, List<TriggerMeta> current) {
return diffTableField(original, current, fieldName, TriggerMeta::getName);
}
}

View File

@ -1,10 +1,14 @@
package com.databasir.core.meta.data;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ColumnMeta {
private String name;

View File

@ -1,12 +1,16 @@
package com.databasir.core.meta.data;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Collections;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DatabaseMeta {

View File

@ -1,12 +1,18 @@
package com.databasir.core.meta.data;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ForeignKeyMeta {
private Integer keySeq;
/**
* may null
*/

View File

@ -1,13 +1,17 @@
package com.databasir.core.meta.data;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Collections;
import java.util.List;
@Data
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class IndexMeta {
private String name;

View File

@ -1,13 +1,17 @@
package com.databasir.core.meta.data;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Collections;
import java.util.List;
@Data
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TableMeta {
private String name;
@ -27,6 +31,4 @@ public class TableMeta {
@Builder.Default
private List<ForeignKeyMeta> foreignKeys = Collections.emptyList();
private String remark;
}

View File

@ -1,13 +1,17 @@
package com.databasir.core.meta.data;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* now: only support mysql, postgresql.
*/
@Data
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TriggerMeta {
private String name;

View File

@ -41,8 +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 keySeq = keyResult.getInt("KEY_SEQ");
int deleteRule = keyResult.getInt("DELETE_RULE");
ForeignKeyMeta meta = ForeignKeyMeta.builder()
.keySeq(keySeq)
.fkTableName(fkTableName)
.fkColumnName(fkColumnName)
.fkName(fkName)

View File

@ -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() + ")";

View File

@ -1,40 +0,0 @@
import com.databasir.core.Databasir;
import com.databasir.core.meta.data.DatabaseMeta;
import org.junit.jupiter.api.Test;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class App {
@Test
public void testRenderAsMarkdown() throws SQLException, ClassNotFoundException {
try (FileOutputStream out = new FileOutputStream("demo.md")) {
Connection connection = getJdbcConnection();
Databasir databasir = Databasir.of();
DatabaseMeta doc = databasir.get(connection, "demo").orElseThrow();
databasir.renderAsMarkdown(doc, out);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
private static Connection getJdbcConnection() throws SQLException, ClassNotFoundException {
// get database connection
Class.forName("com.mysql.cj.jdbc.Driver");
Properties info = new Properties();
info.put("user", "root");
info.put("password", "123456");
// this config is used by mysql
info.put("useInformationSchema", "true");
String url = "jdbc:mysql://localhost:3306/demo?"
+ "useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true";
return DriverManager.getConnection(url, info);
}
}

View File

@ -0,0 +1,597 @@
package com.databasir.core.diff.service;
import com.databasir.core.diff.Diffs;
import com.databasir.core.diff.data.DiffType;
import com.databasir.core.diff.data.FieldDiff;
import com.databasir.core.diff.data.RootDiff;
import com.databasir.core.meta.data.*;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TimeZone;
import java.util.function.Function;
import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.*;
class DiffsTest {
private static ObjectMapper objectMapper;
@BeforeAll
static void init() {
objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT)
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.disable(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)
.disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS)
.setTimeZone(TimeZone.getDefault());
}
@Test
void diffEmptyDatabaseSame() {
DatabaseMeta original = DatabaseMeta.builder().build();
DatabaseMeta current = DatabaseMeta.builder().build();
RootDiff diff = Diffs.diff(original, current);
assertEquals(DiffType.NONE, diff.getDiffType());
}
@Test
void diffDatabaseSame() {
DatabaseMeta original = load("ut/diffsTest/diffDatabaseSame/original.json");
DatabaseMeta current = load("ut/diffsTest/diffDatabaseSame/current.json");
RootDiff diff = Diffs.diff(original, current);
assertEquals(DiffType.NONE, diff.getDiffType());
assertSame(1, diff.getFields().size());
FieldDiff tableField = diff.getFields().iterator().next();
assertEquals("tables", tableField.getFieldName());
assertEquals(DiffType.NONE, tableField.getDiffType());
assertTrue(tableField.getFields().isEmpty());
}
@Test
void diffDatabaseAdded() {
DatabaseMeta current = load("ut/diffsTest/diffDatabaseAdded/current.json");
RootDiff diff = Diffs.diff(null, current);
assertEquals(DiffType.ADDED, diff.getDiffType());
}
@Test
void diffDatabaseRemoved() {
DatabaseMeta original = load("ut/diffsTest/diffDatabaseRemoved/original.json");
RootDiff diff = Diffs.diff(original, null);
assertEquals(DiffType.REMOVED, diff.getDiffType());
}
@Test
void diffDatabaseModified() {
DatabaseMeta original = load("ut/diffsTest/diffDatabaseModified/original.json");
DatabaseMeta current = load("ut/diffsTest/diffDatabaseModified/current.json");
// database
RootDiff diff = Diffs.diff(original, current);
assertEquals(DiffType.MODIFIED, diff.getDiffType());
assertSame(2, diff.getFields().size());
Map<String, FieldDiff> diffMap = diff.getFields()
.stream()
.collect(Collectors.toMap(d -> d.getFieldName(), Function.identity()));
// productVersion
assertTrue(diffMap.containsKey("productVersion"));
assertIsModified(diffMap.get("productVersion"));
assertEquals(original.getProductVersion(), diffMap.get("productVersion").getOriginal());
assertEquals(current.getProductVersion(), diffMap.get("productVersion").getCurrent());
// tables
assertTrue(diffMap.containsKey("tables"));
assertIsNone(diffMap.get("tables"));
assertTrue(diffMap.get("tables").getFields().isEmpty());
}
@Test
void diffTableAdded() {
DatabaseMeta original = load("ut/diffsTest/diffTableAdded/original.json");
DatabaseMeta current = load("ut/diffsTest/diffTableAdded/current.json");
// database
RootDiff diff = Diffs.diff(original, current);
assertEquals(DiffType.MODIFIED, diff.getDiffType());
// add table: departments, dept_emp
assertSame(1, diff.getFields().size());
FieldDiff tableField = diff.getFields().iterator().next();
assertEquals("tables", tableField.getFieldName());
assertEquals(DiffType.ADDED, tableField.getDiffType());
// tables without original & current value
assertNull(tableField.getOriginal());
assertNull(tableField.getCurrent());
// add two tables
assertSame(2, tableField.getFields().size());
Map<String, FieldDiff> tableFieldMap = tableField.getFields()
.stream()
.collect(Collectors.toMap(FieldDiff::getFieldName, Function.identity()));
Map<String, TableMeta> currentTablesMap = current.getTables()
.stream()
.collect(Collectors.toMap(TableMeta::getName, Function.identity()));
List.of("departments", "dept_emp").forEach(tableName -> {
assertTrue(tableFieldMap.containsKey(tableName));
FieldDiff departments = tableFieldMap.get(tableName);
assertIsAdded(departments);
assertNull(departments.getOriginal());
assertNotNull(departments.getCurrent());
assertEquals(currentTablesMap.get(tableName), departments.getCurrent());
});
}
@Test
void diffTableRemoved() {
DatabaseMeta original = load("ut/diffsTest/diffTableRemoved/original.json");
DatabaseMeta current = load("ut/diffsTest/diffTableRemoved/current.json");
// database
RootDiff diff = Diffs.diff(original, current);
assertEquals(DiffType.MODIFIED, diff.getDiffType());
// remove table: departments, dept_emp
assertSame(1, diff.getFields().size());
FieldDiff tableField = diff.getFields().iterator().next();
assertEquals("tables", tableField.getFieldName());
assertEquals(DiffType.REMOVED, tableField.getDiffType());
// tables without original & current value
assertNull(tableField.getOriginal());
assertNull(tableField.getCurrent());
// remove two tables
assertSame(2, tableField.getFields().size());
Map<String, FieldDiff> tableFieldMap = tableField.getFields()
.stream()
.collect(Collectors.toMap(FieldDiff::getFieldName, Function.identity()));
Map<String, TableMeta> originalTablesMap = original.getTables()
.stream()
.collect(Collectors.toMap(TableMeta::getName, Function.identity()));
List.of("departments", "dept_emp").forEach(tableName -> {
assertTrue(tableFieldMap.containsKey(tableName));
FieldDiff field = tableFieldMap.get(tableName);
assertIsRemoved(field);
assertNull(field.getCurrent());
assertNotNull(field.getOriginal());
assertEquals(originalTablesMap.get(tableName), field.getOriginal());
});
}
/**
* modify three table: departments, dept_emp
* - dept_manager: add comment, change table type
* - departments: add comment
* - dept_emp: add comment
*/
@Test
void diffTableModified() {
DatabaseMeta original = load("ut/diffsTest/diffTableModified/original.json");
DatabaseMeta current = load("ut/diffsTest/diffTableModified/current.json");
// database
RootDiff diff = Diffs.diff(original, current);
assertEquals(DiffType.MODIFIED, diff.getDiffType());
assertSame(1, diff.getFields().size());
FieldDiff tableField = diff.getFields().iterator().next();
assertEquals("tables", tableField.getFieldName());
assertEquals(DiffType.MODIFIED, tableField.getDiffType());
// tables without original & current value
assertNull(tableField.getOriginal());
assertNull(tableField.getCurrent());
// modify 3 tables
assertSame(3, tableField.getFields().size());
Map<String, FieldDiff> tableFieldMap = tableField.getFields()
.stream()
.collect(Collectors.toMap(FieldDiff::getFieldName, Function.identity()));
Map<String, TableMeta> originalTableMap = original.getTables()
.stream()
.collect(Collectors.toMap(TableMeta::getName, Function.identity()));
Map<String, TableMeta> currentTableMap = current.getTables()
.stream()
.collect(Collectors.toMap(TableMeta::getName, Function.identity()));
List.of("departments", "dept_emp", "dept_manager").forEach(tableName -> {
assertTrue(tableFieldMap.containsKey(tableName));
FieldDiff departments = tableFieldMap.get(tableName);
assertIsModified(departments);
assertNull(departments.getCurrent());
assertNull(departments.getOriginal());
if ("dept_manager".equals(tableName)) {
// columns \ indexes \ triggers \ forgienKes \ comment
assertSame(6, departments.getFields().size());
FieldDiff departmentCommentField = departments.getFields().stream()
.filter(f -> f.getFieldName().equals("type"))
.findAny()
.orElseThrow();
assertEquals(originalTableMap.get(tableName).getType(), departmentCommentField.getOriginal());
assertEquals(currentTableMap.get(tableName).getType(), departmentCommentField.getCurrent());
} else {
// columns \ indexes \ triggers \ forgienKes \ comment
assertSame(5, departments.getFields().size());
}
FieldDiff departmentCommentField = departments.getFields().stream()
.filter(f -> f.getFieldName().equals("comment"))
.findAny()
.orElseThrow();
assertEquals(originalTableMap.get(tableName).getComment(), departmentCommentField.getOriginal());
assertEquals(currentTableMap.get(tableName).getComment(), departmentCommentField.getCurrent());
});
}
/**
* add columns \ indexes \ triggers \ foreignKeys
* <p>
* department:
* - add column [deleted], [dept_code]
* - add index [dept_deleted]
* - add triggers [before_insert]
* - add foreignKeys [dept_emp_ibfk_1]
* </p>
*/
@Test
void diffTableFieldsAdded() {
DatabaseMeta original = load("ut/diffsTest/diffTableFieldsAdded/original.json");
DatabaseMeta current = load("ut/diffsTest/diffTableFieldsAdded/current.json");
// database
RootDiff diff = Diffs.diff(original, current);
assertEquals(DiffType.MODIFIED, diff.getDiffType());
// modified table: departments
assertSame(1, diff.getFields().size());
FieldDiff tableField = diff.getFields().iterator().next();
assertEquals("tables", tableField.getFieldName());
assertEquals(DiffType.MODIFIED, tableField.getDiffType());
// tables without original & current value
assertNull(tableField.getOriginal());
assertNull(tableField.getCurrent());
// modified 1 tables
assertSame(1, tableField.getFields().size());
Map<String, FieldDiff> tableFieldMap = tableField.getFields()
.stream()
.collect(Collectors.toMap(FieldDiff::getFieldName, Function.identity()));
TableMeta currentDepartment = current.getTables()
.stream()
.filter(t -> "departments".equals(t.getName()))
.findFirst()
.orElseThrow();
List.of("departments").forEach(tableName -> {
assertTrue(tableFieldMap.containsKey(tableName));
FieldDiff departments = tableFieldMap.get(tableName);
assertIsModified(departments);
assertNull(departments.getOriginal());
assertNull(departments.getCurrent());
// columns / indexes / triggers / foreignKes
assertSame(4, departments.getFields().size());
for (FieldDiff field : departments.getFields()) {
assertIsModified(field);
if ("columns".equals(field.getFieldName())) {
assertSame(2, field.getFields().size());
for (FieldDiff columnField : field.getFields()) {
assertIsAdded(columnField);
assertNull(columnField.getOriginal());
assertNotNull(columnField.getCurrent());
ColumnMeta colMeta = (ColumnMeta) columnField.getCurrent();
boolean matched = currentDepartment.getColumns().stream()
.anyMatch(idx -> Objects.equals(idx, colMeta));
assertTrue(matched);
}
}
if ("indexes".equals(field.getFieldName())) {
assertSame(1, field.getFields().size());
FieldDiff indexes = field.getFields().iterator().next();
assertIsAdded(indexes);
assertNull(indexes.getOriginal());
IndexMeta index = (IndexMeta) indexes.getCurrent();
assertNotNull(index);
boolean matched = currentDepartment.getIndexes().stream()
.anyMatch(idx -> Objects.equals(idx, index));
assertTrue(matched);
}
if ("triggers".equals(field.getFieldName())) {
assertSame(1, field.getFields().size());
FieldDiff triggers = field.getFields().iterator().next();
assertIsAdded(triggers);
assertNull(triggers.getOriginal());
TriggerMeta tg = (TriggerMeta) triggers.getCurrent();
assertNotNull(tg);
boolean matched = currentDepartment.getTriggers().stream().anyMatch(t -> Objects.equals(t, tg));
assertTrue(matched);
}
if ("foreignKeys".equals(field.getFieldName())) {
assertSame(1, field.getFields().size());
FieldDiff foreignKeys = field.getFields().iterator().next();
assertIsAdded(foreignKeys);
assertNull(foreignKeys.getOriginal());
ForeignKeyMeta fk = (ForeignKeyMeta) foreignKeys.getCurrent();
assertNotNull(fk);
boolean matched = currentDepartment.getForeignKeys().stream().anyMatch(f -> Objects.equals(f, fk));
assertTrue(matched);
}
}
});
}
/**
* dept_emp
* fk: dept_emp_ibfk_2
* column: from_date, to_date
* index: dept_no
* trigger: before_insert
*/
@Test
void diffTableFieldsRemoved() {
DatabaseMeta original = load("ut/diffsTest/diffTableFieldsRemoved/original.json");
DatabaseMeta current = load("ut/diffsTest/diffTableFieldsRemoved/current.json");
// database
RootDiff diff = Diffs.diff(original, current);
assertEquals(DiffType.MODIFIED, diff.getDiffType());
// modified table: departments
assertSame(1, diff.getFields().size());
FieldDiff tableField = diff.getFields().iterator().next();
assertEquals("tables", tableField.getFieldName());
assertEquals(DiffType.MODIFIED, tableField.getDiffType());
// tables without original & current value
assertNull(tableField.getOriginal());
assertNull(tableField.getCurrent());
// modified 1 tables
assertSame(1, tableField.getFields().size());
Map<String, FieldDiff> tableFieldMap = tableField.getFields()
.stream()
.collect(Collectors.toMap(FieldDiff::getFieldName, Function.identity()));
TableMeta originalTable = original.getTables()
.stream()
.filter(t -> "dept_emp".equals(t.getName()))
.findFirst()
.orElseThrow();
List.of("dept_emp").forEach(tableName -> {
assertTrue(tableFieldMap.containsKey(tableName));
FieldDiff departments = tableFieldMap.get(tableName);
assertIsModified(departments);
assertNull(departments.getOriginal());
assertNull(departments.getCurrent());
// columns / indexes / triggers / foreignKes
assertSame(4, departments.getFields().size());
for (FieldDiff field : departments.getFields()) {
assertIsModified(field);
if ("columns".equals(field.getFieldName())) {
assertSame(2, field.getFields().size());
for (FieldDiff columnField : field.getFields()) {
assertIsRemoved(columnField);
assertNull(columnField.getCurrent());
assertNotNull(columnField.getOriginal());
ColumnMeta colMeta = (ColumnMeta) columnField.getOriginal();
boolean matched = originalTable.getColumns().stream()
.anyMatch(idx -> Objects.equals(idx, colMeta));
assertTrue(matched);
}
}
if ("indexes".equals(field.getFieldName())) {
assertSame(1, field.getFields().size());
FieldDiff indexes = field.getFields().iterator().next();
assertIsRemoved(indexes);
assertNull(indexes.getCurrent());
IndexMeta index = (IndexMeta) indexes.getOriginal();
assertNotNull(index);
boolean matched = originalTable.getIndexes().stream()
.anyMatch(idx -> Objects.equals(idx, index));
assertTrue(matched);
}
if ("triggers".equals(field.getFieldName())) {
assertSame(1, field.getFields().size());
FieldDiff triggers = field.getFields().iterator().next();
assertIsRemoved(triggers);
assertNull(triggers.getCurrent());
TriggerMeta tg = (TriggerMeta) triggers.getOriginal();
assertNotNull(tg);
boolean matched = originalTable.getTriggers().stream().anyMatch(t -> Objects.equals(t, tg));
assertTrue(matched);
}
if ("foreignKeys".equals(field.getFieldName())) {
assertSame(1, field.getFields().size());
FieldDiff foreignKeys = field.getFields().iterator().next();
assertIsRemoved(foreignKeys);
assertNull(foreignKeys.getCurrent());
ForeignKeyMeta fk = (ForeignKeyMeta) foreignKeys.getOriginal();
assertNotNull(fk);
boolean matched = originalTable.getForeignKeys().stream().anyMatch(f -> Objects.equals(f, fk));
assertTrue(matched);
}
}
});
}
/**
* departments
* column: dept_no add comment
* column: dept_name add comment
* indexes: dept_name change unique=false
* <p>
* dept_emp
* column: emp_no change default value
* column: dept_noL change auto increment true
* indexes: dept_no
* triggers: before_insert
* foreignKeys: dept_emp_ibfk_2
* </p>
*/
@Test
void diffTableFieldsModified() {
DatabaseMeta original = load("ut/diffsTest/diffTableFieldsModified/original.json");
DatabaseMeta current = load("ut/diffsTest/diffTableFieldsModified/current.json");
// database
RootDiff diff = Diffs.diff(original, current);
assertEquals(DiffType.MODIFIED, diff.getDiffType());
// modified table: departments, dept_emp
assertSame(1, diff.getFields().size());
FieldDiff tablesField = diff.getFields().iterator().next();
assertEquals("tables", tablesField.getFieldName());
assertEquals(DiffType.MODIFIED, tablesField.getDiffType());
// tables without original & current value
assertNull(tablesField.getOriginal());
assertNull(tablesField.getCurrent());
// modified 1 tables
assertSame(2, tablesField.getFields().size());
Map<String, FieldDiff> tableFieldMap = tablesField.getFields()
.stream()
.collect(Collectors.toMap(FieldDiff::getFieldName, Function.identity()));
Map<String, TableMeta> originalTaleMap = original.getTables()
.stream()
.collect(Collectors.toMap(TableMeta::getName, Function.identity()));
Map<String, TableMeta> currentTableMap = current.getTables()
.stream()
.collect(Collectors.toMap(TableMeta::getName, Function.identity()));
List.of("departments", "dept_emp").forEach(tableName -> {
assertTrue(tableFieldMap.containsKey(tableName));
FieldDiff tableField = tableFieldMap.get(tableName);
assertIsModified(tableField);
assertNull(tableField.getOriginal());
assertNull(tableField.getCurrent());
// columns / indexes / triggers / foreignKes
assertSame(4, tableField.getFields().size());
for (FieldDiff field : tableField.getFields()) {
if ("columns".equals(field.getFieldName())) {
assertIsModified(field);
assertSame(2, field.getFields().size());
for (FieldDiff columnField : field.getFields()) {
assertIsModified(columnField);
assertNotNull(columnField.getCurrent());
assertNotNull(columnField.getOriginal());
ColumnMeta originalCol = (ColumnMeta) columnField.getOriginal();
boolean matched = originalTaleMap.get(tableName)
.getColumns()
.stream()
.anyMatch(idx -> Objects.equals(idx, originalCol));
assertTrue(matched);
ColumnMeta currentCol = (ColumnMeta) columnField.getCurrent();
assertTrue(currentTableMap.get(tableName)
.getColumns()
.stream()
.anyMatch(idx -> Objects.equals(idx, currentCol)));
}
}
if ("indexes".equals(field.getFieldName())) {
assertIsModified(field);
assertSame(1, field.getFields().size());
FieldDiff indexes = field.getFields().iterator().next();
assertIsModified(indexes);
assertNotNull(indexes.getCurrent());
assertNotNull(indexes.getOriginal());
IndexMeta originalIndex = (IndexMeta) indexes.getOriginal();
boolean matched = originalTaleMap.get(tableName)
.getIndexes()
.stream()
.anyMatch(idx -> Objects.equals(idx, originalIndex));
assertTrue(matched);
IndexMeta currentIndex = (IndexMeta) indexes.getCurrent();
assertTrue(currentTableMap.get(tableName)
.getIndexes()
.stream()
.anyMatch(idx -> Objects.equals(idx, currentIndex)));
}
if (tableName.equals("dept_emp") && "triggers".equals(field.getFieldName())) {
assertIsModified(field);
assertSame(1, field.getFields().size());
FieldDiff triggers = field.getFields().iterator().next();
assertIsModified(triggers);
assertNotNull(triggers.getCurrent());
assertNotNull(triggers.getOriginal());
TriggerMeta originalTg = (TriggerMeta) triggers.getOriginal();
assertTrue(originalTaleMap.get(tableName).getTriggers().stream()
.anyMatch(t -> Objects.equals(t, originalTg)));
TriggerMeta currentTg = (TriggerMeta) triggers.getCurrent();
assertTrue(currentTableMap.get(tableName).getTriggers().stream()
.anyMatch(t -> Objects.equals(t, currentTg)));
}
if (tableName.equals("dept_emp") && "foreignKeys".equals(field.getFieldName())) {
assertIsModified(field);
assertSame(1, field.getFields().size());
FieldDiff foreignKeys = field.getFields().iterator().next();
assertIsModified(foreignKeys);
assertNotNull(foreignKeys.getCurrent());
assertNotNull(foreignKeys.getOriginal());
ForeignKeyMeta originalFk = (ForeignKeyMeta) foreignKeys.getOriginal();
assertTrue(originalTaleMap.get(tableName)
.getForeignKeys().stream().anyMatch(f -> Objects.equals(f, originalFk)));
ForeignKeyMeta currentFk = (ForeignKeyMeta) foreignKeys.getCurrent();
assertTrue(currentTableMap.get(tableName)
.getForeignKeys().stream().anyMatch(f -> Objects.equals(f, currentFk)));
}
if (tableName.equals("departments")
&& List.of("foreignKeys", "triggers").contains(field.getFieldName())) {
assertIsNone(field);
}
}
});
}
private void assertIsModified(FieldDiff diff) {
assertEquals(DiffType.MODIFIED, diff.getDiffType());
}
private void assertIsNone(FieldDiff diff) {
assertEquals(DiffType.NONE, diff.getDiffType());
}
private void assertIsRemoved(FieldDiff diff) {
assertEquals(DiffType.REMOVED, diff.getDiffType());
}
private void assertIsAdded(FieldDiff diff) {
assertEquals(DiffType.ADDED, diff.getDiffType());
}
private DatabaseMeta load(String url) {
URL originalUrl = Thread.currentThread().getContextClassLoader()
.getResource(url);
try {
return objectMapper.readValue(originalUrl, DatabaseMeta.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,466 @@
{
"tables": [
{
"name": "departments",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_name",
"type": "VARCHAR",
"size": 40,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_name",
"isUniqueKey": true,
"columnNames": [
"dept_name"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"dept_no"
]
}
],
"foreignKeys": [],
"triggers": []
},
{
"name": "dept_emp",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_no",
"isUniqueKey": false,
"columnNames": [
"dept_no"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"dept_no"
]
}
],
"foreignKeys": [
{
"fkName": "dept_emp_ibfk_2",
"fkTableName": "dept_emp",
"fkColumnName": "dept_no",
"pkName": "PRIMARY",
"pkTableName": "departments",
"pkColumnName": "dept_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
},
{
"fkName": "dept_emp_ibfk_1",
"fkTableName": "dept_emp",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "dept_manager",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_no",
"isUniqueKey": false,
"columnNames": [
"dept_no"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"dept_no"
]
}
],
"foreignKeys": [
{
"fkName": "dept_manager_ibfk_2",
"fkTableName": "dept_manager",
"fkColumnName": "dept_no",
"pkName": "PRIMARY",
"pkTableName": "departments",
"pkColumnName": "dept_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
},
{
"fkName": "dept_manager_ibfk_1",
"fkTableName": "dept_manager",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "employees",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "birth_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "first_name",
"type": "VARCHAR",
"size": 14,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "last_name",
"type": "VARCHAR",
"size": 16,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "gender",
"type": "ENUM",
"size": 1,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "hire_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no"
]
}
],
"foreignKeys": [],
"triggers": []
},
{
"name": "salaries",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "salary",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"from_date"
]
}
],
"foreignKeys": [
{
"fkName": "salaries_ibfk_1",
"fkTableName": "salaries",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "titles",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "title",
"type": "VARCHAR",
"size": 50,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "YES",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"title",
"from_date"
]
}
],
"foreignKeys": [
{
"fkName": "titles_ibfk_1",
"fkTableName": "titles",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
}
]
}

View File

@ -0,0 +1,470 @@
{
"databaseName": "employees",
"schemaName": "employees",
"productName": "MySQL",
"productVersion": "8.0.26",
"tables": [
{
"name": "departments",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_name",
"type": "VARCHAR",
"size": 40,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_name",
"isUniqueKey": true,
"columnNames": [
"dept_name"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"dept_no"
]
}
],
"foreignKeys": [],
"triggers": []
},
{
"name": "dept_emp",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_no",
"isUniqueKey": false,
"columnNames": [
"dept_no"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"dept_no"
]
}
],
"foreignKeys": [
{
"fkName": "dept_emp_ibfk_2",
"fkTableName": "dept_emp",
"fkColumnName": "dept_no",
"pkName": "PRIMARY",
"pkTableName": "departments",
"pkColumnName": "dept_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
},
{
"fkName": "dept_emp_ibfk_1",
"fkTableName": "dept_emp",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "dept_manager",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_no",
"isUniqueKey": false,
"columnNames": [
"dept_no"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"dept_no"
]
}
],
"foreignKeys": [
{
"fkName": "dept_manager_ibfk_2",
"fkTableName": "dept_manager",
"fkColumnName": "dept_no",
"pkName": "PRIMARY",
"pkTableName": "departments",
"pkColumnName": "dept_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
},
{
"fkName": "dept_manager_ibfk_1",
"fkTableName": "dept_manager",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "employees",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "birth_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "first_name",
"type": "VARCHAR",
"size": 14,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "last_name",
"type": "VARCHAR",
"size": 16,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "gender",
"type": "ENUM",
"size": 1,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "hire_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no"
]
}
],
"foreignKeys": [],
"triggers": []
},
{
"name": "salaries",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "salary",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"from_date"
]
}
],
"foreignKeys": [
{
"fkName": "salaries_ibfk_1",
"fkTableName": "salaries",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "titles",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "title",
"type": "VARCHAR",
"size": 50,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "YES",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"title",
"from_date"
]
}
],
"foreignKeys": [
{
"fkName": "titles_ibfk_1",
"fkTableName": "titles",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
}
]
}

View File

@ -0,0 +1,470 @@
{
"databaseName": "employees",
"schemaName": "employees",
"productName": "MySQL",
"productVersion": "9.0",
"tables": [
{
"name": "departments",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_name",
"type": "VARCHAR",
"size": 40,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_name",
"isUniqueKey": true,
"columnNames": [
"dept_name"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"dept_no"
]
}
],
"foreignKeys": [],
"triggers": []
},
{
"name": "dept_emp",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_no",
"isUniqueKey": false,
"columnNames": [
"dept_no"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"dept_no"
]
}
],
"foreignKeys": [
{
"fkName": "dept_emp_ibfk_2",
"fkTableName": "dept_emp",
"fkColumnName": "dept_no",
"pkName": "PRIMARY",
"pkTableName": "departments",
"pkColumnName": "dept_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
},
{
"fkName": "dept_emp_ibfk_1",
"fkTableName": "dept_emp",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "dept_manager",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_no",
"isUniqueKey": false,
"columnNames": [
"dept_no"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"dept_no"
]
}
],
"foreignKeys": [
{
"fkName": "dept_manager_ibfk_2",
"fkTableName": "dept_manager",
"fkColumnName": "dept_no",
"pkName": "PRIMARY",
"pkTableName": "departments",
"pkColumnName": "dept_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
},
{
"fkName": "dept_manager_ibfk_1",
"fkTableName": "dept_manager",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "employees",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "birth_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "first_name",
"type": "VARCHAR",
"size": 14,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "last_name",
"type": "VARCHAR",
"size": 16,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "gender",
"type": "ENUM",
"size": 1,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "hire_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no"
]
}
],
"foreignKeys": [],
"triggers": []
},
{
"name": "salaries",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "salary",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"from_date"
]
}
],
"foreignKeys": [
{
"fkName": "salaries_ibfk_1",
"fkTableName": "salaries",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "titles",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "title",
"type": "VARCHAR",
"size": 50,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "YES",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"title",
"from_date"
]
}
],
"foreignKeys": [
{
"fkName": "titles_ibfk_1",
"fkTableName": "titles",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
}
]
}

View File

@ -0,0 +1,466 @@
{
"tables": [
{
"name": "departments",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_name",
"type": "VARCHAR",
"size": 40,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_name",
"isUniqueKey": true,
"columnNames": [
"dept_name"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"dept_no"
]
}
],
"foreignKeys": [],
"triggers": []
},
{
"name": "dept_emp",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_no",
"isUniqueKey": false,
"columnNames": [
"dept_no"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"dept_no"
]
}
],
"foreignKeys": [
{
"fkName": "dept_emp_ibfk_2",
"fkTableName": "dept_emp",
"fkColumnName": "dept_no",
"pkName": "PRIMARY",
"pkTableName": "departments",
"pkColumnName": "dept_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
},
{
"fkName": "dept_emp_ibfk_1",
"fkTableName": "dept_emp",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "dept_manager",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_no",
"isUniqueKey": false,
"columnNames": [
"dept_no"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"dept_no"
]
}
],
"foreignKeys": [
{
"fkName": "dept_manager_ibfk_2",
"fkTableName": "dept_manager",
"fkColumnName": "dept_no",
"pkName": "PRIMARY",
"pkTableName": "departments",
"pkColumnName": "dept_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
},
{
"fkName": "dept_manager_ibfk_1",
"fkTableName": "dept_manager",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "employees",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "birth_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "first_name",
"type": "VARCHAR",
"size": 14,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "last_name",
"type": "VARCHAR",
"size": 16,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "gender",
"type": "ENUM",
"size": 1,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "hire_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no"
]
}
],
"foreignKeys": [],
"triggers": []
},
{
"name": "salaries",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "salary",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"from_date"
]
}
],
"foreignKeys": [
{
"fkName": "salaries_ibfk_1",
"fkTableName": "salaries",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "titles",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "title",
"type": "VARCHAR",
"size": 50,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "YES",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"title",
"from_date"
]
}
],
"foreignKeys": [
{
"fkName": "titles_ibfk_1",
"fkTableName": "titles",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
}
]
}

View File

@ -0,0 +1,466 @@
{
"tables": [
{
"name": "departments",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_name",
"type": "VARCHAR",
"size": 40,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_name",
"isUniqueKey": true,
"columnNames": [
"dept_name"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"dept_no"
]
}
],
"foreignKeys": [],
"triggers": []
},
{
"name": "dept_emp",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_no",
"isUniqueKey": false,
"columnNames": [
"dept_no"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"dept_no"
]
}
],
"foreignKeys": [
{
"fkName": "dept_emp_ibfk_2",
"fkTableName": "dept_emp",
"fkColumnName": "dept_no",
"pkName": "PRIMARY",
"pkTableName": "departments",
"pkColumnName": "dept_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
},
{
"fkName": "dept_emp_ibfk_1",
"fkTableName": "dept_emp",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "dept_manager",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "dept_no",
"type": "CHAR",
"size": 4,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "dept_no",
"isUniqueKey": false,
"columnNames": [
"dept_no"
]
},
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"dept_no"
]
}
],
"foreignKeys": [
{
"fkName": "dept_manager_ibfk_2",
"fkTableName": "dept_manager",
"fkColumnName": "dept_no",
"pkName": "PRIMARY",
"pkTableName": "departments",
"pkColumnName": "dept_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
},
{
"fkName": "dept_manager_ibfk_1",
"fkTableName": "dept_manager",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "employees",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "birth_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "first_name",
"type": "VARCHAR",
"size": 14,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "last_name",
"type": "VARCHAR",
"size": 16,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "gender",
"type": "ENUM",
"size": 1,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "hire_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no"
]
}
],
"foreignKeys": [],
"triggers": []
},
{
"name": "salaries",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "salary",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"from_date"
]
}
],
"foreignKeys": [
{
"fkName": "salaries_ibfk_1",
"fkTableName": "salaries",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
},
{
"name": "titles",
"type": "TABLE",
"comment": "",
"columns": [
{
"name": "emp_no",
"type": "INT",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "title",
"type": "VARCHAR",
"size": 50,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "from_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": true,
"nullable": "NO",
"autoIncrement": "NO",
"defaultValue": null
},
{
"name": "to_date",
"type": "DATE",
"size": 10,
"decimalDigits": null,
"comment": "",
"isPrimaryKey": false,
"nullable": "YES",
"autoIncrement": "NO",
"defaultValue": null
}
],
"indexes": [
{
"name": "PRIMARY",
"isUniqueKey": true,
"columnNames": [
"emp_no",
"title",
"from_date"
]
}
],
"foreignKeys": [
{
"fkName": "titles_ibfk_1",
"fkTableName": "titles",
"fkColumnName": "emp_no",
"pkName": "PRIMARY",
"pkTableName": "employees",
"pkColumnName": "emp_no",
"updateRule": "CASCADE",
"deleteRule": "CASCADE"
}
],
"triggers": []
}
]
}

Some files were not shown because too many files have changed in this diff Show More