执行器查询展示增加多窗口展示

This commit is contained in:
暮光:城中城
2019-09-01 18:41:17 +08:00
parent 38e1f28305
commit 6f38aed1ae
6 changed files with 336 additions and 56 deletions

View File

@@ -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,19 +58,29 @@ public class DbSqlExecutorController {
if (!manageAuth && !select && !update) {
return DocDbResponseJson.warn("没有该数据源的执行权限");
}
List<String> resultList = new LinkedList<>();
// 支持;分割的多个sql执行
String[] sqlArr = sql.split(";");
for (String sqlItem : sqlArr) {
if (StringUtils.isBlank(sqlItem)) {
continue;
}
try {
Map<String, Object> paramMap = JSON.parseObject(params);
ExecuteType executeType = (!manageAuth && select) ? ExecuteType.SELECT : ExecuteType.ALL;
ExecuteResult executeResult = sqlExecutor.execute(sourceId, executeId, executeType, sql, paramMap);
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);
return DocDbResponseJson.ok(resultJsonStr);
resultList.add(resultJsonStr);
} catch (Exception e) {
return DocDbResponseJson.warn(StringUtil.getException(e));
ExecuteResult executeResult = ExecuteResult.error(StringUtil.getException(e));
resultList.add(JSON.toJSONString(executeResult));
}
}
return DocDbResponseJson.ok(resultList);
}
@PostMapping(value = "/cancel")
public ResponseJson cancel(String executeId) {

View File

@@ -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<Map<String, Object>> result;
public ExecuteResult() {
@@ -21,10 +23,11 @@ public class ExecuteResult {
this.result = Collections.emptyList();
}
public ExecuteResult(int updateCount, List<Map<String, Object>> result, long useTime) {
public ExecuteResult(int updateCount, List<Map<String, Object>> 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;
}
}

View File

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

View File

@@ -63,5 +63,16 @@
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<!--redis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</project>

View File

@@ -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> T apply(Function<? super Jedis, ? extends T> consumer) {
return expireAndApply(null, 0, consumer);
}
/**
* 获取连接,续期,执行,释放连接
* @author 暮光:城中城
* @since 2019年08月25日
* @param key 为空则不续期
* @param expire 小于等于0则不续期
* @param consumer 获取连接后的处理
*/
public static <T> T expireAndApply(String key, int expire, Function<? super Jedis, ? extends T> 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<String> keys(String pattern) {
return apply(jedis -> jedis.keys(pattern));
}
/**
* 返回值在指定区间内的集合
*/
public static Set<Tuple> 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));
}
}

View File

@@ -23,20 +23,27 @@
</div>
</el-card>
<el-card>
<div v-if="!!executeError" style="color: #f00;">
{{executeError}}
</div>
<div v-if="!!executeError" style="color: #f00;">{{executeError}}</div>
<div v-else-if="executeResultList.length <= 0" v-loading="sqlExecuting">暂无数据</div>
<div v-else>
<el-table :data="executeResultList" stripe border style="width: 100%; margin-bottom: 5px;" class="execute-result-table" v-loading="sqlExecuting" max-height="600">
<el-table-column width="60px" v-if="executeResultCols.length > 0">
<el-tabs value="table1">
<el-tab-pane label="信息" name="table0">
<pre type="textarea" :rows="10" readonly v1-model="">{{executeResultInfo}}</pre>
</el-tab-pane>
<el-tab-pane :label="'结果'+(index+1)" :name="'table'+(index+1)" v-for="(resultItem, index) in executeResultList">
<div v-if="!!resultItem.errMsg" style="color: #f00;">{{resultItem.errMsg}}</div>
<el-table v-else :data="resultItem.dataList" stripe border style="width: 100%; margin-bottom: 5px;" class="execute-result-table" max-height="600">
<el-table-column width="60px" v-if="resultItem.dataCols.length > 0">
<template slot-scope="scope">{{scope.row._index}}</template>
</el-table-column>
<el-table-column v-for="item in executeResultCols" :prop="item.prop" :label="item.prop" :width="item.width">
<el-table-column v-for="item in resultItem.dataCols" :prop="item.prop" :label="item.prop" :width="item.width">
<template slot-scope="scope">
<el-input :value="scope.row[item.prop]" :readonly="true"></el-input>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</div>
</el-card>
</div>
@@ -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});
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);
}
for (var i = 0; i < dataList.length; i++) {
dataList[i]._index = i + 1;
}
}
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");