mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-14 05:43:51 +00:00
add switch to translate S2QL into SQL (#314)
This commit is contained in:
@@ -8,7 +8,6 @@ import org.springframework.context.annotation.PropertySource;
|
|||||||
@Configuration
|
@Configuration
|
||||||
@Data
|
@Data
|
||||||
@PropertySource("classpath:optimization.properties")
|
@PropertySource("classpath:optimization.properties")
|
||||||
//@ComponentScan(basePackages = "com.tencent.supersonic.chat")
|
|
||||||
public class OptimizationConfig {
|
public class OptimizationConfig {
|
||||||
|
|
||||||
@Value("${one.detection.size}")
|
@Value("${one.detection.size}")
|
||||||
@@ -40,4 +39,7 @@ public class OptimizationConfig {
|
|||||||
@Value("${candidate.threshold}")
|
@Value("${candidate.threshold}")
|
||||||
private Double candidateThreshold;
|
private Double candidateThreshold;
|
||||||
|
|
||||||
|
@Value("${user.s2ql.switch:false}")
|
||||||
|
private boolean useS2qlSwitch;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,19 @@ import com.tencent.supersonic.chat.api.pojo.QueryContext;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* a mapper that is capable of semantic understanding of text.
|
* A mapper that is capable of semantic understanding of text.
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class EmbeddingMapper extends BaseMapper {
|
public class EmbeddingMapper extends BaseMapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void work(QueryContext queryContext) {
|
public void work(QueryContext queryContext) {
|
||||||
|
//1. query from embedding by queryText
|
||||||
|
|
||||||
|
|
||||||
|
//2. build SchemaElementMatch by info
|
||||||
|
|
||||||
|
//3. add to mapInfo
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,11 +171,10 @@ public class FuzzyNameMapper extends BaseMapper {
|
|||||||
if (CollectionUtils.isEmpty(elements)) {
|
if (CollectionUtils.isEmpty(elements)) {
|
||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
Set<Long> regElementSet = elements.stream()
|
return elements.stream()
|
||||||
.filter(elementMatch -> schemaElementType.equals(elementMatch.getElement().getType()))
|
.filter(elementMatch -> schemaElementType.equals(elementMatch.getElement().getType()))
|
||||||
.map(elementMatch -> elementMatch.getElement().getId())
|
.map(elementMatch -> elementMatch.getElement().getId())
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
return regElementSet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.tencent.supersonic.chat.api.pojo.SchemaElementMatch;
|
|||||||
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
import com.tencent.supersonic.chat.api.pojo.SchemaElementType;
|
||||||
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
|
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
|
||||||
import com.tencent.supersonic.chat.api.pojo.response.QueryState;
|
import com.tencent.supersonic.chat.api.pojo.response.QueryState;
|
||||||
|
import com.tencent.supersonic.chat.config.OptimizationConfig;
|
||||||
import com.tencent.supersonic.chat.plugin.PluginManager;
|
import com.tencent.supersonic.chat.plugin.PluginManager;
|
||||||
import com.tencent.supersonic.chat.query.QueryManager;
|
import com.tencent.supersonic.chat.query.QueryManager;
|
||||||
import com.tencent.supersonic.chat.query.plugin.PluginSemanticQuery;
|
import com.tencent.supersonic.chat.query.plugin.PluginSemanticQuery;
|
||||||
@@ -20,6 +21,11 @@ import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
|
|||||||
import com.tencent.supersonic.common.util.ContextUtils;
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
||||||
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.calcite.sql.parser.SqlParseException;
|
import org.apache.calcite.sql.parser.SqlParseException;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -27,12 +33,6 @@ import org.springframework.http.ResponseEntity;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class MetricInterpretQuery extends PluginSemanticQuery {
|
public class MetricInterpretQuery extends PluginSemanticQuery {
|
||||||
@@ -55,6 +55,10 @@ public class MetricInterpretQuery extends PluginSemanticQuery {
|
|||||||
fillAggregator(queryStructReq, parseInfo.getMetrics());
|
fillAggregator(queryStructReq, parseInfo.getMetrics());
|
||||||
queryStructReq.setNativeQuery(true);
|
queryStructReq.setNativeQuery(true);
|
||||||
SemanticInterpreter semanticInterpreter = ComponentFactory.getSemanticLayer();
|
SemanticInterpreter semanticInterpreter = ComponentFactory.getSemanticLayer();
|
||||||
|
|
||||||
|
OptimizationConfig optimizationConfig = ContextUtils.getBean(OptimizationConfig.class);
|
||||||
|
queryStructReq.setUseS2qlSwitch(optimizationConfig.isUseS2qlSwitch());
|
||||||
|
|
||||||
QueryResultWithSchemaResp queryResultWithSchemaResp = semanticInterpreter.queryByStruct(queryStructReq, user);
|
QueryResultWithSchemaResp queryResultWithSchemaResp = semanticInterpreter.queryByStruct(queryStructReq, user);
|
||||||
String text = generateTableText(queryResultWithSchemaResp);
|
String text = generateTableText(queryResultWithSchemaResp);
|
||||||
Map<String, Object> properties = parseInfo.getProperties();
|
Map<String, Object> properties = parseInfo.getProperties();
|
||||||
@@ -76,7 +80,7 @@ public class MetricInterpretQuery extends PluginSemanticQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String replaceText(String text, List<SchemaElementMatch> schemaElementMatches,
|
private String replaceText(String text, List<SchemaElementMatch> schemaElementMatches,
|
||||||
Map<String, String> replacedMap) {
|
Map<String, String> replacedMap) {
|
||||||
if (CollectionUtils.isEmpty(schemaElementMatches)) {
|
if (CollectionUtils.isEmpty(schemaElementMatches)) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,16 +14,17 @@ import com.tencent.supersonic.chat.api.pojo.SemanticParseInfo;
|
|||||||
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
|
import com.tencent.supersonic.chat.api.pojo.request.QueryFilter;
|
||||||
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
|
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
|
||||||
import com.tencent.supersonic.chat.api.pojo.response.QueryState;
|
import com.tencent.supersonic.chat.api.pojo.response.QueryState;
|
||||||
|
import com.tencent.supersonic.chat.config.OptimizationConfig;
|
||||||
import com.tencent.supersonic.chat.query.QueryManager;
|
import com.tencent.supersonic.chat.query.QueryManager;
|
||||||
import com.tencent.supersonic.chat.service.SemanticService;
|
import com.tencent.supersonic.chat.service.SemanticService;
|
||||||
import com.tencent.supersonic.chat.utils.ComponentFactory;
|
import com.tencent.supersonic.chat.utils.ComponentFactory;
|
||||||
import com.tencent.supersonic.chat.utils.QueryReqBuilder;
|
import com.tencent.supersonic.chat.utils.QueryReqBuilder;
|
||||||
import com.tencent.supersonic.common.pojo.QueryColumn;
|
import com.tencent.supersonic.common.pojo.QueryColumn;
|
||||||
|
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
|
||||||
import com.tencent.supersonic.common.util.ContextUtils;
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
import com.tencent.supersonic.semantic.api.model.enums.QueryTypeEnum;
|
import com.tencent.supersonic.semantic.api.model.enums.QueryTypeEnum;
|
||||||
import com.tencent.supersonic.semantic.api.model.response.ExplainResp;
|
import com.tencent.supersonic.semantic.api.model.response.ExplainResp;
|
||||||
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
||||||
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
|
|
||||||
import com.tencent.supersonic.semantic.api.query.request.ExplainSqlReq;
|
import com.tencent.supersonic.semantic.api.query.request.ExplainSqlReq;
|
||||||
import com.tencent.supersonic.semantic.api.query.request.QueryMultiStructReq;
|
import com.tencent.supersonic.semantic.api.query.request.QueryMultiStructReq;
|
||||||
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
||||||
@@ -195,11 +196,17 @@ public abstract class RuleSemanticQuery implements SemanticQuery, Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QueryResult queryResult = new QueryResult();
|
QueryResult queryResult = new QueryResult();
|
||||||
QueryResultWithSchemaResp queryResp = semanticInterpreter.queryByStruct(convertQueryStruct(), user);
|
QueryStructReq queryStructReq = convertQueryStruct();
|
||||||
|
|
||||||
|
OptimizationConfig optimizationConfig = ContextUtils.getBean(OptimizationConfig.class);
|
||||||
|
queryStructReq.setUseS2qlSwitch(optimizationConfig.isUseS2qlSwitch());
|
||||||
|
|
||||||
|
QueryResultWithSchemaResp queryResp = semanticInterpreter.queryByStruct(queryStructReq, user);
|
||||||
|
|
||||||
if (queryResp != null) {
|
if (queryResp != null) {
|
||||||
queryResult.setQueryAuthorization(queryResp.getQueryAuthorization());
|
queryResult.setQueryAuthorization(queryResp.getQueryAuthorization());
|
||||||
}
|
}
|
||||||
|
|
||||||
String sql = queryResp == null ? null : queryResp.getSql();
|
String sql = queryResp == null ? null : queryResp.getSql();
|
||||||
List<Map<String, Object>> resultList = queryResp == null ? new ArrayList<>()
|
List<Map<String, Object>> resultList = queryResp == null ? new ArrayList<>()
|
||||||
: queryResp.getResultList();
|
: queryResp.getResultList();
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ public class EntityInfoExecuteResponder implements ExecuteResponder {
|
|||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.map(String::valueOf)
|
.map(String::valueOf)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(entities)) {
|
if (CollectionUtils.isEmpty(entities)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,18 +30,19 @@ import com.tencent.supersonic.chat.api.pojo.response.EntityInfo;
|
|||||||
import com.tencent.supersonic.chat.api.pojo.response.MetricInfo;
|
import com.tencent.supersonic.chat.api.pojo.response.MetricInfo;
|
||||||
import com.tencent.supersonic.chat.api.pojo.response.ModelInfo;
|
import com.tencent.supersonic.chat.api.pojo.response.ModelInfo;
|
||||||
import com.tencent.supersonic.chat.config.AggregatorConfig;
|
import com.tencent.supersonic.chat.config.AggregatorConfig;
|
||||||
|
import com.tencent.supersonic.chat.config.OptimizationConfig;
|
||||||
import com.tencent.supersonic.chat.utils.ComponentFactory;
|
import com.tencent.supersonic.chat.utils.ComponentFactory;
|
||||||
import com.tencent.supersonic.chat.utils.QueryReqBuilder;
|
import com.tencent.supersonic.chat.utils.QueryReqBuilder;
|
||||||
import com.tencent.supersonic.common.pojo.DateConf;
|
import com.tencent.supersonic.common.pojo.DateConf;
|
||||||
import com.tencent.supersonic.common.pojo.DateConf.DateMode;
|
import com.tencent.supersonic.common.pojo.DateConf.DateMode;
|
||||||
import com.tencent.supersonic.common.pojo.QueryColumn;
|
import com.tencent.supersonic.common.pojo.QueryColumn;
|
||||||
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
|
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
|
||||||
|
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
|
||||||
import com.tencent.supersonic.common.pojo.enums.RatioOverType;
|
import com.tencent.supersonic.common.pojo.enums.RatioOverType;
|
||||||
import com.tencent.supersonic.common.util.ContextUtils;
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
import com.tencent.supersonic.common.util.DateUtils;
|
import com.tencent.supersonic.common.util.DateUtils;
|
||||||
import com.tencent.supersonic.knowledge.service.SchemaService;
|
import com.tencent.supersonic.knowledge.service.SchemaService;
|
||||||
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
||||||
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
|
|
||||||
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.time.DayOfWeek;
|
import java.time.DayOfWeek;
|
||||||
@@ -262,8 +263,10 @@ public class SemanticService {
|
|||||||
|
|
||||||
QueryResultWithSchemaResp queryResultWithColumns = null;
|
QueryResultWithSchemaResp queryResultWithColumns = null;
|
||||||
try {
|
try {
|
||||||
queryResultWithColumns = semanticInterpreter.queryByStruct(
|
QueryStructReq queryStructReq = QueryReqBuilder.buildStructReq(semanticParseInfo);
|
||||||
QueryReqBuilder.buildStructReq(semanticParseInfo), user);
|
OptimizationConfig optimizationConfig = ContextUtils.getBean(OptimizationConfig.class);
|
||||||
|
queryStructReq.setUseS2qlSwitch(optimizationConfig.isUseS2qlSwitch());
|
||||||
|
queryResultWithColumns = semanticInterpreter.queryByStruct(queryStructReq, user);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("setMainModel queryByStruct error, e:", e);
|
log.warn("setMainModel queryByStruct error, e:", e);
|
||||||
}
|
}
|
||||||
@@ -425,7 +428,12 @@ public class SemanticService {
|
|||||||
|
|
||||||
queryStructReq.setGroups(new ArrayList<>(Arrays.asList(dateField)));
|
queryStructReq.setGroups(new ArrayList<>(Arrays.asList(dateField)));
|
||||||
queryStructReq.setDateInfo(getRatioDateConf(aggOperatorEnum, semanticParseInfo, results));
|
queryStructReq.setDateInfo(getRatioDateConf(aggOperatorEnum, semanticParseInfo, results));
|
||||||
|
|
||||||
|
OptimizationConfig optimizationConfig = ContextUtils.getBean(OptimizationConfig.class);
|
||||||
|
queryStructReq.setUseS2qlSwitch(optimizationConfig.isUseS2qlSwitch());
|
||||||
|
|
||||||
QueryResultWithSchemaResp queryResp = semanticInterpreter.queryByStruct(queryStructReq, user);
|
QueryResultWithSchemaResp queryResp = semanticInterpreter.queryByStruct(queryStructReq, user);
|
||||||
|
|
||||||
if (Objects.nonNull(queryResp) && !CollectionUtils.isEmpty(queryResp.getResultList())) {
|
if (Objects.nonNull(queryResp) && !CollectionUtils.isEmpty(queryResp.getResultList())) {
|
||||||
|
|
||||||
Map<String, Object> result = queryResp.getResultList().get(0);
|
Map<String, Object> result = queryResp.getResultList().get(0);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.tencent.supersonic.chat.api.pojo.response.EntityInfo;
|
|||||||
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
|
import com.tencent.supersonic.chat.api.pojo.response.ParseResp;
|
||||||
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
|
import com.tencent.supersonic.chat.api.pojo.response.QueryResult;
|
||||||
import com.tencent.supersonic.chat.api.pojo.response.QueryState;
|
import com.tencent.supersonic.chat.api.pojo.response.QueryState;
|
||||||
|
import com.tencent.supersonic.chat.config.OptimizationConfig;
|
||||||
import com.tencent.supersonic.chat.persistence.dataobject.ChatParseDO;
|
import com.tencent.supersonic.chat.persistence.dataobject.ChatParseDO;
|
||||||
import com.tencent.supersonic.chat.persistence.dataobject.ChatQueryDO;
|
import com.tencent.supersonic.chat.persistence.dataobject.ChatQueryDO;
|
||||||
import com.tencent.supersonic.chat.persistence.dataobject.CostType;
|
import com.tencent.supersonic.chat.persistence.dataobject.CostType;
|
||||||
@@ -659,6 +660,9 @@ public class QueryServiceImpl implements QueryService {
|
|||||||
groups.add(dimensionValueReq.getBizName());
|
groups.add(dimensionValueReq.getBizName());
|
||||||
queryStructReq.setGroups(groups);
|
queryStructReq.setGroups(groups);
|
||||||
SemanticInterpreter semanticInterpreter = ComponentFactory.getSemanticLayer();
|
SemanticInterpreter semanticInterpreter = ComponentFactory.getSemanticLayer();
|
||||||
|
|
||||||
|
OptimizationConfig optimizationConfig = ContextUtils.getBean(OptimizationConfig.class);
|
||||||
|
queryStructReq.setUseS2qlSwitch(optimizationConfig.isUseS2qlSwitch());
|
||||||
QueryResultWithSchemaResp queryResultWithSchemaResp = semanticInterpreter.queryByStruct(queryStructReq, user);
|
QueryResultWithSchemaResp queryResultWithSchemaResp = semanticInterpreter.queryByStruct(queryStructReq, user);
|
||||||
return queryResultWithSchemaResp;
|
return queryResultWithSchemaResp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,27 @@
|
|||||||
package com.tencent.supersonic.chat.utils;
|
package com.tencent.supersonic.chat.utils;
|
||||||
|
|
||||||
|
import static com.tencent.supersonic.common.pojo.Constants.AND_UPPER;
|
||||||
|
import static com.tencent.supersonic.common.pojo.Constants.APOSTROPHE;
|
||||||
|
import static com.tencent.supersonic.common.pojo.Constants.COMMA;
|
||||||
|
import static com.tencent.supersonic.common.pojo.Constants.SPACE;
|
||||||
|
import static com.tencent.supersonic.common.pojo.Constants.UNDERLINE_DOUBLE;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||||
import com.tencent.supersonic.chat.api.component.SemanticInterpreter;
|
import com.tencent.supersonic.chat.api.component.SemanticInterpreter;
|
||||||
import com.tencent.supersonic.chat.config.DefaultMetric;
|
import com.tencent.supersonic.chat.config.DefaultMetric;
|
||||||
import com.tencent.supersonic.chat.config.Dim4Dict;
|
import com.tencent.supersonic.chat.config.Dim4Dict;
|
||||||
import com.tencent.supersonic.common.pojo.QueryColumn;
|
import com.tencent.supersonic.chat.config.OptimizationConfig;
|
||||||
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
|
||||||
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
|
|
||||||
import com.tencent.supersonic.common.pojo.Filter;
|
|
||||||
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
|
||||||
import com.tencent.supersonic.common.pojo.Constants;
|
|
||||||
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
|
|
||||||
import com.tencent.supersonic.common.pojo.Aggregator;
|
import com.tencent.supersonic.common.pojo.Aggregator;
|
||||||
|
import com.tencent.supersonic.common.pojo.Constants;
|
||||||
import com.tencent.supersonic.common.pojo.DateConf;
|
import com.tencent.supersonic.common.pojo.DateConf;
|
||||||
|
import com.tencent.supersonic.common.pojo.Filter;
|
||||||
import com.tencent.supersonic.common.pojo.Order;
|
import com.tencent.supersonic.common.pojo.Order;
|
||||||
|
import com.tencent.supersonic.common.pojo.QueryColumn;
|
||||||
|
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
|
||||||
|
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
|
||||||
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
|
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
||||||
|
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -22,19 +29,12 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.StringJoiner;
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.logging.log4j.util.Strings;
|
import org.apache.logging.log4j.util.Strings;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import static com.tencent.supersonic.common.pojo.Constants.SPACE;
|
|
||||||
import static com.tencent.supersonic.common.pojo.Constants.AND_UPPER;
|
|
||||||
import static com.tencent.supersonic.common.pojo.Constants.COMMA;
|
|
||||||
import static com.tencent.supersonic.common.pojo.Constants.APOSTROPHE;
|
|
||||||
import static com.tencent.supersonic.common.pojo.Constants.UNDERLINE_DOUBLE;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class DictQueryHelper {
|
public class DictQueryHelper {
|
||||||
@@ -55,7 +55,11 @@ public class DictQueryHelper {
|
|||||||
List<String> data = new ArrayList<>();
|
List<String> data = new ArrayList<>();
|
||||||
QueryStructReq queryStructCmd = generateQueryStructCmd(modelId, defaultMetricDesc, dim4Dict);
|
QueryStructReq queryStructCmd = generateQueryStructCmd(modelId, defaultMetricDesc, dim4Dict);
|
||||||
try {
|
try {
|
||||||
|
OptimizationConfig optimizationConfig = ContextUtils.getBean(OptimizationConfig.class);
|
||||||
|
queryStructCmd.setUseS2qlSwitch(optimizationConfig.isUseS2qlSwitch());
|
||||||
|
|
||||||
QueryResultWithSchemaResp queryResultWithColumns = semanticInterpreter.queryByStruct(queryStructCmd, user);
|
QueryResultWithSchemaResp queryResultWithColumns = semanticInterpreter.queryByStruct(queryStructCmd, user);
|
||||||
|
|
||||||
log.info("fetchDimValueSingle sql:{}", queryResultWithColumns.getSql());
|
log.info("fetchDimValueSingle sql:{}", queryResultWithColumns.getSql());
|
||||||
String nature = String.format("_%d_%d", modelId, dim4Dict.getDimId());
|
String nature = String.format("_%d_%d", modelId, dim4Dict.getDimId());
|
||||||
String dimNameRewrite = rewriteDimName(queryResultWithColumns.getColumns(), dim4Dict.getBizName());
|
String dimNameRewrite = rewriteDimName(queryResultWithColumns.getColumns(), dim4Dict.getBizName());
|
||||||
|
|||||||
@@ -11,10 +11,6 @@ import com.tencent.supersonic.common.pojo.Filter;
|
|||||||
import com.tencent.supersonic.common.pojo.Order;
|
import com.tencent.supersonic.common.pojo.Order;
|
||||||
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
|
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
|
||||||
import com.tencent.supersonic.common.pojo.enums.AggregateTypeEnum;
|
import com.tencent.supersonic.common.pojo.enums.AggregateTypeEnum;
|
||||||
import com.tencent.supersonic.common.util.ContextUtils;
|
|
||||||
import com.tencent.supersonic.common.util.DateModeUtils;
|
|
||||||
import com.tencent.supersonic.common.util.SqlFilterUtils;
|
|
||||||
import com.tencent.supersonic.common.util.jsqlparser.SqlParserAddHelper;
|
|
||||||
import com.tencent.supersonic.semantic.api.model.enums.TimeDimensionEnum;
|
import com.tencent.supersonic.semantic.api.model.enums.TimeDimensionEnum;
|
||||||
import com.tencent.supersonic.semantic.api.query.request.QueryMultiStructReq;
|
import com.tencent.supersonic.semantic.api.query.request.QueryMultiStructReq;
|
||||||
import com.tencent.supersonic.semantic.api.query.request.QueryS2QLReq;
|
import com.tencent.supersonic.semantic.api.query.request.QueryS2QLReq;
|
||||||
@@ -22,7 +18,6 @@ import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -30,22 +25,6 @@ import java.util.Objects;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.sf.jsqlparser.JSQLParserException;
|
|
||||||
import net.sf.jsqlparser.expression.Expression;
|
|
||||||
import net.sf.jsqlparser.expression.Function;
|
|
||||||
import net.sf.jsqlparser.expression.LongValue;
|
|
||||||
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
|
|
||||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
|
||||||
import net.sf.jsqlparser.schema.Column;
|
|
||||||
import net.sf.jsqlparser.schema.Table;
|
|
||||||
import net.sf.jsqlparser.statement.select.GroupByElement;
|
|
||||||
import net.sf.jsqlparser.statement.select.Limit;
|
|
||||||
import net.sf.jsqlparser.statement.select.OrderByElement;
|
|
||||||
import net.sf.jsqlparser.statement.select.PlainSelect;
|
|
||||||
import net.sf.jsqlparser.statement.select.Select;
|
|
||||||
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
|
|
||||||
import net.sf.jsqlparser.statement.select.SelectItem;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.logging.log4j.util.Strings;
|
import org.apache.logging.log4j.util.Strings;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
@@ -159,104 +138,6 @@ public class QueryReqBuilder {
|
|||||||
return queryS2QLReq;
|
return queryS2QLReq;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* convert queryStructReq to QueryS2QLReq
|
|
||||||
*
|
|
||||||
* @param queryStructReq
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static QueryS2QLReq buildS2QLReq(QueryStructReq queryStructReq) throws JSQLParserException {
|
|
||||||
Select select = new Select();
|
|
||||||
//1.Set the select items (columns)
|
|
||||||
PlainSelect plainSelect = new PlainSelect();
|
|
||||||
List<SelectItem> selectItems = new ArrayList<>();
|
|
||||||
List<String> groups = queryStructReq.getGroups();
|
|
||||||
if (!CollectionUtils.isEmpty(groups)) {
|
|
||||||
for (String group : groups) {
|
|
||||||
selectItems.add(new SelectExpressionItem(new Column(group)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
List<Aggregator> aggregators = queryStructReq.getAggregators();
|
|
||||||
if (!CollectionUtils.isEmpty(aggregators)) {
|
|
||||||
for (Aggregator aggregator : aggregators) {
|
|
||||||
if (queryStructReq.getNativeQuery()) {
|
|
||||||
selectItems.add(new SelectExpressionItem(new Column(aggregator.getColumn())));
|
|
||||||
} else {
|
|
||||||
Function sumFunction = new Function();
|
|
||||||
AggOperatorEnum func = aggregator.getFunc();
|
|
||||||
if (AggOperatorEnum.UNKNOWN.equals(func)) {
|
|
||||||
func = AggOperatorEnum.SUM;
|
|
||||||
}
|
|
||||||
sumFunction.setName(func.getOperator());
|
|
||||||
sumFunction.setParameters(new ExpressionList(new Column(aggregator.getColumn())));
|
|
||||||
selectItems.add(new SelectExpressionItem(sumFunction));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
plainSelect.setSelectItems(selectItems);
|
|
||||||
//2.Set the table name
|
|
||||||
Table table = new Table(Constants.TABLE_PREFIX + queryStructReq.getModelId());
|
|
||||||
plainSelect.setFromItem(table);
|
|
||||||
|
|
||||||
//3.Set the order by clause
|
|
||||||
List<Order> orders = queryStructReq.getOrders();
|
|
||||||
if (!CollectionUtils.isEmpty(orders)) {
|
|
||||||
List<OrderByElement> orderByElements = new ArrayList<>();
|
|
||||||
for (Order order : orders) {
|
|
||||||
OrderByElement orderByElement = new OrderByElement();
|
|
||||||
orderByElement.setExpression(new Column(order.getColumn()));
|
|
||||||
orderByElement.setAsc(false);
|
|
||||||
if (Constants.ASC_UPPER.equalsIgnoreCase(order.getDirection())) {
|
|
||||||
orderByElement.setAsc(true);
|
|
||||||
}
|
|
||||||
orderByElements.add(orderByElement);
|
|
||||||
}
|
|
||||||
plainSelect.setOrderByElements(orderByElements);
|
|
||||||
}
|
|
||||||
|
|
||||||
//4.Set the group by clause
|
|
||||||
if (!CollectionUtils.isEmpty(groups) && !queryStructReq.getNativeQuery()) {
|
|
||||||
GroupByElement groupByElement = new GroupByElement();
|
|
||||||
for (String group : groups) {
|
|
||||||
groupByElement.addGroupByExpression(new Column(group));
|
|
||||||
}
|
|
||||||
plainSelect.setGroupByElement(groupByElement);
|
|
||||||
}
|
|
||||||
|
|
||||||
//7.Set the limit clause
|
|
||||||
if (Objects.nonNull(queryStructReq.getLimit())) {
|
|
||||||
Limit limit = new Limit();
|
|
||||||
limit.setRowCount(new LongValue(queryStructReq.getLimit()));
|
|
||||||
plainSelect.setLimit(limit);
|
|
||||||
}
|
|
||||||
select.setSelectBody(plainSelect);
|
|
||||||
|
|
||||||
//5.Set where
|
|
||||||
List<Filter> dimensionFilters = queryStructReq.getDimensionFilters();
|
|
||||||
SqlFilterUtils sqlFilterUtils = ContextUtils.getBean(SqlFilterUtils.class);
|
|
||||||
String whereClause = sqlFilterUtils.getWhereClause(dimensionFilters);
|
|
||||||
|
|
||||||
String sql = select.toString();
|
|
||||||
if (StringUtils.isNotBlank(whereClause)) {
|
|
||||||
Expression expression = CCJSqlParserUtil.parseCondExpression(whereClause);
|
|
||||||
sql = SqlParserAddHelper.addWhere(sql, expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
//6.Set DateInfo
|
|
||||||
DateModeUtils dateModeUtils = ContextUtils.getBean(DateModeUtils.class);
|
|
||||||
String dateWhereStr = dateModeUtils.getDateWhereStr(queryStructReq.getDateInfo());
|
|
||||||
if (StringUtils.isNotBlank(dateWhereStr)) {
|
|
||||||
Expression expression = CCJSqlParserUtil.parseCondExpression(dateWhereStr);
|
|
||||||
sql = SqlParserAddHelper.addWhere(sql, expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryS2QLReq result = new QueryS2QLReq();
|
|
||||||
result.setSql(sql);
|
|
||||||
result.setModelId(queryStructReq.getModelId());
|
|
||||||
result.setVariables(new HashMap<>());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Aggregator> getAggregatorByMetric(AggregateTypeEnum aggregateType, SchemaElement metric) {
|
private static List<Aggregator> getAggregatorByMetric(AggregateTypeEnum aggregateType, SchemaElement metric) {
|
||||||
List<Aggregator> aggregators = new ArrayList<>();
|
List<Aggregator> aggregators = new ArrayList<>();
|
||||||
if (metric != null) {
|
if (metric != null) {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import net.sf.jsqlparser.JSQLParserException;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.MockedStatic;
|
import org.mockito.MockedStatic;
|
||||||
@@ -26,7 +25,7 @@ import org.mockito.Mockito;
|
|||||||
class QueryReqBuilderTest {
|
class QueryReqBuilderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void buildS2QLReq() throws JSQLParserException {
|
void buildS2QLReq() {
|
||||||
init();
|
init();
|
||||||
QueryStructReq queryStructReq = new QueryStructReq();
|
QueryStructReq queryStructReq = new QueryStructReq();
|
||||||
queryStructReq.setModelId(1L);
|
queryStructReq.setModelId(1L);
|
||||||
@@ -50,13 +49,13 @@ class QueryReqBuilderTest {
|
|||||||
orders.add(order);
|
orders.add(order);
|
||||||
queryStructReq.setOrders(orders);
|
queryStructReq.setOrders(orders);
|
||||||
|
|
||||||
QueryS2QLReq queryS2QLReq = QueryReqBuilder.buildS2QLReq(queryStructReq);
|
QueryS2QLReq queryS2QLReq = queryStructReq.convert(queryStructReq);
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(
|
||||||
"SELECT department, SUM(pv) FROM t_1 WHERE (sys_imp_date IN ('2023-08-01')) "
|
"SELECT department, SUM(pv) FROM t_1 WHERE (sys_imp_date IN ('2023-08-01')) "
|
||||||
+ "GROUP BY department ORDER BY uv LIMIT 2000", queryS2QLReq.getSql());
|
+ "GROUP BY department ORDER BY uv LIMIT 2000", queryS2QLReq.getSql());
|
||||||
|
|
||||||
queryStructReq.setNativeQuery(true);
|
queryStructReq.setNativeQuery(true);
|
||||||
queryS2QLReq = QueryReqBuilder.buildS2QLReq(queryStructReq);
|
queryS2QLReq = queryStructReq.convert(queryStructReq);
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(
|
||||||
"SELECT department, pv FROM t_1 WHERE (sys_imp_date IN ('2023-08-01')) "
|
"SELECT department, pv FROM t_1 WHERE (sys_imp_date IN ('2023-08-01')) "
|
||||||
+ "ORDER BY uv LIMIT 2000",
|
+ "ORDER BY uv LIMIT 2000",
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import com.tencent.supersonic.semantic.query.service.SchemaService;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class LocalSemanticInterpreter extends BaseSemanticInterpreter {
|
public class LocalSemanticInterpreter extends BaseSemanticInterpreter {
|
||||||
@@ -39,6 +40,12 @@ public class LocalSemanticInterpreter extends BaseSemanticInterpreter {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@Override
|
@Override
|
||||||
public QueryResultWithSchemaResp queryByStruct(QueryStructReq queryStructReq, User user) {
|
public QueryResultWithSchemaResp queryByStruct(QueryStructReq queryStructReq, User user) {
|
||||||
|
QueryS2QLReq queryS2QLReq = queryStructReq.convert(queryStructReq);
|
||||||
|
if (queryStructReq.isUseS2qlSwitch() && StringUtils.isNotBlank(queryS2QLReq.getSql())) {
|
||||||
|
log.info("queryStructReq convert to sql:{},queryStructReq:{}", queryS2QLReq.getSql(), queryStructReq);
|
||||||
|
return queryByS2QL(queryS2QLReq, user);
|
||||||
|
}
|
||||||
|
|
||||||
queryService = ContextUtils.getBean(QueryService.class);
|
queryService = ContextUtils.getBean(QueryService.class);
|
||||||
return queryService.queryByStructWithAuth(queryStructReq, user);
|
return queryService.queryByStructWithAuth(queryStructReq, user);
|
||||||
}
|
}
|
||||||
@@ -59,9 +66,7 @@ public class LocalSemanticInterpreter extends BaseSemanticInterpreter {
|
|||||||
public QueryResultWithSchemaResp queryByS2QL(QueryS2QLReq queryS2QLReq, User user) {
|
public QueryResultWithSchemaResp queryByS2QL(QueryS2QLReq queryS2QLReq, User user) {
|
||||||
queryService = ContextUtils.getBean(QueryService.class);
|
queryService = ContextUtils.getBean(QueryService.class);
|
||||||
Object object = queryService.queryBySql(queryS2QLReq, user);
|
Object object = queryService.queryBySql(queryS2QLReq, user);
|
||||||
QueryResultWithSchemaResp queryResultWithSchemaResp = JsonUtil.toObject(JsonUtil.toString(object),
|
return JsonUtil.toObject(JsonUtil.toString(object), QueryResultWithSchemaResp.class);
|
||||||
QueryResultWithSchemaResp.class);
|
|
||||||
return queryResultWithSchemaResp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.util.Strings;
|
import org.apache.logging.log4j.util.Strings;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.core.ParameterizedTypeReference;
|
import org.springframework.core.ParameterizedTypeReference;
|
||||||
@@ -68,6 +69,12 @@ public class RemoteSemanticInterpreter extends BaseSemanticInterpreter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QueryResultWithSchemaResp queryByStruct(QueryStructReq queryStructReq, User user) {
|
public QueryResultWithSchemaResp queryByStruct(QueryStructReq queryStructReq, User user) {
|
||||||
|
QueryS2QLReq queryS2QLReq = queryStructReq.convert(queryStructReq);
|
||||||
|
if (queryStructReq.isUseS2qlSwitch() && StringUtils.isNotBlank(queryS2QLReq.getSql())) {
|
||||||
|
log.info("queryStructReq convert to sql:{},queryStructReq:{}", queryS2QLReq.getSql(), queryStructReq);
|
||||||
|
return queryByS2QL(queryS2QLReq, user);
|
||||||
|
}
|
||||||
|
|
||||||
DefaultSemanticConfig defaultSemanticConfig = ContextUtils.getBean(DefaultSemanticConfig.class);
|
DefaultSemanticConfig defaultSemanticConfig = ContextUtils.getBean(DefaultSemanticConfig.class);
|
||||||
return searchByRestTemplate(
|
return searchByRestTemplate(
|
||||||
defaultSemanticConfig.getSemanticUrl() + defaultSemanticConfig.getSearchByStructPath(),
|
defaultSemanticConfig.getSemanticUrl() + defaultSemanticConfig.getSearchByStructPath(),
|
||||||
|
|||||||
@@ -8,3 +8,4 @@ long.text.threshold=0.8
|
|||||||
short.text.threshold=0.5
|
short.text.threshold=0.5
|
||||||
query.text.length.threshold=10
|
query.text.length.threshold=10
|
||||||
candidate.threshold=0.2
|
candidate.threshold=0.2
|
||||||
|
user.s2ql.switch=false
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
package com.tencent.supersonic.semantic.api.query.request;
|
package com.tencent.supersonic.semantic.api.query.request;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.tencent.supersonic.common.pojo.Constants;
|
||||||
|
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
|
||||||
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
|
import com.tencent.supersonic.common.util.DateModeUtils;
|
||||||
|
import com.tencent.supersonic.common.util.SqlFilterUtils;
|
||||||
|
import com.tencent.supersonic.common.util.jsqlparser.SqlParserAddHelper;
|
||||||
import com.tencent.supersonic.semantic.api.query.pojo.Cache;
|
import com.tencent.supersonic.semantic.api.query.pojo.Cache;
|
||||||
import com.tencent.supersonic.common.pojo.Filter;
|
import com.tencent.supersonic.common.pojo.Filter;
|
||||||
import com.tencent.supersonic.semantic.api.query.pojo.Param;
|
import com.tencent.supersonic.semantic.api.query.pojo.Param;
|
||||||
@@ -9,16 +15,36 @@ import com.tencent.supersonic.common.pojo.DateConf;
|
|||||||
import com.tencent.supersonic.common.pojo.Order;
|
import com.tencent.supersonic.common.pojo.Order;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.sf.jsqlparser.JSQLParserException;
|
||||||
|
import net.sf.jsqlparser.expression.Expression;
|
||||||
|
import net.sf.jsqlparser.expression.Function;
|
||||||
|
import net.sf.jsqlparser.expression.LongValue;
|
||||||
|
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
|
||||||
|
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||||
|
import net.sf.jsqlparser.schema.Column;
|
||||||
|
import net.sf.jsqlparser.schema.Table;
|
||||||
|
import net.sf.jsqlparser.statement.select.GroupByElement;
|
||||||
|
import net.sf.jsqlparser.statement.select.Limit;
|
||||||
|
import net.sf.jsqlparser.statement.select.OrderByElement;
|
||||||
|
import net.sf.jsqlparser.statement.select.PlainSelect;
|
||||||
|
import net.sf.jsqlparser.statement.select.Select;
|
||||||
|
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
|
||||||
|
import net.sf.jsqlparser.statement.select.SelectItem;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.util.Strings;
|
import org.apache.logging.log4j.util.Strings;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
|
@Slf4j
|
||||||
public class QueryStructReq {
|
public class QueryStructReq {
|
||||||
|
|
||||||
private Long modelId;
|
private Long modelId;
|
||||||
@@ -34,6 +60,8 @@ public class QueryStructReq {
|
|||||||
private Boolean nativeQuery = false;
|
private Boolean nativeQuery = false;
|
||||||
private Cache cacheInfo;
|
private Cache cacheInfo;
|
||||||
|
|
||||||
|
private boolean useS2qlSwitch;
|
||||||
|
|
||||||
public List<String> getGroups() {
|
public List<String> getGroups() {
|
||||||
if (!CollectionUtils.isEmpty(this.groups)) {
|
if (!CollectionUtils.isEmpty(this.groups)) {
|
||||||
this.groups = groups.stream().filter(group -> !Strings.isEmpty(group)).collect(Collectors.toList());
|
this.groups = groups.stream().filter(group -> !Strings.isEmpty(group)).collect(Collectors.toList());
|
||||||
@@ -129,4 +157,114 @@ public class QueryStructReq {
|
|||||||
sb.append('}');
|
sb.append('}');
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert queryStructReq to QueryS2QLReq
|
||||||
|
*
|
||||||
|
* @param queryStructReq
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public QueryS2QLReq convert(QueryStructReq queryStructReq) {
|
||||||
|
String sql = null;
|
||||||
|
try {
|
||||||
|
sql = buildSql(queryStructReq);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("buildSql error", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryS2QLReq result = new QueryS2QLReq();
|
||||||
|
result.setSql(sql);
|
||||||
|
result.setModelId(queryStructReq.getModelId());
|
||||||
|
result.setVariables(new HashMap<>());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildSql(QueryStructReq queryStructReq) throws JSQLParserException {
|
||||||
|
Select select = new Select();
|
||||||
|
//1.Set the select items (columns)
|
||||||
|
PlainSelect plainSelect = new PlainSelect();
|
||||||
|
List<SelectItem> selectItems = new ArrayList<>();
|
||||||
|
List<String> groups = queryStructReq.getGroups();
|
||||||
|
if (!CollectionUtils.isEmpty(groups)) {
|
||||||
|
for (String group : groups) {
|
||||||
|
selectItems.add(new SelectExpressionItem(new Column(group)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<Aggregator> aggregators = queryStructReq.getAggregators();
|
||||||
|
if (!CollectionUtils.isEmpty(aggregators)) {
|
||||||
|
for (Aggregator aggregator : aggregators) {
|
||||||
|
if (queryStructReq.getNativeQuery()) {
|
||||||
|
selectItems.add(new SelectExpressionItem(new Column(aggregator.getColumn())));
|
||||||
|
} else {
|
||||||
|
Function sumFunction = new Function();
|
||||||
|
AggOperatorEnum func = aggregator.getFunc();
|
||||||
|
if (AggOperatorEnum.UNKNOWN.equals(func)) {
|
||||||
|
func = AggOperatorEnum.SUM;
|
||||||
|
}
|
||||||
|
sumFunction.setName(func.getOperator());
|
||||||
|
sumFunction.setParameters(new ExpressionList(new Column(aggregator.getColumn())));
|
||||||
|
selectItems.add(new SelectExpressionItem(sumFunction));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plainSelect.setSelectItems(selectItems);
|
||||||
|
//2.Set the table name
|
||||||
|
Table table = new Table(Constants.TABLE_PREFIX + queryStructReq.getModelId());
|
||||||
|
plainSelect.setFromItem(table);
|
||||||
|
|
||||||
|
//3.Set the order by clause
|
||||||
|
List<Order> orders = queryStructReq.getOrders();
|
||||||
|
if (!CollectionUtils.isEmpty(orders)) {
|
||||||
|
List<OrderByElement> orderByElements = new ArrayList<>();
|
||||||
|
for (Order order : orders) {
|
||||||
|
OrderByElement orderByElement = new OrderByElement();
|
||||||
|
orderByElement.setExpression(new Column(order.getColumn()));
|
||||||
|
orderByElement.setAsc(false);
|
||||||
|
if (Constants.ASC_UPPER.equalsIgnoreCase(order.getDirection())) {
|
||||||
|
orderByElement.setAsc(true);
|
||||||
|
}
|
||||||
|
orderByElements.add(orderByElement);
|
||||||
|
}
|
||||||
|
plainSelect.setOrderByElements(orderByElements);
|
||||||
|
}
|
||||||
|
|
||||||
|
//4.Set the group by clause
|
||||||
|
if (!CollectionUtils.isEmpty(groups) && !queryStructReq.getNativeQuery()) {
|
||||||
|
GroupByElement groupByElement = new GroupByElement();
|
||||||
|
for (String group : groups) {
|
||||||
|
groupByElement.addGroupByExpression(new Column(group));
|
||||||
|
}
|
||||||
|
plainSelect.setGroupByElement(groupByElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
//5.Set the limit clause
|
||||||
|
if (Objects.nonNull(queryStructReq.getLimit())) {
|
||||||
|
Limit limit = new Limit();
|
||||||
|
limit.setRowCount(new LongValue(queryStructReq.getLimit()));
|
||||||
|
plainSelect.setLimit(limit);
|
||||||
|
}
|
||||||
|
select.setSelectBody(plainSelect);
|
||||||
|
|
||||||
|
//6.Set where
|
||||||
|
List<Filter> dimensionFilters = queryStructReq.getDimensionFilters();
|
||||||
|
SqlFilterUtils sqlFilterUtils = ContextUtils.getBean(SqlFilterUtils.class);
|
||||||
|
String whereClause = sqlFilterUtils.getWhereClause(dimensionFilters);
|
||||||
|
|
||||||
|
String sql = select.toString();
|
||||||
|
if (StringUtils.isNotBlank(whereClause)) {
|
||||||
|
Expression expression = CCJSqlParserUtil.parseCondExpression(whereClause);
|
||||||
|
sql = SqlParserAddHelper.addWhere(sql, expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
//7.Set DateInfo
|
||||||
|
DateModeUtils dateModeUtils = ContextUtils.getBean(DateModeUtils.class);
|
||||||
|
String dateWhereStr = dateModeUtils.getDateWhereStr(queryStructReq.getDateInfo());
|
||||||
|
if (StringUtils.isNotBlank(dateWhereStr)) {
|
||||||
|
Expression expression = CCJSqlParserUtil.parseCondExpression(dateWhereStr);
|
||||||
|
sql = SqlParserAddHelper.addWhere(sql, expression);
|
||||||
|
}
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user