diff --git a/.gitignore b/.gitignore index 9b1ddc0..2d50711 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ /.idea/ /out/ /tmp/ -/libs/ \ No newline at end of file +/libs/ + +apidoc.* \ No newline at end of file diff --git a/pom.xml b/pom.xml index b3bdc61..349c0b9 100644 --- a/pom.xml +++ b/pom.xml @@ -35,6 +35,12 @@ 5.0.1 + + com.lxyer + excel + 0.1.0 + + com.google.code.gson gson diff --git a/root/_back/ddl_export.html b/root/_back/ddl_export.html deleted file mode 100644 index 2d74141..0000000 --- a/root/_back/ddl_export.html +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - MySql数据库表结构导出 - - - - - - - - -
- -
-

导出数据库表结构(导出后使用wps打开)

-
-
- - - - -
- -
- - - - -
- -
- - - - -
- -
- - - - -
- -
-
- -
-
- -
-
- - -
-
- -
-

最近使用记录 共 {{logs.total}} 条记录

- - - - - - - - - - - - - - - -
IP时间导出数据类型
-
- -
- -
- - - - - - - - - - - \ No newline at end of file diff --git a/root/_back/list.html b/root/_back/list.html deleted file mode 100644 index cf21e48..0000000 --- a/root/_back/list.html +++ /dev/null @@ -1,321 +0,0 @@ - - - - - 高级查询 - - - - - - - -
-

高级查询 - [测试用例]

-
-
- -
-
-
- - - - - - - - - - - - -
-
- -
-
- {{x.label}} - - - - -
- -
-
- - - - - - - - - - - - -
- -
-
-
- -
-
- - -
- - - - - - - - - \ No newline at end of file diff --git a/root/_back/meta.html b/root/_back/meta.html deleted file mode 100644 index 28dd39d..0000000 --- a/root/_back/meta.html +++ /dev/null @@ -1,511 +0,0 @@ - - - - - Title - - - - - - - -
- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字段名中文名数据类型输入类型附加属性备注
- - - - - - -
-
- -
- - - - - - - - - - - - - - - - - -
字段名中文名展示名
-
-
-
-
- 列表展示的属性 -
-
- - - - - - - - - - - - - - - -
字段名中文名支持排序
- - {{getFieldLabel(item)}}
-
-
-
- - -
-
-
- 导出的属性配置 -
-
- - - - - - - - - - - - - - - -
字段名中文名
- - {{getFieldLabel(item)}}
-
-
-
- - -
-
-
- 导入的属性配置 -
-
- - - - - - - - - - - - - - - -
字段名中文名
- - {{getFieldLabel(item)}}
-
-
-
- - -
- - -
-
- 高级查询的属性配置 -
-
- - - - - - - - - - - - - - - -
字段名中文名支持查询类型
- - {{getFieldLabel(item.name)}} - -
-
-
-
- -
- - -
- - - - - - - - - - - - \ No newline at end of file diff --git a/root/api/plat.js b/root/api/plat.js index d6e999d..c28d24c 100644 --- a/root/api/plat.js +++ b/root/api/plat.js @@ -1,7 +1,8 @@ const plat = { - platList(params) { // 平台列表 + platList(params = {}) { // 平台列表 + params['platToken'] = 'xx' return red.getX('/plat/list', params) }, platSave({plat}) { @@ -14,4 +15,8 @@ const plat = { dbSave({plat}) { return red.postX('/plat/db_save', {plat}) }, + catalogList({dbAccount, dbPlatId}) { // database列表 + console.log(dbAccount) + return red.postX('/_db/catalog_list', {dbAccount: JSON.stringify(dbAccount), dbPlatId}) + } } \ No newline at end of file diff --git a/root/api/qtask.js b/root/api/qtask.js index e69de29..726e3bd 100644 --- a/root/api/qtask.js +++ b/root/api/qtask.js @@ -0,0 +1,5 @@ +const qtask = { + qtaskList() { + return red.getX('_qtask/list',{}) + } +} \ No newline at end of file diff --git a/root/api/user.js b/root/api/user.js index 34c6703..e2c0ded 100644 --- a/root/api/user.js +++ b/root/api/user.js @@ -1,9 +1,7 @@ //import red from '../res/js/red' -const login = ({username, pwd}, callback) => { - $.post("/user/login", {username, pwd}, function (json) { - callback(json); - }); +const login = ({username, pwd}) => { + return red.postX("/user/login", {username, pwd, platToken: 'xx'}) } const logout = () => { diff --git a/root/index.html b/root/index.html index 84e0fe1..57397d3 100644 --- a/root/index.html +++ b/root/index.html @@ -91,7 +91,9 @@ + + \ No newline at end of file diff --git a/root/metadata/metaLink.html b/root/metadata/metaLink.html new file mode 100644 index 0000000..b6f43af --- /dev/null +++ b/root/metadata/metaLink.html @@ -0,0 +1,52 @@ + +
+ +
+ + +
+ + \ No newline at end of file diff --git a/root/metadata/metaService.html b/root/metadata/metaService.html index f9dc9ae..6a24338 100644 --- a/root/metadata/metaService.html +++ b/root/metadata/metaService.html @@ -16,6 +16,48 @@
+
+ +
+ + + +
@@ -25,6 +67,9 @@ + + + @@ -40,6 +85,9 @@ + @@ -218,6 +266,7 @@ //import { login } from '../api/user.js' //import { getServiceInfo, getServiceDetail, getServiceList } from '/api/meta.js' let { getServiceInfo, getServiceDetail, getServiceList } = meta; + let { showOk } = red var vm = new Vue({ el: ".meta-service", @@ -453,14 +502,14 @@ red.postX("/meta/itemsort", { serviceKey: vm.table, items: JSON.stringify(vm.itemSort) - }); + }).then(() => showOk()); } else if (vm.status == 2 && vm.itemEdit.length > 0) { red.postX("/meta/itemupdate", { serviceKey: vm.table, items: JSON.stringify(vm.itemEdit) - }); + }).then(() => showOk()); } else if (vm.status == 3 || vm.status == 4 /*|| vm.status == 5*/) { var urls = {3: "/meta/exportsort", 4: "/meta/importsort", 5: "/meta/showsort"}; @@ -471,7 +520,7 @@ red.postX(urls[vm.status], { serviceKey: this.service, items: dataStr - }); + }).then(() => showOk()); } else if (vm.status == 5) { @@ -480,7 +529,7 @@ red.postX("/meta/showsort", { serviceKey: vm.service, items: dataStr - }); + }).then(() => showOk()); } else if (vm.status == 6) { @@ -493,18 +542,24 @@ red.postX("/meta/filter_update", { serviceKey: vm.service, filters: JSON.stringify(red.replace$(filterData)) - }); + }).then(() => showOk()); } else if (vm.status == 7) { console.log(vm.row); - red.postX("/meta/dbplatupdate", vm.row) + red.postX("/meta/dbplatupdate", vm.row).then(() => showOk()) } else { red.showMsg(); } + }, + tipShow() { + red.showMsg({msg: '开发中'}) + }, + showInfo() { + $('#f-info').modal({moveable: true}) } }, diff --git a/root/metadata/metatable/import.html b/root/metadata/metatable/import.html new file mode 100644 index 0000000..50f584b --- /dev/null +++ b/root/metadata/metatable/import.html @@ -0,0 +1,336 @@ + + +
+
+ +
+ + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + +
选择上传文件
+
+ +
+
+
+
+
+

数据文件已上传,下面红色 部分已经导入过的数据表

+
+ + +
+
+ +
+
+
Excel-Sheet
+ +

已选择 个实体待导入

+
+
+
Sheet-Detail
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 表名称: ,中文名: +
字段名中文名数据类型输入类型附加属性备注
ABCDEF
+
+
+
+ +
+
+
+
+ +
+ +
+ +
+
+ +
+ + +
+
+

其他一些定制的特殊格式的 实体数据形式

+
+
+ + +
+ + \ No newline at end of file diff --git a/root/metadata/metatable/metaTable.html b/root/metadata/metatable/metaTable.html index 38e8d19..d9af7a4 100644 --- a/root/metadata/metatable/metaTable.html +++ b/root/metadata/metatable/metaTable.html @@ -12,6 +12,10 @@ + + + + @@ -283,7 +287,8 @@ \ No newline at end of file diff --git a/root/user/login.html b/root/user/login.html index e231604..ea2926d 100644 --- a/root/user/login.html +++ b/root/user/login.html @@ -120,8 +120,30 @@ }, methods: { - loginCheck: function ({username, pwd}) { - login({username, pwd}, function (json) { + login({username, pwd}) { + login({username, pwd}).then(res => { + console.log(res) + platList().then(res => { + let rows = res.rows + console.log(rows) + red.showMsg({msg:"请选择业务平台"}) + + this.sysPlats = rows; + if (!this.sysPlat) { + this.sysPlat = rows[0]; + } + + red.setData("sysPlats", rows); + red.setData('userName', username) + setTimeout(function () { + vm.choose = true; + }, 500); + }) + }) + }, + /*loginCheck: function ({username, pwd}) { + + /!*login({username, pwd}, function (json) { if (json.code == 0) { platList().then(res => { let rows = res.rows @@ -139,12 +161,12 @@ } else { red.showMsg({msg: json.message}) } - }); - }, + });*!/ + },*/ /*loadPlats: function () { var para = { doc:"sys_plat", - shows: JSON.stringify(["_id", "_key", "name", "token","remark", "status"]) + shows: JSON.stringify(["_id", "_key", "field", "token","remark", "status"]) }; red.getJSON("/meta/plat_list", {}, function (json) { vm.sysPlats = json; @@ -166,7 +188,7 @@ $('body').bind('keyup', function(event) { if (event.keyCode == "13") { if (!vm.choose) { - vm.loginCheck(vm.row); + vm.login(vm.row); } else { vm.goIndex(); } diff --git a/src/main/java/net/tccn/meta/MetaKit.java b/src/main/java/net/tccn/base/MetaKit.java similarity index 91% rename from src/main/java/net/tccn/meta/MetaKit.java rename to src/main/java/net/tccn/base/MetaKit.java index 2ae31f1..74795dd 100644 --- a/src/main/java/net/tccn/meta/MetaKit.java +++ b/src/main/java/net/tccn/base/MetaKit.java @@ -1,10 +1,15 @@ -package net.tccn.meta; +package net.tccn.base; -import net.tccn.base.Kv; -import net.tccn.base.UtilityExt; +import net.tccn.base.arango.Doc; import net.tccn.dbq.Field; import net.tccn.dbq.fbean.FilterType; import net.tccn.dbq.jdbc.api.DbAccount; +import net.tccn.dbq.jdbc.api.DbKit; +import net.tccn.meta.MetaLink; +import net.tccn.meta.MetaService; +import net.tccn.meta.MetaTable; +import net.tccn.plat.DbPlat; +import net.tccn.plat.SysPlat; import java.util.*; import java.util.function.BiFunction; @@ -23,6 +28,7 @@ public class MetaKit { private static List metaServices; private static List dbPlats; + private static List sysPlats; static { metaTables = MetaTable.dao.find(); @@ -30,6 +36,17 @@ public class MetaKit { metaServices = MetaService.dao.find(); dbPlats = DbAccount.dao.find(); + sysPlats = SysPlat.dao.find(); + } + + public static void reload(Class clazz) { + + if (MetaTable.class == clazz) metaTables = MetaTable.dao.find(); + else if (MetaLink.class == clazz) metaLinks = MetaLink.dao.find(); + else if (MetaService.class == clazz) metaServices = MetaService.dao.find(); + else if (DbAccount.class == clazz) dbPlats = DbAccount.dao.find(); + else if (DbPlat.class == clazz) dbPlats = DbAccount.dao.find(); + else if (SysPlat.class == clazz) sysPlats = SysPlat.dao.find(); } //----- get/set ---- @@ -61,6 +78,14 @@ public class MetaKit { MetaKit.dbPlats = dbPlats; } + public static List getSysPlats() { + return sysPlats; + } + + public static void setSysPlats(List sysPlats) { + MetaKit.sysPlats = sysPlats; + } + //----------------------------------- public static void setMetaServices(List metaServices) { MetaKit.metaServices = metaServices; @@ -433,6 +458,18 @@ public class MetaKit { return tables; } + public static DbKit getDbKit(String dbPlatId) { + Optional dbAccount = dbPlats.stream().filter(x -> x.getKey().equals(dbPlatId)).findAny(); + + return new DbKit(dbAccount.get()); + } + + public static DbAccount getDbPlat(String dbPlatId) { + Optional dbAccount = dbPlats.stream().filter(x -> x.getKey().equals(dbPlatId)).findFirst(); + + return dbAccount.get(); + } + public String nextAlias(String x) { return next(x, ""); } diff --git a/src/main/java/net/tccn/base/arango/ArangoSource.java b/src/main/java/net/tccn/base/arango/ArangoSource.java index 96d5bbc..474e401 100644 --- a/src/main/java/net/tccn/base/arango/ArangoSource.java +++ b/src/main/java/net/tccn/base/arango/ArangoSource.java @@ -206,7 +206,7 @@ public class ArangoSource { StringBuilder buf = new StringBuilder(); Map order = t.getOrder(); if (isEmpty.test(order)) { - return buf; + return buf.append(" sort d._key desc"); } buf.append(" sort "); order.forEach((k, v) -> { diff --git a/src/main/java/net/tccn/base/arango/Doc.java b/src/main/java/net/tccn/base/arango/Doc.java index 750f73a..c96b21c 100644 --- a/src/main/java/net/tccn/base/arango/Doc.java +++ b/src/main/java/net/tccn/base/arango/Doc.java @@ -25,6 +25,7 @@ public abstract class Doc { private Set _shows; private Map _order; + private List _filters;//[{col, value, expr}] public String getId() { return _id; @@ -194,6 +195,9 @@ public abstract class Doc { if (flipper == null) { flipper = new Flipper(); } + if (t == null) { + t = (T) this; + } List list = find(t, flipper.getOffset(), flipper.getLimit()); long count = count(t); @@ -251,7 +255,7 @@ public abstract class Doc { return (T) collection.getDocument(String.valueOf(key), this.getClass()); } - //ok + // ok todo: 将数据放入回收库 public void delete() { collection.deleteDocument(getKey()); } diff --git a/src/main/java/net/tccn/dbq/DbExecutors.java b/src/main/java/net/tccn/dbq/DbExecutors.java index 10eacae..b7f1df6 100644 --- a/src/main/java/net/tccn/dbq/DbExecutors.java +++ b/src/main/java/net/tccn/dbq/DbExecutors.java @@ -1,23 +1,24 @@ package net.tccn.dbq; +import net.tccn.base.MetaKit; import net.tccn.base.PageBean; import net.tccn.dbq.fbean.FBean; -import net.tccn.dbq.jdbc.api.DbAccount; import net.tccn.dbq.jdbc.api.DbKit; import net.tccn.dbq.parser.ParseMysql; import net.tccn.dbq.parser.Parser; -import net.tccn.meta.MetaKit; import net.tccn.meta.MetaService; import net.tccn.meta.MetaTable; import java.util.List; import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; public class DbExecutors { private final static Parser PARSER = new ParseMysql(); - public static PageBean findPage(FBean fBean) { - + public static PageBean findPage(FBean fBean) throws ExecutionException, InterruptedException { + //sql解析 String[] sqls = PARSER.parse(fBean); //当前的业务 => 获取主表 信息 => 数据源信息 => 数据源对象 => 创建数据工具对象 => 查询数据 @@ -25,15 +26,13 @@ public class DbExecutors { MetaTable mainTable = MetaKit.getMetaTableByAlias(metaService.getTable()); - DbAccount dbAccount = DbAccount.dao.findByKey(mainTable.getDbPlatId()); - - DbKit dbKit = new DbKit(dbAccount); + DbKit dbKit = MetaKit.getDbKit(mainTable.getDbPlatId()); System.out.println("countSql: " + sqls[0]); System.out.println("findSql: " + sqls[1]); - Integer count = dbKit.queryColumn(sqls[0], int.class); - List list = dbKit.findList(sqls[1], Map.class); + CompletableFuture countFuture = CompletableFuture.supplyAsync(() -> dbKit.queryColumn(sqls[0], int.class)); + CompletableFuture> listFuture = CompletableFuture.supplyAsync(() -> dbKit.findList(sqls[1], Map.class)); - return PageBean.by(list, count); + return PageBean.by(listFuture.get(), countFuture.get()); } } diff --git a/src/main/java/net/tccn/dbq/jdbc/api/DbKit.java b/src/main/java/net/tccn/dbq/jdbc/api/DbKit.java index e5b06bc..5187e95 100644 --- a/src/main/java/net/tccn/dbq/jdbc/api/DbKit.java +++ b/src/main/java/net/tccn/dbq/jdbc/api/DbKit.java @@ -34,4 +34,14 @@ public class DbKit implements DbSource{ public T queryColumn(String sql, Class type) { return dbSource.queryColumn(sql, type); } + + @Override + public void createTable(String sql) { + dbSource.createTable(sql); + } + + @Override + public void dropTable(String tableName) { + dbSource.dropTable(tableName); + } } diff --git a/src/main/java/net/tccn/dbq/jdbc/api/DbSource.java b/src/main/java/net/tccn/dbq/jdbc/api/DbSource.java index 3023cb2..8096d35 100644 --- a/src/main/java/net/tccn/dbq/jdbc/api/DbSource.java +++ b/src/main/java/net/tccn/dbq/jdbc/api/DbSource.java @@ -32,4 +32,7 @@ public interface DbSource { default Date queryDate(String sql) { return queryColumn(sql, Date.class); } + + void createTable(String sql); + void dropTable(String tableName); } diff --git a/src/main/java/net/tccn/dbq/jdbc/api/DbSourceMysql.java b/src/main/java/net/tccn/dbq/jdbc/api/DbSourceMysql.java index 6b5858f..f1796a1 100644 --- a/src/main/java/net/tccn/dbq/jdbc/api/DbSourceMysql.java +++ b/src/main/java/net/tccn/dbq/jdbc/api/DbSourceMysql.java @@ -8,8 +8,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReferenceArray; /** * Created by liangxianyou at 2019/3/12 14:20. @@ -17,7 +17,7 @@ import java.util.concurrent.atomic.AtomicReferenceArray; @SuppressWarnings("Duplicates") public class DbSourceMysql implements DbSource { - private static ConcurrentHashMap> conns = new ConcurrentHashMap<>(); + private static ConcurrentHashMap> conns = new ConcurrentHashMap<>(); private static ConcurrentHashMap counter = new ConcurrentHashMap<>(); private String accountKey; @@ -111,57 +111,66 @@ public class DbSourceMysql implements DbSource { } } + @Override + public void createTable(String sql) { + new RuntimeException("DbSourceMysql.createTable NOT SUPPORT right now" ); // todo: + } + + @Override + public void dropTable(String tableName) { + new RuntimeException("[DbSourceMysql.dropTable] NOT SUPPORT right now" ); // todo: + } + private Connection connection() { return connection(0); } private Connection connection(int n) { - AtomicReferenceArray arr = conns.getOrDefault(accountKey, new AtomicReferenceArray<>(15)); - Connection connection = null; - AtomicInteger num = counter.getOrDefault(accountKey, new AtomicInteger(0)); - for (int i = 0; num.get() > 0 && i < arr.length() && connection == null; i++) { - try { - connection = arr.getAndUpdate(i, null); - } catch (Exception e) { - System.out.println("getAndUpdate exception"); - } - } - if (connection == null) { - try { - if (num.get() < 15) { - connection = DriverManager.getConnection(dbAccount.getUrl(), dbAccount.getUser(), dbAccount.getPwd()); - num.getAndIncrement(); - } else { - //连接被全部使用中,等待1s后再次获取连接,直到得到连接 !!! - Thread.sleep(1000); - if (++n > 3) - connection(n); - } - } catch (SQLException e) { - e.printStackTrace(); - throw new IllegalArgumentException("获取数据库连接失败"); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + LinkedBlockingQueue queue = conns.getOrDefault(accountKey, new LinkedBlockingQueue<>(15)); - return connection; + Connection conn = null; + AtomicInteger num = counter.getOrDefault(accountKey, new AtomicInteger(0)); + try { + if (queue.size() == 0 && num.get() < 15) { + conn = DriverManager.getConnection(dbAccount.getUrl(), dbAccount.getUser(), dbAccount.getPwd()); + int x = num.incrementAndGet(); + counter.put(accountKey, num); + System.out.println("创建新的连接:" + x); + } else { + conn = queue.take(); + if (conn != null) { + System.out.println("获取已有连接" + conn); + } + } + } catch (SQLException | InterruptedException e) { + if (e instanceof InterruptedException) { + try { + conn = DriverManager.getConnection(dbAccount.getUrl(), dbAccount.getUser(), dbAccount.getPwd()); + num.getAndIncrement(); + if (conn != null) { + System.out.println("获取连接异常,并重新创建成功"); + } + } catch (SQLException ex) { + new IllegalArgumentException("创建连接失败", e); + } + num.getAndIncrement(); + counter.put(accountKey, num); + } else { + new IllegalArgumentException("获取连接失败", e); + } + } + conns.put(accountKey, queue); + return conn; } private void release(Connection connection) { - AtomicReferenceArray arr = conns.getOrDefault(accountKey, new AtomicReferenceArray<>(15)); - - int i = 0; - boolean bool = false; - while (i < arr.length() && !bool){ - bool = arr.compareAndSet(i++, null, connection); - } - - //如果没成功释放,关系连接 - if (!bool && connection != null) { - try { - connection.close(); - } catch (SQLException e) { - e.printStackTrace(); + LinkedBlockingQueue queue = conns.getOrDefault(accountKey, new LinkedBlockingQueue<>(15)); + try { + if (connection != null) { + queue.put(connection); + conns.put(accountKey, queue); + System.out.println("还回连接:" + connection); } + } catch (InterruptedException e) { + e.printStackTrace(); } } } diff --git a/src/main/java/net/tccn/dbq/parser/ParseMysql.java b/src/main/java/net/tccn/dbq/parser/ParseMysql.java index 1d17056..488e749 100644 --- a/src/main/java/net/tccn/dbq/parser/ParseMysql.java +++ b/src/main/java/net/tccn/dbq/parser/ParseMysql.java @@ -2,7 +2,7 @@ package net.tccn.dbq.parser; import net.tccn.base.Kv; import net.tccn.dbq.fbean.*; -import net.tccn.meta.MetaKit; +import net.tccn.base.MetaKit; import net.tccn.meta.MetaLink; import net.tccn.meta.MetaService; import net.tccn.meta.MetaTable; diff --git a/src/main/java/net/tccn/dbq/table/Column.java b/src/main/java/net/tccn/dbq/table/Column.java index 93e8bc3..66d5b95 100644 --- a/src/main/java/net/tccn/dbq/table/Column.java +++ b/src/main/java/net/tccn/dbq/table/Column.java @@ -5,7 +5,7 @@ package net.tccn.dbq.table; * @author: liangxianyou at 2018/10/8 10:59. */ public class Column { - private String name; //列名称 + private String field; //列名称 private String type; //列类型 private boolean notNull; //不为null private String comment; //列说明 @@ -14,18 +14,18 @@ public class Column { } public Column(String name, String type, boolean notNull, String comment) { - this.name = name; + this.field = name; this.type = type; this.notNull = notNull; this.comment = comment; } - public String getName() { - return name; + public String getField() { + return field; } - public void setName(String name) { - this.name = name; + public void setField(String field) { + this.field = field; } public String getType() { @@ -52,4 +52,9 @@ public class Column { this.comment = comment; } + //----------------------- + public void setNull(String notNull) { + this.notNull = "NO".equalsIgnoreCase(notNull) ? true : false; + } + } diff --git a/src/main/java/net/tccn/dbq/table/Table.java b/src/main/java/net/tccn/dbq/table/Table.java index df1e689..41abcf5 100644 --- a/src/main/java/net/tccn/dbq/table/Table.java +++ b/src/main/java/net/tccn/dbq/table/Table.java @@ -60,7 +60,7 @@ public class Table { buf.append("CREATE TABLE " + name + "("); columns.forEach(x -> { - buf.append("\n " + x.getName() + " " + x.getType() + ","); + buf.append("\n " + x.getField() + " " + x.getType() + ","); }); buf.deleteCharAt(buf.length() - 1); diff --git a/src/main/java/net/tccn/meta/MetaExecutor.java b/src/main/java/net/tccn/meta/MetaExecutor.java index 292631c..5e02328 100644 --- a/src/main/java/net/tccn/meta/MetaExecutor.java +++ b/src/main/java/net/tccn/meta/MetaExecutor.java @@ -1,6 +1,7 @@ package net.tccn.meta; import net.tccn.base.JBean; +import net.tccn.qtask.Task; /** * Created by liangxianyou at 2019/3/7 16:13. diff --git a/src/main/java/net/tccn/meta/MetaTable.java b/src/main/java/net/tccn/meta/MetaTable.java index b691663..8628b61 100644 --- a/src/main/java/net/tccn/meta/MetaTable.java +++ b/src/main/java/net/tccn/meta/MetaTable.java @@ -20,6 +20,7 @@ public class MetaTable extends Doc implements Serializable { private String alias; //表别名:全库唯一,程序自动生成 private String comment; private List items; + private String sysPlatId; //所属系统平台 private String dbPlatId; //所属数据平台 private String catalog; //所在database @@ -57,6 +58,14 @@ public class MetaTable extends Doc implements Serializable { this.items = items; } + public String getSysPlatId() { + return sysPlatId; + } + + public void setSysPlatId(String sysPlatId) { + this.sysPlatId = sysPlatId; + } + public String getDbPlatId() { return dbPlatId; } diff --git a/src/main/java/net/tccn/meta/Task.java b/src/main/java/net/tccn/meta/Task.java deleted file mode 100644 index 1cf83c7..0000000 --- a/src/main/java/net/tccn/meta/Task.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.tccn.meta; - -/** - * Created by liangxianyou at 2019/3/7 16:24. - */ -public class Task { -} diff --git a/src/main/java/net/tccn/meta/_DbService.java b/src/main/java/net/tccn/meta/_DbService.java new file mode 100644 index 0000000..414a996 --- /dev/null +++ b/src/main/java/net/tccn/meta/_DbService.java @@ -0,0 +1,91 @@ +package net.tccn.meta; + +import net.tccn.base.JBean; +import net.tccn.base.MetaKit; +import net.tccn.dbq.jdbc.api.DbAccount; +import net.tccn.dbq.jdbc.api.DbKit; +import net.tccn.dbq.table.Column; +import net.tccn.dbq.table.Table; +import net.tccn.service.BaseService; +import org.redkale.net.http.RestMapping; +import org.redkale.net.http.RestService; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.stream.Stream; + +@RestService(automapping = true, comment = "数据库操作类") +public class _DbService extends BaseService { + + @RestMapping(name = "catalog_list", comment = "获取数据源的database") + public JBean catalogList(DbAccount dbAccount, String dbPlatId) { + JBean jBean = new JBean(); + DbKit dbKit = null; + if (dbAccount != null) { + dbKit = new DbKit(dbAccount); + } else { + dbKit = MetaKit.getDbKit(dbPlatId); + } + + List list = dbKit.findList("SHOW DATABASES;", Map.class); + + Stream database = list.stream().map(x -> String.valueOf(x.get("Database"))); + + return jBean.setBody(database.toArray()); + } + + @RestMapping(name = "table_list", comment = "数据库表列表") + public JBean tableList(DbAccount dbAccount, String dbPlatId, String[] catalogs) { + JBean jBean = new JBean(); + DbKit dbKit = MetaKit.getDbKit(dbPlatId); + + StringBuffer sqlBuf = new StringBuffer("SELECT TABLE_NAME 'name',TABLE_COMMENT 'comment',table_schema 'catalog' FROM INFORMATION_SCHEMA.TABLES"); + if (catalogs != null && catalogs.length > 0) { + sqlBuf.append("WHERE TABLE_SCHEMA in ("); + for (String catalog : catalogs) { + sqlBuf.append("'").append(catalog).append("',"); + } + sqlBuf.deleteCharAt(sqlBuf.length() - 1); + sqlBuf.append(")"); + } + List list = dbKit.findList(sqlBuf.toString(), Table.class); + + return jBean.setBody(list); + } + + @RestMapping(name = "table_info", comment = "数据库表详情") + public JBean tableInfo(DbAccount dbAccount, + String dbPlatId, String catalog, String tableName) { + JBean jBean = new JBean(); + DbKit dbKit = MetaKit.getDbKit(dbPlatId); + + String sql = String.format("SELECT TABLE_NAME 'name',TABLE_COMMENT 'comment',table_schema 'catalog' FROM INFORMATION_SCHEMA.TABLES where TABLE_NAME='%s'", tableName); + String columnSql = String.format("SHOW FULL COLUMNS FROM '%s.%s'", catalog, tableName); + + CompletableFuture
tableFuture = CompletableFuture.supplyAsync(() -> dbKit.findfirst(sql, Table.class)); + CompletableFuture> columnFuture = CompletableFuture.supplyAsync(() -> dbKit.findList(columnSql, Column.class)); + + try { + Table table = tableFuture.get(); + table.setColumns(columnFuture.get()); + jBean.setBody(table); + } catch (InterruptedException | ExecutionException e) { + jBean.set(-1, "查询表信息失败"); + new IllegalArgumentException("查询表信息失败", e); + } + + return jBean; + } + + @RestMapping(name = "table_create", comment = "新建表[mysql]") + public JBean tableCreate(String dbPlatId, String catalog, String sql) { + JBean jBean = new JBean(); + + DbKit dbKit = MetaKit.getDbKit(dbPlatId); + dbKit.createTable(sql); + + return jBean; + } +} diff --git a/src/main/java/net/tccn/plat/PlatService.java b/src/main/java/net/tccn/plat/PlatService.java index 4619dec..31b8c13 100644 --- a/src/main/java/net/tccn/plat/PlatService.java +++ b/src/main/java/net/tccn/plat/PlatService.java @@ -1,13 +1,17 @@ package net.tccn.plat; import net.tccn.base.JBean; +import net.tccn.base.MetaKit; import net.tccn.base.PageBean; +import net.tccn.dbq.jdbc.api.DbAccount; import net.tccn.service.BaseService; import org.redkale.net.http.RestMapping; import org.redkale.net.http.RestService; import org.redkale.source.Flipper; import org.redkale.util.Comment; +import java.util.List; + @RestService(name = "plat", automapping = true, comment = "业务/数据平台") public class PlatService extends BaseService { @@ -15,7 +19,9 @@ public class PlatService extends BaseService { public JBean list(SysPlat plat, Flipper flipper) { JBean jBean = new JBean(); - PageBean page = SysPlat.dao.findPage(plat, flipper); + //PageBean page = SysPlat.dao.findPage(plat, flipper); + List list = MetaKit.getSysPlats(); + PageBean page = PageBean.by(list, list.size()); return jBean.setBody(page); } @@ -42,19 +48,24 @@ public class PlatService extends BaseService { public JBean dbList(DbPlat plat, Flipper flipper) { JBean jBean = new JBean(); - PageBean page = DbPlat.dao.findPage(plat, flipper); + //PageBean page = DbPlat.dao.findPage(plat, flipper); + + List list = MetaKit.getDbPlats(); + PageBean page = PageBean.by(list, list.size()); return jBean.setBody(page); } @RestMapping(name = "db_save", comment = "数据源信息保存") public JBean dbSave(DbPlat plat) { + //DbAccount dbPlat = MetaKit.getDbPlat(plat.getKey()); if (plat.getKey() == null) { plat.save(); } else { plat.update(); } + MetaKit.reload(DbPlat.class); return new JBean(); } diff --git a/src/main/java/net/tccn/qtask/Task.java b/src/main/java/net/tccn/qtask/Task.java index 82c05ee..01c0051 100644 --- a/src/main/java/net/tccn/qtask/Task.java +++ b/src/main/java/net/tccn/qtask/Task.java @@ -2,6 +2,9 @@ package net.tccn.qtask; import net.tccn.base.Kv; +import net.tccn.base.arango.Doc; + +import javax.persistence.Table; /** * cate:mysql @@ -22,7 +25,9 @@ import net.tccn.base.Kv; * * */ -public class Task { +@Table(name = "qtask", catalog = "db_dev") +public class Task extends Doc { + public static Task dao = dao(Task.class); public String cate;//MYSQL,ES,METHOD,HTTP public String queryId; diff --git a/src/main/java/net/tccn/service/BaseService.java b/src/main/java/net/tccn/service/BaseService.java index 76ba392..8348c69 100644 --- a/src/main/java/net/tccn/service/BaseService.java +++ b/src/main/java/net/tccn/service/BaseService.java @@ -23,6 +23,9 @@ import java.util.logging.Logger; */ public class BaseService implements Service { + @Resource(name = "SERVER_ROOT") + protected File webroot; + public static Gson gson = new Gson(); public Logger logger = Logger.getLogger(this.getClass().getSimpleName()); diff --git a/src/main/java/net/tccn/service/MetadataService.java b/src/main/java/net/tccn/service/MetadataService.java index c107fac..7d82e02 100644 --- a/src/main/java/net/tccn/service/MetadataService.java +++ b/src/main/java/net/tccn/service/MetadataService.java @@ -5,7 +5,7 @@ import net.tccn.base.Kv; import net.tccn.dbq.Field; import net.tccn.dbq.jdbc.api.DbAccount; import net.tccn.plat.SysPlat; -import net.tccn.meta.MetaKit; +import net.tccn.base.MetaKit; import net.tccn.meta.MetaService; import net.tccn.meta.MetaTable; import org.redkale.net.http.RestMapping; diff --git a/src/main/java/net/tccn/service/_FileService.java b/src/main/java/net/tccn/service/_FileService.java new file mode 100644 index 0000000..f65674f --- /dev/null +++ b/src/main/java/net/tccn/service/_FileService.java @@ -0,0 +1,243 @@ +package net.tccn.service; + +import com.lxyer.excel.poi.ExcelKit; +import net.tccn.base.JBean; +import net.tccn.base.Kv; +import net.tccn.dbq.Field; +import net.tccn.meta.MetaTable; +import net.tccn.plat.SysPlat; +import org.redkale.net.http.RestMapping; +import org.redkale.net.http.RestParam; +import org.redkale.net.http.RestService; + +import javax.annotation.Resource; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static java.util.Arrays.asList; + +/** + * @author: liangxianyou at 2018/10/24 10:57. + */ +@RestService(automapping = true, comment = "文件服务") +public class _FileService extends BaseService { + + private final static String[] FIELDS = {"field", "cate", "must", "remark1", "remark2", "tag", "selects", "column", "filter", "ck", "edit"}; + + @Resource + private QtaskService qtaskService; + + + @RestMapping(name = "sheets", comment = "得到所有的sheetName") + public List sheets(String filePath) { + List sheets = new ArrayList<>(); + try { + + File file = new File(webroot, filePath); + if (file.exists()) { + sheets = ExcelKit.getSheetNames(file); + } + } catch (IOException e) { + e.printStackTrace(); + } + + return sheets.stream().filter(x -> { + return !x.contains("版本记录") && !x.contains("表说明") && !x.contains("表名称"); + }).collect(Collectors.toList()); + } + + @RestMapping(name = "data", comment = "得到文件数据") + public JBean data(String filePath, @RestParam(name = "platToken") String token) { + JBean jBean = new JBean(); + SysPlat sysPlat = qtaskService.getSysPlat(token); + File file = new File(webroot, filePath); + if (file.exists()) { + try { + Map> map = ExcelKit.readExcelAll(file, FIELDS); + + Kv data = Kv.of(); + map.forEach((k, v) -> { + if (v.size() > 2) { + data.put(k.replace(" ", ""), toCols(v)); + } + }); + + StringBuffer buf = new StringBuffer(); + buf.append("for d in meta_cols\n" + + " filter d.name in ["); + data.values().forEach(x -> { + buf.append("'").append(x.getName()).append("',"); + }); + buf.deleteCharAt(buf.length() - 1); + buf.append("] and d.sysPlatId=='" + sysPlat.getKey() + "'\n" + + " return d.name"); + + List hv = MetaTable.dao.find(buf.toString(), String.class); + + Kv res = Kv.of(); + data.forEach((k, v) -> { + Kv kv = Kv.of(); + res.put(k, + kv.set("name", v.getName()) + .set("hv", hv.contains(v.getName()) ? 1 : 0) + .set("comment", v.getComment()) + ); + }); + + jBean.setBody(res); + } catch (IOException e) { + e.printStackTrace(); + } + } + + return jBean; + } + + @RestMapping(name = "sheet_data", comment = "得到sheet数据") + public JBean sheetData(String filePath, String sheetName, @RestParam(name = "platToken") String token) { + JBean jBean = new JBean(); + SysPlat sysPlat = qtaskService.getSysPlat(token); + File file = new File(webroot, filePath); + try { + List list = ExcelKit.readExcel(file, FIELDS, sheetName); + MetaTable metaTable = toCols(list); + + jBean.setBody(metaTable); + } catch (IOException e) { + e.printStackTrace(); + jBean.set(-1, String.format("读取sheet[%s]失败", sheetName)); + } + + return jBean; + } + + @RestMapping(name = "import_metatable", comment = "导入excel数据到metatable") + public JBean importMetaTable(@RestParam(name = "sheetArr", comment = "sheet名") String[] sheetArr, + @RestParam(name = "filePath", comment = "文件路径") String filePath, + @RestParam(name = "platToken") String token) { + JBean jBean = new JBean(); + SysPlat sysPlat = qtaskService.getSysPlat(token); + + File file = new File(webroot, filePath); + String[] fields = {"field", "cate", "must", "remark1", "remark2", "tag", "selects", "column", "filter", "ck", "edit"}; + try { + Map> map = ExcelKit.readExcelAll(file, fields); + map.forEach((k, v) -> { + if (v.size() > 2) { + MetaTable table = toCols(v); + for (String sn : sheetArr) { + if (table.getName().equals(sn)) { //在选中列表中 + MetaTable metaTable = new MetaTable(); + metaTable.setSysPlatId(sysPlat.getKey()); + metaTable.setName(table.getName()); + + MetaTable _metaTable = MetaTable.dao.findFirst(metaTable); + if (_metaTable == null) {//库里没有数据保存 + table.setSysPlatId(sysPlat.getKey()); + table.save(); + } + break; + } + } + } + }); + + } catch (IOException e) { + e.printStackTrace(); + } + return jBean; + } + + /** + * 组装元数据 + */ + private MetaTable toCols(List list) { + + //Kv col = Kv.of(); + MetaTable metaTable = new MetaTable(); + + list.remove(1);//list[0] head info + Map rowHead = list.remove(0); + + String comment = getComment(rowHead);//list[1] comment, + String tableName = getTableName(rowHead); + //col.set("name", tableName).set("comment", comment); + metaTable.setName(tableName); + metaTable.setComment(comment); + + //所有字段 + List items = new ArrayList<>(); + + //展示的字段 + List shows = new ArrayList<>(); + + //编辑的字段 + List edits = new ArrayList<>(); + + //查询过滤用字段 + List filters = new ArrayList<>(); + + + list.forEach(x -> { + String colName = x.getOrDefault("field", "") + ""; + + Field item = new Field(); + item.setName(colName); + item.setLabel(x.getOrDefault("remark1", "") + ""); + item.setType(x.getOrDefault("cate", "") + ""); + item.setInType(x.getOrDefault("tag", "") + ""); + item.setInExt(x.getOrDefault("selects", "") + ""); + + items.add(item); + + if ("1".equals(x.getOrDefault("column", "") + "")) { + shows.add(colName); + } + + if ("1".equals(x.getOrDefault("edit", "") + "")) { + edits.add(Kv.of("col", colName)); + } + + if (x.get("filter") != null && !"".equals(x.get("filter") + "")) { + String filter = x.getOrDefault("filter", "") + ""; + filter = filter.replace("1", "EQUAL"); + filter = filter.replace("!1", "NOTEQUAL"); + filter = filter.replace("like", "LIKE"); + + filters.add(Kv.of("name", item).set("filterType", asList(filter.split(",")))); + } + + }); + + metaTable.setItems(items); + //metaTable.setShows(shows); + //metaTable.setEdits(edits); + //metaTable.setFilters(filters); + return metaTable; + } + + private String getTableName(Map rowHead) { + String field = rowHead.get("field") + ""; + + int s = field.indexOf("("); + if (s > 0) { + return field.substring(0, s); + } + return field; + } + + private String getComment(Map rowHead) { + String field = rowHead.get("field") + ""; + + int s = field.indexOf("("); + int e = field.indexOf(")"); + if (s > 0) { + return field.substring(s + 1, e > 0 ? e : field.length()); + } + return ""; + } +} diff --git a/src/main/java/net/tccn/service/_QtaskService.java b/src/main/java/net/tccn/service/_QtaskService.java new file mode 100644 index 0000000..1285a68 --- /dev/null +++ b/src/main/java/net/tccn/service/_QtaskService.java @@ -0,0 +1,22 @@ +package net.tccn.service; + +import net.tccn.base.JBean; +import net.tccn.base.PageBean; +import net.tccn.qtask.Task; +import org.redkale.net.http.RestParam; +import org.redkale.net.http.RestService; +import org.redkale.source.Flipper; +import org.redkale.util.Comment; + +@RestService(automapping = true) +public class _QtaskService extends BaseService{ + + @Comment("qtask列表") + public JBean list(Task task, Flipper flipper, @RestParam(name = "platToken") String token) { + PageBean page = Task.dao.findPage(task, flipper); + + + return JBean.by(0, "", page); + } + +} diff --git a/src/test/java/RunTest.java b/src/test/java/RunTest.java index b23f490..b98df81 100644 --- a/src/test/java/RunTest.java +++ b/src/test/java/RunTest.java @@ -4,7 +4,7 @@ import net.tccn.dbq.fbean.FBean; import net.tccn.dbq.parser.ParseMysql; import net.tccn.dbq.jdbc.api.DbAccount; import net.tccn.dbq.jdbc.api.DbKit; -import net.tccn.meta.MetaKit; +import net.tccn.base.MetaKit; import net.tccn.qtask.QRuner; import net.tccn.qtask.Task; import org.junit.Test; @@ -60,8 +60,11 @@ public class RunTest { DbKit dbKit = new DbKit(dbAccount); + //String sql = "select * from basic_concat limit 1"; + String sql = "show databases;"; + // find list - List list = dbKit.findList("select * from basic_concat limit 1", Map.class); + List list = dbKit.findList(sql, Map.class); System.out.println(list.get(0));