use of org.sagacity.sqltoy.config.model.LinkModel in project sagacity-sqltoy by chenrenfei.
the class ResultUtils method getResultSet.
private static List getResultSet(SqlToyConfig sqlToyConfig, SqlToyContext sqlToyContext, Connection conn, ResultSet rs, UpdateRowHandler updateRowHandler, DecryptHandler decryptHandler, int rowCnt, HashMap<String, Integer> labelIndexMap, String[] labelNames, int startColIndex) throws Exception {
// 字段连接(多行数据拼接成一个数据,以一行显示)
LinkModel linkModel = sqlToyConfig.getLinkModel();
// update 2020-09-13 存在多列link(独立出去编写,避免对单列产生影响)
if (linkModel != null && linkModel.getColumns().length > 1) {
return getMoreLinkResultSet(sqlToyConfig, sqlToyContext, decryptHandler, conn, rs, rowCnt, labelIndexMap, labelNames, startColIndex);
}
List<List> items = new ArrayList();
// 判断是否有缓存翻译器定义
Boolean hasTranslate = (sqlToyConfig.getTranslateMap().isEmpty()) ? false : true;
HashMap<String, Translate> translateMap = sqlToyConfig.getTranslateMap();
HashMap<String, HashMap<String, Object[]>> translateCache = null;
if (hasTranslate) {
translateCache = sqlToyContext.getTranslateManager().getTranslates(translateMap);
if (translateCache == null || translateCache.isEmpty()) {
hasTranslate = false;
logger.debug("通过缓存配置未获取到缓存数据,请正确配置TranslateManager!");
}
}
// link 目前只支持单个字段运算
int columnSize = labelNames.length;
int index = 0;
// 警告阀值
int warnThresholds = SqlToyConstants.getWarnThresholds();
boolean warnLimit = false;
// 最大阀值
long maxThresholds = SqlToyConstants.getMaxThresholds();
boolean maxLimit = false;
// 是否判断全部为null的行记录
boolean ignoreAllEmpty = sqlToyConfig.isIgnoreEmpty();
// 最大值要大于等于警告阀值
if (maxThresholds > 1 && maxThresholds <= warnThresholds) {
maxThresholds = warnThresholds;
}
List rowTemp;
if (linkModel != null) {
Object identity = null;
String linkColumn = linkModel.getColumns()[0];
String linkColumnLow = linkColumn.toLowerCase();
if (!labelIndexMap.containsKey(linkColumnLow)) {
throw new DataAccessException("做link操作时,查询结果字段中没有字段:" + linkColumn + ",请检查sql或link 配置的正确性!");
}
Set<String> linkSet = new HashSet<String>();
int linkIndex = labelIndexMap.get(linkColumnLow);
StringBuilder linkBuffer = new StringBuilder();
boolean hasDecorate = (linkModel.getDecorateAppendChar() == null) ? false : true;
boolean isLeft = true;
if (hasDecorate) {
isLeft = linkModel.getDecorateAlign().equals("left") ? true : false;
}
Object preIdentity = null;
Object linkValue;
String linkStr;
boolean translateLink = hasTranslate ? translateMap.containsKey(linkColumnLow) : false;
HashMap<String, Object[]> linkTranslateMap = null;
int linkTranslateIndex = 1;
TranslateExtend extend = null;
if (translateLink) {
extend = translateMap.get(linkColumnLow).getExtend();
linkTranslateIndex = extend.index;
linkTranslateMap = translateCache.get(extend.column);
}
Object[] cacheValues;
// 判断link拼接是否重新开始
boolean isLastProcess = false;
boolean doLink = true;
while (rs.next()) {
isLastProcess = false;
linkValue = rs.getObject(linkColumn);
if (linkValue == null) {
linkStr = "";
} else {
if (translateLink) {
cacheValues = linkTranslateMap.get(linkValue.toString());
if (cacheValues == null) {
linkStr = "[" + linkValue + "]未匹配";
logger.debug("translate cache:{},cacheType:{}, 对应的key:{} 没有设置相应的value!", extend.cache, extend.cacheType, linkValue);
} else {
linkStr = (cacheValues[linkTranslateIndex] == null) ? "" : cacheValues[linkTranslateIndex].toString();
}
} else {
linkStr = linkValue.toString();
}
}
identity = (linkModel.getIdColumns() == null) ? "default" : getLinkColumnsId(rs, linkModel.getIdColumns());
// 不相等
if (!identity.equals(preIdentity)) {
if (index != 0) {
items.get(items.size() - 1).set(linkIndex, linkBuffer.toString());
linkBuffer.delete(0, linkBuffer.length());
linkSet.clear();
}
linkBuffer.append(linkStr);
linkSet.add(linkStr);
if (hasTranslate) {
rowTemp = processResultRowWithTranslate(translateMap, translateCache, labelNames, rs, columnSize, decryptHandler, ignoreAllEmpty);
} else {
rowTemp = processResultRow(rs, labelNames, columnSize, decryptHandler, ignoreAllEmpty);
}
if (rowTemp != null) {
items.add(rowTemp);
}
preIdentity = identity;
} else {
isLastProcess = true;
doLink = true;
if (linkModel.isDistinct() && linkSet.contains(linkStr)) {
doLink = false;
}
linkSet.add(linkStr);
if (doLink) {
if (linkBuffer.length() > 0) {
linkBuffer.append(linkModel.getSign());
}
linkBuffer.append(hasDecorate ? StringUtil.appendStr(linkStr, linkModel.getDecorateAppendChar(), linkModel.getDecorateSize(), isLeft) : linkStr);
}
}
index++;
// 存在超出25000条数据的查询
if (index == warnThresholds) {
warnLimit = true;
}
// 提取数据超过上限(-1表示不限制)
if (index == maxThresholds) {
maxLimit = true;
break;
}
}
// 对最后一条写入循环值
if (isLastProcess) {
items.get(items.size() - 1).set(linkIndex, linkBuffer.toString());
}
} else {
// 修改操作不支持link操作
boolean isUpdate = false;
if (updateRowHandler != null) {
isUpdate = true;
}
// 循环通过java reflection将rs中的值映射到VO中
if (hasTranslate) {
while (rs.next()) {
// 先修改后再获取最终值
if (isUpdate) {
updateRowHandler.updateRow(rs, index);
rs.updateRow();
}
rowTemp = processResultRowWithTranslate(translateMap, translateCache, labelNames, rs, columnSize, decryptHandler, ignoreAllEmpty);
if (rowTemp != null) {
items.add(rowTemp);
}
index++;
// 存在超出25000条数据的查询(具体数据规模可以通过参数进行定义)
if (index == warnThresholds) {
warnLimit = true;
}
// 超出最大提取数据阀值,直接终止数据提取
if (index == maxThresholds) {
maxLimit = true;
break;
}
}
} else {
while (rs.next()) {
if (isUpdate) {
updateRowHandler.updateRow(rs, index);
rs.updateRow();
}
rowTemp = processResultRow(rs, labelNames, columnSize, decryptHandler, ignoreAllEmpty);
if (rowTemp != null) {
items.add(rowTemp);
}
index++;
// 存在超出警告规模级的数据查询
if (index == warnThresholds) {
warnLimit = true;
}
// 提取数据超过上限(-1表示不限制)
if (index == maxThresholds) {
maxLimit = true;
break;
}
}
}
}
// 超出警告阀值
if (warnLimit) {
warnLog(sqlToyConfig, index);
}
// 超过最大提取数据阀值
if (maxLimit) {
logger.error("MaxLargeResult:执行sql提取数据超出最大阀值限制{},sqlId={},具体语句={}", index, sqlToyConfig.getId(), sqlToyConfig.getSql(null));
}
return items;
}
use of org.sagacity.sqltoy.config.model.LinkModel in project sagacity-sqltoy by chenrenfei.
the class SqlXMLConfigParse method parseLink.
/**
* @todo 解析Link 查询
* @param sqlToyConfig
* @param linkNode
* @param local
*/
private static void parseLink(SqlToyConfig sqlToyConfig, NodeList linkNode, String local) {
if (linkNode == null || linkNode.getLength() == 0) {
return;
}
Element link = (Element) linkNode.item(0);
LinkModel linkModel = new LinkModel();
// update 2020-09-07 增加支持多列场景(兼容旧的模式)
if (link.hasAttribute("column")) {
linkModel.setColumns(trimParams(link.getAttribute("column").split("\\,")));
} else if (link.hasAttribute("columns")) {
linkModel.setColumns(trimParams(link.getAttribute("columns").split("\\,")));
}
// update 2021-10-15 支持多列
if (link.hasAttribute("id-columns")) {
linkModel.setIdColumns(trimParams(link.getAttribute("id-columns").split("\\,")));
} else if (link.hasAttribute("id-column")) {
linkModel.setIdColumns(trimParams(link.getAttribute("id-column").split("\\,")));
}
if (link.hasAttribute("sign")) {
linkModel.setSign(link.getAttribute("sign"));
}
if (link.hasAttribute("distinct")) {
linkModel.setDistinct(Boolean.parseBoolean(link.getAttribute("distinct")));
}
NodeList nodeList = link.getElementsByTagName(local.concat("decorate"));
if (nodeList.getLength() > 0) {
Element decorateElt = (Element) nodeList.item(0);
if (decorateElt.hasAttribute("align")) {
linkModel.setDecorateAlign(decorateElt.getAttribute("align").toLowerCase());
}
linkModel.setDecorateAppendChar(decorateElt.getAttribute("char"));
linkModel.setDecorateSize(Integer.parseInt(decorateElt.getAttribute("size")));
}
sqlToyConfig.setLinkModel(linkModel);
}
use of org.sagacity.sqltoy.config.model.LinkModel in project sagacity-sqltoy by chenrenfei.
the class SqlXMLConfigParse method parseLink.
/**
* @todo 解析Link 查询
* @param sqlToyConfig
* @param link
*/
private static void parseLink(SqlToyConfig sqlToyConfig, Element link) {
if (link == null)
return;
LinkModel linkModel = new LinkModel();
linkModel.setColumn(link.attributeValue("column"));
if (link.attribute("id-column") != null)
linkModel.setIdColumn(link.attributeValue("id-column"));
if (link.attribute("sign") != null)
linkModel.setSign(link.attributeValue("sign"));
if (link.element("decorate") != null) {
Element decorateElt = link.element("decorate");
if (decorateElt.attribute("align") != null)
linkModel.setDecorateAlign(decorateElt.attributeValue("align").toLowerCase());
linkModel.setDecorateAppendChar(decorateElt.attributeValue("char"));
linkModel.setDecorateSize(Integer.parseInt(decorateElt.attributeValue("size")));
}
sqlToyConfig.setLinkModel(linkModel);
}
use of org.sagacity.sqltoy.config.model.LinkModel in project sagacity-sqltoy by chenrenfei.
the class ResultUtils method getResultSet.
private static List getResultSet(SqlToyConfig sqlToyConfig, SqlToyContext sqlToyContext, Connection conn, ResultSet rs, UpdateRowHandler updateRowHandler, int rowCnt, HashMap<String, Integer> labelIndexMap, String[] labelNames, int startColIndex) throws Exception {
// 字段连接(多行数据拼接成一个数据,以一行显示)
LinkModel linkModel = (sqlToyConfig == null) ? null : sqlToyConfig.getLinkModel();
List<List> items = new ArrayList();
boolean isDebug = logger.isDebugEnabled();
// 判断是否有缓存翻译器定义
Boolean hasTranslate = (sqlToyConfig.getTranslateMap() == null) ? false : true;
HashMap<String, SqlTranslate> translateMap = hasTranslate ? sqlToyConfig.getTranslateMap() : null;
HashMap<String, HashMap<String, Object[]>> translateCache = null;
if (hasTranslate) {
translateCache = sqlToyContext.getTranslateManager().getTranslates(sqlToyContext, conn, translateMap);
if (translateCache == null || translateCache.isEmpty()) {
hasTranslate = false;
logger.debug("请正确配置TranslateManager!");
}
}
// link 目前只支持单个字段运算
int columnSize = labelNames.length;
int index = 0;
// 警告阀值
int warnThresholds = SqlToyConstants.getWarnThresholds();
boolean warnLimit = false;
// 最大阀值
long maxThresholds = SqlToyConstants.getMaxThresholds();
boolean maxLimit = false;
// 最大值要大于等于警告阀值
if (maxThresholds > 1 && maxThresholds <= warnThresholds)
maxThresholds = warnThresholds;
if (linkModel != null) {
Object identity = null;
int linkIndex = labelIndexMap.get(linkModel.getColumn().toLowerCase());
StringBuilder linkBuffer = new StringBuilder();
boolean hasDecorate = (linkModel.getDecorateAppendChar() == null) ? false : true;
boolean isLeft = true;
if (hasDecorate) {
isLeft = linkModel.getDecorateAlign().equals("left") ? true : false;
}
Object preIdentity = null;
Object linkValue;
Object linkStr;
boolean translateLink = hasTranslate ? translateMap.containsKey(linkModel.getColumn().toLowerCase()) : false;
HashMap<String, Object[]> linkTranslateMap = null;
int linkTranslateIndex = 1;
SqlTranslate translateModel = null;
if (translateLink) {
translateModel = translateMap.get(linkModel.getColumn().toLowerCase());
linkTranslateIndex = translateModel.getIndex();
linkTranslateMap = translateCache.get(translateModel.getColumn());
}
Object[] cacheValues;
// 判断link拼接是否重新开始
boolean isLastProcess = false;
while (rs.next()) {
isLastProcess = false;
linkValue = rs.getObject(linkModel.getColumn());
if (linkValue == null)
linkStr = "";
else if (translateLink) {
cacheValues = linkTranslateMap.get(linkValue.toString());
if (cacheValues == null) {
linkStr = "";
if (isDebug)
logger.debug("translate cache:" + translateModel.getCache() + " 对应的key:" + linkValue + " 没有设置相应的value!");
} else
linkStr = cacheValues[linkTranslateIndex];
} else
linkStr = linkValue.toString();
identity = (linkModel.getIdColumn() == null) ? "default" : rs.getObject(linkModel.getIdColumn());
// 不相等
if (!identity.equals(preIdentity)) {
if (index != 0) {
items.get(items.size() - 1).set(linkIndex, linkBuffer.toString());
linkBuffer.delete(0, linkBuffer.length());
}
linkBuffer.append(linkStr);
if (hasTranslate)
items.add(processResultRowWithTranslate(translateMap, translateCache, labelNames, rs, columnSize));
else
items.add(processResultRow(rs, startColIndex, rowCnt));
preIdentity = identity;
} else {
if (linkBuffer.length() > 0)
linkBuffer.append(linkModel.getSign());
linkBuffer.append(hasDecorate ? StringUtil.appendStr(linkStr.toString(), linkModel.getDecorateAppendChar(), linkModel.getDecorateSize(), isLeft) : linkStr);
isLastProcess = true;
}
index++;
// 存在超出25000条数据的查询
if (index == warnThresholds) {
warnLimit = true;
}
// 提取数据超过上限(-1表示不限制)
if (index == maxThresholds) {
maxLimit = true;
break;
}
}
if (isLastProcess) {
items.get(items.size() - 1).set(linkIndex, linkBuffer.toString());
}
} else {
// 修改操作不支持link操作
boolean isUpdate = false;
if (updateRowHandler != null)
isUpdate = true;
// 循环通过java reflection将rs中的值映射到VO中
if (hasTranslate) {
while (rs.next()) {
// 先修改后再获取最终值
if (isUpdate) {
updateRowHandler.updateRow(rs, index);
rs.updateRow();
}
items.add(processResultRowWithTranslate(translateMap, translateCache, labelNames, rs, columnSize));
index++;
// 存在超出25000条数据的查询(具体数据规模可以通过参数进行定义)
if (index == warnThresholds) {
warnLimit = true;
}
// 超出最大提取数据阀值,直接终止数据提取
if (index == maxThresholds) {
maxLimit = true;
break;
}
}
} else {
while (rs.next()) {
if (isUpdate) {
updateRowHandler.updateRow(rs, index);
rs.updateRow();
}
items.add(processResultRow(rs, startColIndex, rowCnt));
index++;
// 存在超出警告规模级的数据查询
if (index == warnThresholds) {
warnLimit = true;
}
// 提取数据超过上限(-1表示不限制)
if (index == maxThresholds) {
maxLimit = true;
break;
}
}
}
}
// 超出警告阀值
if (warnLimit)
warnLog(sqlToyConfig, index);
// 超过最大提取数据阀值
if (maxLimit)
logger.error("Max Large Result:执行sql提取数据超出最大阀值限制{},sqlId={},具体语句={}", index, sqlToyConfig.getId(), sqlToyConfig.getSql());
return items;
}
use of org.sagacity.sqltoy.config.model.LinkModel in project sagacity-sqltoy by chenrenfei.
the class ResultUtils method getMoreLinkResultSet.
/**
* @TODO 实现多列link
* @param sqlToyConfig
* @param sqlToyContext
* @param decryptHandler
* @param conn
* @param rs
* @param rowCnt
* @param labelIndexMap
* @param labelNames
* @param startColIndex
* @return
* @throws Exception
*/
private static List getMoreLinkResultSet(SqlToyConfig sqlToyConfig, SqlToyContext sqlToyContext, DecryptHandler decryptHandler, Connection conn, ResultSet rs, int rowCnt, HashMap<String, Integer> labelIndexMap, String[] labelNames, int startColIndex) throws Exception {
// 字段连接(多行数据拼接成一个数据,以一行显示)
LinkModel linkModel = sqlToyConfig.getLinkModel();
List<List> items = new ArrayList();
// 判断是否有缓存翻译器定义
Boolean hasTranslate = (sqlToyConfig.getTranslateMap().isEmpty()) ? false : true;
HashMap<String, Translate> translateMap = sqlToyConfig.getTranslateMap();
HashMap<String, HashMap<String, Object[]>> translateCache = null;
if (hasTranslate) {
translateCache = sqlToyContext.getTranslateManager().getTranslates(translateMap);
if (translateCache == null || translateCache.isEmpty()) {
hasTranslate = false;
logger.debug("通过缓存配置未获取到缓存数据,请正确配置TranslateManager!");
}
}
// link 目前只支持单个字段运算
int columnSize = labelNames.length;
int index = 0;
// 警告阀值
int warnThresholds = SqlToyConstants.getWarnThresholds();
boolean warnLimit = false;
// 最大阀值
long maxThresholds = SqlToyConstants.getMaxThresholds();
boolean maxLimit = false;
// 是否判断全部为null的行记录
boolean ignoreAllEmpty = sqlToyConfig.isIgnoreEmpty();
// 最大值要大于等于警告阀值
if (maxThresholds > 1 && maxThresholds <= warnThresholds) {
maxThresholds = warnThresholds;
}
int linkCols = linkModel.getColumns().length;
String[] linkColumns = linkModel.getColumns();
int[] linkIndexs = new int[linkCols];
StringBuilder[] linkBuffers = new StringBuilder[linkCols];
Set<String>[] linkSets = linkModel.isDistinct() ? new HashSet[linkCols] : null;
boolean[] translateLinks = new boolean[linkCols];
TranslateExtend[] transExtends = new TranslateExtend[linkCols];
String linkColumnLow;
for (int i = 0; i < linkCols; i++) {
linkBuffers[i] = new StringBuilder();
linkColumnLow = linkColumns[i].toLowerCase();
if (!labelIndexMap.containsKey(linkColumnLow)) {
throw new DataAccessException("做link操作时,查询结果字段中没有字段:" + linkColumnLow + ",请检查sql或link 配置的正确性!");
}
linkIndexs[i] = labelIndexMap.get(linkColumnLow);
if (hasTranslate) {
translateLinks[i] = translateMap.containsKey(linkColumnLow);
if (translateLinks[i]) {
transExtends[i] = translateMap.get(linkColumnLow).getExtend();
}
}
if (linkModel.isDistinct()) {
linkSets[i] = new HashSet<String>();
}
}
// link是否有修饰器
boolean hasDecorate = (linkModel.getDecorateAppendChar() == null) ? false : true;
boolean isLeft = true;
if (hasDecorate) {
isLeft = linkModel.getDecorateAlign().equals("left") ? true : false;
}
Object preIdentity = null;
Object[] linkValues = new Object[linkCols];
String[] linkStrs = new String[linkCols];
TranslateExtend extend = null;
Object[] cacheValues;
List rowTemp;
Object identity = null;
// 判断link拼接是否重新开始
boolean isLastProcess = false;
boolean doLink = false;
while (rs.next()) {
isLastProcess = false;
// 对多个link字段取值并进行翻译转义
for (int i = 0; i < linkCols; i++) {
linkValues[i] = rs.getObject(linkColumns[i]);
if (linkValues[i] == null) {
linkStrs[i] = "";
} else {
if (translateLinks[i]) {
extend = transExtends[i];
cacheValues = translateCache.get(extend.column).get(linkValues[i].toString());
if (cacheValues == null) {
linkStrs[i] = "[" + linkValues[i] + "]未匹配";
logger.debug("translate cache:{},cacheType:{}, 对应的key:{} 没有设置相应的value!", extend.cache, extend.cacheType, linkValues[i]);
} else {
linkStrs[i] = (cacheValues[extend.index] == null) ? "" : cacheValues[extend.index].toString();
}
} else {
linkStrs[i] = linkValues[i].toString();
}
}
}
// 取分组列的值
identity = (linkModel.getIdColumns() == null) ? "default" : getLinkColumnsId(rs, linkModel.getIdColumns());
// 不相等
if (!identity.equals(preIdentity)) {
// 不相等时先对最后一条记录修改,写入拼接后的字符串
if (index != 0) {
rowTemp = items.get(items.size() - 1);
for (int i = 0; i < linkCols; i++) {
rowTemp.set(linkIndexs[i], linkBuffers[i].toString());
linkBuffers[i].delete(0, linkBuffers[i].length());
// 清除
if (linkModel.isDistinct()) {
linkSets[i].clear();
}
}
}
// 再写入新的拼接串
for (int i = 0; i < linkCols; i++) {
linkBuffers[i].append(linkStrs[i]);
if (linkModel.isDistinct()) {
linkSets[i].add(linkStrs[i]);
}
}
// 提取result中的数据(identity相等时不需要提取)
if (hasTranslate) {
rowTemp = processResultRowWithTranslate(translateMap, translateCache, labelNames, rs, columnSize, decryptHandler, ignoreAllEmpty);
} else {
rowTemp = processResultRow(rs, labelNames, columnSize, decryptHandler, ignoreAllEmpty);
}
if (rowTemp != null) {
items.add(rowTemp);
}
preIdentity = identity;
} else {
isLastProcess = true;
// identity相同,表示还在同一组内,直接拼接link字符
for (int i = 0; i < linkCols; i++) {
doLink = true;
// 判断是否已经重复
if (linkModel.isDistinct()) {
if (linkSets[i].contains(linkStrs[i])) {
doLink = false;
}
linkSets[i].add(linkStrs[i]);
}
if (doLink) {
if (linkBuffers[i].length() > 0) {
linkBuffers[i].append(linkModel.getSign());
}
linkBuffers[i].append(hasDecorate ? StringUtil.appendStr(linkStrs[i], linkModel.getDecorateAppendChar(), linkModel.getDecorateSize(), isLeft) : linkStrs[i]);
}
}
}
index++;
// 存在超出25000条数据的查询
if (index == warnThresholds) {
warnLimit = true;
}
// 提取数据超过上限(-1表示不限制)
if (index == maxThresholds) {
maxLimit = true;
break;
}
}
// 数据集合不为空,对最后一条记录写入循环值
if (isLastProcess) {
rowTemp = items.get(items.size() - 1);
for (int i = 0; i < linkCols; i++) {
rowTemp.set(linkIndexs[i], linkBuffers[i].toString());
}
}
// 超出警告阀值
if (warnLimit) {
warnLog(sqlToyConfig, index);
}
// 超过最大提取数据阀值
if (maxLimit) {
logger.error("MaxLargeResult:执行sql提取数据超出最大阀值限制{},sqlId={},具体语句={}", index, sqlToyConfig.getId(), sqlToyConfig.getSql(null));
}
return items;
}
Aggregations