From 6f38aed1aebe7cd780785981f73066b7a415f3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9A=AE=E5=85=89=EF=BC=9A=E5=9F=8E=E4=B8=AD=E5=9F=8E?= <806783409@qq.com> Date: Sun, 1 Sep 2019 18:41:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=A7=E8=A1=8C=E5=99=A8=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E5=B1=95=E7=A4=BA=E5=A2=9E=E5=8A=A0=E5=A4=9A=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/DbSqlExecutorController.java | 37 ++-- .../db/mapper/base/ExecuteResult.java | 27 ++- .../framework/db/mapper/base/SqlExecutor.java | 2 +- zyplayer-doc-other/zyplayer-doc-test/pom.xml | 11 + .../zyplayer/doc/test/utils/RedisUtil.java | 204 ++++++++++++++++++ .../db-ui/src/views/data/Executor.vue | 111 ++++++---- 6 files changed, 336 insertions(+), 56 deletions(-) create mode 100644 zyplayer-doc-other/zyplayer-doc-test/src/main/java/com/zyplayer/doc/test/utils/RedisUtil.java diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/controller/DbSqlExecutorController.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/controller/DbSqlExecutorController.java index bebe3c1d..90c73bbf 100644 --- a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/controller/DbSqlExecutorController.java +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/controller/DbSqlExecutorController.java @@ -27,10 +27,7 @@ import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.sql.Timestamp; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; /** * sql执行器 @@ -61,18 +58,28 @@ public class DbSqlExecutorController { if (!manageAuth && !select && !update) { return DocDbResponseJson.warn("没有该数据源的执行权限"); } - try { - Map paramMap = JSON.parseObject(params); - ExecuteType executeType = (!manageAuth && select) ? ExecuteType.SELECT : ExecuteType.ALL; - ExecuteResult executeResult = sqlExecutor.execute(sourceId, executeId, executeType, sql, paramMap); - SerializeConfig mapping = new SerializeConfig(); - mapping.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss")); - mapping.put(Timestamp.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss")); - String resultJsonStr = JSON.toJSONString(executeResult, mapping, SerializerFeature.WriteMapNullValue); - return DocDbResponseJson.ok(resultJsonStr); - } catch (Exception e) { - return DocDbResponseJson.warn(StringUtil.getException(e)); + List resultList = new LinkedList<>(); + // 支持;分割的多个sql执行 + String[] sqlArr = sql.split(";"); + for (String sqlItem : sqlArr) { + if (StringUtils.isBlank(sqlItem)) { + continue; + } + try { + Map paramMap = JSON.parseObject(params); + ExecuteType executeType = (!manageAuth && select) ? ExecuteType.SELECT : ExecuteType.ALL; + ExecuteResult executeResult = sqlExecutor.execute(sourceId, executeId, executeType, sqlItem, paramMap); + SerializeConfig mapping = new SerializeConfig(); + mapping.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss")); + mapping.put(Timestamp.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss")); + String resultJsonStr = JSON.toJSONString(executeResult, mapping, SerializerFeature.WriteMapNullValue); + resultList.add(resultJsonStr); + } catch (Exception e) { + ExecuteResult executeResult = ExecuteResult.error(StringUtil.getException(e)); + resultList.add(JSON.toJSONString(executeResult)); + } } + return DocDbResponseJson.ok(resultList); } @PostMapping(value = "/cancel") diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/mapper/base/ExecuteResult.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/mapper/base/ExecuteResult.java index 9e4306dd..1dbfce23 100644 --- a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/mapper/base/ExecuteResult.java +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/mapper/base/ExecuteResult.java @@ -13,6 +13,8 @@ import java.util.Map; public class ExecuteResult { private int updateCount; private long useTime; + private String errMsg; + private String sql; private List> result; public ExecuteResult() { @@ -21,10 +23,11 @@ public class ExecuteResult { this.result = Collections.emptyList(); } - public ExecuteResult(int updateCount, List> result, long useTime) { + public ExecuteResult(int updateCount, List> result, long useTime, String sql) { this.updateCount = updateCount; this.result = result; this.useTime = useTime; + this.sql = sql; } public int getUpdateCount() { @@ -50,4 +53,26 @@ public class ExecuteResult { public void setUseTime(long useTime) { this.useTime = useTime; } + + public String getErrMsg() { + return errMsg; + } + + public void setErrMsg(String errMsg) { + this.errMsg = errMsg; + } + + public static ExecuteResult error(String errMsg) { + ExecuteResult executeResult = new ExecuteResult(); + executeResult.setErrMsg(errMsg); + return executeResult; + } + + public String getSql() { + return sql; + } + + public void setSql(String sql) { + this.sql = sql; + } } diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/mapper/base/SqlExecutor.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/mapper/base/SqlExecutor.java index 9d84cf67..d01238d9 100644 --- a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/mapper/base/SqlExecutor.java +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/mapper/base/SqlExecutor.java @@ -124,7 +124,7 @@ public class SqlExecutor { int updateCount = preparedStatement.getUpdateCount(); updateCount = (updateCount < 0) ? 0 : updateCount; long useTime = System.currentTimeMillis() - startTime; - return new ExecuteResult(updateCount, resultList, useTime); + return new ExecuteResult(updateCount, resultList, useTime, sql); } catch (Exception e) { throw new RuntimeException(e); } finally { diff --git a/zyplayer-doc-other/zyplayer-doc-test/pom.xml b/zyplayer-doc-other/zyplayer-doc-test/pom.xml index a6a60516..b55bca6a 100644 --- a/zyplayer-doc-other/zyplayer-doc-test/pom.xml +++ b/zyplayer-doc-other/zyplayer-doc-test/pom.xml @@ -63,5 +63,16 @@ elasticsearch-rest-high-level-client ${elasticsearch.version} + + + redis.clients + jedis + 2.7.0 + + + commons-lang + commons-lang + 2.6 + diff --git a/zyplayer-doc-other/zyplayer-doc-test/src/main/java/com/zyplayer/doc/test/utils/RedisUtil.java b/zyplayer-doc-other/zyplayer-doc-test/src/main/java/com/zyplayer/doc/test/utils/RedisUtil.java new file mode 100644 index 00000000..03e82050 --- /dev/null +++ b/zyplayer-doc-other/zyplayer-doc-test/src/main/java/com/zyplayer/doc/test/utils/RedisUtil.java @@ -0,0 +1,204 @@ +package com.zyplayer.doc.test.utils; + +import org.apache.commons.lang.math.NumberUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; +import redis.clients.jedis.Tuple; + +import java.util.Set; +import java.util.function.Function; + +/** + * redis缓存工具类 + * + * @author 暮光:城中城 + * @since 2019年08月25日 + */ +public class RedisUtil { + private static Logger logger = LoggerFactory.getLogger(RedisUtil.class); + private static JedisPool pool; + + public static void init(String host, int port, int timeout) { + if (pool != null) { + logger.warn("redis连接池已初始化,请勿重复操作"); + return; + } + logger.info("初始化redis连接池..."); + JedisPoolConfig poolConfig = new JedisPoolConfig(); + poolConfig.setMaxTotal(200); + poolConfig.setMaxIdle(50); + poolConfig.setMinIdle(10); + poolConfig.setTestOnReturn(true); + pool = new JedisPool(poolConfig, host, port, timeout); + logger.info("初始化redis连接池完毕"); + } + + /** + * 获取连接,执行,释放连接 + * @author 暮光:城中城 + * @since 2019年08月25日 + * @param consumer 获取连接后的处理 + */ + public static T apply(Function consumer) { + return expireAndApply(null, 0, consumer); + } + + /** + * 获取连接,续期,执行,释放连接 + * @author 暮光:城中城 + * @since 2019年08月25日 + * @param key 为空则不续期 + * @param expire 小于等于0则不续期 + * @param consumer 获取连接后的处理 + */ + public static T expireAndApply(String key, int expire, Function consumer) { + Jedis jedis = null; + try { + jedis = pool.getResource(); + if (key != null && expire > 0) { + jedis.expire(key, expire); + } + return consumer.apply(jedis); + } catch (Exception e) { + logger.error("redis操作失败:{}", e.getMessage()); + return null; + } finally { + pool.returnResourceObject(jedis); + } + } + + /** + * 累加 + */ + public static Long incr(String key, int expire) { + return expireAndApply(key, expire, jedis -> jedis.incr(key)); + } + + /** + * 浮点型累加 + */ + public static Double incrByFloat(String key, Double value, int expire) { + return expireAndApply(key, expire, jedis -> jedis.incrByFloat(key, value)); + } + + /** + * 累加指定值 + */ + public static Long incrByNum(String key, long num, int expire) { + return expireAndApply(key, expire, jedis -> jedis.incrBy(key, num)); + } + + /** + * 排重set + */ + public static void uniqueSet(String key, int expire, String... member) { + expireAndApply(key, expire, jedis -> jedis.sadd(key, member)); + } + + /** + * 判断set中成员是否存在 + */ + public static boolean checkExitInSet(String key, String member) { + return apply(jedis -> jedis.sismember(key, member)); + } + + /** + * 添加到有序集合中 + */ + public static void topSet(String key, String name, long score, int expire) { + expireAndApply(key, expire, jedis -> jedis.zadd(key, score, name)); + } + + /** + * 是否存在 + */ + public static boolean exists(String key) { + return apply(jedis -> jedis.exists(key)); + } + + /** + * 续期 + */ + public static void expire(String key, int seconds) { + apply(jedis -> jedis.expire(key, seconds)); + } + + /** + * 获取值 + */ + public static String get(String key) { + return apply(jedis -> jedis.get(key)); + } + + /** + * 获取long型值 + */ + public static long getLong(String key) { + return NumberUtils.toLong(get(key)); + } + + /** + * 设置值 + */ + public static void set(String key, String value, int expire) { + expireAndApply(key, expire, jedis -> jedis.set(key, value)); + } + + /** + * 设置值 + * @param nxxx NX|XX, NX -- Only set the key if it does not already exist. XX -- Only set the key + * if it already exist. + * @param expx EX|PX, expire time units: EX = seconds; PX = milliseconds + * @param time expire time in the units of {@param #expx} + * @return Status code reply + */ + public static String set(String key, String value, String nxxx, String expx, Long time) { + return apply(jedis -> jedis.set(key, value, nxxx, expx, time)); + } + + /** + * 添加List值 + */ + public static Long sadd(String key, String... member) { + return apply(jedis -> jedis.sadd(key, member)); + } + + /** + * 删除key + */ + public static void del(String key) { + apply(jedis -> jedis.del(key)); + } + + /** + * 模糊匹配获取key列表 + */ + public static Set keys(String pattern) { + return apply(jedis -> jedis.keys(pattern)); + } + + /** + * 返回值在指定区间内的集合 + */ + public static Set zrevrangeWithScores(String topSetKey, int start, int end) { + return apply(jedis -> jedis.zrevrangeWithScores(topSetKey, start, end)); + } + + /** + * 将参数添加到 HyperLogLog 数据结构中 + */ + public static Long pfadd(String key, String value, int expire) { + return expireAndApply(key, expire, jedis -> jedis.pfadd(key, value)); + } + + /** + * 返回 HyperLogLog 的基数估算值 + */ + public static long pfcount(String key) { + return apply(jedis -> jedis.pfcount(key)); + } + +} diff --git a/zyplayer-doc-ui/db-ui/src/views/data/Executor.vue b/zyplayer-doc-ui/db-ui/src/views/data/Executor.vue index 04b79cd2..2ee9dfe5 100644 --- a/zyplayer-doc-ui/db-ui/src/views/data/Executor.vue +++ b/zyplayer-doc-ui/db-ui/src/views/data/Executor.vue @@ -23,20 +23,27 @@ -
- {{executeError}} -
+
{{executeError}}
+
暂无数据
- - - - - - - - + + +
{{executeResultInfo}}
+
+ +
{{resultItem.errMsg}}
+ + + + + + + + +
+
@@ -94,7 +101,7 @@ sqlExecuting: false, executeResultList: [], - executeResultCols: [], + executeResultInfo: "", executeUseTime: 0, executeUpdateCount: 0, sqlExecutorEditor: {}, @@ -111,7 +118,7 @@ this.loadDatasourceList(); // 下面两行先后顺序不能改 this.addEditorCompleter(); - app.sqlExecutorEditor = app.initAceEditor("sqlExecutorEditor", 20); + app.sqlExecutorEditor = app.initAceEditor("sqlExecutorEditor", 15); }, methods: { initAceEditor(editor, minLines) { @@ -179,7 +186,6 @@ app.executeError = ""; app.executeUseTime = ""; app.executeResultList = []; - app.executeResultCols = []; this.nowExecutorId = (new Date()).getTime() + Math.ceil(Math.random() * 1000); var sqlValue = this.sqlExecutorEditor.getSelectedText(); @@ -198,30 +204,22 @@ app.executeError = json.errMsg; return; } - var resultData = JSON.parse(json.data) || {}; - var dataList = resultData.result || []; - var executeResultCols = []; - if (dataList.length > 0) { - var propData = dataList[0]; - for (var key in propData) { - // 动态计算宽度~自己想的一个方法,666 - document.getElementById("widthCalculate").innerText = key; - var width1 = document.getElementById("widthCalculate").offsetWidth; - document.getElementById("widthCalculate").innerText = propData[key]; - var width2 = document.getElementById("widthCalculate").offsetWidth; - var width = (width1 > width2) ? width1 : width2; - width = (width < 60) ? 60 : width; - width = (width > 200) ? 200 : width; - executeResultCols.push({prop: key, width: width + 20}); - } - for (var i = 0; i < dataList.length; i++) { - dataList[i]._index = i + 1; - } + var resultList = json.data || []; + var executeResultList = []; + var executeUpdateCount = 0, executeUseTime = 0; + var executeResultInfo = ""; + for (var i = 0; i < resultList.length; i++) { + var objItem = JSON.parse(resultList[i]); + executeUpdateCount += (objItem.updateCount || 0); + executeUseTime += (objItem.useTime || 0); + executeResultInfo += app.getExecuteInfoStr(objItem); + var resultItem = app.dealExecuteResult(objItem); + executeResultList.push(resultItem); } - app.executeResultList = dataList; - app.executeResultCols = executeResultCols; - app.executeUseTime = resultData.useTime || 0; - app.executeUpdateCount = resultData.updateCount || 0; + app.executeResultInfo = executeResultInfo; + app.executeUseTime = executeUseTime; + app.executeUpdateCount = executeUpdateCount; + app.executeResultList = executeResultList; }); }, loadDatasourceList() { @@ -249,6 +247,41 @@ }, databaseChangeEvents() { + }, + getExecuteInfoStr(resultData) { + var resultStr = resultData.sql; + resultStr += "\n> " + ((!!resultData.errMsg) ? "ERROR" : "OK"); + resultStr += "\n> " + (resultData.useTime || 0) / 1000 + "s"; + resultStr += "\n\n"; + return resultStr; + }, + dealExecuteResult(resultData) { + var dataList = resultData.result || []; + var executeResultCols = []; + if (dataList.length > 0) { + var propData = dataList[0]; + for (var key in propData) { + // 动态计算宽度~自己想的一个方法,666 + document.getElementById("widthCalculate").innerText = key; + var width1 = document.getElementById("widthCalculate").offsetWidth; + document.getElementById("widthCalculate").innerText = propData[key]; + var width2 = document.getElementById("widthCalculate").offsetWidth; + var width = (width1 > width2) ? width1 : width2; + width = (width < 60) ? 60 : width; + width = (width > 200) ? 200 : width; + executeResultCols.push({prop: key, width: width + 20}); + } + for (var i = 0; i < dataList.length; i++) { + dataList[i]._index = i + 1; + } + } + var resultObj = {}; + resultObj.dataList = dataList; + resultObj.dataCols = executeResultCols; + resultObj.useTime = resultData.useTime || 0; + resultObj.errMsg = resultData.errMsg || ""; + resultObj.updateCount = resultData.updateCount || 0; + return resultObj; }, addEditorCompleter() { var languageTools = ace.require("ace/ext/language_tools");