mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-12 04:27:39 +00:00
[improvement](supersonic) based on version 0.7.2 (#34)
Co-authored-by: zuopengge <hwzuopengge@tencent.com>
This commit is contained in:
@@ -1,26 +1,13 @@
|
||||
package com.tencent.supersonic.semantic.model.application;
|
||||
|
||||
import com.tencent.supersonic.semantic.api.model.pojo.ItemDateFilter;
|
||||
import com.tencent.supersonic.semantic.api.model.response.DatabaseResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.DatasourceResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.ItemDateResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.*;
|
||||
import com.tencent.supersonic.semantic.api.model.yaml.DatasourceYamlTpl;
|
||||
import com.tencent.supersonic.semantic.api.model.yaml.DimensionYamlTpl;
|
||||
import com.tencent.supersonic.semantic.api.model.yaml.MetricYamlTpl;
|
||||
import com.tencent.supersonic.semantic.model.domain.Catalog;
|
||||
import com.tencent.supersonic.semantic.model.domain.DatasourceService;
|
||||
import com.tencent.supersonic.semantic.model.domain.DimensionService;
|
||||
import com.tencent.supersonic.semantic.model.domain.MetricService;
|
||||
import com.tencent.supersonic.semantic.model.domain.ModelService;
|
||||
import com.tencent.supersonic.semantic.model.domain.dataobject.DatabaseDO;
|
||||
import com.tencent.supersonic.semantic.model.domain.repository.DatabaseRepository;
|
||||
import com.tencent.supersonic.semantic.model.domain.utils.DatabaseConverter;
|
||||
import com.tencent.supersonic.semantic.model.domain.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -29,17 +16,17 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
public class CatalogImpl implements Catalog {
|
||||
|
||||
private final DatabaseRepository databaseRepository;
|
||||
private final DatabaseService databaseService;
|
||||
private final ModelService modelService;
|
||||
private final DimensionService dimensionService;
|
||||
private final DatasourceService datasourceService;
|
||||
private final MetricService metricService;
|
||||
|
||||
public CatalogImpl(DatabaseRepository databaseRepository,
|
||||
public CatalogImpl(DatabaseService databaseService,
|
||||
ModelService modelService, DimensionService dimensionService,
|
||||
DatasourceService datasourceService,
|
||||
MetricService metricService) {
|
||||
this.databaseRepository = databaseRepository;
|
||||
this.databaseService = databaseService;
|
||||
this.modelService = modelService;
|
||||
this.dimensionService = dimensionService;
|
||||
this.datasourceService = datasourceService;
|
||||
@@ -47,14 +34,11 @@ public class CatalogImpl implements Catalog {
|
||||
}
|
||||
|
||||
public DatabaseResp getDatabase(Long id) {
|
||||
DatabaseDO databaseDO = databaseRepository.getDatabase(id);
|
||||
return DatabaseConverter.convert(databaseDO);
|
||||
return databaseService.getDatabase(id);
|
||||
}
|
||||
|
||||
public DatabaseResp getDatabaseByModelId(Long modelId) {
|
||||
List<DatabaseDO> databaseDOS = databaseRepository.getDatabaseByDomainId(modelId);
|
||||
Optional<DatabaseDO> databaseDO = databaseDOS.stream().findFirst();
|
||||
return databaseDO.map(DatabaseConverter::convert).orElse(null);
|
||||
return databaseService.getDatabaseByModelId(modelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,27 +1,37 @@
|
||||
package com.tencent.supersonic.semantic.model.application;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||
import com.tencent.supersonic.common.pojo.enums.SensitiveLevelEnum;
|
||||
import com.tencent.supersonic.common.pojo.QueryColumn;
|
||||
import com.tencent.supersonic.common.util.ChatGptHelper;
|
||||
import com.tencent.supersonic.semantic.api.model.pojo.DatasourceDetail;
|
||||
import com.tencent.supersonic.semantic.api.model.pojo.DimValueMap;
|
||||
import com.tencent.supersonic.semantic.api.model.request.DimensionReq;
|
||||
import com.tencent.supersonic.semantic.api.model.request.PageDimensionReq;
|
||||
import com.tencent.supersonic.semantic.api.model.response.DatabaseResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.DatasourceResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
|
||||
import com.tencent.supersonic.common.pojo.enums.SensitiveLevelEnum;
|
||||
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
||||
import com.tencent.supersonic.semantic.model.domain.DatabaseService;
|
||||
import com.tencent.supersonic.semantic.model.domain.dataobject.DimensionDO;
|
||||
import com.tencent.supersonic.semantic.model.domain.repository.DimensionRepository;
|
||||
import com.tencent.supersonic.semantic.model.domain.utils.DimensionConverter;
|
||||
import com.tencent.supersonic.semantic.model.domain.DatasourceService;
|
||||
import com.tencent.supersonic.semantic.model.domain.DimensionService;
|
||||
import com.tencent.supersonic.semantic.model.domain.DomainService;
|
||||
import com.tencent.supersonic.semantic.model.domain.dataobject.DimensionDO;
|
||||
import com.tencent.supersonic.semantic.model.domain.pojo.Dimension;
|
||||
import com.tencent.supersonic.semantic.model.domain.pojo.DimensionFilter;
|
||||
import com.tencent.supersonic.semantic.model.domain.repository.DimensionRepository;
|
||||
import com.tencent.supersonic.semantic.model.domain.utils.DimensionConverter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -39,13 +49,22 @@ public class DimensionServiceImpl implements DimensionService {
|
||||
|
||||
private DomainService domainService;
|
||||
|
||||
private ChatGptHelper chatGptHelper;
|
||||
|
||||
private DatabaseService databaseService;
|
||||
|
||||
|
||||
public DimensionServiceImpl(DimensionRepository dimensionRepository,
|
||||
DomainService domainService,
|
||||
DatasourceService datasourceService) {
|
||||
DatasourceService datasourceService,
|
||||
ChatGptHelper chatGptHelper,
|
||||
DatabaseService databaseService) {
|
||||
this.domainService = domainService;
|
||||
this.dimensionRepository = dimensionRepository;
|
||||
this.datasourceService = datasourceService;
|
||||
this.chatGptHelper = chatGptHelper;
|
||||
this.databaseService = databaseService;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -238,6 +257,53 @@ public class DimensionServiceImpl implements DimensionService {
|
||||
dimensionRepository.deleteDimension(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> mockAlias(DimensionReq dimensionReq, String mockType, User user) {
|
||||
String mockAlias = chatGptHelper.mockAlias(mockType,dimensionReq.getName(), dimensionReq.getBizName(), "", dimensionReq.getDescription() ,false);
|
||||
return JSONObject.parseObject(mockAlias, new TypeReference<List<String>>() {});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DimValueMap> mockDimensionValueAlias(DimensionReq dimensionReq, User user) {
|
||||
|
||||
List<DatasourceResp> datasourceList = datasourceService.getDatasourceList();
|
||||
List<DatasourceResp> collect = datasourceList.stream().filter(datasourceResp -> datasourceResp.getId().equals(dimensionReq.getDatasourceId())).collect(Collectors.toList());
|
||||
|
||||
if (collect.isEmpty()){
|
||||
return null;
|
||||
}
|
||||
DatasourceResp datasourceResp = collect.get(0);
|
||||
DatasourceDetail datasourceDetail = datasourceResp.getDatasourceDetail();
|
||||
String sqlQuery = datasourceDetail.getSqlQuery();
|
||||
|
||||
DatabaseResp database = databaseService.getDatabase(datasourceResp.getDatabaseId());
|
||||
|
||||
String sql = "select ai_talk."+dimensionReq.getBizName()+" from ("+sqlQuery +") as ai_talk group by ai_talk."+dimensionReq.getBizName();
|
||||
QueryResultWithSchemaResp queryResultWithSchemaResp = databaseService.executeSql(sql, database);
|
||||
List<Map<String, Object>> resultList = queryResultWithSchemaResp.getResultList();
|
||||
List<String> valueList = new ArrayList<>();
|
||||
for (Map<String, Object> stringObjectMap : resultList) {
|
||||
String value = (String) stringObjectMap.get(dimensionReq.getBizName());
|
||||
valueList.add(value);
|
||||
}
|
||||
String json = chatGptHelper.mockDimensionValueAlias(JSON.toJSONString(valueList));
|
||||
log.info("return llm res is :{}",json);
|
||||
|
||||
JSONObject jsonObject = JSON.parseObject(json);
|
||||
|
||||
List<DimValueMap> dimValueMapsResp = new ArrayList<>();
|
||||
int i = 0;
|
||||
for (Map<String, Object> stringObjectMap : resultList) {
|
||||
DimValueMap dimValueMap = new DimValueMap();
|
||||
dimValueMap.setTechName((String) stringObjectMap.get(dimensionReq.getBizName()));
|
||||
dimValueMap.setBizName(jsonObject.getJSONArray("tran").getString(i));
|
||||
dimValueMap. setAlias(jsonObject.getJSONObject("alias").getJSONArray((String) stringObjectMap.get(dimensionReq.getBizName())).toJavaList(String.class));
|
||||
dimValueMapsResp.add(dimValueMap);
|
||||
i ++ ;
|
||||
}
|
||||
return dimValueMapsResp;
|
||||
}
|
||||
|
||||
|
||||
private void checkExist(List<DimensionReq> dimensionReqs) {
|
||||
Long modelId = dimensionReqs.get(0).getModelId();
|
||||
|
||||
@@ -16,16 +16,8 @@ import com.tencent.supersonic.semantic.model.domain.dataobject.DomainDO;
|
||||
import com.tencent.supersonic.semantic.model.domain.pojo.Domain;
|
||||
import com.tencent.supersonic.semantic.model.domain.repository.DomainRepository;
|
||||
import com.tencent.supersonic.semantic.model.domain.utils.DomainConvert;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.assertj.core.util.Sets;
|
||||
@@ -101,7 +93,8 @@ public class DomainServiceImpl implements DomainService {
|
||||
List<Long> domainIds = modelResps.stream().map(ModelResp::getDomainId).collect(Collectors.toList());
|
||||
domainWithAuthAll.addAll(getParentDomain(domainIds));
|
||||
}
|
||||
return new ArrayList<>(domainWithAuthAll);
|
||||
return new ArrayList<>(domainWithAuthAll).stream()
|
||||
.sorted(Comparator.comparingLong(DomainResp::getId)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
package com.tencent.supersonic.semantic.model.application;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.plexpt.chatgpt.ChatGPT;
|
||||
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||
import com.tencent.supersonic.common.pojo.enums.SensitiveLevelEnum;
|
||||
import com.tencent.supersonic.common.util.ChatGptHelper;
|
||||
import com.tencent.supersonic.semantic.api.model.pojo.Measure;
|
||||
import com.tencent.supersonic.semantic.api.model.pojo.MetricTypeParams;
|
||||
import com.tencent.supersonic.semantic.api.model.request.MetricReq;
|
||||
import com.tencent.supersonic.semantic.api.model.request.PageMetricReq;
|
||||
import com.tencent.supersonic.semantic.api.model.response.DomainResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
|
||||
import com.tencent.supersonic.common.pojo.enums.SensitiveLevelEnum;
|
||||
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
|
||||
import com.tencent.supersonic.semantic.model.domain.DomainService;
|
||||
import com.tencent.supersonic.semantic.model.domain.MetricService;
|
||||
import com.tencent.supersonic.semantic.model.domain.ModelService;
|
||||
import com.tencent.supersonic.semantic.model.domain.dataobject.MetricDO;
|
||||
import com.tencent.supersonic.semantic.model.domain.pojo.Metric;
|
||||
import com.tencent.supersonic.semantic.model.domain.pojo.MetricFilter;
|
||||
import com.tencent.supersonic.semantic.model.domain.repository.MetricRepository;
|
||||
import com.tencent.supersonic.semantic.model.domain.utils.MetricConverter;
|
||||
import com.tencent.supersonic.semantic.model.domain.MetricService;
|
||||
import com.tencent.supersonic.semantic.model.domain.pojo.Metric;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -42,12 +45,16 @@ public class MetricServiceImpl implements MetricService {
|
||||
|
||||
private DomainService domainService;
|
||||
|
||||
private ChatGptHelper chatGptHelper;
|
||||
|
||||
public MetricServiceImpl(MetricRepository metricRepository,
|
||||
ModelService modelService,
|
||||
DomainService domainService) {
|
||||
ModelService modelService,
|
||||
DomainService domainService,
|
||||
ChatGptHelper chatGptHelper) {
|
||||
this.domainService = domainService;
|
||||
this.metricRepository = metricRepository;
|
||||
this.modelService = modelService;
|
||||
this.chatGptHelper = chatGptHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,7 +81,7 @@ public class MetricServiceImpl implements MetricService {
|
||||
log.info("[insert metric] object:{}", JSONObject.toJSONString(metricToInsert));
|
||||
saveMetricBatch(metricToInsert, user);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<MetricResp> getMetrics(Long modelId) {
|
||||
return convertList(metricRepository.getMetricList(modelId));
|
||||
@@ -201,6 +208,14 @@ public class MetricServiceImpl implements MetricService {
|
||||
metricRepository.deleteMetric(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> mockAlias(MetricReq metricReq,String mockType,User user) {
|
||||
|
||||
String mockAlias = chatGptHelper.mockAlias(mockType,metricReq.getName(), metricReq.getBizName(), "", metricReq.getDescription() ,!"".equals(metricReq.getDataFormatType()));
|
||||
return JSONObject.parseObject(mockAlias, new TypeReference<List<String>>() {});
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void saveMetricBatch(List<Metric> metrics, User user) {
|
||||
if (CollectionUtils.isEmpty(metrics)) {
|
||||
|
||||
@@ -2,7 +2,9 @@ package com.tencent.supersonic.semantic.model.domain;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||
import com.tencent.supersonic.semantic.api.model.pojo.DimValueMap;
|
||||
import com.tencent.supersonic.semantic.api.model.request.DimensionReq;
|
||||
import com.tencent.supersonic.semantic.api.model.request.MetricReq;
|
||||
import com.tencent.supersonic.semantic.api.model.request.PageDimensionReq;
|
||||
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
|
||||
import java.util.List;
|
||||
@@ -32,4 +34,8 @@ public interface DimensionService {
|
||||
List<DimensionResp> getAllHighSensitiveDimension();
|
||||
|
||||
void deleteDimension(Long id) throws Exception;
|
||||
|
||||
List<String> mockAlias(DimensionReq dimensionReq, String mockType, User user);
|
||||
|
||||
List<DimValueMap> mockDimensionValueAlias(DimensionReq dimensionReq, User user);
|
||||
}
|
||||
|
||||
@@ -32,4 +32,6 @@ public interface MetricService {
|
||||
List<MetricResp> getAllHighSensitiveMetric();
|
||||
|
||||
void deleteMetric(Long id) throws Exception;
|
||||
|
||||
List<String> mockAlias(MetricReq metricReq,String mockType,User user);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ public class DimensionConverter {
|
||||
dimensionDO.setDefaultValues(JSONObject.toJSONString(dimension.getDefaultValues()));
|
||||
if (!CollectionUtils.isEmpty(dimension.getDimValueMaps())) {
|
||||
dimensionDO.setDimValueMaps(JSONObject.toJSONString(dimension.getDimValueMaps()));
|
||||
} else {
|
||||
dimensionDO.setDimValueMaps(JSONObject.toJSONString(new ArrayList<>()));
|
||||
}
|
||||
return dimensionDO;
|
||||
}
|
||||
|
||||
@@ -3,13 +3,17 @@ package com.tencent.supersonic.semantic.model.rest;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
|
||||
import com.tencent.supersonic.semantic.api.model.pojo.DimValueMap;
|
||||
import com.tencent.supersonic.semantic.api.model.request.DimensionReq;
|
||||
import com.tencent.supersonic.semantic.api.model.request.MetricReq;
|
||||
import com.tencent.supersonic.semantic.api.model.request.PageDimensionReq;
|
||||
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
|
||||
import com.tencent.supersonic.semantic.model.domain.DimensionService;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.tencent.supersonic.semantic.model.domain.MetricService;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
@@ -27,7 +31,10 @@ public class DimensionController {
|
||||
private DimensionService dimensionService;
|
||||
|
||||
|
||||
public DimensionController(DimensionService dimensionService) {
|
||||
private MetricService metricService;
|
||||
|
||||
public DimensionController(DimensionService dimensionService,MetricService metricService) {
|
||||
this.metricService = metricService;
|
||||
this.dimensionService = dimensionService;
|
||||
}
|
||||
|
||||
@@ -56,6 +63,22 @@ public class DimensionController {
|
||||
return true;
|
||||
}
|
||||
|
||||
@PostMapping("/mockDimensionAlias")
|
||||
public List<String> mockMetricAlias(@RequestBody DimensionReq dimensionReq,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response){
|
||||
User user = UserHolder.findUser(request, response);
|
||||
return dimensionService.mockAlias(dimensionReq,"dimension",user);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/mockDimensionValuesAlias")
|
||||
public List<DimValueMap> mockDimensionValuesAlias(@RequestBody DimensionReq dimensionReq,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response){
|
||||
User user = UserHolder.findUser(request, response);
|
||||
return dimensionService.mockDimensionValueAlias(dimensionReq,user);
|
||||
}
|
||||
|
||||
@GetMapping("/getDimensionList/{modelId}")
|
||||
public List<DimensionResp> getDimension(@PathVariable("modelId") Long modelId) {
|
||||
|
||||
@@ -11,13 +11,9 @@ import com.tencent.supersonic.semantic.model.domain.MetricService;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
@RestController
|
||||
@@ -52,6 +48,14 @@ public class MetricController {
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/mockMetricAlias")
|
||||
public List<String> mockMetricAlias(@RequestBody MetricReq metricReq,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response){
|
||||
User user = UserHolder.findUser(request, response);
|
||||
return metricService.mockAlias(metricReq,"indicator",user);
|
||||
}
|
||||
|
||||
@GetMapping("/getMetricList/{modelId}")
|
||||
public List<MetricResp> getMetricList(@PathVariable("modelId") Long modelId) {
|
||||
return metricService.getMetrics(modelId);
|
||||
|
||||
@@ -416,7 +416,7 @@ public class CalculateAggConverter implements SemanticConverter {
|
||||
}
|
||||
|
||||
private static String getLimit(QueryStructReq queryStructCmd) {
|
||||
if (queryStructCmd.getLimit() > 0) {
|
||||
if (queryStructCmd != null && queryStructCmd.getLimit() > 0) {
|
||||
return " limit " + String.valueOf(queryStructCmd.getLimit());
|
||||
}
|
||||
return "";
|
||||
|
||||
@@ -23,8 +23,7 @@ import org.springframework.util.CollectionUtils;
|
||||
@Slf4j
|
||||
public class ParserDefaultConverter implements SemanticConverter {
|
||||
|
||||
@Value("${internal.metric.cnt.suffix:internal_cnt}")
|
||||
private String internalMetricNameSuffix;
|
||||
|
||||
|
||||
private final CalculateAggConverter calculateCoverterAgg;
|
||||
private final QueryStructUtils queryStructUtils;
|
||||
@@ -69,7 +68,7 @@ public class ParserDefaultConverter implements SemanticConverter {
|
||||
// todo tmp delete
|
||||
// support detail query
|
||||
if (queryStructCmd.getNativeQuery() && CollectionUtils.isEmpty(sqlCommend.getMetrics())) {
|
||||
String internalMetricName = generateInternalMetricName(catalog, queryStructCmd);
|
||||
String internalMetricName = queryStructUtils.generateInternalMetricName(queryStructCmd.getModelId(), queryStructCmd.getGroups());
|
||||
sqlCommend.getMetrics().add(internalMetricName);
|
||||
}
|
||||
|
||||
@@ -77,21 +76,5 @@ public class ParserDefaultConverter implements SemanticConverter {
|
||||
}
|
||||
|
||||
|
||||
public String generateInternalMetricName(Catalog catalog, QueryStructReq queryStructCmd) {
|
||||
String internalMetricNamePrefix = "";
|
||||
if (CollectionUtils.isEmpty(queryStructCmd.getGroups())) {
|
||||
log.warn("group is empty!");
|
||||
} else {
|
||||
String group = queryStructCmd.getGroups().get(0).equalsIgnoreCase("sys_imp_date")
|
||||
? queryStructCmd.getGroups().get(1) : queryStructCmd.getGroups().get(0);
|
||||
DimensionResp dimension = catalog.getDimension(group, queryStructCmd.getModelId());
|
||||
String datasourceBizName = dimension.getDatasourceBizName();
|
||||
if (Strings.isNotEmpty(datasourceBizName)) {
|
||||
internalMetricNamePrefix = datasourceBizName + UNDERLINE;
|
||||
}
|
||||
|
||||
}
|
||||
String internalMetricName = internalMetricNamePrefix + internalMetricNameSuffix;
|
||||
return internalMetricName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class QueryController {
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response) throws Exception {
|
||||
User user = UserHolder.findUser(request, response);
|
||||
return queryService.queryByStruct(queryStructReq, user, request);
|
||||
return queryService.queryByStructWithAuth(queryStructReq, user);
|
||||
}
|
||||
|
||||
@PostMapping("/struct/parse")
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.tencent.supersonic.semantic.query.service;
|
||||
|
||||
import com.tencent.supersonic.auth.api.authentication.pojo.User;
|
||||
import com.tencent.supersonic.semantic.api.model.pojo.QueryStat;
|
||||
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
||||
import com.tencent.supersonic.semantic.api.query.request.ItemUseReq;
|
||||
import com.tencent.supersonic.semantic.api.query.request.QueryDslReq;
|
||||
@@ -9,22 +8,18 @@ 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.response.ItemUseResp;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
public interface QueryService {
|
||||
|
||||
|
||||
Object queryBySql(QueryDslReq querySqlCmd, User user) throws Exception;
|
||||
|
||||
QueryResultWithSchemaResp queryByStruct(QueryStructReq queryStructCmd, User user) throws Exception;
|
||||
|
||||
QueryResultWithSchemaResp queryByStruct(QueryStructReq queryStructCmd, User user, HttpServletRequest request)
|
||||
QueryResultWithSchemaResp queryByStructWithAuth(QueryStructReq queryStructCmd, User user)
|
||||
throws Exception;
|
||||
|
||||
QueryResultWithSchemaResp queryByMultiStruct(QueryMultiStructReq queryMultiStructCmd, User user) throws Exception;
|
||||
|
||||
List<ItemUseResp> getStatInfo(ItemUseReq itemUseCommend);
|
||||
|
||||
List<QueryStat> getQueryStatInfoWithoutCache(ItemUseReq itemUseCommend);
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import com.tencent.supersonic.semantic.query.utils.StatUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -110,8 +110,8 @@ public class QueryServiceImpl implements QueryService {
|
||||
|
||||
@Override
|
||||
@DataPermission
|
||||
public QueryResultWithSchemaResp queryByStruct(QueryStructReq queryStructCmd, User user, HttpServletRequest request)
|
||||
throws Exception {
|
||||
@SneakyThrows
|
||||
public QueryResultWithSchemaResp queryByStructWithAuth(QueryStructReq queryStructCmd, User user) {
|
||||
return queryByStruct(queryStructCmd, user);
|
||||
}
|
||||
|
||||
@@ -171,12 +171,6 @@ public class QueryServiceImpl implements QueryService {
|
||||
return statInfos;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<QueryStat> getQueryStatInfoWithoutCache(ItemUseReq itemUseCommend) {
|
||||
return statUtils.getQueryStatInfoWithoutCache(itemUseCommend);
|
||||
}
|
||||
|
||||
private boolean isCache(QueryStructReq queryStructCmd) {
|
||||
if (!cacheEnable) {
|
||||
return false;
|
||||
|
||||
@@ -90,11 +90,15 @@ public class DataPermissionAOP {
|
||||
if (Objects.isNull(user) || Strings.isNullOrEmpty(user.getName())) {
|
||||
throw new RuntimeException("lease provide user information");
|
||||
}
|
||||
//1. determine whether admin of the model
|
||||
if (doModelAdmin(user, queryStructReq)) {
|
||||
return point.proceed();
|
||||
}
|
||||
|
||||
// 1. determine whether the subject field is visible
|
||||
doDomainVisible(user, queryStructReq);
|
||||
// 2. determine whether the subject field is visible
|
||||
doModelVisible(user, queryStructReq);
|
||||
|
||||
// 2. fetch data permission meta information
|
||||
// 3. fetch data permission meta information
|
||||
Long modelId = queryStructReq.getModelId();
|
||||
Set<String> res4Privilege = queryStructUtils.getResNameEnExceptInternalCol(queryStructReq);
|
||||
log.info("modelId:{}, res4Privilege:{}", modelId, res4Privilege);
|
||||
@@ -105,18 +109,17 @@ public class DataPermissionAOP {
|
||||
log.info("this query domainId:{}, sensitiveResReq:{}", modelId, sensitiveResReq);
|
||||
|
||||
// query user privilege info
|
||||
HttpServletRequest request = (HttpServletRequest) args[2];
|
||||
AuthorizedResourceResp authorizedResource = getAuthorizedResource(user, request, modelId, sensitiveResReq);
|
||||
AuthorizedResourceResp authorizedResource = getAuthorizedResource(user, modelId, sensitiveResReq);
|
||||
// get sensitiveRes that user has privilege
|
||||
Set<String> resAuthSet = getAuthResNameSet(authorizedResource, queryStructReq.getModelId());
|
||||
|
||||
// 3.if sensitive fields without permission are involved in filter, thrown an exception
|
||||
// 4.if sensitive fields without permission are involved in filter, thrown an exception
|
||||
doFilterCheckLogic(queryStructReq, resAuthSet, sensitiveResReq);
|
||||
|
||||
// 4.row permission pre-filter
|
||||
// 5.row permission pre-filter
|
||||
doRowPermission(queryStructReq, authorizedResource);
|
||||
|
||||
// 5.proceed
|
||||
// 6.proceed
|
||||
QueryResultWithSchemaResp queryResultWithColumns = (QueryResultWithSchemaResp) point.proceed();
|
||||
|
||||
if (CollectionUtils.isEmpty(sensitiveResReq) || allSensitiveResReqIsOk(sensitiveResReq, resAuthSet)) {
|
||||
@@ -136,7 +139,19 @@ public class DataPermissionAOP {
|
||||
|
||||
}
|
||||
|
||||
private void doDomainVisible(User user, QueryStructReq queryStructCmd) {
|
||||
private boolean doModelAdmin(User user, QueryStructReq queryStructCmd) {
|
||||
Long modelId = queryStructCmd.getModelId();
|
||||
List<ModelResp> modelListAdmin = modelService.getModelListWithAuth(user.getName(), null, AuthType.ADMIN);
|
||||
if (CollectionUtils.isEmpty(modelListAdmin)) {
|
||||
return false;
|
||||
} else {
|
||||
Map<Long, List<ModelResp>> id2modelResp = modelListAdmin.stream()
|
||||
.collect(Collectors.groupingBy(SchemaItem::getId));
|
||||
return !CollectionUtils.isEmpty(id2modelResp) && id2modelResp.containsKey(modelId);
|
||||
}
|
||||
}
|
||||
|
||||
private void doModelVisible(User user, QueryStructReq queryStructCmd) {
|
||||
Boolean visible = true;
|
||||
Long domainId = queryStructCmd.getModelId();
|
||||
List<ModelResp> modelListVisible = modelService.getModelListWithAuth(user.getName(), null, AuthType.VISIBLE);
|
||||
@@ -251,15 +266,14 @@ public class DataPermissionAOP {
|
||||
return resAuthName;
|
||||
}
|
||||
|
||||
private AuthorizedResourceResp getAuthorizedResource(User user, HttpServletRequest request, Long domainId,
|
||||
private AuthorizedResourceResp getAuthorizedResource(User user, Long domainId,
|
||||
Set<String> sensitiveResReq) {
|
||||
List<AuthRes> resourceReqList = new ArrayList<>();
|
||||
sensitiveResReq.stream().forEach(res -> resourceReqList.add(new AuthRes(domainId.toString(), res)));
|
||||
sensitiveResReq.forEach(res -> resourceReqList.add(new AuthRes(domainId.toString(), res)));
|
||||
QueryAuthResReq queryAuthResReq = new QueryAuthResReq();
|
||||
queryAuthResReq.setUser(user.getName());
|
||||
queryAuthResReq.setResources(resourceReqList);
|
||||
queryAuthResReq.setModelId(domainId + "");
|
||||
AuthorizedResourceResp authorizedResource = fetchAuthRes(request, queryAuthResReq);
|
||||
AuthorizedResourceResp authorizedResource = fetchAuthRes(queryAuthResReq, user);
|
||||
log.info("user:{}, domainId:{}, after queryAuthorizedResources:{}", user.getName(), domainId,
|
||||
authorizedResource);
|
||||
return authorizedResource;
|
||||
@@ -396,10 +410,9 @@ public class DataPermissionAOP {
|
||||
}
|
||||
|
||||
|
||||
private AuthorizedResourceResp fetchAuthRes(HttpServletRequest request, QueryAuthResReq queryAuthResReq) {
|
||||
log.info("Authorization:{}", request.getHeader("Authorization"));
|
||||
private AuthorizedResourceResp fetchAuthRes(QueryAuthResReq queryAuthResReq, User user) {
|
||||
log.info("queryAuthResReq:{}", queryAuthResReq);
|
||||
return authService.queryAuthorizedResources(queryAuthResReq, request);
|
||||
return authService.queryAuthorizedResources(queryAuthResReq, user);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,7 +35,8 @@ public class DimValueAspect {
|
||||
private DimensionService dimensionService;
|
||||
|
||||
@Around("execution(* com.tencent.supersonic.semantic.query.rest.QueryController.queryByStruct(..))" +
|
||||
" || execution(* com.tencent.supersonic.semantic.query.service.QueryService.queryByStruct(..))")
|
||||
" || execution(* com.tencent.supersonic.semantic.query.service.QueryService.queryByStruct(..))" +
|
||||
" || execution(* com.tencent.supersonic.semantic.query.service.QueryService.queryByStructWithAuth(..))")
|
||||
public Object handleDimValue(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
|
||||
if (!dimensionValueMapEnable) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.tencent.supersonic.semantic.model.domain.ModelService;
|
||||
import com.tencent.supersonic.semantic.query.persistence.pojo.QueryStatement;
|
||||
import com.tencent.supersonic.semantic.query.service.SemanticQueryEngine;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -28,6 +29,9 @@ public class QueryReqConverter {
|
||||
@Autowired
|
||||
private SemanticQueryEngine parserService;
|
||||
|
||||
@Autowired
|
||||
private QueryStructUtils queryStructUtils;
|
||||
|
||||
public QueryStatement convert(QueryDslReq databaseReq, List<ModelSchemaResp> domainSchemas) throws Exception {
|
||||
|
||||
List<MetricTable> tables = new ArrayList<>();
|
||||
@@ -60,6 +64,12 @@ public class QueryReqConverter {
|
||||
}
|
||||
metricTable.setDimensions(new ArrayList<>(collect));
|
||||
metricTable.setAlias(tableName.toLowerCase());
|
||||
// if metric empty , fill model default
|
||||
if (CollectionUtils.isEmpty(metricTable.getMetrics())) {
|
||||
metricTable.setMetrics(new ArrayList<>(Arrays.asList(
|
||||
queryStructUtils.generateInternalMetricName(databaseReq.getModelId(),
|
||||
metricTable.getDimensions()))));
|
||||
}
|
||||
tables.add(metricTable);
|
||||
|
||||
ParseSqlReq result = new ParseSqlReq();
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
package com.tencent.supersonic.semantic.query.utils;
|
||||
|
||||
import com.tencent.supersonic.common.pojo.Aggregator;
|
||||
import com.tencent.supersonic.common.pojo.DateConf;
|
||||
import static com.tencent.supersonic.common.pojo.Constants.UNDERLINE;
|
||||
|
||||
import com.tencent.supersonic.common.pojo.DateConf.DateMode;
|
||||
import com.tencent.supersonic.common.pojo.enums.TypeEnums;
|
||||
import com.tencent.supersonic.semantic.api.model.pojo.ItemDateFilter;
|
||||
import com.tencent.supersonic.common.pojo.Aggregator;
|
||||
import com.tencent.supersonic.common.pojo.DateConf;
|
||||
import com.tencent.supersonic.semantic.api.model.pojo.SchemaItem;
|
||||
import com.tencent.supersonic.semantic.api.model.pojo.ItemDateFilter;
|
||||
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.ItemDateResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
|
||||
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
|
||||
import com.tencent.supersonic.semantic.model.domain.Catalog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
@@ -19,9 +22,12 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@@ -32,6 +38,8 @@ public class QueryStructUtils {
|
||||
private final SqlFilterUtils sqlFilterUtils;
|
||||
private final Catalog catalog;
|
||||
|
||||
@Value("${internal.metric.cnt.suffix:internal_cnt}")
|
||||
private String internalMetricNameSuffix;
|
||||
|
||||
public static Set<String> internalCols = new HashSet<>(
|
||||
Arrays.asList("dayno", "plat_sys_var", "sys_imp_date", "sys_imp_week", "sys_imp_month"));
|
||||
@@ -157,5 +165,23 @@ public class QueryStructUtils {
|
||||
return resNameEnSet.stream().filter(res -> !internalCols.contains(res)).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public String generateInternalMetricName(Long modelId, List<String> groups) {
|
||||
String internalMetricNamePrefix = "";
|
||||
if (CollectionUtils.isEmpty(groups)) {
|
||||
log.warn("group is empty!");
|
||||
} else {
|
||||
String group = groups.get(0).equalsIgnoreCase("sys_imp_date")
|
||||
? groups.get(1) : groups.get(0);
|
||||
DimensionResp dimension = catalog.getDimension(group, modelId);
|
||||
String datasourceBizName = dimension.getDatasourceBizName();
|
||||
if (Strings.isNotEmpty(datasourceBizName)) {
|
||||
internalMetricNamePrefix = datasourceBizName + UNDERLINE;
|
||||
}
|
||||
|
||||
}
|
||||
String internalMetricName = internalMetricNamePrefix + internalMetricNameSuffix;
|
||||
return internalMetricName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,11 @@ package com.tencent.supersonic.semantic.query.utils;
|
||||
import static com.tencent.supersonic.common.pojo.Constants.JOIN_UNDERLINE;
|
||||
import static com.tencent.supersonic.common.pojo.Constants.UNIONALL;
|
||||
|
||||
import com.tencent.supersonic.common.pojo.Aggregator;
|
||||
import com.tencent.supersonic.common.pojo.Constants;
|
||||
import com.tencent.supersonic.common.pojo.QueryColumn;
|
||||
import com.tencent.supersonic.common.pojo.Aggregator;
|
||||
import com.tencent.supersonic.common.util.cache.CacheUtils;
|
||||
import com.tencent.supersonic.semantic.api.model.enums.TimeDimensionEnum;
|
||||
import com.tencent.supersonic.common.pojo.QueryColumn;
|
||||
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
|
||||
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
|
||||
@@ -67,8 +67,8 @@ public class QueryUtils {
|
||||
public void fillItemNameInfo(QueryResultWithSchemaResp queryResultWithColumns, Long modelId) {
|
||||
List<MetricResp> metricDescList = catalog.getMetrics(modelId);
|
||||
List<DimensionResp> dimensionDescList = catalog.getDimensions(modelId);
|
||||
Map<String, MetricResp> metricRespMap =
|
||||
metricDescList.stream().collect(Collectors.toMap(MetricResp::getBizName, a -> a, (k1, k2) -> k1));
|
||||
Map<String,MetricResp> metricRespMap =
|
||||
metricDescList.stream().collect(Collectors.toMap(MetricResp::getBizName, a -> a,(k1, k2)->k1));
|
||||
Map<String, String> namePair = new HashMap<>();
|
||||
Map<String, String> nameTypePair = new HashMap<>();
|
||||
addSysTimeDimension(namePair, nameTypePair);
|
||||
@@ -92,13 +92,27 @@ public class QueryUtils {
|
||||
if (nameTypePair.containsKey(nameEn)) {
|
||||
column.setShowType(nameTypePair.get(nameEn));
|
||||
}
|
||||
if (metricRespMap.containsKey(nameEn)) {
|
||||
if (!nameTypePair.containsKey(nameEn) && isNumberType(column.getType())) {
|
||||
column.setShowType("NUMBER");
|
||||
}
|
||||
if(metricRespMap.containsKey(nameEn)){
|
||||
column.setDataFormatType(metricRespMap.get(nameEn).getDataFormatType());
|
||||
column.setDataFormat(metricRespMap.get(nameEn).getDataFormat());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isNumberType(String type) {
|
||||
if (StringUtils.isBlank(type)) {
|
||||
return false;
|
||||
}
|
||||
if (type.equalsIgnoreCase("int") || type.equalsIgnoreCase("bigint")
|
||||
|| type.equalsIgnoreCase("float") || type.equalsIgnoreCase("double")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void fillItemNameInfo(QueryResultWithSchemaResp queryResultWithColumns,
|
||||
QueryMultiStructReq queryMultiStructCmd) {
|
||||
List<Aggregator> aggregators = queryMultiStructCmd.getQueryStructReqs().stream()
|
||||
|
||||
Reference in New Issue
Block a user