(improvement) Move out the datasource and merge the datasource with the model, and adapt the chat module (#423)

Co-authored-by: jolunoluo <jolunoluo@tencent.com>
This commit is contained in:
jipeli
2023-11-27 11:05:24 +08:00
committed by GitHub
parent 0534053ff9
commit 27bb1b322e
190 changed files with 3900 additions and 10561 deletions

View File

@@ -1,11 +1,13 @@
package com.tencent.supersonic.semantic.api.model.pojo;
import java.util.List;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
@Data
public class DatasourceDetail {
public class ModelDetail {
private String queryType;
@@ -19,5 +21,11 @@ public class DatasourceDetail {
private List<Measure> measures;
public String getSqlQuery() {
if (StringUtils.isNotBlank(sqlQuery) && sqlQuery.endsWith(";")) {
sqlQuery = sqlQuery.substring(0, sqlQuery.length() - 1);
}
return sqlQuery;
}
}

View File

@@ -1,23 +0,0 @@
package com.tencent.supersonic.semantic.api.model.request;
import javax.validation.constraints.NotNull;
import lombok.Data;
@Data
public class DatasourceRelaReq {
private Long id;
@NotNull(message = "model id cat not be null")
private Long modelId;
@NotNull(message = "datasource id cat not be null")
private Long datasourceFrom;
@NotNull(message = "datasource id cat not be null")
private Long datasourceTo;
@NotNull(message = "join key cat not be null")
private String joinKey;
}

View File

@@ -1,56 +0,0 @@
package com.tencent.supersonic.semantic.api.model.request;
import com.google.common.collect.Lists;
import com.tencent.supersonic.semantic.api.model.enums.DimensionTypeEnum;
import com.tencent.supersonic.semantic.api.model.pojo.Dim;
import com.tencent.supersonic.semantic.api.model.pojo.Identify;
import com.tencent.supersonic.semantic.api.model.pojo.Measure;
import com.tencent.supersonic.semantic.api.model.pojo.SchemaItem;
import java.util.List;
import java.util.stream.Collectors;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
@Data
public class DatasourceReq extends SchemaItem {
private Long databaseId;
private String queryType;
private String sqlQuery;
private String tableQuery;
private Long modelId;
private List<Identify> identifiers;
private List<Dim> dimensions;
private List<Measure> measures;
private String filterSql;
public List<Dim> getTimeDimension() {
if (CollectionUtils.isEmpty(dimensions)) {
return Lists.newArrayList();
}
return dimensions.stream()
.filter(dim -> DimensionTypeEnum.time.name().equalsIgnoreCase(dim.getType()))
.collect(Collectors.toList());
}
public String getSqlQuery() {
if (StringUtils.isNotBlank(sqlQuery) && sqlQuery.endsWith(";")) {
sqlQuery = sqlQuery.substring(0, sqlQuery.length() - 1);
}
return sqlQuery;
}
}

View File

@@ -18,9 +18,6 @@ public class DimensionReq extends SchemaItem {
@NotNull(message = "expr can not be null")
private String expr;
private Long datasourceId;
//DATE ID CATEGORY
private String semanticType = "CATEGORY";

View File

@@ -1,14 +1,12 @@
package com.tencent.supersonic.semantic.api.model.request;
import com.tencent.supersonic.semantic.api.model.pojo.SchemaItem;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
@Data
public class DomainReq extends SchemaItem {
@@ -24,4 +22,22 @@ public class DomainReq extends SchemaItem {
private List<String> admins = new ArrayList<>();
private List<String> adminOrgs = new ArrayList<>();
public String getViewer() {
return String.join(",", viewers);
}
public String getViewOrg() {
return String.join(",", viewOrgs);
}
public String getAdmin() {
return String.join(",", admins);
}
public String getAdminOrg() {
return String.join(",", adminOrgs);
}
}

View File

@@ -1,24 +1,37 @@
package com.tencent.supersonic.semantic.api.model.request;
import com.google.common.collect.Lists;
import com.tencent.supersonic.semantic.api.model.enums.DimensionTypeEnum;
import com.tencent.supersonic.semantic.api.model.pojo.Dim;
import com.tencent.supersonic.semantic.api.model.pojo.DrillDownDimension;
import com.tencent.supersonic.semantic.api.model.pojo.Entity;
import com.tencent.supersonic.semantic.api.model.pojo.ModelDetail;
import com.tencent.supersonic.semantic.api.model.pojo.SchemaItem;
import lombok.Data;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Data
public class ModelReq extends SchemaItem {
private Long domainId = 0L;
private Long databaseId;
private Integer isOpen = 0;
private Long domainId;
private String filterSql;
private Integer isOpen;
private List<DrillDownDimension> drillDownDimensions;
private String alias;
private ModelDetail modelDetail;
private List<String> viewers = new ArrayList<>();
private List<String> viewOrgs = new ArrayList<>();
@@ -27,9 +40,16 @@ public class ModelReq extends SchemaItem {
private List<String> adminOrgs = new ArrayList<>();
private Entity entity;
private List<DrillDownDimension> drillDownDimensions;
public List<Dim> getTimeDimension() {
if (CollectionUtils.isEmpty(modelDetail.getDimensions())) {
return Lists.newArrayList();
}
return modelDetail.getDimensions().stream()
.filter(dim -> DimensionTypeEnum.time.name().equalsIgnoreCase(dim.getType()))
.collect(Collectors.toList());
}
public String getViewer() {
return String.join(",", viewers);
@@ -48,4 +68,5 @@ public class ModelReq extends SchemaItem {
return String.join(",", adminOrgs);
}
}

View File

@@ -1,27 +0,0 @@
package com.tencent.supersonic.semantic.api.model.response;
import java.util.Date;
import lombok.Data;
@Data
public class DatasourceRelaResp {
private Long id;
private Long domainId;
private Long datasourceFrom;
private Long datasourceTo;
private String joinKey;
private Date createdAt;
private String createdBy;
private Date updatedAt;
private String updatedBy;
}

View File

@@ -1,20 +0,0 @@
package com.tencent.supersonic.semantic.api.model.response;
import com.tencent.supersonic.semantic.api.model.pojo.DatasourceDetail;
import com.tencent.supersonic.semantic.api.model.pojo.SchemaItem;
import lombok.Data;
@Data
public class DatasourceResp extends SchemaItem {
private Long modelId;
private Long databaseId;
private DatasourceDetail datasourceDetail;
private String depends;
private String filterSql;
}

View File

@@ -3,10 +3,14 @@ package com.tencent.supersonic.semantic.api.model.response;
import lombok.Data;
import lombok.ToString;
import java.util.List;
@Data
@ToString(callSuper = true)
public class DimSchemaResp extends DimensionResp {
private Long useCnt = 0L;
private List<String> entityAlias;
}

View File

@@ -22,13 +22,11 @@ public class DimensionResp extends SchemaItem {
private String fullPath;
private Long datasourceId;
private String modelName;
private String datasourceName;
private String modelBizName;
private String datasourceBizName;
private String datasourceFilterSql;
private String modelFilterSql;
//DATE ID CATEGORY
private String semanticType;

View File

@@ -46,8 +46,6 @@ public class MetricResp extends SchemaItem {
private boolean hasAdminRes = false;
private String defaultAgg;
public void setTag(String tag) {
if (StringUtils.isBlank(tag)) {
tags = Lists.newArrayList();
@@ -80,4 +78,8 @@ public class MetricResp extends SchemaItem {
}
return typeParams.getMeasures();
}
public String getDefaultAgg() {
return typeParams.getMeasures().get(0).getAgg();
}
}

View File

@@ -1,43 +1,66 @@
package com.tencent.supersonic.semantic.api.model.response;
import com.tencent.supersonic.semantic.api.model.pojo.Identify;
import com.tencent.supersonic.semantic.api.model.pojo.ModelDetail;
import com.tencent.supersonic.semantic.api.model.pojo.DrillDownDimension;
import com.tencent.supersonic.semantic.api.model.pojo.Entity;
import com.tencent.supersonic.semantic.api.model.pojo.SchemaItem;
import lombok.Data;
import lombok.ToString;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
@Data
@ToString
public class ModelResp extends SchemaItem {
private Long domainId;
private Long databaseId;
private ModelDetail modelDetail;
private String depends;
private String filterSql;
private List<String> viewers = new ArrayList<>();
private List<String> viewOrgs = new ArrayList<>();
private List<String> admins = new ArrayList<>();
private List<String> adminOrgs = new ArrayList<>();
private Integer isOpen;
private List<DrillDownDimension> drillDownDimensions;
private String alias;
private List<String> viewers;
private List<String> viewOrgs;
private List<String> admins;
private List<String> adminOrgs;
private Integer isOpen = 0;
private String fullPath;
private Integer dimensionCnt;
private Integer metricCnt;
private Entity entity;
private String fullPath;
private List<DrillDownDimension> drillDownDimensions;
public boolean openToAll() {
return isOpen != null && isOpen == 1;
}
public Identify getPrimaryIdentify() {
if (modelDetail == null) {
return null;
}
if (CollectionUtils.isEmpty(modelDetail.getIdentifiers())) {
return null;
}
for (Identify identify : modelDetail.getIdentifiers()) {
if (!CollectionUtils.isEmpty(identify.getEntityNames())) {
return identify;
}
}
return null;
}
}

View File

@@ -1,14 +1,15 @@
package com.tencent.supersonic.semantic.api.model.response;
import java.util.List;
import lombok.Data;
import java.util.List;
@Data
public class ModelSchemaRelaResp {
private Long domainId;
private DatasourceResp datasource;
private ModelResp model;
private List<MetricResp> metrics;

View File

@@ -1,11 +1,13 @@
package com.tencent.supersonic.semantic.api.model.response;
import java.util.List;
import com.tencent.supersonic.common.pojo.ModelRela;
import com.tencent.supersonic.semantic.api.model.pojo.Identify;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@@ -13,5 +15,20 @@ public class ModelSchemaResp extends ModelResp {
private List<MetricSchemaResp> metrics;
private List<DimSchemaResp> dimensions;
private List<ModelRela> modelRelas;
public DimSchemaResp getPrimaryKey() {
Identify identify = getPrimaryIdentify();
if (identify == null) {
return null;
}
for (DimSchemaResp dimension : dimensions) {
if (identify.getBizName().equals(dimension.getBizName())) {
dimension.setEntityAlias(identify.getEntityNames());
return dimension;
}
}
return null;
}
}

View File

@@ -5,7 +5,7 @@ import lombok.Data;
@Data
public class DatasourceYamlTpl {
public class DataModelYamlTpl {
private String name;

View File

@@ -1,17 +1,30 @@
package com.tencent.supersonic.semantic.api.query.request;
import java.util.Map;
import com.google.common.collect.Lists;
import lombok.Data;
import lombok.ToString;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Data
@ToString
public class QueryS2SQLReq {
private Long modelId;
private Set<Long> modelIds;
private String sql;
private Map<String, String> variables;
public void setModelId(Long modelId) {
modelIds = new HashSet<>();
modelIds.add(modelId);
}
public List<Long> getModelIds() {
return Lists.newArrayList(modelIds);
}
}

View File

@@ -14,11 +14,6 @@ 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.Param;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
@@ -42,12 +37,20 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@Data
@Slf4j
public class QueryStructReq {
private Long modelId;
private Set<Long> modelIds;
private String modelName;
private List<String> groups = new ArrayList<>();
@@ -70,6 +73,19 @@ public class QueryStructReq {
*/
private String correctS2SQL;
public void setModelId(Long modelId) {
modelIds = new HashSet<>();
modelIds.add(modelId);
}
public List<Long> getModelIds() {
return Lists.newArrayList(modelIds);
}
public Set<Long> getModelIdSet() {
return modelIds;
}
public List<String> getGroups() {
if (!CollectionUtils.isEmpty(this.groups)) {
this.groups = groups.stream().filter(group -> !Strings.isEmpty(group)).collect(Collectors.toList());
@@ -107,7 +123,7 @@ public class QueryStructReq {
public String toCustomizedString() {
StringBuilder stringBuilder = new StringBuilder("{");
stringBuilder.append("\"modelId\":")
.append(modelId);
.append(modelIds);
stringBuilder.append(",\"groups\":")
.append(groups);
stringBuilder.append(",\"aggregators\":")
@@ -139,7 +155,7 @@ public class QueryStructReq {
public String toString() {
final StringBuilder sb = new StringBuilder("{");
sb.append("\"modelId\":")
.append(modelId);
.append(modelIds);
sb.append(",\"groups\":")
.append(groups);
sb.append(",\"aggregators\":")
@@ -179,7 +195,7 @@ public class QueryStructReq {
QueryS2SQLReq result = new QueryS2SQLReq();
result.setSql(sql);
result.setModelId(queryStructReq.getModelId());
result.setModelIds(queryStructReq.getModelIdSet());
result.setVariables(new HashMap<>());
return result;
}

View File

@@ -20,10 +20,10 @@ import com.tencent.supersonic.semantic.api.materialization.response.Materializat
import com.tencent.supersonic.semantic.api.model.pojo.Measure;
import com.tencent.supersonic.semantic.api.model.pojo.SchemaItem;
import com.tencent.supersonic.semantic.api.model.request.ModelSchemaFilterReq;
import com.tencent.supersonic.semantic.api.model.response.DatasourceResp;
import com.tencent.supersonic.semantic.api.model.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.model.response.MeasureResp;
import com.tencent.supersonic.semantic.api.model.response.MetricSchemaResp;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.api.model.response.ModelSchemaResp;
import com.tencent.supersonic.semantic.materialization.domain.MaterializationConfService;
import com.tencent.supersonic.semantic.materialization.domain.pojo.Materialization;
@@ -32,8 +32,11 @@ import com.tencent.supersonic.semantic.materialization.domain.repository.Materia
import com.tencent.supersonic.semantic.materialization.domain.repository.MaterializationRepository;
import com.tencent.supersonic.semantic.materialization.domain.utils.MaterializationConverter;
import com.tencent.supersonic.semantic.materialization.domain.utils.MaterializationZipperUtils;
import com.tencent.supersonic.semantic.model.domain.DatasourceService;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Arrays;
@@ -46,11 +49,6 @@ import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@Slf4j
@Service
@@ -59,18 +57,16 @@ public class MaterializationConfServiceImpl implements MaterializationConfServic
private final MaterializationRepository materializationRepository;
private final MaterializationElementRepository materializationElementRepository;
private final ModelService modelService;
private final DatasourceService datasourceService;
private final MaterializationZipperUtils materializationZipperUtils;
private String typeAndIdSplit = "_";
public MaterializationConfServiceImpl(MaterializationRepository materializationRepository,
MaterializationElementRepository materializationElementRepository,
ModelService modelService, DatasourceService datasourceService,
ModelService modelService,
MaterializationZipperUtils materializationZipperUtils) {
this.materializationRepository = materializationRepository;
this.materializationElementRepository = materializationElementRepository;
this.modelService = modelService;
this.datasourceService = datasourceService;
this.materializationZipperUtils = materializationZipperUtils;
}
@@ -309,7 +305,7 @@ public class MaterializationConfServiceImpl implements MaterializationConfServic
ModelSchemaFilterReq modelFilter = new ModelSchemaFilterReq();
modelFilter.setModelIds(Arrays.asList(materializationResp.getModelId()));
List<ModelSchemaResp> modelSchemaRespList = modelService.fetchModelSchema(modelFilter);
List<MeasureResp> measureRespList = datasourceService.getMeasureListOfModel(
List<MeasureResp> measureRespList = modelService.getMeasureListOfModel(
Lists.newArrayList(materializationResp.getModelId()));
Map<String, DimSchemaResp> dimSchemaRespMap = new HashMap<>();
Map<String, MetricSchemaResp> metricSchemaRespHashMap = new HashMap<>();
@@ -363,13 +359,11 @@ public class MaterializationConfServiceImpl implements MaterializationConfServic
@Override
public List<MaterializationSourceResp> getMaterializationSourceResp(
Long materializationId) {
MaterializationResp materializationResp = materializationRepository.getMaterialization(
materializationId);
Long modelId = materializationResp.getModelId();
List<DatasourceResp> modelDataSources = datasourceService.getDatasourceList(modelId);
Set<Long> dataSourceIds = new HashSet<>();
Set<Long> modelIds = new HashSet<>();
Map<Long, Map<Long, String>> dataSourceDimensions = new HashMap<>();
Map<Long, Map<Long, String>> dataSourceMetrics = new HashMap<>();
MaterializationConfFilter materializationConfFilter = new MaterializationConfFilter();
@@ -380,7 +374,7 @@ public class MaterializationConfServiceImpl implements MaterializationConfServic
ModelSchemaFilterReq modelSchemaFilterReq = new ModelSchemaFilterReq();
modelSchemaFilterReq.setModelIds(Arrays.asList(modelId));
List<ModelSchemaResp> modelSchemaRespList = modelService.fetchModelSchema(modelSchemaFilterReq);
List<MeasureResp> measureRespList = datasourceService.getMeasureListOfModel(Lists.newArrayList(modelId));
List<MeasureResp> measureRespList = modelService.getMeasureListOfModel(Lists.newArrayList(modelId));
Set<Long> dimensionIds = new HashSet<>();
Set<Long> metricIds = new HashSet<>();
materializationElementRespList.stream().forEach(e -> {
@@ -393,11 +387,11 @@ public class MaterializationConfServiceImpl implements MaterializationConfServic
});
modelSchemaRespList.stream().forEach(m -> {
m.getDimensions().stream().filter(mm -> dimensionIds.contains(mm.getId())).forEach(mm -> {
if (!dataSourceDimensions.containsKey(mm.getDatasourceId())) {
dataSourceDimensions.put(mm.getDatasourceId(), new HashMap<>());
if (!dataSourceDimensions.containsKey(mm.getModelId())) {
dataSourceDimensions.put(mm.getModelId(), new HashMap<>());
}
dataSourceDimensions.get(mm.getDatasourceId()).put(mm.getId(), mm.getBizName());
dataSourceIds.add(mm.getDatasourceId());
dataSourceDimensions.get(mm.getModelId()).put(mm.getId(), mm.getBizName());
modelIds.add(mm.getModelId());
});
m.getMetrics().stream().filter(mm -> metricIds.contains(mm.getId())).forEach(mm -> {
Long sourceId = 0L;
@@ -412,27 +406,29 @@ public class MaterializationConfServiceImpl implements MaterializationConfServic
dataSourceMetrics.put(sourceId, new HashMap<>());
}
dataSourceMetrics.get(sourceId).put(mm.getId(), mm.getBizName());
dataSourceIds.add(sourceId);
modelIds.add(sourceId);
}
});
});
}
List<MaterializationSourceResp> materializationSourceResps = new ArrayList<>();
for (Long sourceId : dataSourceIds) {
Optional<DatasourceResp> datasourceResp = modelDataSources.stream().filter(d -> d.getId().equals(sourceId))
.findFirst();
if (datasourceResp.isPresent()) {
for (Long sourceId : modelIds) {
//todo
// Optional<ModelResp> modelResp = modelSchemaRespList.stream().filter(d -> d.getId().equals(sourceId))
// .findFirst();
Optional<ModelResp> modelResp = Optional.empty();
if (modelResp.isPresent()) {
MaterializationSourceResp materializationSourceResp = MaterializationSourceResp.builder()
.dataSourceId(sourceId)
.materializationId(materializationId)
.modelId(modelId)
.depends(datasourceResp.get().getDepends())
.depends(modelResp.get().getDepends())
.materializedType(materializationResp.getMaterializedType())
.entities(materializationResp.getEntities())
.dateInfo(materializationResp.getDateInfo())
.updateCycle(materializationResp.getUpdateCycle())
.build();
setDataSourceDb(datasourceResp.get(), materializationSourceResp);
setDataSourceDb(modelResp.get(), materializationSourceResp);
materializationSourceResp.setMetrics(
dataSourceMetrics.containsKey(sourceId) ? dataSourceMetrics.get(sourceId)
: new HashMap<>());
@@ -456,16 +452,16 @@ public class MaterializationConfServiceImpl implements MaterializationConfServic
return 0L;
}
private void setDataSourceDb(DatasourceResp datasourceResp, MaterializationSourceResp materializationSourceResp) {
if (Objects.nonNull(datasourceResp.getDatasourceDetail())) {
private void setDataSourceDb(ModelResp datasourceResp, MaterializationSourceResp materializationSourceResp) {
if (Objects.nonNull(datasourceResp.getModelDetail())) {
String dbTable = "";
if (Objects.nonNull(datasourceResp.getDatasourceDetail().getTableQuery())
&& !datasourceResp.getDatasourceDetail().getTableQuery().isEmpty()) {
dbTable = datasourceResp.getDatasourceDetail().getTableQuery();
if (Objects.nonNull(datasourceResp.getModelDetail().getTableQuery())
&& !datasourceResp.getModelDetail().getTableQuery().isEmpty()) {
dbTable = datasourceResp.getModelDetail().getTableQuery();
}
if (Objects.nonNull(datasourceResp.getDatasourceDetail().getSqlQuery())
&& !datasourceResp.getDatasourceDetail().getSqlQuery().isEmpty()) {
dbTable = SqlParserSelectHelper.getDbTableName(datasourceResp.getDatasourceDetail().getSqlQuery());
if (Objects.nonNull(datasourceResp.getModelDetail().getSqlQuery())
&& !datasourceResp.getModelDetail().getSqlQuery().isEmpty()) {
dbTable = SqlParserSelectHelper.getDbTableName(datasourceResp.getModelDetail().getSqlQuery());
}
if (!dbTable.isEmpty()) {
String[] db = dbTable.split("\\.");

View File

@@ -1,35 +1,30 @@
package com.tencent.supersonic.semantic.model.application;
import com.google.common.collect.Lists;
import com.tencent.supersonic.common.pojo.ItemDateResp;
import com.tencent.supersonic.common.pojo.ModelRela;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
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.common.pojo.ItemDateResp;
import com.tencent.supersonic.semantic.api.model.response.MeasureResp;
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.yaml.DatasourceYamlTpl;
import com.tencent.supersonic.semantic.api.model.yaml.DataModelYamlTpl;
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.DatabaseService;
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.ModelRelaService;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import com.tencent.supersonic.semantic.model.domain.pojo.MetaFilter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Slf4j
@Component
@@ -38,18 +33,20 @@ public class CatalogImpl implements Catalog {
private final DatabaseService databaseService;
private final ModelService modelService;
private final DimensionService dimensionService;
private final DatasourceService datasourceService;
private final ModelService datasourceService;
private final MetricService metricService;
private final ModelRelaService modelRelaService;
public CatalogImpl(DatabaseService databaseService,
ModelService modelService, DimensionService dimensionService,
DatasourceService datasourceService,
MetricService metricService) {
ModelService datasourceService,
MetricService metricService, ModelRelaService modelRelaService) {
this.databaseService = databaseService;
this.modelService = modelService;
this.dimensionService = dimensionService;
this.datasourceService = datasourceService;
this.metricService = metricService;
this.modelRelaService = modelRelaService;
}
public DatabaseResp getDatabase(Long id) {
@@ -62,7 +59,7 @@ public class CatalogImpl implements Catalog {
@Override
public String getModelFullPath(Long modelId) {
ModelResp modelResp = modelService.getModelMap().get(modelId);
ModelResp modelResp = modelService.getModel(modelId);
if (modelResp != null) {
return modelResp.getFullPath();
}
@@ -70,8 +67,8 @@ public class CatalogImpl implements Catalog {
}
@Override
public Map<Long, String> getModelFullPath() {
return modelService.getModelFullPathMap();
public String getModelFullPath(List<Long> modelIds) {
return String.join(",", modelIds.stream().map(Object::toString).collect(Collectors.toList()));
}
@Override
@@ -80,27 +77,21 @@ public class CatalogImpl implements Catalog {
}
@Override
public void getModelYamlTplByModelIds(Set<Long> modelIds, Map<String, List<DimensionYamlTpl>> dimensionYamlMap,
List<DatasourceYamlTpl> datasourceYamlTplList, List<MetricYamlTpl> metricYamlTplList) {
datasourceService.getModelYamlTplByModelIds(modelIds, dimensionYamlMap, datasourceYamlTplList,
metricYamlTplList);
public List<ModelRela> getModelRela(List<Long> modelIds) {
return modelRelaService.getModelRela(modelIds);
}
@Override
public List<DimensionResp> getDimensions(Long modelId) {
MetaFilter metricFilter = new MetaFilter(Lists.newArrayList(modelId));
public List<DimensionResp> getDimensions(List<Long> modelIds) {
MetaFilter metricFilter = new MetaFilter(modelIds);
metricFilter.setStatus(StatusEnum.ONLINE.getCode());
return dimensionService.getDimensions(metricFilter);
}
@Override
public List<DatasourceResp> getDatasourceList(Long modelId) {
return datasourceService.getDatasourceList(modelId);
}
@Override
public List<MetricResp> getMetrics(Long modelId) {
MetaFilter metricFilter = new MetaFilter(Lists.newArrayList(modelId));
public List<MetricResp> getMetrics(List<Long> modelIds) {
MetaFilter metricFilter = new MetaFilter(modelIds);
return metricService.getMetrics(metricFilter);
}
@@ -110,33 +101,11 @@ public class CatalogImpl implements Catalog {
}
@Override
public String getAgg(List<MetricResp> metricResps, List<MeasureResp> measureRespList, String metricBizName) {
try {
if (!CollectionUtils.isEmpty(metricResps)) {
Optional<MetricResp> metric = metricResps.stream()
.filter(m -> m.getBizName().equalsIgnoreCase(metricBizName)).findFirst();
if (metric.isPresent() && Objects.nonNull(metric.get().getTypeParams()) && !CollectionUtils.isEmpty(
metric.get().getTypeParams().getMeasures())) {
if (!CollectionUtils.isEmpty(measureRespList)) {
String measureName = metric.get().getTypeParams().getMeasures().get(0).getBizName();
Optional<MeasureResp> measure = measureRespList.stream()
.filter(Objects::nonNull)
.filter(m -> {
if (StringUtils.isNotEmpty(m.getBizName())) {
return m.getBizName().equalsIgnoreCase(measureName);
}
return false;
})
.findFirst();
if (measure.isPresent()) {
return measure.get().getAgg();
}
}
}
}
} catch (Exception e) {
log.error("getAgg:", e);
}
return "";
public void getModelYamlTplByModelIds(Set<Long> modelIds, Map<String, List<DimensionYamlTpl>> dimensionYamlMap,
List<DataModelYamlTpl> dataModelYamlTplList, List<MetricYamlTpl> metricYamlTplList,
Map<Long, String> modelIdName) {
datasourceService.getModelYamlTplByModelIds(modelIds, dimensionYamlMap, dataModelYamlTplList,
metricYamlTplList, modelIdName);
}
}

View File

@@ -3,25 +3,27 @@ package com.tencent.supersonic.semantic.model.application;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.semantic.api.model.request.DatabaseReq;
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.ModelResp;
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
import com.tencent.supersonic.semantic.model.domain.DatasourceService;
import com.tencent.supersonic.semantic.model.domain.DatabaseService;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import com.tencent.supersonic.semantic.model.domain.adaptor.engineadapter.EngineAdaptor;
import com.tencent.supersonic.semantic.model.domain.adaptor.engineadapter.EngineAdaptorFactory;
import com.tencent.supersonic.semantic.model.domain.dataobject.DatabaseDO;
import com.tencent.supersonic.semantic.model.domain.pojo.Database;
import com.tencent.supersonic.semantic.model.domain.pojo.ModelFilter;
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.utils.JdbcDataSourceUtils;
import com.tencent.supersonic.semantic.model.domain.utils.SqlUtils;
import com.tencent.supersonic.semantic.model.domain.DatabaseService;
import com.tencent.supersonic.semantic.model.domain.pojo.Database;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
@@ -29,11 +31,11 @@ public class DatabaseServiceImpl implements DatabaseService {
private final SqlUtils sqlUtils;
private DatabaseRepository databaseRepository;
private DatasourceService datasourceService;
private ModelService datasourceService;
public DatabaseServiceImpl(DatabaseRepository databaseRepository,
SqlUtils sqlUtils,
@Lazy DatasourceService datasourceService) {
@Lazy ModelService datasourceService) {
this.databaseRepository = databaseRepository;
this.sqlUtils = sqlUtils;
this.datasourceService = datasourceService;
@@ -88,11 +90,13 @@ public class DatabaseServiceImpl implements DatabaseService {
@Override
public void deleteDatabase(Long databaseId) {
List<DatasourceResp> datasourceResps = datasourceService.getDatasourceByDatabase(databaseId);
if (!CollectionUtils.isEmpty(datasourceResps)) {
List<String> datasourceNames = datasourceResps.stream()
.map(DatasourceResp::getName).collect(Collectors.toList());
String message = String.format("该数据库被数据源%s使用无法删除", datasourceNames);
ModelFilter modelFilter = new ModelFilter();
modelFilter.setDatabaseId(databaseId);
List<ModelResp> modelResps = datasourceService.getModelList(modelFilter);
if (!CollectionUtils.isEmpty(modelResps)) {
List<String> datasourceNames = modelResps.stream()
.map(ModelResp::getName).collect(Collectors.toList());
String message = String.format("该数据库被模型%s使用无法删除", datasourceNames);
throw new RuntimeException(message);
}
databaseRepository.deleteDatabase(databaseId);

View File

@@ -1,355 +0,0 @@
package com.tencent.supersonic.semantic.model.application;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.pojo.exception.InvalidArgumentException;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.semantic.api.model.pojo.DatasourceDetail;
import com.tencent.supersonic.semantic.api.model.pojo.Dim;
import com.tencent.supersonic.semantic.api.model.pojo.Identify;
import com.tencent.supersonic.semantic.api.model.pojo.ItemDateFilter;
import com.tencent.supersonic.semantic.api.model.pojo.Measure;
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.api.model.request.DatasourceReq;
import com.tencent.supersonic.semantic.api.model.request.DateInfoReq;
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.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.ItemDateResp;
import com.tencent.supersonic.semantic.api.model.response.MeasureResp;
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
import com.tencent.supersonic.semantic.model.domain.DatabaseService;
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.dataobject.DatasourceDO;
import com.tencent.supersonic.semantic.model.domain.dataobject.DateInfoDO;
import com.tencent.supersonic.semantic.model.domain.manager.DatasourceYamlManager;
import com.tencent.supersonic.semantic.model.domain.manager.DimensionYamlManager;
import com.tencent.supersonic.semantic.model.domain.manager.MetricYamlManager;
import com.tencent.supersonic.semantic.model.domain.pojo.MetaFilter;
import com.tencent.supersonic.semantic.model.domain.repository.DatasourceRepository;
import com.tencent.supersonic.semantic.model.domain.repository.DateInfoRepository;
import com.tencent.supersonic.semantic.model.domain.utils.DatasourceConverter;
import com.tencent.supersonic.semantic.model.domain.utils.DimensionConverter;
import com.tencent.supersonic.semantic.model.domain.utils.MetricConverter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import com.tencent.supersonic.semantic.model.domain.utils.NameCheckUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
@Service
@Slf4j
public class DatasourceServiceImpl implements DatasourceService {
private DatasourceRepository datasourceRepository;
private DatabaseService databaseService;
private DimensionService dimensionService;
private MetricService metricService;
private DateInfoRepository dateInfoRepository;
public DatasourceServiceImpl(DatasourceRepository datasourceRepository,
DatabaseService databaseService,
@Lazy DimensionService dimensionService,
@Lazy MetricService metricService,
DateInfoRepository dateInfoRepository) {
this.datasourceRepository = datasourceRepository;
this.databaseService = databaseService;
this.dimensionService = dimensionService;
this.metricService = metricService;
this.dateInfoRepository = dateInfoRepository;
}
@Override
@Transactional
public DatasourceResp createDatasource(DatasourceReq datasourceReq, User user) throws Exception {
checkName(datasourceReq);
checkExist(datasourceReq);
DatasourceDO datasourceDO = DatasourceConverter.convert(datasourceReq, user);
datasourceRepository.createDatasource(datasourceDO);
batchCreateDimension(datasourceDO, user);
batchCreateMetric(datasourceDO, user);
return DatasourceConverter.convert(datasourceDO);
}
@Override
@Transactional
public DatasourceResp updateDatasource(DatasourceReq datasourceReq, User user) throws Exception {
checkName(datasourceReq);
DatasourceDO datasourceDO = datasourceRepository.getDatasourceById(datasourceReq.getId());
DatasourceConverter.convert(datasourceDO, datasourceReq, user);
datasourceRepository.updateDatasource(datasourceDO);
batchCreateDimension(datasourceDO, user);
batchCreateMetric(datasourceDO, user);
return DatasourceConverter.convert(datasourceDO);
}
@Override
public List<MeasureResp> getMeasureListOfModel(List<Long> modelIds) {
if (CollectionUtils.isEmpty(modelIds)) {
return Lists.newArrayList();
}
List<DatasourceResp> datasourceResps = getDatasourceList().stream().filter(datasourceResp ->
modelIds.contains(datasourceResp.getModelId())).collect(Collectors.toList());
List<MeasureResp> measureResps = Lists.newArrayList();
if (!CollectionUtils.isEmpty(datasourceResps)) {
for (DatasourceResp datasourceDesc : datasourceResps) {
DatasourceDetail datasourceDetail = datasourceDesc.getDatasourceDetail();
List<Measure> measures = datasourceDetail.getMeasures();
if (!CollectionUtils.isEmpty(measures)) {
measureResps.addAll(
measures.stream().map(measure -> DatasourceConverter.convert(measure, datasourceDesc))
.collect(Collectors.toList()));
}
}
}
return measureResps;
}
private void batchCreateDimension(DatasourceDO datasourceDO, User user) throws Exception {
List<DimensionReq> dimensionReqs = DatasourceConverter.convertDimensionList(datasourceDO);
dimensionService.createDimensionBatch(dimensionReqs, user);
}
private void batchCreateMetric(DatasourceDO datasourceDO, User user) throws Exception {
List<MetricReq> exprMetricReqs = DatasourceConverter.convertMetricList(datasourceDO);
metricService.createMetricBatch(exprMetricReqs, user);
}
private Optional<DatasourceResp> getDatasource(Long modelId, String bizName) {
List<DatasourceResp> datasourceResps = getDatasourceList(modelId);
if (CollectionUtils.isEmpty(datasourceResps)) {
return Optional.empty();
}
for (DatasourceResp datasourceDesc : datasourceResps) {
if (datasourceDesc.getBizName().equals(bizName)) {
return Optional.of(datasourceDesc);
}
}
return Optional.empty();
}
private void checkName(DatasourceReq datasourceReq) {
if (NameCheckUtils.containsSpecialCharacters(datasourceReq.getName())) {
String message = String.format("数据源名称[%s]包含特殊字符, 请修改", datasourceReq.getName());
throw new InvalidArgumentException(message);
}
List<Dim> dims = datasourceReq.getDimensions();
List<Measure> measures = datasourceReq.getMeasures();
List<Dim> timeDims = datasourceReq.getTimeDimension();
List<Identify> identifies = datasourceReq.getIdentifiers();
if (CollectionUtils.isEmpty(dims)) {
throw new InvalidArgumentException("缺少维度信息");
}
if (CollectionUtils.isEmpty(identifies)) {
throw new InvalidArgumentException("缺少主键信息");
}
if (!CollectionUtils.isEmpty(measures) && CollectionUtils.isEmpty(timeDims)) {
throw new InvalidArgumentException("有度量时, 不可缺少时间维度");
}
for (Measure measure : measures) {
if (StringUtils.isNotBlank(measure.getName())
&& NameCheckUtils.containsSpecialCharacters(measure.getName())) {
String message = String.format("度量[%s]包含特殊字符, 请修改", measure.getName());
throw new InvalidArgumentException(message);
}
}
for (Dim dim : dims) {
if (StringUtils.isNotBlank(dim.getName())
&& NameCheckUtils.containsSpecialCharacters(dim.getName())) {
String message = String.format("维度[%s]包含特殊字符, 请修改", dim.getName());
throw new InvalidArgumentException(message);
}
}
for (Identify identify : identifies) {
if (StringUtils.isNotBlank(identify.getName())
&& NameCheckUtils.containsSpecialCharacters(identify.getName())) {
String message = String.format("主键/外键[%s]包含特殊字符, 请修改", identify.getName());
throw new InvalidArgumentException(message);
}
}
}
private void checkExist(DatasourceReq datasourceReq) {
Optional<DatasourceResp> datasourceRespOptional = getDatasource(datasourceReq.getModelId(),
datasourceReq.getBizName());
if (datasourceRespOptional.isPresent()) {
throw new InvalidArgumentException("已存在相同名字的数据源:" + datasourceReq.getBizName());
}
}
@Override
public List<DatasourceResp> getDatasourceList(Long modelId) {
return DatasourceConverter.convertList(datasourceRepository.getDatasourceList(modelId));
}
@Override
public List<DatasourceResp> getDatasourceList() {
return DatasourceConverter.convertList(datasourceRepository.getDatasourceList());
}
@Override
public List<DatasourceResp> getDatasourceByDatabase(Long databaseId) {
return DatasourceConverter.convertList(datasourceRepository.getDatasourceByDatabase(databaseId));
}
@Override
public List<DatasourceResp> getDatasourceListNoMeasurePrefix(Long modelId) {
List<DatasourceResp> datasourceResps = getDatasourceList(modelId);
for (DatasourceResp datasourceResp : datasourceResps) {
if (!CollectionUtils.isEmpty(datasourceResp.getDatasourceDetail().getMeasures())) {
for (Measure measure : datasourceResp.getDatasourceDetail().getMeasures()) {
measure.setBizName(Optional.ofNullable(measure.getBizName()).orElse("")
.replace(getDatasourcePrefix(datasourceResp.getBizName()), ""));
}
}
}
return datasourceResps;
}
private String getDatasourcePrefix(String datasourceBizName) {
return String.format("%s_", datasourceBizName);
}
@Override
public Map<Long, DatasourceResp> getDatasourceMap() {
Map<Long, DatasourceResp> map = new HashMap<>();
List<DatasourceResp> datasourceResps = getDatasourceList();
if (CollectionUtils.isEmpty(datasourceResps)) {
return map;
}
return datasourceResps.stream().collect(Collectors.toMap(DatasourceResp::getId, a -> a, (k1, k2) -> k1));
}
@Override
public void deleteDatasource(Long id, User user) {
DatasourceDO datasourceDO = datasourceRepository.getDatasourceById(id);
if (datasourceDO == null) {
return;
}
checkDelete(id);
datasourceDO.setStatus(StatusEnum.DELETED.getCode());
datasourceDO.setUpdatedAt(new Date());
datasourceDO.setUpdatedBy(user.getName());
datasourceRepository.updateDatasource(datasourceDO);
}
private void checkDelete(Long datasourceId) {
MetaFilter metaFilter = new MetaFilter();
metaFilter.setDatasourceId(datasourceId);
List<MetricResp> metricResps = metricService.getMetrics(metaFilter);
List<DimensionResp> dimensionResps = dimensionService.getDimensions(metaFilter);
if (!CollectionUtils.isEmpty(metricResps) || !CollectionUtils.isEmpty(dimensionResps)) {
throw new RuntimeException("存在基于该数据源创建的指标和维度, 暂不能删除, 请确认");
}
}
@Override
public ItemDateResp getItemDate(ItemDateFilter dimension, ItemDateFilter metric) {
List<DateInfoReq> itemDates = new ArrayList<>();
List<DateInfoDO> dimensions = dateInfoRepository.getDateInfos(dimension);
List<DateInfoDO> metrics = dateInfoRepository.getDateInfos(metric);
log.info("getDateDate, dimension:{}, dimensions dateInfo:{}", dimension, dimensions);
log.info("getDateDate, metric:{}, metrics dateInfo:{}", metric, metrics);
itemDates.addAll(convert(dimensions));
itemDates.addAll(convert(metrics));
ItemDateResp itemDateDescriptor = calculateDateInternal(itemDates);
log.info("itemDateDescriptor:{}", itemDateDescriptor);
return itemDateDescriptor;
}
private List<DateInfoReq> convert(List<DateInfoDO> dateInfoDOList) {
List<DateInfoReq> dateInfoCommendList = new ArrayList<>();
dateInfoDOList.stream().forEach(dateInfoDO -> {
DateInfoReq dateInfoCommend = new DateInfoReq();
BeanUtils.copyProperties(dateInfoDO, dateInfoCommend);
dateInfoCommend.setUnavailableDateList(JsonUtil.toList(dateInfoDO.getUnavailableDateList(), String.class));
dateInfoCommendList.add(dateInfoCommend);
});
return dateInfoCommendList;
}
private ItemDateResp calculateDateInternal(List<DateInfoReq> itemDates) {
if (CollectionUtils.isEmpty(itemDates)) {
log.warn("itemDates is empty!");
return null;
}
String dateFormat = itemDates.get(0).getDateFormat();
String startDate = itemDates.get(0).getStartDate();
String endDate = itemDates.get(0).getEndDate();
String datePeriod = itemDates.get(0).getDatePeriod();
List<String> unavailableDateList = itemDates.get(0).getUnavailableDateList();
for (DateInfoReq item : itemDates) {
String startDate1 = item.getStartDate();
String endDate1 = item.getEndDate();
List<String> unavailableDateList1 = item.getUnavailableDateList();
if (Strings.isNotEmpty(startDate1) && startDate1.compareTo(startDate) > 0) {
startDate = startDate1;
}
if (Strings.isNotEmpty(endDate1) && endDate1.compareTo(endDate) < 0) {
endDate = endDate1;
}
if (!CollectionUtils.isEmpty(unavailableDateList1)) {
unavailableDateList.addAll(unavailableDateList1);
}
}
return new ItemDateResp(dateFormat, startDate, endDate, datePeriod, unavailableDateList);
}
@Override
public void getModelYamlTplByModelIds(Set<Long> modelIds, Map<String, List<DimensionYamlTpl>> dimensionYamlMap,
List<DatasourceYamlTpl> datasourceYamlTplList, List<MetricYamlTpl> metricYamlTplList) {
for (Long modelId : modelIds) {
List<DatasourceResp> datasourceResps = getDatasourceList(modelId);
MetaFilter metaFilter = new MetaFilter(Lists.newArrayList(modelId));
List<MetricResp> metricResps = metricService.getMetrics(metaFilter);
metricYamlTplList.addAll(MetricYamlManager.convert2YamlObj(MetricConverter.metricInfo2Metric(metricResps)));
Long databaseId = datasourceResps.iterator().next().getDatabaseId();
DatabaseResp databaseResp = databaseService.getDatabase(databaseId);
List<DimensionResp> dimensionResps = dimensionService.getDimensions(metaFilter);
for (DatasourceResp datasourceResp : datasourceResps) {
datasourceYamlTplList.add(DatasourceYamlManager.convert2YamlObj(
DatasourceConverter.datasourceInfo2Datasource(datasourceResp), databaseResp));
if (!dimensionYamlMap.containsKey(datasourceResp.getBizName())) {
dimensionYamlMap.put(datasourceResp.getBizName(), new ArrayList<>());
}
List<DimensionResp> dimensionRespList = dimensionResps.stream()
.filter(d -> d.getDatasourceBizName().equalsIgnoreCase(datasourceResp.getBizName()))
.collect(Collectors.toList());
dimensionYamlMap.get(datasourceResp.getBizName()).addAll(DimensionYamlManager.convert2DimensionYaml(
DimensionConverter.dimensionInfo2Dimension(dimensionRespList)));
}
}
}
}

View File

@@ -7,37 +7,30 @@ 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.DataItem;
import com.tencent.supersonic.common.pojo.DataEvent;
import com.tencent.supersonic.common.pojo.DataItem;
import com.tencent.supersonic.common.pojo.enums.EventType;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.pojo.enums.TypeEnums;
import com.tencent.supersonic.common.pojo.exception.InvalidArgumentException;
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.pojo.ModelDetail;
import com.tencent.supersonic.semantic.api.model.request.DimensionReq;
import com.tencent.supersonic.semantic.api.model.request.MetaBatchReq;
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.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
import com.tencent.supersonic.semantic.model.domain.DatabaseService;
import com.tencent.supersonic.semantic.model.domain.DimensionService;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import com.tencent.supersonic.semantic.model.domain.dataobject.DimensionDO;
import com.tencent.supersonic.semantic.model.domain.pojo.DimensionFilter;
import com.tencent.supersonic.semantic.model.domain.pojo.MetaFilter;
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.pojo.DimensionFilter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.stream.Collectors;
import com.tencent.supersonic.semantic.model.domain.utils.NameCheckUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
@@ -46,6 +39,13 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Slf4j
@@ -54,8 +54,6 @@ public class DimensionServiceImpl implements DimensionService {
private DimensionRepository dimensionRepository;
private DatasourceService datasourceService;
private ModelService modelService;
private ChatGptHelper chatGptHelper;
@@ -68,12 +66,10 @@ public class DimensionServiceImpl implements DimensionService {
public DimensionServiceImpl(DimensionRepository dimensionRepository,
ModelService modelService,
DatasourceService datasourceService,
ChatGptHelper chatGptHelper,
DatabaseService databaseService) {
this.modelService = modelService;
this.dimensionRepository = dimensionRepository;
this.datasourceService = datasourceService;
this.chatGptHelper = chatGptHelper;
this.databaseService = databaseService;
}
@@ -185,7 +181,7 @@ public class DimensionServiceImpl implements DimensionService {
@Override
public DimensionResp getDimension(Long id) {
DimensionDO dimensionDO = dimensionRepository.getDimensionById(id);
return DimensionConverter.convert2DimensionResp(dimensionDO, new HashMap<>(), new HashMap<>());
return DimensionConverter.convert2DimensionResp(dimensionDO, new HashMap<>());
}
@Override
@@ -198,7 +194,7 @@ public class DimensionServiceImpl implements DimensionService {
.doSelectPageInfo(() -> queryDimension(dimensionFilter));
PageInfo<DimensionResp> pageInfo = new PageInfo<>();
BeanUtils.copyProperties(dimensionDOPageInfo, pageInfo);
pageInfo.setList(convertList(dimensionDOPageInfo.getList(), datasourceService.getDatasourceMap()));
pageInfo.setList(convertList(dimensionDOPageInfo.getList(), modelService.getModelMap()));
return pageInfo;
}
@@ -210,7 +206,7 @@ public class DimensionServiceImpl implements DimensionService {
public List<DimensionResp> getDimensions(MetaFilter metaFilter) {
DimensionFilter dimensionFilter = new DimensionFilter();
BeanUtils.copyProperties(metaFilter, dimensionFilter);
return convertList(dimensionRepository.getDimension(dimensionFilter), datasourceService.getDatasourceMap());
return convertList(dimensionRepository.getDimension(dimensionFilter), modelService.getModelMap());
}
private List<DimensionResp> getDimensions(Long modelId) {
@@ -218,13 +214,11 @@ public class DimensionServiceImpl implements DimensionService {
}
private List<DimensionResp> convertList(List<DimensionDO> dimensionDOS,
Map<Long, DatasourceResp> datasourceRespMap) {
Map<Long, ModelResp> modelRespMap) {
List<DimensionResp> dimensionResps = Lists.newArrayList();
Map<Long, String> modelFullPathMap = modelService.getModelFullPathMap();
if (!CollectionUtils.isEmpty(dimensionDOS)) {
dimensionResps = dimensionDOS.stream()
.map(dimensionDO -> DimensionConverter.convert2DimensionResp(dimensionDO, modelFullPathMap,
datasourceRespMap))
.map(dimensionDO -> DimensionConverter.convert2DimensionResp(dimensionDO, modelRespMap))
.collect(Collectors.toList());
}
return dimensionResps;
@@ -251,19 +245,10 @@ public class DimensionServiceImpl implements DimensionService {
@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());
ModelResp modelResp = modelService.getModel(dimensionReq.getModelId());
ModelDetail modelDetail = modelResp.getModelDetail();
String sqlQuery = modelDetail.getSqlQuery();
DatabaseResp database = databaseService.getDatabase(modelResp.getDatabaseId());
String sql = "select ai_talk." + dimensionReq.getBizName() + " from (" + sqlQuery
+ ") as ai_talk group by ai_talk." + dimensionReq.getBizName();

View File

@@ -1,39 +1,38 @@
package com.tencent.supersonic.semantic.model.application;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.service.UserService;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.semantic.api.model.request.DomainReq;
import com.tencent.supersonic.semantic.api.model.request.DomainUpdateReq;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.api.model.response.DomainResp;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.model.domain.DomainService;
import com.tencent.supersonic.semantic.model.domain.ModelService;
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.List;
import java.util.Date;
import java.util.Set;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.Queue;
import java.util.LinkedList;
import java.util.Objects;
import java.util.Comparator;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Sets;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Comparator;
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.stream.Collectors;
@Service
@Slf4j
@@ -54,22 +53,16 @@ public class DomainServiceImpl implements DomainService {
@Override
public void createDomain(DomainReq domainReq, User user) {
log.info("[create domain] cmd : {}", JSONObject.toJSONString(domainReq));
Domain domain = DomainConvert.convert(domainReq);
log.info("[create domain] object:{}", JSONObject.toJSONString(domainReq));
saveDomain(domain, user);
DomainDO domainDO = DomainConvert.convert(domainReq, user);
domainDO.setStatus(StatusEnum.ONLINE.getCode());
domainRepository.createDomain(domainDO);
}
@Override
public void updateDomain(DomainUpdateReq domainUpdateReq, User user) {
domainUpdateReq.updatedBy(user.getName());
DomainDO domainDO = getDomainDO(domainUpdateReq.getId());
domainDO.setUpdatedAt(new Date());
domainDO.setUpdatedBy(user.getName());
BeanMapper.mapper(domainUpdateReq, domainDO);
domainDO.setAdmin(String.join(",", domainUpdateReq.getAdmins()));
domainDO.setAdminOrg(String.join(",", domainUpdateReq.getAdminOrgs()));
domainDO.setViewer(String.join(",", domainUpdateReq.getViewers()));
domainDO.setViewOrg(String.join(",", domainUpdateReq.getViewOrgs()));
domainRepository.updateDomain(domainDO);
}
@@ -161,13 +154,6 @@ public class DomainServiceImpl implements DomainService {
return getDomainFullPathMap();
}
//保存并获取自增ID
private void saveDomain(Domain domain, User user) {
DomainDO domainDO = DomainConvert.convert(domain, user);
domainRepository.createDomain(domainDO);
domain.setId(domainDO.getId());
}
private List<DomainResp> convertList(List<DomainDO> domainDOS) {
List<DomainResp> domainDescs = Lists.newArrayList();
if (CollectionUtils.isEmpty(domainDOS)) {

View File

@@ -6,8 +6,8 @@ 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.DataItem;
import com.tencent.supersonic.common.pojo.DataEvent;
import com.tencent.supersonic.common.pojo.DataItem;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.common.pojo.enums.EventType;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
@@ -20,27 +20,17 @@ import com.tencent.supersonic.semantic.api.model.pojo.MetricTypeParams;
import com.tencent.supersonic.semantic.api.model.request.MetaBatchReq;
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.DatasourceResp;
import com.tencent.supersonic.semantic.api.model.response.DomainResp;
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.model.domain.DatasourceService;
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.MetaFilter;
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 java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import com.tencent.supersonic.semantic.model.domain.utils.NameCheckUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@@ -48,6 +38,13 @@ import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@Slf4j
@@ -59,8 +56,6 @@ public class MetricServiceImpl implements MetricService {
private DomainService domainService;
private DatasourceService datasourceService;
private ChatGptHelper chatGptHelper;
private ApplicationEventPublisher eventPublisher;
@@ -68,13 +63,11 @@ public class MetricServiceImpl implements MetricService {
public MetricServiceImpl(MetricRepository metricRepository,
ModelService modelService,
DomainService domainService,
DatasourceService datasourceService,
ChatGptHelper chatGptHelper,
ApplicationEventPublisher eventPublisher) {
this.domainService = domainService;
this.metricRepository = metricRepository;
this.modelService = modelService;
this.datasourceService = datasourceService;
this.chatGptHelper = chatGptHelper;
this.eventPublisher = eventPublisher;
}
@@ -198,21 +191,7 @@ public class MetricServiceImpl implements MetricService {
public List<MetricResp> getMetrics(MetaFilter metaFilter) {
MetricFilter metricFilter = new MetricFilter();
BeanUtils.copyProperties(metaFilter, metricFilter);
List<MetricResp> metricResps = convertList(queryMetric(metricFilter));
if (metricFilter.getDatasourceId() != null) {
return filterByDatasource(metricFilter.getDatasourceId(), metricResps);
}
return metricResps;
}
private List<MetricResp> filterByDatasource(Long datasourceId, List<MetricResp> metricResps) {
return metricResps.stream().filter(metricResp -> {
Set<Long> datasourceIdSet = metricResp.getTypeParams().getMeasures().stream()
.map(Measure::getDatasourceId)
.filter(Objects::nonNull).collect(Collectors.toSet());
return !CollectionUtils.isEmpty(datasourceIdSet)
&& datasourceIdSet.contains(datasourceId);
}).collect(Collectors.toList());
return convertList(queryMetric(metricFilter));
}
private void fillAdminRes(List<MetricResp> metricResps, User user) {
@@ -257,20 +236,7 @@ public class MetricServiceImpl implements MetricService {
if (metricDO == null) {
return null;
}
MetricResp metricResp = MetricConverter.convert2MetricResp(metricDO, new HashMap<>());
List<Measure> measures = metricResp.getMeasures();
if (CollectionUtils.isEmpty(measures)) {
return metricResp;
}
Map<Long, DatasourceResp> datasourceResps = datasourceService.getDatasourceList().stream()
.collect(Collectors.toMap(DatasourceResp::getId, datasourceResp -> datasourceResp));
measures.forEach(measure -> {
DatasourceResp datasourceResp = datasourceResps.get(measure.getDatasourceId());
if (datasourceResp != null) {
measure.setDatasourceName(datasourceResp.getName());
}
});
return metricResp;
return MetricConverter.convert2MetricResp(metricDO, new HashMap<>());
}
@Override

View File

@@ -0,0 +1,73 @@
package com.tencent.supersonic.semantic.model.application;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.JoinCondition;
import com.tencent.supersonic.common.pojo.ModelRela;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.semantic.model.domain.ModelRelaService;
import com.tencent.supersonic.semantic.model.domain.dataobject.ModelRelaDO;
import com.tencent.supersonic.semantic.model.infrastructure.mapper.ModelRelaDOMapper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class ModelRelaServiceImpl
extends ServiceImpl<ModelRelaDOMapper, ModelRelaDO> implements ModelRelaService {
@Override
public void save(ModelRela modelRela, User user) {
modelRela.createdBy(user.getName());
ModelRelaDO modelRelaDO = convert(modelRela);
save(modelRelaDO);
}
@Override
public void update(ModelRela modelRela, User user) {
modelRela.updatedBy(user.getName());
ModelRelaDO modelRelaDO = convert(modelRela);
updateById(modelRelaDO);
}
@Override
public List<ModelRela> getModelRelaList(Long domainId) {
QueryWrapper<ModelRelaDO> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(ModelRelaDO::getDomainId, domainId);
return list(wrapper).stream().map(this::convert).collect(Collectors.toList());
}
@Override
public List<ModelRela> getModelRela(List<Long> modelIds) {
QueryWrapper<ModelRelaDO> wrapper = new QueryWrapper<>();
if (CollectionUtils.isEmpty(modelIds)) {
wrapper.lambda().in(ModelRelaDO::getFromModelId, modelIds).or()
.in(ModelRelaDO::getToModelId, modelIds);
}
return list(wrapper).stream().map(this::convert).collect(Collectors.toList());
}
@Override
public void delete(Long id) {
removeById(id);
}
private ModelRela convert(ModelRelaDO modelRelaDO) {
ModelRela modelRela = new ModelRela();
BeanMapper.mapper(modelRelaDO, modelRela);
modelRela.setJoinConditions(JSONObject.parseArray(modelRelaDO.getJoinCondition(), JoinCondition.class));
return modelRela;
}
private ModelRelaDO convert(ModelRela modelRelaReq) {
ModelRelaDO modelRelaDO = new ModelRelaDO();
BeanMapper.mapper(modelRelaReq, modelRelaDO);
modelRelaDO.setJoinCondition(JSONObject.toJSONString(modelRelaReq.getJoinConditions()));
return modelRelaDO;
}
}

View File

@@ -3,17 +3,25 @@ package com.tencent.supersonic.semantic.model.application;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.service.UserService;
import com.tencent.supersonic.common.pojo.DataEvent;
import com.tencent.supersonic.common.pojo.ItemDateResp;
import com.tencent.supersonic.common.pojo.ModelRela;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.common.pojo.enums.EventType;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.common.pojo.exception.InvalidArgumentException;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.semantic.api.model.pojo.Dim;
import com.tencent.supersonic.semantic.api.model.pojo.Identify;
import com.tencent.supersonic.semantic.api.model.pojo.ItemDateFilter;
import com.tencent.supersonic.semantic.api.model.pojo.Measure;
import com.tencent.supersonic.semantic.api.model.pojo.RelateDimension;
import com.tencent.supersonic.semantic.api.model.pojo.SchemaItem;
import com.tencent.supersonic.semantic.api.model.request.DateInfoReq;
import com.tencent.supersonic.semantic.api.model.request.DimensionReq;
import com.tencent.supersonic.semantic.api.model.request.MetaBatchReq;
import com.tencent.supersonic.semantic.api.model.request.MetricReq;
import com.tencent.supersonic.semantic.api.model.request.ModelReq;
import com.tencent.supersonic.semantic.api.model.request.ModelSchemaFilterReq;
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.DimSchemaResp;
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
import com.tencent.supersonic.semantic.api.model.response.DomainResp;
@@ -22,117 +30,251 @@ import com.tencent.supersonic.semantic.api.model.response.MetricResp;
import com.tencent.supersonic.semantic.api.model.response.MetricSchemaResp;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.api.model.response.ModelSchemaResp;
import com.tencent.supersonic.semantic.model.domain.Catalog;
import com.tencent.supersonic.semantic.api.model.yaml.DataModelYamlTpl;
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.DatabaseService;
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.MetricService;
import com.tencent.supersonic.semantic.model.domain.ModelRelaService;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import com.tencent.supersonic.semantic.model.domain.dataobject.DateInfoDO;
import com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO;
import com.tencent.supersonic.semantic.model.domain.manager.DatasourceYamlManager;
import com.tencent.supersonic.semantic.model.domain.manager.DimensionYamlManager;
import com.tencent.supersonic.semantic.model.domain.manager.MetricYamlManager;
import com.tencent.supersonic.semantic.model.domain.pojo.Datasource;
import com.tencent.supersonic.semantic.model.domain.pojo.DimensionFilter;
import com.tencent.supersonic.semantic.model.domain.pojo.MetaFilter;
import com.tencent.supersonic.semantic.model.domain.pojo.MetricFilter;
import com.tencent.supersonic.semantic.model.domain.pojo.ModelFilter;
import com.tencent.supersonic.semantic.model.domain.repository.DateInfoRepository;
import com.tencent.supersonic.semantic.model.domain.repository.ModelRepository;
import com.tencent.supersonic.semantic.model.domain.utils.ModelConvert;
import com.tencent.supersonic.semantic.model.domain.utils.DimensionConverter;
import com.tencent.supersonic.semantic.model.domain.utils.MetricConverter;
import com.tencent.supersonic.semantic.model.domain.utils.ModelConverter;
import com.tencent.supersonic.semantic.model.domain.utils.NameCheckUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@Slf4j
@Service
@Slf4j
public class ModelServiceImpl implements ModelService {
private final ModelRepository modelRepository;
private final MetricService metricService;
private final DimensionService dimensionService;
private final DatasourceService datasourceService;
private final DomainService domainService;
private final UserService userService;
private final DatabaseService databaseService;
private final Catalog catalog;
private ApplicationEventPublisher eventPublisher;
private ModelRepository modelRepository;
public ModelServiceImpl(ModelRepository modelRepository, @Lazy MetricService metricService,
@Lazy DimensionService dimensionService, @Lazy DatasourceService datasourceService,
@Lazy DomainService domainService, UserService userService,
@Lazy DatabaseService databaseService,
@Lazy Catalog catalog, ApplicationEventPublisher eventPublisher) {
private DatabaseService databaseService;
private DimensionService dimensionService;
private MetricService metricService;
private DomainService domainService;
private ModelRelaService modelRelaService;
private UserService userService;
private DateInfoRepository dateInfoRepository;
public ModelServiceImpl(ModelRepository modelRepository,
DatabaseService databaseService,
@Lazy DimensionService dimensionService,
@Lazy MetricService metricService,
ModelRelaService modelRelaService,
DomainService domainService,
UserService userService,
DateInfoRepository dateInfoRepository) {
this.modelRepository = modelRepository;
this.metricService = metricService;
this.dimensionService = dimensionService;
this.datasourceService = datasourceService;
this.domainService = domainService;
this.userService = userService;
this.databaseService = databaseService;
this.catalog = catalog;
this.eventPublisher = eventPublisher;
this.dimensionService = dimensionService;
this.metricService = metricService;
this.domainService = domainService;
this.modelRelaService = modelRelaService;
this.userService = userService;
this.dateInfoRepository = dateInfoRepository;
}
@Override
public void createModel(ModelReq modelReq, User user) {
modelReq.createdBy(user.getName());
ModelDO modelDO = ModelConvert.convert(modelReq);
modelRepository.createModel(modelDO);
@Transactional
public ModelResp createModel(ModelReq modelReq, User user) throws Exception {
checkName(modelReq);
ModelDO datasourceDO = ModelConverter.convert(modelReq, user);
modelRepository.createModel(datasourceDO);
batchCreateDimension(datasourceDO, user);
batchCreateMetric(datasourceDO, user);
return ModelConverter.convert(datasourceDO);
}
@Override
public void updateModel(ModelReq modelReq, User user) {
ModelDO modelDO = getModelDO(modelReq.getId());
modelReq.updatedBy(user.getName());
int oldStatus = modelDO.getStatus();
BeanMapper.mapper(modelReq, modelDO);
if (modelReq.getEntity() != null) {
modelDO.setEntity(JsonUtil.toString(modelReq.getEntity()));
}
if (modelReq.getDrillDownDimensions() != null) {
modelDO.setDrillDownDimensions(JsonUtil.toString(modelReq.getDrillDownDimensions()));
}
@Transactional
public ModelResp updateModel(ModelReq modelReq, User user) throws Exception {
checkName(modelReq);
ModelDO modelDO = modelRepository.getModelById(modelReq.getId());
ModelConverter.convert(modelDO, modelReq, user);
modelRepository.updateModel(modelDO);
statusPublish(oldStatus, modelDO);
batchCreateDimension(modelDO, user);
batchCreateMetric(modelDO, user);
return ModelConverter.convert(modelDO);
}
private void statusPublish(Integer oldStatus, ModelDO modelDO) {
if (oldStatus.equals(modelDO.getStatus())) {
return;
}
if (oldStatus.equals(StatusEnum.ONLINE.getCode())
&& modelDO.getStatus().equals(StatusEnum.OFFLINE.getCode())) {
publishEvent(EventType.DELETE, modelDO);
} else if (oldStatus.equals(StatusEnum.OFFLINE.getCode())
&& modelDO.getStatus().equals(StatusEnum.ONLINE.getCode())) {
publishEvent(EventType.ADD, modelDO);
}
@Override
public List<ModelResp> getModelList(ModelFilter modelFilter) {
return ModelConverter.convertList(modelRepository.getModelList(modelFilter));
}
private void publishEvent(EventType eventType, ModelDO modelDO) {
eventPublisher.publishEvent(
new DataEvent(this, metricService.getDataItems(modelDO.getId()),
eventType));
eventPublisher.publishEvent(
new DataEvent(this, dimensionService.getDataItems(modelDO.getId()),
eventType));
@Override
public Map<Long, ModelResp> getModelMap() {
Map<Long, ModelResp> map = new HashMap<>();
List<ModelResp> modelResps = getModelList(new ModelFilter());
if (CollectionUtils.isEmpty(modelResps)) {
return map;
}
return modelResps.stream().collect(Collectors.toMap(ModelResp::getId, a -> a, (k1, k2) -> k1));
}
@Override
public void deleteModel(Long id, User user) {
ModelDO datasourceDO = modelRepository.getModelById(id);
if (datasourceDO == null) {
return;
}
checkDelete(id);
ModelDO modelDO = getModelDO(id);
modelDO.setStatus(StatusEnum.DELETED.getCode());
modelDO.setUpdatedAt(new Date());
modelDO.setUpdatedBy(user.getName());
modelRepository.updateModel(modelDO);
datasourceDO.setStatus(StatusEnum.DELETED.getCode());
datasourceDO.setUpdatedAt(new Date());
datasourceDO.setUpdatedBy(user.getName());
modelRepository.updateModel(datasourceDO);
}
@Override
public ItemDateResp getItemDate(ItemDateFilter dimension, ItemDateFilter metric) {
List<DateInfoReq> itemDates = new ArrayList<>();
List<DateInfoDO> dimensions = dateInfoRepository.getDateInfos(dimension);
List<DateInfoDO> metrics = dateInfoRepository.getDateInfos(metric);
log.info("getDateDate, dimension:{}, dimensions dateInfo:{}", dimension, dimensions);
log.info("getDateDate, metric:{}, metrics dateInfo:{}", metric, metrics);
itemDates.addAll(convert(dimensions));
itemDates.addAll(convert(metrics));
ItemDateResp itemDateDescriptor = calculateDateInternal(itemDates);
log.info("itemDateDescriptor:{}", itemDateDescriptor);
return itemDateDescriptor;
}
@Override
public List<MeasureResp> getMeasureListOfModel(List<Long> modelIds) {
ModelFilter modelFilter = new ModelFilter();
modelFilter.setIds(modelIds);
List<ModelResp> modelResps = getModelList(modelFilter);
return modelResps.stream().flatMap(modelResp -> modelResp.getModelDetail().getMeasures()
.stream().map(measure -> ModelConverter.convert(measure, modelResp))).collect(Collectors.toList());
}
private void batchCreateDimension(ModelDO datasourceDO, User user) throws Exception {
List<DimensionReq> dimensionReqs = ModelConverter.convertDimensionList(datasourceDO);
dimensionService.createDimensionBatch(dimensionReqs, user);
}
private void batchCreateMetric(ModelDO datasourceDO, User user) throws Exception {
List<MetricReq> exprMetricReqs = ModelConverter.convertMetricList(datasourceDO);
metricService.createMetricBatch(exprMetricReqs, user);
}
private void checkName(ModelReq modelReq) {
if (NameCheckUtils.containsSpecialCharacters(modelReq.getName())) {
String message = String.format("模型名称[%s]包含特殊字符, 请修改", modelReq.getName());
throw new InvalidArgumentException(message);
}
List<Dim> dims = modelReq.getModelDetail().getDimensions();
List<Measure> measures = modelReq.getModelDetail().getMeasures();
List<Dim> timeDims = modelReq.getTimeDimension();
List<Identify> identifies = modelReq.getModelDetail().getIdentifiers();
if (CollectionUtils.isEmpty(dims)) {
throw new InvalidArgumentException("缺少维度信息");
}
if (!CollectionUtils.isEmpty(measures) && CollectionUtils.isEmpty(timeDims)) {
throw new InvalidArgumentException("有度量时, 不可缺少时间维度");
}
for (Measure measure : measures) {
if (StringUtils.isNotBlank(measure.getName())
&& NameCheckUtils.containsSpecialCharacters(measure.getName())) {
String message = String.format("度量[%s]包含特殊字符, 请修改", measure.getName());
throw new InvalidArgumentException(message);
}
}
for (Dim dim : dims) {
if (StringUtils.isNotBlank(dim.getName())
&& NameCheckUtils.containsSpecialCharacters(dim.getName())) {
String message = String.format("维度[%s]包含特殊字符, 请修改", dim.getName());
throw new InvalidArgumentException(message);
}
}
for (Identify identify : identifies) {
if (StringUtils.isNotBlank(identify.getName())
&& NameCheckUtils.containsSpecialCharacters(identify.getName())) {
String message = String.format("主键/外键[%s]包含特殊字符, 请修改", identify.getName());
throw new InvalidArgumentException(message);
}
}
}
private void checkDelete(Long modelId) {
MetaFilter metaFilter = new MetaFilter();
metaFilter.setModelIds(Lists.newArrayList(modelId));
List<MetricResp> metricResps = metricService.getMetrics(metaFilter);
List<DimensionResp> dimensionResps = dimensionService.getDimensions(metaFilter);
if (!CollectionUtils.isEmpty(metricResps) || !CollectionUtils.isEmpty(dimensionResps)) {
throw new RuntimeException("存在基于该模型创建的指标和维度, 暂不能删除, 请确认");
}
}
private ItemDateResp calculateDateInternal(List<DateInfoReq> itemDates) {
if (CollectionUtils.isEmpty(itemDates)) {
log.warn("itemDates is empty!");
return null;
}
String dateFormat = itemDates.get(0).getDateFormat();
String startDate = itemDates.get(0).getStartDate();
String endDate = itemDates.get(0).getEndDate();
String datePeriod = itemDates.get(0).getDatePeriod();
List<String> unavailableDateList = itemDates.get(0).getUnavailableDateList();
for (DateInfoReq item : itemDates) {
String startDate1 = item.getStartDate();
String endDate1 = item.getEndDate();
List<String> unavailableDateList1 = item.getUnavailableDateList();
if (Strings.isNotEmpty(startDate1) && startDate1.compareTo(startDate) > 0) {
startDate = startDate1;
}
if (Strings.isNotEmpty(endDate1) && endDate1.compareTo(endDate) < 0) {
endDate = endDate1;
}
if (!CollectionUtils.isEmpty(unavailableDateList1)) {
unavailableDateList.addAll(unavailableDateList1);
}
}
return new ItemDateResp(dateFormat, startDate, endDate, datePeriod, unavailableDateList);
}
@Override
@@ -145,7 +287,8 @@ public class ModelServiceImpl implements ModelService {
modelRespSet = modelRespSet.stream().filter(modelResp ->
modelResp.getDomainId().equals(domainId)).collect(Collectors.toSet());
}
return fillMetricInfo(new ArrayList<>(modelRespSet));
return fillMetricInfo(new ArrayList<>(modelRespSet)).stream()
.sorted(Comparator.comparingLong(SchemaItem::getId)).collect(Collectors.toList());
}
public List<ModelResp> getModelRespAuthInheritDomain(User user, AuthType authType) {
@@ -153,7 +296,7 @@ public class ModelServiceImpl implements ModelService {
if (CollectionUtils.isEmpty(domainResps)) {
return Lists.newArrayList();
}
List<ModelResp> allModelList = getModelList();
List<ModelResp> allModelList = getModelList(new ModelFilter());
Set<Long> domainIds = domainResps.stream().map(DomainResp::getId).collect(Collectors.toSet());
return allModelList.stream().filter(modelResp ->
domainIds.contains(modelResp.getDomainId())).collect(Collectors.toList());
@@ -161,7 +304,7 @@ public class ModelServiceImpl implements ModelService {
@Override
public List<ModelResp> getModelAuthList(User user, AuthType authTypeEnum) {
List<ModelResp> modelResps = getModelList();
List<ModelResp> modelResps = getModelList(new ModelFilter());
Set<String> orgIds = userService.getUserAllOrgId(user.getName());
List<ModelResp> modelWithAuth = Lists.newArrayList();
if (authTypeEnum.equals(AuthType.ADMIN)) {
@@ -182,7 +325,9 @@ public class ModelServiceImpl implements ModelService {
if (CollectionUtils.isEmpty(domainIds)) {
return Lists.newArrayList();
}
List<ModelResp> modelResps = getModelList();
ModelFilter modelFilter = new ModelFilter();
modelFilter.setDomainIds(domainIds);
List<ModelResp> modelResps = getModelList(modelFilter);
if (CollectionUtils.isEmpty(modelResps)) {
return modelResps;
}
@@ -190,75 +335,15 @@ public class ModelServiceImpl implements ModelService {
domainIds.contains(modelResp.getDomainId())).collect(Collectors.toList());
}
@Override
public List<ModelResp> getModelList(List<Long> modelIds) {
return getModelList().stream()
.filter(modelDO -> modelIds.contains(modelDO.getId()))
.collect(Collectors.toList());
}
@Override
public List<ModelResp> getModelList() {
return convertList(modelRepository.getModelList());
}
@Override
public ModelResp getModel(Long id) {
ModelDO modelDO = getModelDO(id);
if (modelDO == null) {
return null;
}
Map<Long, DomainResp> domainRespMap = domainService.getDomainList().stream()
.collect(Collectors.toMap(DomainResp::getId, d -> d));
return ModelConvert.convert(getModelDO(id), domainRespMap);
}
private void checkDelete(Long id) {
MetaFilter metaFilter = new MetaFilter(Lists.newArrayList(id));
List<MetricResp> metricResps = metricService.getMetrics(metaFilter);
List<DimensionResp> dimensionResps = dimensionService.getDimensions(metaFilter);
List<DatasourceResp> datasourceResps = datasourceService.getDatasourceList(id);
if (!CollectionUtils.isEmpty(metricResps) || !CollectionUtils.isEmpty(datasourceResps)
|| !CollectionUtils.isEmpty(dimensionResps)) {
throw new RuntimeException("该模型下存在数据源、指标或者维度, 暂不能删除, 请确认");
}
}
private List<ModelResp> convertList(List<ModelDO> modelDOS) {
List<ModelResp> modelResps = Lists.newArrayList();
if (CollectionUtils.isEmpty(modelDOS)) {
return modelResps;
}
Map<Long, DomainResp> domainRespMap = domainService.getDomainList()
.stream().collect(Collectors.toMap(DomainResp::getId, d -> d));
return modelDOS.stream()
.map(modelDO -> ModelConvert.convert(modelDO, domainRespMap))
.collect(Collectors.toList());
}
private List<ModelResp> fillMetricInfo(List<ModelResp> modelResps) {
if (CollectionUtils.isEmpty(modelResps)) {
return modelResps;
}
Map<Long, List<MetricResp>> metricMap = metricService.getMetrics(new MetricFilter()).stream()
.collect(Collectors.groupingBy(MetricResp::getModelId));
Map<Long, List<DimensionResp>> dimensionMap = dimensionService.getDimensions(new DimensionFilter()).stream()
.collect(Collectors.groupingBy(DimensionResp::getModelId));
modelResps.forEach(modelResp -> {
modelResp.setDimensionCnt(dimensionMap.getOrDefault(modelResp.getId(), Lists.newArrayList()).size());
modelResp.setMetricCnt(metricMap.getOrDefault(modelResp.getId(), Lists.newArrayList()).size());
});
return modelResps;
}
@Override
public Map<Long, ModelResp> getModelMap() {
return getModelList().stream().collect(Collectors.toMap(ModelResp::getId, a -> a, (k1, k2) -> k1));
}
@Override
public Map<Long, String> getModelFullPathMap() {
return getModelList().stream().filter(m -> m != null && m.getFullPath() != null)
.collect(Collectors.toMap(ModelResp::getId,
ModelResp::getFullPath, (k1, k2) -> k1));
return ModelConverter.convert(modelDO, domainRespMap);
}
@Override
@@ -282,12 +367,9 @@ public class ModelServiceImpl implements ModelService {
return Lists.newArrayList();
}
protected ModelDO getModelDO(Long id) {
return modelRepository.getModelById(id);
}
private ModelSchemaResp fetchSingleModelSchema(ModelResp modelResp) {
Long modelId = modelResp.getId();
@Override
public ModelSchemaResp fetchSingleModelSchema(Long modelId) {
ModelResp modelResp = getModel(modelId);
ModelSchemaResp modelSchemaResp = new ModelSchemaResp();
BeanUtils.copyProperties(modelResp, modelSchemaResp);
modelSchemaResp.setDimensions(generateDimSchema(modelId));
@@ -295,12 +377,6 @@ public class ModelServiceImpl implements ModelService {
return modelSchemaResp;
}
@Override
public ModelSchemaResp fetchSingleModelSchema(Long modelId) {
ModelResp model = getModel(modelId);
return fetchSingleModelSchema(model);
}
@Override
public List<ModelSchemaResp> fetchModelSchema(ModelSchemaFilterReq modelSchemaFilterReq) {
List<ModelSchemaResp> modelSchemaRespList = new ArrayList<>();
@@ -314,23 +390,24 @@ public class ModelServiceImpl implements ModelService {
.stream().collect(Collectors.groupingBy(MetricResp::getModelId));
Map<Long, List<DimensionResp>> dimensionRespsMap = dimensionService.getDimensions(metaFilter)
.stream().collect(Collectors.groupingBy(DimensionResp::getModelId));
Map<Long, List<MeasureResp>> measureRespsMap = datasourceService.getMeasureListOfModel(modelIds)
.stream().collect(Collectors.groupingBy(MeasureResp::getModelId));
List<ModelRela> modelRelas = modelRelaService.getModelRela(modelIds);
for (Long modelId : modelIds) {
ModelResp modelResp = getModelMap().get(modelId);
if (modelResp == null || !StatusEnum.ONLINE.getCode().equals(modelResp.getStatus())) {
continue;
}
List<MeasureResp> measureResps = measureRespsMap.getOrDefault(modelId, Lists.newArrayList());
List<MetricResp> metricResps = metricRespMap.getOrDefault(modelId, Lists.newArrayList());
List<MetricSchemaResp> metricSchemaResps = metricResps.stream().map(metricResp ->
convert(metricResp, metricResps, measureResps, modelResp)).collect(Collectors.toList());
convert(metricResp, modelResp)).collect(Collectors.toList());
List<DimSchemaResp> dimensionResps = dimensionRespsMap.getOrDefault(modelId, Lists.newArrayList())
.stream().map(this::convert).collect(Collectors.toList());
ModelSchemaResp modelSchemaResp = new ModelSchemaResp();
BeanUtils.copyProperties(modelResp, modelSchemaResp);
modelSchemaResp.setDimensions(dimensionResps);
modelSchemaResp.setMetrics(metricSchemaResps);
modelSchemaResp.setModelRelas(modelRelas.stream().filter(modelRela
-> modelRela.getFromModelId().equals(modelId) || modelRela.getToModelId().equals(modelId))
.collect(Collectors.toList()));
modelSchemaRespList.add(modelSchemaResp);
}
return modelSchemaRespList;
@@ -338,20 +415,58 @@ public class ModelServiceImpl implements ModelService {
@Override
public DatabaseResp getDatabaseByModelId(Long modelId) {
List<DatasourceResp> datasourceResps = datasourceService.getDatasourceList(modelId);
if (!CollectionUtils.isEmpty(datasourceResps)) {
Long databaseId = datasourceResps.iterator().next().getDatabaseId();
ModelResp modelResp = getModel(modelId);
if (modelResp != null) {
Long databaseId = modelResp.getDatabaseId();
return databaseService.getDatabase(databaseId);
}
return null;
}
@Override
public void batchUpdateStatus(MetaBatchReq metaBatchReq, User user) {
if (CollectionUtils.isEmpty(metaBatchReq.getIds())) {
return;
}
ModelFilter modelFilter = new ModelFilter();
modelFilter.setIds(metaBatchReq.getIds());
List<ModelDO> modelDOS = modelRepository.getModelList(modelFilter);
if (CollectionUtils.isEmpty(modelDOS)) {
return;
}
modelDOS = modelDOS.stream()
.peek(modelDO -> {
modelDO.setStatus(metaBatchReq.getStatus());
modelDO.setUpdatedAt(new Date());
modelDO.setUpdatedBy(user.getName());
})
.collect(Collectors.toList());
modelRepository.batchUpdate(modelDOS);
}
private List<ModelResp> fillMetricInfo(List<ModelResp> modelResps) {
if (CollectionUtils.isEmpty(modelResps)) {
return modelResps;
}
Map<Long, List<MetricResp>> metricMap = metricService.getMetrics(new MetricFilter()).stream()
.collect(Collectors.groupingBy(MetricResp::getModelId));
Map<Long, List<DimensionResp>> dimensionMap = dimensionService.getDimensions(new DimensionFilter()).stream()
.collect(Collectors.groupingBy(DimensionResp::getModelId));
modelResps.forEach(modelResp -> {
modelResp.setDimensionCnt(dimensionMap.getOrDefault(modelResp.getId(), Lists.newArrayList()).size());
modelResp.setMetricCnt(metricMap.getOrDefault(modelResp.getId(), Lists.newArrayList()).size());
});
return modelResps;
}
protected ModelDO getModelDO(Long id) {
return modelRepository.getModelById(id);
}
private List<MetricSchemaResp> generateMetricSchema(Long modelId, ModelResp modelResp) {
List<MetricSchemaResp> metricSchemaDescList = new ArrayList<>();
List<MetricResp> metricResps = metricService.getMetrics(new MetaFilter(Lists.newArrayList(modelId)));
List<MeasureResp> measureResps = datasourceService.getMeasureListOfModel(Lists.newArrayList(modelId));
metricResps.stream().forEach(metricResp ->
metricSchemaDescList.add(convert(metricResp, metricResps, measureResps, modelResp)));
metricResps.forEach(metricResp -> metricSchemaDescList.add(convert(metricResp, modelResp)));
return metricSchemaDescList;
}
@@ -367,8 +482,7 @@ public class ModelServiceImpl implements ModelService {
return dimSchemaResp;
}
private MetricSchemaResp convert(MetricResp metricResp, List<MetricResp> metricResps,
List<MeasureResp> measureResps, ModelResp modelResp) {
private MetricSchemaResp convert(MetricResp metricResp, ModelResp modelResp) {
MetricSchemaResp metricSchemaResp = new MetricSchemaResp();
BeanUtils.copyProperties(metricResp, metricSchemaResp);
RelateDimension relateDimension = metricResp.getRelateDimension();
@@ -377,11 +491,20 @@ public class ModelServiceImpl implements ModelService {
.drillDownDimensions(modelResp.getDrillDownDimensions()).build());
}
metricSchemaResp.setUseCnt(0L);
String agg = catalog.getAgg(metricResps, measureResps, metricSchemaResp.getBizName());
metricSchemaResp.setDefaultAgg(agg);
return metricSchemaResp;
}
private List<DateInfoReq> convert(List<DateInfoDO> dateInfoDOList) {
List<DateInfoReq> dateInfoCommendList = new ArrayList<>();
dateInfoDOList.forEach(dateInfoDO -> {
DateInfoReq dateInfoCommend = new DateInfoReq();
BeanUtils.copyProperties(dateInfoDO, dateInfoCommend);
dateInfoCommend.setUnavailableDateList(JsonUtil.toList(dateInfoDO.getUnavailableDateList(), String.class));
dateInfoCommendList.add(dateInfoCommend);
});
return dateInfoCommendList;
}
private List<Long> generateModelIdsReq(ModelSchemaFilterReq filter) {
if (Objects.nonNull(filter) && !CollectionUtils.isEmpty(filter.getModelIds())) {
return filter.getModelIds();
@@ -411,9 +534,10 @@ public class ModelServiceImpl implements ModelService {
}
public static boolean checkViewerPermission(Set<String> orgIds, User user, ModelResp modelResp) {
List<String> admins = modelResp.getAdmins();
if (checkAdminPermission(orgIds, user, modelResp)) {
return true;
}
List<String> viewers = modelResp.getViewers();
List<String> adminOrgs = modelResp.getAdminOrgs();
List<String> viewOrgs = modelResp.getViewOrgs();
if (user.isSuperAdmin()) {
return true;
@@ -422,17 +546,12 @@ public class ModelServiceImpl implements ModelService {
return true;
}
String userName = user.getName();
if (admins.contains(userName) || viewers.contains(userName) || modelResp.getCreatedBy().equals(userName)) {
if (viewers.contains(userName) || modelResp.getCreatedBy().equals(userName)) {
return true;
}
if (CollectionUtils.isEmpty(adminOrgs) && CollectionUtils.isEmpty(viewOrgs)) {
if (CollectionUtils.isEmpty(viewOrgs)) {
return false;
}
for (String orgId : orgIds) {
if (adminOrgs.contains(orgId)) {
return true;
}
}
for (String orgId : orgIds) {
if (viewOrgs.contains(orgId)) {
return true;
@@ -440,4 +559,43 @@ public class ModelServiceImpl implements ModelService {
}
return false;
}
@Override
public void getModelYamlTplByModelIds(Set<Long> modelIds, Map<String, List<DimensionYamlTpl>> dimensionYamlMap,
List<DataModelYamlTpl> dataModelYamlTplList, List<MetricYamlTpl> metricYamlTplList,
Map<Long, String> modelIdName) {
for (Long modelId : modelIds) {
ModelResp modelResp = getModel(modelId);
modelIdName.put(modelId, modelResp.getBizName());
MetaFilter metaFilter = new MetaFilter(Lists.newArrayList(modelId));
List<MetricResp> metricResps = metricService.getMetrics(metaFilter);
metricYamlTplList.addAll(MetricYamlManager.convert2YamlObj(MetricConverter.metricInfo2Metric(metricResps)));
Long databaseId = modelResp.getDatabaseId();
DatabaseResp databaseResp = databaseService.getDatabase(databaseId);
List<DimensionResp> dimensionResps = dimensionService.getDimensions(metaFilter);
dataModelYamlTplList.add(DatasourceYamlManager.convert2YamlObj(
datasourceInfo2Datasource(modelResp), databaseResp));
if (!dimensionYamlMap.containsKey(modelResp.getBizName())) {
dimensionYamlMap.put(modelResp.getBizName(), new ArrayList<>());
}
List<DimensionResp> dimensionRespList = dimensionResps.stream()
.filter(d -> d.getModelBizName().equalsIgnoreCase(modelResp.getBizName()))
.collect(Collectors.toList());
dimensionYamlMap.get(modelResp.getBizName()).addAll(DimensionYamlManager.convert2DimensionYaml(
DimensionConverter.dimensionInfo2Dimension(dimensionRespList)));
}
}
public static Datasource datasourceInfo2Datasource(ModelResp modelResp) {
Datasource datasource = new Datasource();
BeanUtils.copyProperties(modelResp, datasource);
datasource.setDatasourceDetail(modelResp.getModelDetail());
datasource.setModelId(modelResp.getId());
datasource.setDatabaseId(modelResp.getDatabaseId());
return datasource;
}
}

View File

@@ -1,63 +1,64 @@
package com.tencent.supersonic.semantic.model.application;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.semantic.api.model.request.ViewInfoReq;
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.ModelSchemaRelaResp;
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
import com.tencent.supersonic.semantic.model.domain.dataobject.ViewInfoDO;
import com.tencent.supersonic.semantic.model.domain.pojo.MetaFilter;
import com.tencent.supersonic.semantic.model.domain.repository.ViewInfoRepository;
import com.tencent.supersonic.semantic.model.domain.DatasourceService;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.api.model.response.ModelSchemaRelaResp;
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.ViewInfoDO;
import com.tencent.supersonic.semantic.model.domain.pojo.MetaFilter;
import com.tencent.supersonic.semantic.model.domain.pojo.ModelFilter;
import com.tencent.supersonic.semantic.model.domain.repository.ViewInfoRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.List;
import org.assertj.core.util.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@Service
public class ViewInfoServiceImpl {
private ViewInfoRepository viewInfoRepository;
private DatasourceService datasourceService;
private ModelService modelService;
private DimensionService dimensionService;
private MetricService metricService;
public ViewInfoServiceImpl(ViewInfoRepository viewInfoRepository, DatasourceService datasourceService,
public ViewInfoServiceImpl(ViewInfoRepository viewInfoRepository, ModelService modelService,
MetricService metricService, DimensionService dimensionService) {
this.viewInfoRepository = viewInfoRepository;
this.dimensionService = dimensionService;
this.metricService = metricService;
this.datasourceService = datasourceService;
this.modelService = modelService;
}
public List<ViewInfoDO> getViewInfoList(Long modelId) {
return viewInfoRepository.getViewInfoList(modelId);
}
public List<ModelSchemaRelaResp> getDomainSchema(Long modelId) {
public List<ModelSchemaRelaResp> getDomainSchema(Long domainId) {
List<ModelSchemaRelaResp> domainSchemaRelaResps = Lists.newArrayList();
List<DatasourceResp> datasourceResps = datasourceService.getDatasourceList(modelId);
for (DatasourceResp datasourceResp : datasourceResps) {
ModelFilter modelFilter = new ModelFilter();
modelFilter.setDomainIds(Lists.newArrayList(domainId));
List<ModelResp> modelResps = modelService.getModelList(modelFilter);
for (ModelResp modelResp : modelResps) {
ModelSchemaRelaResp domainSchemaRelaResp = new ModelSchemaRelaResp();
Long datasourceId = datasourceResp.getId();
MetaFilter metaFilter = new MetaFilter();
metaFilter.setModelIds(Lists.newArrayList(modelId));
metaFilter.setDatasourceId(datasourceId);
metaFilter.setModelIds(Lists.newArrayList(modelResp.getId()));
List<MetricResp> metricResps = metricService.getMetrics(metaFilter);
List<DimensionResp> dimensionResps = dimensionService.getDimensions(metaFilter);
domainSchemaRelaResp.setDatasource(datasourceResp);
domainSchemaRelaResp.setModel(modelResp);
domainSchemaRelaResp.setDimensions(dimensionResps);
domainSchemaRelaResp.setMetrics(metricResps);
domainSchemaRelaResp.setDomainId(modelId);
domainSchemaRelaResp.setDomainId(domainId);
domainSchemaRelaResps.add(domainSchemaRelaResp);
}
return domainSchemaRelaResps;

View File

@@ -1,15 +1,15 @@
package com.tencent.supersonic.semantic.model.domain;
import com.tencent.supersonic.common.pojo.ItemDateResp;
import com.tencent.supersonic.common.pojo.ModelRela;
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.common.pojo.ItemDateResp;
import com.tencent.supersonic.semantic.api.model.response.MeasureResp;
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
import com.tencent.supersonic.semantic.api.model.yaml.DatasourceYamlTpl;
import com.tencent.supersonic.semantic.api.model.yaml.DataModelYamlTpl;
import com.tencent.supersonic.semantic.api.model.yaml.DimensionYamlTpl;
import com.tencent.supersonic.semantic.api.model.yaml.MetricYamlTpl;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -20,24 +20,23 @@ public interface Catalog {
DatabaseResp getDatabaseByModelId(Long modelId);
List<DatasourceResp> getDatasourceList(Long modelId);
String getModelFullPath(Long modelId);
Map<Long, String> getModelFullPath();
String getModelFullPath(List<Long> modelIds);
DimensionResp getDimension(String bizName, Long modelId);
List<DimensionResp> getDimensions(Long modelId);
List<DimensionResp> getDimensions(List<Long> modelIds);
List<MetricResp> getMetrics(Long modelId);
List<MetricResp> getMetrics(List<Long> modelIds);
List<ModelRela> getModelRela(List<Long> modelIds);
void getModelYamlTplByModelIds(Set<Long> modelIds, Map<String, List<DimensionYamlTpl>> dimensionYamlMap,
List<DatasourceYamlTpl> datasourceYamlTplList, List<MetricYamlTpl> metricYamlTplList);
List<DataModelYamlTpl> dataModelYamlTplList, List<MetricYamlTpl> metricYamlTplList,
Map<Long, String> modelIdName);
ItemDateResp getItemDate(ItemDateFilter dimension, ItemDateFilter metric);
String getAgg(List<MetricResp> metricResps, List<MeasureResp> measureRespList, String metricBizName);
}

View File

@@ -1,42 +0,0 @@
package com.tencent.supersonic.semantic.model.domain;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.semantic.api.model.pojo.ItemDateFilter;
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.api.model.request.DatasourceReq;
import com.tencent.supersonic.semantic.api.model.response.DatasourceResp;
import com.tencent.supersonic.common.pojo.ItemDateResp;
import com.tencent.supersonic.semantic.api.model.response.MeasureResp;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface DatasourceService {
DatasourceResp createDatasource(DatasourceReq datasourceReq, User user) throws Exception;
DatasourceResp updateDatasource(DatasourceReq datasourceReq, User user) throws Exception;
List<DatasourceResp> getDatasourceListNoMeasurePrefix(Long modelId);
List<DatasourceResp> getDatasourceList();
List<DatasourceResp> getDatasourceList(Long modelId);
List<DatasourceResp> getDatasourceByDatabase(Long databaseId);
Map<Long, DatasourceResp> getDatasourceMap();
void deleteDatasource(Long id, User user);
ItemDateResp getItemDate(ItemDateFilter dimension, ItemDateFilter metric);
List<MeasureResp> getMeasureListOfModel(List<Long> modelIds);
void getModelYamlTplByModelIds(Set<Long> modelIds, Map<String, List<DimensionYamlTpl>> dimensionYamlMap,
List<DatasourceYamlTpl> datasourceYamlTplList, List<MetricYamlTpl> metricYamlTplList);
}

View File

@@ -0,0 +1,20 @@
package com.tencent.supersonic.semantic.model.domain;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.ModelRela;
import java.util.List;
public interface ModelRelaService {
void save(ModelRela modelRela, User user);
void update(ModelRela modelRela, User user);
List<ModelRela> getModelRelaList(Long domainId);
List<ModelRela> getModelRela(List<Long> modelIds);
void delete(Long id);
}

View File

@@ -1,39 +1,48 @@
package com.tencent.supersonic.semantic.model.domain;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.ItemDateResp;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.semantic.api.model.pojo.ItemDateFilter;
import com.tencent.supersonic.semantic.api.model.request.MetaBatchReq;
import com.tencent.supersonic.semantic.api.model.request.ModelReq;
import com.tencent.supersonic.semantic.api.model.request.ModelSchemaFilterReq;
import com.tencent.supersonic.semantic.api.model.response.DatabaseResp;
import com.tencent.supersonic.semantic.api.model.response.MeasureResp;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.api.model.response.ModelSchemaResp;
import com.tencent.supersonic.semantic.api.model.yaml.DataModelYamlTpl;
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.pojo.ModelFilter;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface ModelService {
ModelResp createModel(ModelReq datasourceReq, User user) throws Exception;
ModelResp updateModel(ModelReq datasourceReq, User user) throws Exception;
List<ModelResp> getModelList(ModelFilter modelFilter);
Map<Long, ModelResp> getModelMap();
void deleteModel(Long id, User user);
ItemDateResp getItemDate(ItemDateFilter dimension, ItemDateFilter metric);
List<MeasureResp> getMeasureListOfModel(List<Long> modelIds);
List<ModelResp> getModelListWithAuth(User user, Long domainId, AuthType authType);
List<ModelResp> getModelAuthList(User user, AuthType authTypeEnum);
List<ModelResp> getModelByDomainIds(List<Long> domainIds);
List<ModelResp> getModelList();
List<ModelResp> getModelList(List<Long> modelIds);
ModelResp getModel(Long id);
void updateModel(ModelReq modelReq, User user);
void createModel(ModelReq modelReq, User user);
void deleteModel(Long id, User user);
Map<Long, ModelResp> getModelMap();
Map<Long, String> getModelFullPathMap();
List<String> getModelAdmin(Long id);
ModelSchemaResp fetchSingleModelSchema(Long modelId);
@@ -41,4 +50,11 @@ public interface ModelService {
List<ModelSchemaResp> fetchModelSchema(ModelSchemaFilterReq modelSchemaFilterReq);
DatabaseResp getDatabaseByModelId(Long modelId);
void batchUpdateStatus(MetaBatchReq metaBatchReq, User user);
void getModelYamlTplByModelIds(Set<Long> modelIds, Map<String, List<DimensionYamlTpl>> dimensionYamlMap,
List<DataModelYamlTpl> dataModelYamlTplList, List<MetricYamlTpl> metricYamlTplList,
Map<Long, String> modelIdName);
}

View File

@@ -1,78 +0,0 @@
package com.tencent.supersonic.semantic.model.domain.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("s2_datasource")
public class DatasourceDO {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 模型ID
*/
private Long modelId;
/**
* 数据源名称
*/
private String name;
/**
* 内部名称
*/
private String bizName;
/**
* 数据源描述
*/
private String description;
/**
* 数据库实例ID
*/
private Long databaseId;
/**
*
*/
private Integer status;
/**
* 创建时间
*/
private Date createdAt;
/**
* 创建人
*/
private String createdBy;
/**
* 更新时间
*/
private Date updatedAt;
/**
* 更新人
*/
private String updatedBy;
/**
* 数据源配置
*/
private String datasourceDetail;
/**
* 上游依赖标识
*/
private String depends;
private String filterSql;
}

View File

@@ -9,105 +9,44 @@ import java.util.Date;
@Data
@TableName("s2_dimension")
public class DimensionDO {
/**
* 维度ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 主题域id
*/
private Long modelId;
/**
* 所属数据源id
*/
private Long datasourceId;
/**
* 维度名称
*/
private String name;
/**
* 字段名称
*/
private String bizName;
/**
* 描述
*/
private String description;
/**
* 维度状态,0正常,1下架,2删除
*/
private Integer status;
/**
* 敏感级别
*/
private Integer sensitiveLevel;
/**
* 维度类型 categorical,time
*/
private String type;
/**
* 创建时间
*/
private Date createdAt;
/**
* 创建人
*/
private String createdBy;
/**
* 更新时间
*/
private Date updatedAt;
/**
* 更新人
*/
private String updatedBy;
/**
* 语义类型DATE, ID, CATEGORY
*/
private String semanticType;
/**
*
*/
private String alias;
/**
* default values of dimension when query
*/
private String defaultValues;
/**
*
*/
private String dimValueMaps;
/**
* 类型参数
*/
private String typeParams;
/**
* 表达式
*/
private String expr;
/**
* 数据类型
*/
private String dataType;
private int isTag;

View File

@@ -1,11 +1,19 @@
package com.tencent.supersonic.semantic.model.domain.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("s2_domain")
public class DomainDO {
/**
* 自增ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
@@ -73,227 +81,4 @@ public class DomainDO {
*/
private String viewOrg;
/**
* 自增ID
* @return id 自增ID
*/
public Long getId() {
return id;
}
/**
* 自增ID
* @param id 自增ID
*/
public void setId(Long id) {
this.id = id;
}
/**
* 主题域名称
* @return name 主题域名称
*/
public String getName() {
return name;
}
/**
* 主题域名称
* @param name 主题域名称
*/
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
/**
* 内部名称
* @return biz_name 内部名称
*/
public String getBizName() {
return bizName;
}
/**
* 内部名称
* @param bizName 内部名称
*/
public void setBizName(String bizName) {
this.bizName = bizName == null ? null : bizName.trim();
}
/**
* 父主题域ID
* @return parent_id 父主题域ID
*/
public Long getParentId() {
return parentId;
}
/**
* 父主题域ID
* @param parentId 父主题域ID
*/
public void setParentId(Long parentId) {
this.parentId = parentId;
}
/**
* 主题域状态
* @return status 主题域状态
*/
public Integer getStatus() {
return status;
}
/**
* 主题域状态
* @param status 主题域状态
*/
public void setStatus(Integer status) {
this.status = status;
}
/**
* 创建时间
* @return created_at 创建时间
*/
public Date getCreatedAt() {
return createdAt;
}
/**
* 创建时间
* @param createdAt 创建时间
*/
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
/**
* 创建人
* @return created_by 创建人
*/
public String getCreatedBy() {
return createdBy;
}
/**
* 创建人
* @param createdBy 创建人
*/
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy == null ? null : createdBy.trim();
}
/**
* 更新时间
* @return updated_at 更新时间
*/
public Date getUpdatedAt() {
return updatedAt;
}
/**
* 更新时间
* @param updatedAt 更新时间
*/
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
/**
* 更新人
* @return updated_by 更新人
*/
public String getUpdatedBy() {
return updatedBy;
}
/**
* 更新人
* @param updatedBy 更新人
*/
public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy == null ? null : updatedBy.trim();
}
/**
* 主题域管理员
* @return admin 主题域管理员
*/
public String getAdmin() {
return admin;
}
/**
* 主题域管理员
* @param admin 主题域管理员
*/
public void setAdmin(String admin) {
this.admin = admin == null ? null : admin.trim();
}
/**
* 主题域管理员组织
* @return admin_org 主题域管理员组织
*/
public String getAdminOrg() {
return adminOrg;
}
/**
* 主题域管理员组织
* @param adminOrg 主题域管理员组织
*/
public void setAdminOrg(String adminOrg) {
this.adminOrg = adminOrg == null ? null : adminOrg.trim();
}
/**
* 主题域是否公开
* @return is_open 主题域是否公开
*/
public Integer getIsOpen() {
return isOpen;
}
/**
* 主题域是否公开
* @param isOpen 主题域是否公开
*/
public void setIsOpen(Integer isOpen) {
this.isOpen = isOpen;
}
/**
* 主题域可用用户
* @return viewer 主题域可用用户
*/
public String getViewer() {
return viewer;
}
/**
* 主题域可用用户
* @param viewer 主题域可用用户
*/
public void setViewer(String viewer) {
this.viewer = viewer == null ? null : viewer.trim();
}
/**
* 主题域可用组织
* @return view_org 主题域可用组织
*/
public String getViewOrg() {
return viewOrg;
}
/**
* 主题域可用组织
* @param viewOrg 主题域可用组织
*/
public void setViewOrg(String viewOrg) {
this.viewOrg = viewOrg == null ? null : viewOrg.trim();
}
}

View File

@@ -1,383 +1,56 @@
package com.tencent.supersonic.semantic.model.domain.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("s2_model")
public class ModelDO {
/**
*
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
*
*/
private String name;
/**
*
*/
private String bizName;
/**
*
*/
private Long domainId;
/**
*
*/
private String alias;
private String name;
private String bizName;
/**
*
*/
private String description;
/**
*
*/
private String viewer;
private Long databaseId;
/**
*
*/
private String viewOrg;
/**
*
*/
private String admin;
/**
*
*/
private String adminOrg;
/**
*
*/
private Integer isOpen;
/**
*
*/
private String createdBy;
/**
*
*/
private Date createdAt;
/**
*
*/
private String updatedBy;
/**
*
*/
private Date updatedAt;
/**
*
*/
private String drillDownDimensions;
/**
*
*/
private Integer status;
/**
*
*/
private String entity;
private Date createdAt;
/**
*
* @return id
*/
public Long getId() {
return id;
}
private String createdBy;
/**
*
* @param id
*/
public void setId(Long id) {
this.id = id;
}
private Date updatedAt;
/**
*
* @return name
*/
public String getName() {
return name;
}
private String updatedBy;
/**
*
* @param name
*/
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
private String modelDetail;
/**
*
* @return biz_name
*/
public String getBizName() {
return bizName;
}
private String depends;
/**
*
* @param bizName
*/
public void setBizName(String bizName) {
this.bizName = bizName == null ? null : bizName.trim();
}
private String filterSql;
/**
*
* @return domain_id
*/
public Long getDomainId() {
return domainId;
}
private String viewer;
/**
*
* @param domainId
*/
public void setDomainId(Long domainId) {
this.domainId = domainId;
}
private String viewOrg;
/**
*
* @return alias
*/
public String getAlias() {
return alias;
}
private String admin;
/**
*
* @param alias
*/
public void setAlias(String alias) {
this.alias = alias == null ? null : alias.trim();
}
private String adminOrg;
/**
*
* @return description
*/
public String getDescription() {
return description;
}
private Integer isOpen;
/**
*
* @param description
*/
public void setDescription(String description) {
this.description = description == null ? null : description.trim();
}
private String drillDownDimensions;
/**
*
* @return viewer
*/
public String getViewer() {
return viewer;
}
private String alias;
/**
*
* @param viewer
*/
public void setViewer(String viewer) {
this.viewer = viewer == null ? null : viewer.trim();
}
/**
*
* @return view_org
*/
public String getViewOrg() {
return viewOrg;
}
/**
*
* @param viewOrg
*/
public void setViewOrg(String viewOrg) {
this.viewOrg = viewOrg == null ? null : viewOrg.trim();
}
/**
*
* @return admin
*/
public String getAdmin() {
return admin;
}
/**
*
* @param admin
*/
public void setAdmin(String admin) {
this.admin = admin == null ? null : admin.trim();
}
/**
*
* @return admin_org
*/
public String getAdminOrg() {
return adminOrg;
}
/**
*
* @param adminOrg
*/
public void setAdminOrg(String adminOrg) {
this.adminOrg = adminOrg == null ? null : adminOrg.trim();
}
/**
*
* @return is_open
*/
public Integer getIsOpen() {
return isOpen;
}
/**
*
* @param isOpen
*/
public void setIsOpen(Integer isOpen) {
this.isOpen = isOpen;
}
/**
*
* @return created_by
*/
public String getCreatedBy() {
return createdBy;
}
/**
*
* @param createdBy
*/
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy == null ? null : createdBy.trim();
}
/**
*
* @return created_at
*/
public Date getCreatedAt() {
return createdAt;
}
/**
*
* @param createdAt
*/
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
/**
*
* @return updated_by
*/
public String getUpdatedBy() {
return updatedBy;
}
/**
*
* @param updatedBy
*/
public void setUpdatedBy(String updatedBy) {
this.updatedBy = updatedBy == null ? null : updatedBy.trim();
}
/**
*
* @return updated_at
*/
public Date getUpdatedAt() {
return updatedAt;
}
/**
*
* @param updatedAt
*/
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
/**
*
* @return drill_down_dimensions
*/
public String getDrillDownDimensions() {
return drillDownDimensions;
}
/**
*
* @param drillDownDimensions
*/
public void setDrillDownDimensions(String drillDownDimensions) {
this.drillDownDimensions = drillDownDimensions == null ? null : drillDownDimensions.trim();
}
/**
*
* @return status
*/
public Integer getStatus() {
return status;
}
/**
*
* @param status
*/
public void setStatus(Integer status) {
this.status = status;
}
/**
*
* @return entity
*/
public String getEntity() {
return entity;
}
/**
*
* @param entity
*/
public void setEntity(String entity) {
this.entity = entity == null ? null : entity.trim();
}
}

View File

@@ -0,0 +1,26 @@
package com.tencent.supersonic.semantic.model.domain.dataobject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("s2_model_rela")
public class ModelRelaDO {
@TableId(type = IdType.AUTO)
private Long id;
private Long domainId;
private Long fromModelId;
private Long toModelId;
private String joinType;
private String joinCondition;
}

View File

@@ -1,11 +1,11 @@
package com.tencent.supersonic.semantic.model.domain.manager;
import com.tencent.supersonic.semantic.api.model.pojo.DatasourceDetail;
import com.tencent.supersonic.semantic.api.model.pojo.ModelDetail;
import com.tencent.supersonic.semantic.api.model.pojo.Dim;
import com.tencent.supersonic.semantic.api.model.pojo.Identify;
import com.tencent.supersonic.semantic.api.model.pojo.Measure;
import com.tencent.supersonic.semantic.api.model.response.DatabaseResp;
import com.tencent.supersonic.semantic.api.model.yaml.DatasourceYamlTpl;
import com.tencent.supersonic.semantic.api.model.yaml.DataModelYamlTpl;
import com.tencent.supersonic.semantic.api.model.yaml.DimensionTimeTypeParamsTpl;
import com.tencent.supersonic.semantic.api.model.yaml.DimensionYamlTpl;
import com.tencent.supersonic.semantic.api.model.yaml.IdentifyYamlTpl;
@@ -27,27 +27,27 @@ import org.springframework.util.CollectionUtils;
@Slf4j
public class DatasourceYamlManager {
public static DatasourceYamlTpl convert2YamlObj(Datasource datasource, DatabaseResp databaseResp) {
DatasourceDetail datasourceDetail = datasource.getDatasourceDetail();
public static DataModelYamlTpl convert2YamlObj(Datasource datasource, DatabaseResp databaseResp) {
ModelDetail datasourceDetail = datasource.getDatasourceDetail();
EngineAdaptor engineAdaptor = EngineAdaptorFactory.getEngineAdaptor(databaseResp.getType());
SysTimeDimensionBuilder.addSysTimeDimension(datasourceDetail.getDimensions(), engineAdaptor);
addInterCntMetric(datasource.getBizName(), datasourceDetail);
DatasourceYamlTpl datasourceYamlTpl = new DatasourceYamlTpl();
BeanUtils.copyProperties(datasourceDetail, datasourceYamlTpl);
datasourceYamlTpl.setIdentifiers(datasourceDetail.getIdentifiers().stream().map(DatasourceYamlManager::convert)
DataModelYamlTpl dataModelYamlTpl = new DataModelYamlTpl();
BeanUtils.copyProperties(datasourceDetail, dataModelYamlTpl);
dataModelYamlTpl.setIdentifiers(datasourceDetail.getIdentifiers().stream().map(DatasourceYamlManager::convert)
.collect(Collectors.toList()));
datasourceYamlTpl.setDimensions(datasourceDetail.getDimensions().stream().map(DatasourceYamlManager::convert)
dataModelYamlTpl.setDimensions(datasourceDetail.getDimensions().stream().map(DatasourceYamlManager::convert)
.collect(Collectors.toList()));
datasourceYamlTpl.setMeasures(datasourceDetail.getMeasures().stream().map(DatasourceYamlManager::convert)
dataModelYamlTpl.setMeasures(datasourceDetail.getMeasures().stream().map(DatasourceYamlManager::convert)
.collect(Collectors.toList()));
datasourceYamlTpl.setName(datasource.getBizName());
datasourceYamlTpl.setSourceId(datasource.getDatabaseId());
dataModelYamlTpl.setName(datasource.getBizName());
dataModelYamlTpl.setSourceId(datasource.getDatabaseId());
if (datasourceDetail.getQueryType().equalsIgnoreCase(DatasourceQueryEnum.SQL_QUERY.getName())) {
datasourceYamlTpl.setSqlQuery(datasourceDetail.getSqlQuery());
dataModelYamlTpl.setSqlQuery(datasourceDetail.getSqlQuery());
} else {
datasourceYamlTpl.setTableQuery(datasourceDetail.getTableQuery());
dataModelYamlTpl.setTableQuery(datasourceDetail.getTableQuery());
}
return datasourceYamlTpl;
return dataModelYamlTpl;
}
public static DimensionYamlTpl convert(Dim dim) {
@@ -81,7 +81,7 @@ public class DatasourceYamlManager {
}
private static void addInterCntMetric(String datasourceEnName, DatasourceDetail datasourceDetail) {
private static void addInterCntMetric(String datasourceEnName, ModelDetail datasourceDetail) {
Measure measure = new Measure();
measure.setExpr("1");
if (!CollectionUtils.isEmpty(datasourceDetail.getIdentifiers())) {

View File

@@ -1,7 +1,7 @@
package com.tencent.supersonic.semantic.model.domain.pojo;
import com.tencent.supersonic.semantic.api.model.pojo.DatasourceDetail;
import com.tencent.supersonic.semantic.api.model.pojo.ModelDetail;
import com.tencent.supersonic.semantic.api.model.pojo.SchemaItem;
import lombok.Data;
@@ -13,7 +13,7 @@ public class Datasource extends SchemaItem {
private Long databaseId;
private DatasourceDetail datasourceDetail;
private ModelDetail datasourceDetail;

View File

@@ -27,8 +27,6 @@ public class MetaFilter {
private List<Long> ids;
private Long datasourceId;
public MetaFilter(List<Long> modelIds) {
this.modelIds = modelIds;
}

View File

@@ -0,0 +1,14 @@
package com.tencent.supersonic.semantic.model.domain.pojo;
import lombok.Data;
import java.util.List;
@Data
public class ModelFilter extends MetaFilter {
private Long databaseId;
private List<Long> domainIds;
}

View File

@@ -1,22 +0,0 @@
package com.tencent.supersonic.semantic.model.domain.repository;
import com.tencent.supersonic.semantic.model.domain.dataobject.DatasourceDO;
import java.util.List;
public interface DatasourceRepository {
void createDatasource(DatasourceDO datasourceDO);
void updateDatasource(DatasourceDO datasourceDO);
List<DatasourceDO> getDatasourceList();
List<DatasourceDO> getDatasourceList(Long modelId);
List<DatasourceDO> getDatasourceByDatabase(Long databaseId);
DatasourceDO getDatasourceById(Long id);
}

View File

@@ -1,6 +1,9 @@
package com.tencent.supersonic.semantic.model.domain.repository;
import com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO;
import com.tencent.supersonic.semantic.model.domain.pojo.ModelFilter;
import java.util.List;
public interface ModelRepository {
@@ -9,10 +12,9 @@ public interface ModelRepository {
void updateModel(ModelDO modelDO);
void deleteModel(Long id);
List<ModelDO> getModelList();
List<ModelDO> getModelList(ModelFilter modelFilter);
ModelDO getModelById(Long id);
void batchUpdate(List<ModelDO> modelDOS);
}

View File

@@ -1,201 +0,0 @@
package com.tencent.supersonic.semantic.model.domain.utils;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.semantic.api.model.enums.MetricTypeEnum;
import com.tencent.supersonic.semantic.api.model.pojo.DatasourceDetail;
import com.tencent.supersonic.semantic.api.model.pojo.Dim;
import com.tencent.supersonic.semantic.api.model.pojo.Identify;
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.DatasourceReq;
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.response.DatasourceResp;
import com.tencent.supersonic.semantic.api.model.response.MeasureResp;
import com.tencent.supersonic.semantic.model.domain.dataobject.DatasourceDO;
import com.tencent.supersonic.semantic.model.domain.pojo.Datasource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class DatasourceConverter {
public static DatasourceDO convert(DatasourceReq datasourceReq, User user) {
DatasourceDO datasource = new DatasourceDO();
DatasourceDetail datasourceDetail = getDatasourceDetail(datasourceReq);
datasourceReq.createdBy(user.getName());
BeanMapper.mapper(datasourceReq, datasource);
datasource.setStatus(StatusEnum.ONLINE.getCode());
datasource.setDatasourceDetail(JSONObject.toJSONString(datasourceDetail));
return datasource;
}
public static DatasourceDO convert(DatasourceDO datasourceDO, DatasourceReq datasourceReq, User user) {
DatasourceDetail datasourceDetail = getDatasourceDetail(datasourceReq);
BeanMapper.mapper(datasourceReq, datasourceDO);
datasourceDO.setDatasourceDetail(JSONObject.toJSONString((datasourceDetail)));
datasourceDO.setUpdatedBy(user.getName());
datasourceDO.setUpdatedAt(new Date());
return datasourceDO;
}
public static DatasourceResp convert(DatasourceDO datasourceDO) {
DatasourceResp datasourceResp = new DatasourceResp();
BeanUtils.copyProperties(datasourceDO, datasourceResp);
datasourceResp.setDatasourceDetail(
JSONObject.parseObject(datasourceDO.getDatasourceDetail(), DatasourceDetail.class));
return datasourceResp;
}
public static MeasureResp convert(Measure measure, DatasourceResp datasourceResp) {
MeasureResp measureResp = new MeasureResp();
BeanUtils.copyProperties(measure, measureResp);
measureResp.setDatasourceId(datasourceResp.getId());
measureResp.setDatasourceName(datasourceResp.getName());
measureResp.setDatasourceBizName(datasourceResp.getBizName());
measureResp.setModelId(datasourceResp.getModelId());
return measureResp;
}
public static DimensionReq convert(Dim dim, DatasourceDO datasourceDO) {
DimensionReq dimensionReq = new DimensionReq();
dimensionReq.setName(dim.getName());
dimensionReq.setBizName(dim.getBizName());
dimensionReq.setDescription(dim.getName());
dimensionReq.setSemanticType("CATEGORY");
dimensionReq.setDatasourceId(datasourceDO.getId());
dimensionReq.setModelId(datasourceDO.getModelId());
dimensionReq.setExpr(dim.getBizName());
dimensionReq.setType("categorical");
dimensionReq.setDescription(Objects.isNull(dim.getDescription()) ? "" : dim.getDescription());
dimensionReq.setIsTag(dim.getIsTag());
return dimensionReq;
}
public static MetricReq convert(Measure measure, DatasourceDO datasourceDO) {
measure.setDatasourceId(datasourceDO.getId());
MetricReq metricReq = new MetricReq();
metricReq.setName(measure.getName());
metricReq.setBizName(measure.getBizName().replaceFirst(datasourceDO.getBizName() + "_", ""));
metricReq.setDescription(measure.getName());
metricReq.setModelId(datasourceDO.getModelId());
metricReq.setMetricType(MetricTypeEnum.ATOMIC);
MetricTypeParams exprTypeParams = new MetricTypeParams();
exprTypeParams.setExpr(measure.getBizName());
exprTypeParams.setMeasures(Lists.newArrayList(measure));
metricReq.setTypeParams(exprTypeParams);
return metricReq;
}
public static DimensionReq convert(Identify identify, DatasourceDO datasourceDO) {
DimensionReq dimensionReq = new DimensionReq();
dimensionReq.setName(identify.getName());
dimensionReq.setBizName(identify.getBizName());
dimensionReq.setDescription(identify.getName());
dimensionReq.setSemanticType("CATEGORY");
dimensionReq.setDatasourceId(datasourceDO.getId());
dimensionReq.setModelId(datasourceDO.getModelId());
dimensionReq.setExpr(identify.getBizName());
dimensionReq.setType(identify.getType());
return dimensionReq;
}
public static List<DatasourceResp> convertList(List<DatasourceDO> datasourceDOS) {
List<DatasourceResp> datasourceDescs = Lists.newArrayList();
if (!CollectionUtils.isEmpty(datasourceDOS)) {
datasourceDescs = datasourceDOS.stream().map(DatasourceConverter::convert).collect(Collectors.toList());
}
return datasourceDescs;
}
private static boolean isCreateDimension(Dim dim) {
return dim.getIsCreateDimension() == 1
&& StringUtils.isNotBlank(dim.getName())
&& !dim.getType().equalsIgnoreCase("time");
}
private static boolean isCreateMetric(Measure measure) {
return measure.getIsCreateMetric() == 1
&& StringUtils.isNotBlank(measure.getName());
}
public static List<Dim> getDimToCreateDimension(DatasourceDetail datasourceDetail) {
return datasourceDetail.getDimensions().stream()
.filter(DatasourceConverter::isCreateDimension)
.collect(Collectors.toList());
}
public static List<Measure> getMeasureToCreateMetric(DatasourceDetail datasourceDetail) {
return datasourceDetail.getMeasures().stream()
.filter(DatasourceConverter::isCreateMetric)
.collect(Collectors.toList());
}
public static List<DimensionReq> convertDimensionList(DatasourceDO datasourceDO) {
List<DimensionReq> dimensionReqs = Lists.newArrayList();
DatasourceDetail datasourceDetail = JSONObject.parseObject(datasourceDO.getDatasourceDetail(),
DatasourceDetail.class);
List<Dim> dims = getDimToCreateDimension(datasourceDetail);
if (!CollectionUtils.isEmpty(dims)) {
dimensionReqs = dims.stream().filter(dim -> StringUtils.isNotBlank(dim.getName()))
.map(dim -> convert(dim, datasourceDO)).collect(Collectors.toList());
}
List<Identify> identifies = datasourceDetail.getIdentifiers();
if (CollectionUtils.isEmpty(identifies)) {
return dimensionReqs;
}
dimensionReqs.addAll(identifies.stream()
.filter(i -> i.getType().equalsIgnoreCase("primary"))
.filter(i -> StringUtils.isNotBlank(i.getName()))
.map(identify -> convert(identify, datasourceDO)).collect(Collectors.toList()));
return dimensionReqs;
}
public static List<MetricReq> convertMetricList(DatasourceDO datasourceDO) {
DatasourceDetail datasourceDetail = JSONObject.parseObject(datasourceDO.getDatasourceDetail(),
DatasourceDetail.class);
List<Measure> measures = getMeasureToCreateMetric(datasourceDetail);
if (CollectionUtils.isEmpty(measures)) {
return Lists.newArrayList();
}
return measures.stream().map(measure -> convert(measure, datasourceDO)).collect(Collectors.toList());
}
public static Datasource datasourceInfo2Datasource(DatasourceResp datasourceResp) {
Datasource datasource = new Datasource();
BeanUtils.copyProperties(datasourceResp, datasource);
return datasource;
}
private static DatasourceDetail getDatasourceDetail(DatasourceReq datasourceReq) {
DatasourceDetail datasourceDetail = new DatasourceDetail();
BeanMapper.mapper(datasourceReq, datasourceDetail);
List<Measure> measures = datasourceDetail.getMeasures();
for (Measure measure : measures) {
if (StringUtils.isBlank(measure.getExpr())) {
measure.setExpr(measure.getBizName());
}
if (StringUtils.isBlank(measure.getConstraint())) {
measure.setConstraint(null);
}
if (StringUtils.isBlank(measure.getAlias())) {
measure.setAlias(null);
}
measure.setBizName(String.format("%s_%s", datasourceReq.getBizName(), measure.getBizName()));
}
return datasourceDetail;
}
}

View File

@@ -3,25 +3,24 @@ package com.tencent.supersonic.semantic.model.domain.utils;
import com.alibaba.fastjson.JSONObject;
import com.tencent.supersonic.common.pojo.enums.DataTypeEnums;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.semantic.api.model.pojo.DimValueMap;
import com.tencent.supersonic.semantic.api.model.yaml.DimensionYamlTpl;
import com.tencent.supersonic.semantic.api.model.request.DimensionReq;
import com.tencent.supersonic.semantic.api.model.response.DatasourceResp;
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.api.model.yaml.DimensionYamlTpl;
import com.tencent.supersonic.semantic.model.domain.dataobject.DimensionDO;
import com.tencent.supersonic.semantic.model.domain.pojo.Dimension;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
public class DimensionConverter {
public static DimensionDO convert(DimensionDO dimensionDO, DimensionReq dimensionReq) {
@@ -57,22 +56,18 @@ public class DimensionConverter {
}
public static DimensionResp convert2DimensionResp(DimensionDO dimensionDO,
Map<Long, String> fullPathMap,
Map<Long, DatasourceResp> datasourceRespMap) {
Map<Long, ModelResp> modelRespMap) {
DimensionResp dimensionResp = new DimensionResp();
BeanUtils.copyProperties(dimensionDO, dimensionResp);
dimensionResp.setFullPath(fullPathMap.get(dimensionDO.getModelId()) + "/" + dimensionDO.getBizName());
dimensionResp.setDatasourceId(
datasourceRespMap.getOrDefault(dimensionResp.getDatasourceId(), new DatasourceResp()).getId());
dimensionResp.setDatasourceName(
datasourceRespMap.getOrDefault(dimensionResp.getDatasourceId(), new DatasourceResp()).getName());
dimensionResp.setDatasourceBizName(
datasourceRespMap.getOrDefault(dimensionResp.getDatasourceId(), new DatasourceResp()).getBizName());
dimensionResp.setModelName(
modelRespMap.getOrDefault(dimensionResp.getModelId(), new ModelResp()).getName());
dimensionResp.setModelBizName(
modelRespMap.getOrDefault(dimensionResp.getModelId(), new ModelResp()).getBizName());
if (dimensionDO.getDefaultValues() != null) {
dimensionResp.setDefaultValues(JSONObject.parseObject(dimensionDO.getDefaultValues(), List.class));
}
dimensionResp.setDatasourceFilterSql(
datasourceRespMap.getOrDefault(dimensionResp.getDatasourceId(), new DatasourceResp()).getFilterSql());
dimensionResp.setModelFilterSql(
modelRespMap.getOrDefault(dimensionResp.getModelId(), new ModelResp()).getFilterSql());
if (Strings.isNotEmpty(dimensionDO.getDimValueMaps())) {
dimensionResp.setDimValueMaps(JsonUtil.toList(dimensionDO.getDimValueMaps(), DimValueMap.class));
}

View File

@@ -6,39 +6,25 @@ import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.semantic.api.model.request.DomainReq;
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
import com.tencent.supersonic.semantic.api.model.response.DomainResp;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
import com.tencent.supersonic.semantic.model.domain.dataobject.DomainDO;
import com.tencent.supersonic.semantic.model.domain.pojo.Domain;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class DomainConvert {
public static Domain convert(DomainReq domainReq) {
Domain domain = new Domain();
BeanUtils.copyProperties(domainReq, domain);
domain.setStatus(StatusEnum.ONLINE.getCode());
return domain;
}
public static DomainDO convert(Domain domain, User user) {
public static DomainDO convert(DomainReq domainReq, User user) {
DomainDO domainDO = new DomainDO();
BeanUtils.copyProperties(domain, domainDO);
domainDO.setCreatedBy(user.getName());
domainDO.setUpdatedBy(user.getName());
domainDO.setCreatedAt(new Date());
domainDO.setUpdatedAt(new Date());
domainDO.setAdmin(String.join(",", domain.getAdmins()));
domainDO.setAdminOrg(String.join(",", domain.getAdminOrgs()));
domainDO.setViewer(String.join(",", domain.getViewers()));
domainDO.setViewOrg(String.join(",", domain.getViewOrgs()));
domainReq.createdBy(user.getName());
BeanUtils.copyProperties(domainReq, domainDO);
domainDO.setAdmin(String.join(",", domainReq.getAdmins()));
domainDO.setAdminOrg(String.join(",", domainReq.getAdminOrgs()));
domainDO.setViewer(String.join(",", domainReq.getViewers()));
domainDO.setViewOrg(String.join(",", domainReq.getViewOrgs()));
return domainDO;
}

View File

@@ -4,25 +4,25 @@ import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.tencent.supersonic.common.pojo.DataFormat;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.util.BeanMapper;
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.pojo.RelateDimension;
import com.tencent.supersonic.semantic.api.model.request.MetricReq;
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.yaml.MeasureYamlTpl;
import com.tencent.supersonic.semantic.api.model.yaml.MetricTypeParamsYamlTpl;
import com.tencent.supersonic.semantic.api.model.yaml.MetricYamlTpl;
import com.tencent.supersonic.semantic.api.model.request.MetricReq;
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.semantic.model.domain.dataobject.MetricDO;
import com.tencent.supersonic.semantic.model.domain.pojo.Metric;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.beans.BeanUtils;
public class MetricConverter {
public static MetricDO convert2MetricDO(MetricReq metricReq) {

View File

@@ -1,58 +0,0 @@
package com.tencent.supersonic.semantic.model.domain.utils;
import com.google.common.collect.Lists;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.semantic.api.model.pojo.DrillDownDimension;
import com.tencent.supersonic.semantic.api.model.pojo.Entity;
import com.tencent.supersonic.semantic.api.model.request.ModelReq;
import com.tencent.supersonic.semantic.api.model.response.DomainResp;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import java.util.Arrays;
import java.util.Map;
public class ModelConvert {
public static ModelDO convert(ModelReq modelReq) {
ModelDO modelDO = new ModelDO();
BeanMapper.mapper(modelReq, modelDO);
modelDO.setEntity(JsonUtil.toString(modelReq.getEntity()));
modelDO.setDrillDownDimensions(JsonUtil.toString(modelReq.getDrillDownDimensions()));
modelDO.setStatus(StatusEnum.ONLINE.getCode());
return modelDO;
}
public static ModelResp convert(ModelDO modelDO) {
ModelResp modelResp = new ModelResp();
BeanUtils.copyProperties(modelDO, modelResp);
modelResp.setAdmins(StringUtils.isBlank(modelDO.getAdmin())
? Lists.newArrayList() : Arrays.asList(modelDO.getAdmin().split(",")));
modelResp.setAdminOrgs(StringUtils.isBlank(modelDO.getAdminOrg())
? Lists.newArrayList() : Arrays.asList(modelDO.getAdminOrg().split(",")));
modelResp.setViewers(StringUtils.isBlank(modelDO.getViewer())
? Lists.newArrayList() : Arrays.asList(modelDO.getViewer().split(",")));
modelResp.setViewOrgs(StringUtils.isBlank(modelDO.getViewOrg())
? Lists.newArrayList() : Arrays.asList(modelDO.getViewOrg().split(",")));
modelResp.setEntity(JsonUtil.toObject(modelDO.getEntity(), Entity.class));
modelResp.setDrillDownDimensions(JsonUtil.toList(modelDO.getDrillDownDimensions(), DrillDownDimension.class));
return modelResp;
}
public static ModelResp convert(ModelDO modelDO,
Map<Long, DomainResp> domainRespMap) {
ModelResp modelResp = convert(modelDO);
DomainResp domainResp = domainRespMap.get(modelResp.getDomainId());
if (domainResp != null) {
String fullBizNamePath = domainResp.getFullPath() + modelResp.getBizName();
modelResp.setFullPath(fullBizNamePath);
}
return modelResp;
}
}

View File

@@ -0,0 +1,218 @@
package com.tencent.supersonic.semantic.model.domain.utils;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.common.util.BeanMapper;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.semantic.api.model.enums.MetricTypeEnum;
import com.tencent.supersonic.semantic.api.model.pojo.Dim;
import com.tencent.supersonic.semantic.api.model.pojo.DrillDownDimension;
import com.tencent.supersonic.semantic.api.model.pojo.Identify;
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.pojo.ModelDetail;
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.ModelReq;
import com.tencent.supersonic.semantic.api.model.response.DomainResp;
import com.tencent.supersonic.semantic.api.model.response.MeasureResp;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
public class ModelConverter {
public static ModelDO convert(ModelReq modelReq, User user) {
ModelDO modelDO = new ModelDO();
ModelDetail modelDetail = getModelDetail(modelReq);
modelReq.createdBy(user.getName());
BeanMapper.mapper(modelReq, modelDO);
modelDO.setStatus(StatusEnum.ONLINE.getCode());
modelDO.setModelDetail(JSONObject.toJSONString(modelDetail));
modelDO.setDrillDownDimensions(JSONObject.toJSONString(modelReq.getDrillDownDimensions()));
return modelDO;
}
public static ModelResp convert(ModelDO modelDO) {
ModelResp modelResp = new ModelResp();
BeanUtils.copyProperties(modelDO, modelResp);
modelResp.setAdmins(StringUtils.isBlank(modelDO.getAdmin())
? Lists.newArrayList() : Arrays.asList(modelDO.getAdmin().split(",")));
modelResp.setAdminOrgs(StringUtils.isBlank(modelDO.getAdminOrg())
? Lists.newArrayList() : Arrays.asList(modelDO.getAdminOrg().split(",")));
modelResp.setViewers(StringUtils.isBlank(modelDO.getViewer())
? Lists.newArrayList() : Arrays.asList(modelDO.getViewer().split(",")));
modelResp.setViewOrgs(StringUtils.isBlank(modelDO.getViewOrg())
? Lists.newArrayList() : Arrays.asList(modelDO.getViewOrg().split(",")));
modelResp.setDrillDownDimensions(JsonUtil.toList(modelDO.getDrillDownDimensions(), DrillDownDimension.class));
modelResp.setModelDetail(JSONObject.parseObject(modelDO.getModelDetail(), ModelDetail.class));
return modelResp;
}
public static ModelResp convert(ModelDO modelDO, Map<Long, DomainResp> domainRespMap) {
ModelResp modelResp = convert(modelDO);
DomainResp domainResp = domainRespMap.get(modelResp.getDomainId());
if (domainResp != null) {
String fullBizNamePath = domainResp.getFullPath() + modelResp.getBizName();
modelResp.setFullPath(fullBizNamePath);
}
return modelResp;
}
public static ModelDO convert(ModelDO modelDO, ModelReq modelReq, User user) {
ModelDetail modelDetail = getModelDetail(modelReq);
BeanMapper.mapper(modelReq, modelDO);
modelDO.setModelDetail(JSONObject.toJSONString((modelDetail)));
modelDO.setUpdatedBy(user.getName());
modelDO.setUpdatedAt(new Date());
return modelDO;
}
public static MeasureResp convert(Measure measure, ModelResp modelResp) {
MeasureResp measureResp = new MeasureResp();
BeanUtils.copyProperties(measure, measureResp);
measureResp.setDatasourceId(modelResp.getId());
measureResp.setDatasourceName(modelResp.getName());
measureResp.setDatasourceBizName(modelResp.getBizName());
measureResp.setModelId(modelResp.getId());
return measureResp;
}
public static DimensionReq convert(Dim dim, ModelDO modelDO) {
DimensionReq dimensionReq = new DimensionReq();
dimensionReq.setName(dim.getName());
dimensionReq.setBizName(dim.getBizName());
dimensionReq.setDescription(dim.getName());
dimensionReq.setSemanticType("CATEGORY");
dimensionReq.setModelId(modelDO.getId());
dimensionReq.setExpr(dim.getBizName());
dimensionReq.setType("categorical");
dimensionReq.setDescription(Objects.isNull(dim.getDescription()) ? "" : dim.getDescription());
dimensionReq.setIsTag(dim.getIsTag());
return dimensionReq;
}
public static MetricReq convert(Measure measure, ModelDO modelDO) {
measure.setDatasourceId(modelDO.getId());
MetricReq metricReq = new MetricReq();
metricReq.setName(measure.getName());
metricReq.setBizName(measure.getBizName().replaceFirst(modelDO.getBizName() + "_", ""));
metricReq.setDescription(measure.getName());
metricReq.setModelId(modelDO.getId());
metricReq.setMetricType(MetricTypeEnum.ATOMIC);
MetricTypeParams exprTypeParams = new MetricTypeParams();
exprTypeParams.setExpr(measure.getBizName());
exprTypeParams.setMeasures(Lists.newArrayList(measure));
metricReq.setTypeParams(exprTypeParams);
return metricReq;
}
public static DimensionReq convert(Identify identify, ModelDO modelDO) {
DimensionReq dimensionReq = new DimensionReq();
dimensionReq.setName(identify.getName());
dimensionReq.setBizName(identify.getBizName());
dimensionReq.setDescription(identify.getName());
dimensionReq.setSemanticType("CATEGORY");
dimensionReq.setModelId(modelDO.getId());
dimensionReq.setExpr(identify.getBizName());
dimensionReq.setType(identify.getType());
return dimensionReq;
}
public static List<ModelResp> convertList(List<ModelDO> modelDOS) {
List<ModelResp> modelDescs = Lists.newArrayList();
if (!CollectionUtils.isEmpty(modelDOS)) {
modelDescs = modelDOS.stream().map(ModelConverter::convert).collect(Collectors.toList());
}
return modelDescs;
}
private static boolean isCreateDimension(Dim dim) {
return dim.getIsCreateDimension() == 1
&& StringUtils.isNotBlank(dim.getName())
&& !dim.getType().equalsIgnoreCase("time");
}
private static boolean isCreateMetric(Measure measure) {
return measure.getIsCreateMetric() == 1
&& StringUtils.isNotBlank(measure.getName());
}
public static List<Dim> getDimToCreateDimension(ModelDetail modelDetail) {
return modelDetail.getDimensions().stream()
.filter(ModelConverter::isCreateDimension)
.collect(Collectors.toList());
}
public static List<Measure> getMeasureToCreateMetric(ModelDetail modelDetail) {
return modelDetail.getMeasures().stream()
.filter(ModelConverter::isCreateMetric)
.collect(Collectors.toList());
}
public static List<DimensionReq> convertDimensionList(ModelDO modelDO) {
List<DimensionReq> dimensionReqs = Lists.newArrayList();
ModelDetail modelDetail = JSONObject.parseObject(modelDO.getModelDetail(),
ModelDetail.class);
List<Dim> dims = getDimToCreateDimension(modelDetail);
if (!CollectionUtils.isEmpty(dims)) {
dimensionReqs = dims.stream().filter(dim -> StringUtils.isNotBlank(dim.getName()))
.map(dim -> convert(dim, modelDO)).collect(Collectors.toList());
}
List<Identify> identifies = modelDetail.getIdentifiers();
if (CollectionUtils.isEmpty(identifies)) {
return dimensionReqs;
}
dimensionReqs.addAll(identifies.stream()
.filter(i -> i.getType().equalsIgnoreCase("primary"))
.filter(i -> StringUtils.isNotBlank(i.getName()))
.map(identify -> convert(identify, modelDO)).collect(Collectors.toList()));
return dimensionReqs;
}
public static List<MetricReq> convertMetricList(ModelDO modelDO) {
ModelDetail modelDetail = JSONObject.parseObject(modelDO.getModelDetail(),
ModelDetail.class);
List<Measure> measures = getMeasureToCreateMetric(modelDetail);
if (CollectionUtils.isEmpty(measures)) {
return Lists.newArrayList();
}
return measures.stream().map(measure -> convert(measure, modelDO)).collect(Collectors.toList());
}
private static ModelDetail getModelDetail(ModelReq modelReq) {
ModelDetail modelDetail = new ModelDetail();
BeanMapper.mapper(modelReq.getModelDetail(), modelDetail);
List<Measure> measures = modelDetail.getMeasures();
for (Measure measure : measures) {
if (StringUtils.isBlank(measure.getExpr())) {
measure.setExpr(measure.getBizName());
}
if (StringUtils.isBlank(measure.getConstraint())) {
measure.setConstraint(null);
}
if (StringUtils.isBlank(measure.getAlias())) {
measure.setAlias(null);
}
measure.setBizName(String.format("%s_%s", modelReq.getBizName(), measure.getBizName()));
}
return modelDetail;
}
}

View File

@@ -1,58 +1,10 @@
package com.tencent.supersonic.semantic.model.infrastructure.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.semantic.model.domain.dataobject.DomainDO;
import com.tencent.supersonic.semantic.model.domain.dataobject.DomainDOExample;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface DomainDOMapper {
/**
*
* @mbg.generated
*/
long countByExample(DomainDOExample example);
public interface DomainDOMapper extends BaseMapper<DomainDO> {
/**
*
* @mbg.generated
*/
int deleteByPrimaryKey(Long id);
/**
*
* @mbg.generated
*/
int insert(DomainDO record);
/**
*
* @mbg.generated
*/
int insertSelective(DomainDO record);
/**
*
* @mbg.generated
*/
List<DomainDO> selectByExample(DomainDOExample example);
/**
*
* @mbg.generated
*/
DomainDO selectByPrimaryKey(Long id);
/**
*
* @mbg.generated
*/
int updateByPrimaryKeySelective(DomainDO record);
/**
*
* @mbg.generated
*/
int updateByPrimaryKey(DomainDO record);
}

View File

@@ -0,0 +1,14 @@
package com.tencent.supersonic.semantic.model.infrastructure.mapper;
import com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ModelDOCustomMapper {
void batchUpdateStatus(List<ModelDO> modelDOS);
}

View File

@@ -1,89 +1,11 @@
package com.tencent.supersonic.semantic.model.infrastructure.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO;
import com.tencent.supersonic.semantic.model.domain.dataobject.ModelDOExample;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface ModelDOMapper {
/**
*
* @mbg.generated
*/
long countByExample(ModelDOExample example);
public interface ModelDOMapper extends BaseMapper<ModelDO> {
/**
*
* @mbg.generated
*/
int deleteByPrimaryKey(Long id);
/**
*
* @mbg.generated
*/
int insert(ModelDO record);
/**
*
* @mbg.generated
*/
int insertSelective(ModelDO record);
/**
*
* @mbg.generated
*/
List<ModelDO> selectByExampleWithBLOBs(ModelDOExample example);
/**
*
* @mbg.generated
*/
List<ModelDO> selectByExample(ModelDOExample example);
/**
*
* @mbg.generated
*/
ModelDO selectByPrimaryKey(Long id);
/**
*
* @mbg.generated
*/
int updateByExampleSelective(@Param("record") ModelDO record, @Param("example") ModelDOExample example);
/**
*
* @mbg.generated
*/
int updateByExampleWithBLOBs(@Param("record") ModelDO record, @Param("example") ModelDOExample example);
/**
*
* @mbg.generated
*/
int updateByExample(@Param("record") ModelDO record, @Param("example") ModelDOExample example);
/**
*
* @mbg.generated
*/
int updateByPrimaryKeySelective(ModelDO record);
/**
*
* @mbg.generated
*/
int updateByPrimaryKeyWithBLOBs(ModelDO record);
/**
*
* @mbg.generated
*/
int updateByPrimaryKey(ModelDO record);
}

View File

@@ -1,11 +1,11 @@
package com.tencent.supersonic.semantic.model.infrastructure.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tencent.supersonic.semantic.model.domain.dataobject.DatasourceDO;
import com.tencent.supersonic.semantic.model.domain.dataobject.ModelRelaDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface DatasourceDOMapper extends BaseMapper<DatasourceDO> {
public interface ModelRelaDOMapper extends BaseMapper<ModelRelaDO> {
}
}

View File

@@ -1,62 +0,0 @@
package com.tencent.supersonic.semantic.model.infrastructure.repository;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.semantic.model.domain.dataobject.DatasourceDO;
import com.tencent.supersonic.semantic.model.domain.repository.DatasourceRepository;
import com.tencent.supersonic.semantic.model.infrastructure.mapper.DatasourceDOMapper;
import java.util.List;
import org.springframework.stereotype.Component;
@Component
public class DatasourceRepositoryImpl implements DatasourceRepository {
private DatasourceDOMapper datasourceMapper;
public DatasourceRepositoryImpl(DatasourceDOMapper datasourceMapper) {
this.datasourceMapper = datasourceMapper;
}
@Override
public void createDatasource(DatasourceDO datasourceDO) {
datasourceMapper.insert(datasourceDO);
}
@Override
public void updateDatasource(DatasourceDO datasourceDO) {
datasourceMapper.updateById(datasourceDO);
}
@Override
public List<DatasourceDO> getDatasourceList() {
QueryWrapper<DatasourceDO> wrapper = new QueryWrapper<>();
wrapper.lambda().ne(DatasourceDO::getStatus, StatusEnum.DELETED.getCode());
return datasourceMapper.selectList(wrapper);
}
@Override
public List<DatasourceDO> getDatasourceList(Long modelId) {
QueryWrapper<DatasourceDO> wrapper = new QueryWrapper<>();
wrapper.lambda().ne(DatasourceDO::getStatus, StatusEnum.DELETED.getCode())
.eq(DatasourceDO::getModelId, modelId);
return datasourceMapper.selectList(wrapper);
}
@Override
public List<DatasourceDO> getDatasourceByDatabase(Long databaseId) {
QueryWrapper<DatasourceDO> wrapper = new QueryWrapper<>();
wrapper.lambda().ne(DatasourceDO::getStatus, StatusEnum.DELETED.getCode())
.eq(DatasourceDO::getDatabaseId, databaseId);
return datasourceMapper.selectList(wrapper);
}
@Override
public DatasourceDO getDatasourceById(Long id) {
return datasourceMapper.selectById(id);
}
}

View File

@@ -1,14 +1,14 @@
package com.tencent.supersonic.semantic.model.infrastructure.repository;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tencent.supersonic.semantic.model.domain.dataobject.DomainDO;
import com.tencent.supersonic.semantic.model.domain.dataobject.DomainDOExample;
import com.tencent.supersonic.semantic.model.domain.repository.DomainRepository;
import com.tencent.supersonic.semantic.model.infrastructure.mapper.DomainDOMapper;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@Slf4j
@@ -27,23 +27,22 @@ public class DomainRepositoryImpl implements DomainRepository {
@Override
public void updateDomain(DomainDO metaDomainDO) {
domainDOMapper.updateByPrimaryKey(metaDomainDO);
domainDOMapper.updateById(metaDomainDO);
}
@Override
public void deleteDomain(Long id) {
domainDOMapper.deleteByPrimaryKey(id);
domainDOMapper.deleteById(id);
}
@Override
public List<DomainDO> getDomainList() {
DomainDOExample metaDomainDOExample = new DomainDOExample();
return domainDOMapper.selectByExample(metaDomainDOExample);
return domainDOMapper.selectList(Wrappers.emptyWrapper());
}
@Override
public DomainDO getDomainById(Long id) {
return domainDOMapper.selectByPrimaryKey(id);
return domainDOMapper.selectById(id);
}

View File

@@ -1,49 +1,67 @@
package com.tencent.supersonic.semantic.model.infrastructure.repository;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
import com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO;
import com.tencent.supersonic.semantic.model.domain.dataobject.ModelDOExample;
import com.tencent.supersonic.semantic.model.domain.pojo.ModelFilter;
import com.tencent.supersonic.semantic.model.domain.repository.ModelRepository;
import com.tencent.supersonic.semantic.model.infrastructure.mapper.ModelDOCustomMapper;
import com.tencent.supersonic.semantic.model.infrastructure.mapper.ModelDOMapper;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
@Component
public class ModelRepositoryImpl implements ModelRepository {
private ModelDOMapper modelDOMapper;
public ModelRepositoryImpl(ModelDOMapper modelDOMapper) {
private ModelDOCustomMapper modelDOCustomMapper;
public ModelRepositoryImpl(ModelDOMapper modelDOMapper,
ModelDOCustomMapper modelDOCustomMapper) {
this.modelDOMapper = modelDOMapper;
this.modelDOCustomMapper = modelDOCustomMapper;
}
@Override
public void createModel(ModelDO datasourceDO) {
modelDOMapper.insert(datasourceDO);
}
@Override
public void createModel(ModelDO modelDO) {
modelDOMapper.insert(modelDO);
public void updateModel(ModelDO datasourceDO) {
modelDOMapper.updateById(datasourceDO);
}
@Override
public void updateModel(ModelDO modelDO) {
modelDOMapper.updateByPrimaryKeySelective(modelDO);
}
@Override
public void deleteModel(Long id) {
ModelDO modelDO = modelDOMapper.selectByPrimaryKey(id);
modelDO.setStatus(StatusEnum.DELETED.getCode());
modelDOMapper.updateByPrimaryKey(modelDO);
}
@Override
public List<ModelDO> getModelList() {
ModelDOExample modelDOExample = new ModelDOExample();
modelDOExample.createCriteria().andStatusNotEqualTo(StatusEnum.DELETED.getCode());
return modelDOMapper.selectByExampleWithBLOBs(modelDOExample);
public List<ModelDO> getModelList(ModelFilter modelFilter) {
QueryWrapper<ModelDO> wrapper = new QueryWrapper<>();
wrapper.lambda().ne(ModelDO::getStatus, StatusEnum.DELETED.getCode());
if (modelFilter.getDatabaseId() != null) {
wrapper.lambda().eq(ModelDO::getDatabaseId, modelFilter.getDatabaseId());
}
if (!CollectionUtils.isEmpty(modelFilter.getDomainIds())) {
wrapper.lambda().in(ModelDO::getDomainId, modelFilter.getDomainIds());
}
if (!CollectionUtils.isEmpty(modelFilter.getIds())) {
wrapper.lambda().in(ModelDO::getId, modelFilter.getIds());
}
return modelDOMapper.selectList(wrapper);
}
@Override
public ModelDO getModelById(Long id) {
return modelDOMapper.selectByPrimaryKey(id);
return modelDOMapper.selectById(id);
}
@Override
public void batchUpdate(List<ModelDO> modelDOS) {
modelDOCustomMapper.batchUpdateStatus(modelDOS);
}
}

View File

@@ -1,66 +0,0 @@
package com.tencent.supersonic.semantic.model.rest;
import com.google.common.collect.Lists;
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.request.DatasourceReq;
import com.tencent.supersonic.semantic.api.model.response.DatasourceResp;
import com.tencent.supersonic.semantic.api.model.response.MeasureResp;
import com.tencent.supersonic.semantic.model.domain.DatasourceService;
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;
@RestController
@RequestMapping("/api/semantic/datasource")
public class DatasourceController {
private DatasourceService datasourceService;
public DatasourceController(DatasourceService datasourceService) {
this.datasourceService = datasourceService;
}
@PostMapping("/createDatasource")
public DatasourceResp createDatasource(@RequestBody DatasourceReq datasourceReq,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
User user = UserHolder.findUser(request, response);
return datasourceService.createDatasource(datasourceReq, user);
}
@PostMapping("/updateDatasource")
public DatasourceResp updateDatasource(@RequestBody DatasourceReq datasourceReq,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
User user = UserHolder.findUser(request, response);
return datasourceService.updateDatasource(datasourceReq, user);
}
@GetMapping("/getDatasourceList/{modelId}")
public List<DatasourceResp> getDatasourceList(@PathVariable("modelId") Long modelId) {
return datasourceService.getDatasourceListNoMeasurePrefix(modelId);
}
@GetMapping("/getMeasureListOfModel/{modelId}")
public List<MeasureResp> getMeasureListOfModel(@PathVariable("modelId") Long modelId) {
return datasourceService.getMeasureListOfModel(Lists.newArrayList(modelId));
}
@DeleteMapping("deleteDatasource/{id}")
public boolean deleteDatasource(@PathVariable("id") Long id,
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
datasourceService.deleteDatasource(id, user);
return true;
}
}

View File

@@ -3,10 +3,12 @@ package com.tencent.supersonic.semantic.model.rest;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.semantic.api.model.request.MetaBatchReq;
import com.tencent.supersonic.semantic.api.model.request.ModelReq;
import com.tencent.supersonic.semantic.api.model.response.DatabaseResp;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import com.tencent.supersonic.semantic.model.domain.pojo.ModelFilter;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.PostMapping;
@@ -33,8 +35,7 @@ public class ModelController {
@PostMapping("/createModel")
public Boolean createModel(@RequestBody ModelReq modelReq,
HttpServletRequest request,
HttpServletResponse response) {
HttpServletRequest request, HttpServletResponse response) throws Exception {
User user = UserHolder.findUser(request, response);
modelService.createModel(modelReq, user);
return true;
@@ -42,8 +43,7 @@ public class ModelController {
@PostMapping("/updateModel")
public Boolean updateModel(@RequestBody ModelReq modelReq,
HttpServletRequest request,
HttpServletResponse response) {
HttpServletRequest request, HttpServletResponse response) throws Exception {
User user = UserHolder.findUser(request, response);
modelService.updateModel(modelReq, user);
return true;
@@ -51,8 +51,7 @@ public class ModelController {
@DeleteMapping("/deleteModel/{modelId}")
public Boolean deleteModel(@PathVariable("modelId") Long modelId,
HttpServletRequest request,
HttpServletResponse response) {
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
modelService.deleteModel(modelId, user);
return true;
@@ -60,8 +59,7 @@ public class ModelController {
@GetMapping("/getModelList/{domainId}")
public List<ModelResp> getModelList(@PathVariable("domainId") Long domainId,
HttpServletRequest request,
HttpServletResponse response) {
HttpServletRequest request, HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
return modelService.getModelListWithAuth(user, domainId, AuthType.ADMIN);
}
@@ -74,8 +72,10 @@ public class ModelController {
@GetMapping("/getModelListByIds/{modelIds}")
public List<ModelResp> getModelListByIds(@PathVariable("modelIds") String modelIds) {
return modelService.getModelList(Arrays.stream(modelIds.split(",")).map(Long::parseLong)
.collect(Collectors.toList()));
List<Long> ids = Arrays.stream(modelIds.split(",")).map(Long::parseLong).collect(Collectors.toList());
ModelFilter modelFilter = new ModelFilter();
modelFilter.setIds(ids);
return modelService.getModelList(modelFilter);
}
@GetMapping("/getModelDatabase/{modelId}")
@@ -83,4 +83,14 @@ public class ModelController {
return modelService.getDatabaseByModelId(modelId);
}
@PostMapping("/batchUpdateStatus")
public Boolean batchUpdateStatus(@RequestBody MetaBatchReq metaBatchReq,
HttpServletRequest request,
HttpServletResponse response) {
User user = UserHolder.findUser(request, response);
modelService.batchUpdateStatus(metaBatchReq, user);
return true;
}
}

View File

@@ -0,0 +1,49 @@
package com.tencent.supersonic.semantic.model.rest;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.ModelRela;
import com.tencent.supersonic.semantic.model.domain.ModelRelaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/api/semantic/modelRela")
public class ModelRelaController {
@Autowired
private ModelRelaService modelRelaService;
@PostMapping
public boolean save(@RequestBody ModelRela modelRela, User user) {
modelRelaService.save(modelRela, user);
return true;
}
@PutMapping
public boolean update(@RequestBody ModelRela modelRela, User user) {
modelRelaService.update(modelRela, user);
return true;
}
@RequestMapping("/list")
public List<ModelRela> getModelRelaList(@RequestParam("domainId") Long domainId) {
return modelRelaService.getModelRelaList(domainId);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable("id") Long id) {
modelRelaService.delete(id);
}
}

View File

@@ -5,12 +5,8 @@ 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.request.ViewInfoReq;
import com.tencent.supersonic.semantic.api.model.response.ModelSchemaRelaResp;
import com.tencent.supersonic.semantic.model.domain.dataobject.ViewInfoDO;
import com.tencent.supersonic.semantic.model.application.ViewInfoServiceImpl;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tencent.supersonic.semantic.model.domain.dataobject.ViewInfoDO;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -19,6 +15,10 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@RestController
@RequestMapping("/api/semantic/viewInfo")
public class ViewInfoController {
@@ -47,9 +47,9 @@ public class ViewInfoController {
viewInfoServiceImpl.deleteViewInfo(id);
}
@GetMapping("/getDomainSchemaRela/{modelId}")
public List<ModelSchemaRelaResp> getDomainSchema(@PathVariable("modelId") Long modelId) {
return viewInfoServiceImpl.getDomainSchema(modelId);
@GetMapping("/getDomainSchemaRela/{domainId}")
public List<ModelSchemaRelaResp> getDomainSchema(@PathVariable("domainId") Long domainId) {
return viewInfoServiceImpl.getDomainSchema(domainId);
}

View File

@@ -1,480 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tencent.supersonic.semantic.model.infrastructure.mapper.ModelDOMapper">
<resultMap id="BaseResultMap" type="com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO">
<id column="id" jdbcType="BIGINT" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="biz_name" jdbcType="VARCHAR" property="bizName" />
<result column="domain_id" jdbcType="BIGINT" property="domainId" />
<result column="alias" jdbcType="VARCHAR" property="alias" />
<result column="description" jdbcType="VARCHAR" property="description" />
<result column="viewer" jdbcType="VARCHAR" property="viewer" />
<result column="view_org" jdbcType="VARCHAR" property="viewOrg" />
<result column="admin" jdbcType="VARCHAR" property="admin" />
<result column="admin_org" jdbcType="VARCHAR" property="adminOrg" />
<result column="is_open" jdbcType="INTEGER" property="isOpen" />
<result column="created_by" jdbcType="VARCHAR" property="createdBy" />
<result column="created_at" jdbcType="TIMESTAMP" property="createdAt" />
<result column="updated_by" jdbcType="VARCHAR" property="updatedBy" />
<result column="updated_at" jdbcType="TIMESTAMP" property="updatedAt" />
<result column="drill_down_dimensions" jdbcType="VARCHAR" property="drillDownDimensions" />
<result column="status" jdbcType="INTEGER" property="status" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO">
<result column="entity" jdbcType="LONGVARCHAR" property="entity" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Update_By_Example_Where_Clause">
<where>
<foreach collection="example.oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Base_Column_List">
id, name, biz_name, domain_id, alias, description, viewer, view_org, admin, admin_org,
is_open, created_by, created_at, updated_by, updated_at, drill_down_dimensions, status
</sql>
<sql id="Blob_Column_List">
entity
</sql>
<select id="selectByExampleWithBLOBs" parameterType="com.tencent.supersonic.semantic.model.domain.dataobject.ModelDOExample" resultMap="ResultMapWithBLOBs">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from s2_model
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByExample" parameterType="com.tencent.supersonic.semantic.model.domain.dataobject.ModelDOExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from s2_model
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
<if test="limitStart != null and limitStart>=0">
limit #{limitStart} , #{limitEnd}
</if>
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="ResultMapWithBLOBs">
select
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from s2_model
where id = #{id,jdbcType=BIGINT}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
delete from s2_model
where id = #{id,jdbcType=BIGINT}
</delete>
<insert id="insert" parameterType="com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO">
insert into s2_model (id, name, biz_name,
domain_id, alias, description,
viewer, view_org, admin,
admin_org, is_open, created_by,
created_at, updated_by, updated_at,
drill_down_dimensions, status, entity
)
values (#{id,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{bizName,jdbcType=VARCHAR},
#{domainId,jdbcType=BIGINT}, #{alias,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR},
#{viewer,jdbcType=VARCHAR}, #{viewOrg,jdbcType=VARCHAR}, #{admin,jdbcType=VARCHAR},
#{adminOrg,jdbcType=VARCHAR}, #{isOpen,jdbcType=INTEGER}, #{createdBy,jdbcType=VARCHAR},
#{createdAt,jdbcType=TIMESTAMP}, #{updatedBy,jdbcType=VARCHAR}, #{updatedAt,jdbcType=TIMESTAMP},
#{drillDownDimensions,jdbcType=VARCHAR}, #{status,jdbcType=INTEGER}, #{entity,jdbcType=LONGVARCHAR}
)
</insert>
<insert id="insertSelective" parameterType="com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO">
insert into s2_model
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="name != null">
name,
</if>
<if test="bizName != null">
biz_name,
</if>
<if test="domainId != null">
domain_id,
</if>
<if test="alias != null">
alias,
</if>
<if test="description != null">
description,
</if>
<if test="viewer != null">
viewer,
</if>
<if test="viewOrg != null">
view_org,
</if>
<if test="admin != null">
admin,
</if>
<if test="adminOrg != null">
admin_org,
</if>
<if test="isOpen != null">
is_open,
</if>
<if test="createdBy != null">
created_by,
</if>
<if test="createdAt != null">
created_at,
</if>
<if test="updatedBy != null">
updated_by,
</if>
<if test="updatedAt != null">
updated_at,
</if>
<if test="drillDownDimensions != null">
drill_down_dimensions,
</if>
<if test="status != null">
status,
</if>
<if test="entity != null">
entity,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=BIGINT},
</if>
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
<if test="bizName != null">
#{bizName,jdbcType=VARCHAR},
</if>
<if test="domainId != null">
#{domainId,jdbcType=BIGINT},
</if>
<if test="alias != null">
#{alias,jdbcType=VARCHAR},
</if>
<if test="description != null">
#{description,jdbcType=VARCHAR},
</if>
<if test="viewer != null">
#{viewer,jdbcType=VARCHAR},
</if>
<if test="viewOrg != null">
#{viewOrg,jdbcType=VARCHAR},
</if>
<if test="admin != null">
#{admin,jdbcType=VARCHAR},
</if>
<if test="adminOrg != null">
#{adminOrg,jdbcType=VARCHAR},
</if>
<if test="isOpen != null">
#{isOpen,jdbcType=INTEGER},
</if>
<if test="createdBy != null">
#{createdBy,jdbcType=VARCHAR},
</if>
<if test="createdAt != null">
#{createdAt,jdbcType=TIMESTAMP},
</if>
<if test="updatedBy != null">
#{updatedBy,jdbcType=VARCHAR},
</if>
<if test="updatedAt != null">
#{updatedAt,jdbcType=TIMESTAMP},
</if>
<if test="drillDownDimensions != null">
#{drillDownDimensions,jdbcType=VARCHAR},
</if>
<if test="status != null">
#{status,jdbcType=INTEGER},
</if>
<if test="entity != null">
#{entity,jdbcType=LONGVARCHAR},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="com.tencent.supersonic.semantic.model.domain.dataobject.ModelDOExample" resultType="java.lang.Long">
select count(*) from s2_model
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map">
update s2_model
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=BIGINT},
</if>
<if test="record.name != null">
name = #{record.name,jdbcType=VARCHAR},
</if>
<if test="record.bizName != null">
biz_name = #{record.bizName,jdbcType=VARCHAR},
</if>
<if test="record.domainId != null">
domain_id = #{record.domainId,jdbcType=BIGINT},
</if>
<if test="record.alias != null">
alias = #{record.alias,jdbcType=VARCHAR},
</if>
<if test="record.description != null">
description = #{record.description,jdbcType=VARCHAR},
</if>
<if test="record.viewer != null">
viewer = #{record.viewer,jdbcType=VARCHAR},
</if>
<if test="record.viewOrg != null">
view_org = #{record.viewOrg,jdbcType=VARCHAR},
</if>
<if test="record.admin != null">
admin = #{record.admin,jdbcType=VARCHAR},
</if>
<if test="record.adminOrg != null">
admin_org = #{record.adminOrg,jdbcType=VARCHAR},
</if>
<if test="record.isOpen != null">
is_open = #{record.isOpen,jdbcType=INTEGER},
</if>
<if test="record.createdBy != null">
created_by = #{record.createdBy,jdbcType=VARCHAR},
</if>
<if test="record.createdAt != null">
created_at = #{record.createdAt,jdbcType=TIMESTAMP},
</if>
<if test="record.updatedBy != null">
updated_by = #{record.updatedBy,jdbcType=VARCHAR},
</if>
<if test="record.updatedAt != null">
updated_at = #{record.updatedAt,jdbcType=TIMESTAMP},
</if>
<if test="record.drillDownDimensions != null">
drill_down_dimensions = #{record.drillDownDimensions,jdbcType=VARCHAR},
</if>
<if test="record.status != null">
status = #{record.status,jdbcType=INTEGER},
</if>
<if test="record.entity != null">
entity = #{record.entity,jdbcType=LONGVARCHAR},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExampleWithBLOBs" parameterType="map">
update s2_model
set id = #{record.id,jdbcType=BIGINT},
name = #{record.name,jdbcType=VARCHAR},
biz_name = #{record.bizName,jdbcType=VARCHAR},
domain_id = #{record.domainId,jdbcType=BIGINT},
alias = #{record.alias,jdbcType=VARCHAR},
description = #{record.description,jdbcType=VARCHAR},
viewer = #{record.viewer,jdbcType=VARCHAR},
view_org = #{record.viewOrg,jdbcType=VARCHAR},
admin = #{record.admin,jdbcType=VARCHAR},
admin_org = #{record.adminOrg,jdbcType=VARCHAR},
is_open = #{record.isOpen,jdbcType=INTEGER},
created_by = #{record.createdBy,jdbcType=VARCHAR},
created_at = #{record.createdAt,jdbcType=TIMESTAMP},
updated_by = #{record.updatedBy,jdbcType=VARCHAR},
updated_at = #{record.updatedAt,jdbcType=TIMESTAMP},
drill_down_dimensions = #{record.drillDownDimensions,jdbcType=VARCHAR},
status = #{record.status,jdbcType=INTEGER},
entity = #{record.entity,jdbcType=LONGVARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
update s2_model
set id = #{record.id,jdbcType=BIGINT},
name = #{record.name,jdbcType=VARCHAR},
biz_name = #{record.bizName,jdbcType=VARCHAR},
domain_id = #{record.domainId,jdbcType=BIGINT},
alias = #{record.alias,jdbcType=VARCHAR},
description = #{record.description,jdbcType=VARCHAR},
viewer = #{record.viewer,jdbcType=VARCHAR},
view_org = #{record.viewOrg,jdbcType=VARCHAR},
admin = #{record.admin,jdbcType=VARCHAR},
admin_org = #{record.adminOrg,jdbcType=VARCHAR},
is_open = #{record.isOpen,jdbcType=INTEGER},
created_by = #{record.createdBy,jdbcType=VARCHAR},
created_at = #{record.createdAt,jdbcType=TIMESTAMP},
updated_by = #{record.updatedBy,jdbcType=VARCHAR},
updated_at = #{record.updatedAt,jdbcType=TIMESTAMP},
drill_down_dimensions = #{record.drillDownDimensions,jdbcType=VARCHAR},
status = #{record.status,jdbcType=INTEGER}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByPrimaryKeySelective" parameterType="com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO">
update s2_model
<set>
<if test="name != null">
name = #{name,jdbcType=VARCHAR},
</if>
<if test="bizName != null">
biz_name = #{bizName,jdbcType=VARCHAR},
</if>
<if test="domainId != null">
domain_id = #{domainId,jdbcType=BIGINT},
</if>
<if test="alias != null">
alias = #{alias,jdbcType=VARCHAR},
</if>
<if test="description != null">
description = #{description,jdbcType=VARCHAR},
</if>
<if test="viewer != null">
viewer = #{viewer,jdbcType=VARCHAR},
</if>
<if test="viewOrg != null">
view_org = #{viewOrg,jdbcType=VARCHAR},
</if>
<if test="admin != null">
admin = #{admin,jdbcType=VARCHAR},
</if>
<if test="adminOrg != null">
admin_org = #{adminOrg,jdbcType=VARCHAR},
</if>
<if test="isOpen != null">
is_open = #{isOpen,jdbcType=INTEGER},
</if>
<if test="createdBy != null">
created_by = #{createdBy,jdbcType=VARCHAR},
</if>
<if test="createdAt != null">
created_at = #{createdAt,jdbcType=TIMESTAMP},
</if>
<if test="updatedBy != null">
updated_by = #{updatedBy,jdbcType=VARCHAR},
</if>
<if test="updatedAt != null">
updated_at = #{updatedAt,jdbcType=TIMESTAMP},
</if>
<if test="drillDownDimensions != null">
drill_down_dimensions = #{drillDownDimensions,jdbcType=VARCHAR},
</if>
<if test="status != null">
status = #{status,jdbcType=INTEGER},
</if>
<if test="entity != null">
entity = #{entity,jdbcType=LONGVARCHAR},
</if>
</set>
where id = #{id,jdbcType=BIGINT}
</update>
<update id="updateByPrimaryKeyWithBLOBs" parameterType="com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO">
update s2_model
set name = #{name,jdbcType=VARCHAR},
biz_name = #{bizName,jdbcType=VARCHAR},
domain_id = #{domainId,jdbcType=BIGINT},
alias = #{alias,jdbcType=VARCHAR},
description = #{description,jdbcType=VARCHAR},
viewer = #{viewer,jdbcType=VARCHAR},
view_org = #{viewOrg,jdbcType=VARCHAR},
admin = #{admin,jdbcType=VARCHAR},
admin_org = #{adminOrg,jdbcType=VARCHAR},
is_open = #{isOpen,jdbcType=INTEGER},
created_by = #{createdBy,jdbcType=VARCHAR},
created_at = #{createdAt,jdbcType=TIMESTAMP},
updated_by = #{updatedBy,jdbcType=VARCHAR},
updated_at = #{updatedAt,jdbcType=TIMESTAMP},
drill_down_dimensions = #{drillDownDimensions,jdbcType=VARCHAR},
status = #{status,jdbcType=INTEGER},
entity = #{entity,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=BIGINT}
</update>
<update id="updateByPrimaryKey" parameterType="com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO">
update s2_model
set name = #{name,jdbcType=VARCHAR},
biz_name = #{bizName,jdbcType=VARCHAR},
domain_id = #{domainId,jdbcType=BIGINT},
alias = #{alias,jdbcType=VARCHAR},
description = #{description,jdbcType=VARCHAR},
viewer = #{viewer,jdbcType=VARCHAR},
view_org = #{viewOrg,jdbcType=VARCHAR},
admin = #{admin,jdbcType=VARCHAR},
admin_org = #{adminOrg,jdbcType=VARCHAR},
is_open = #{isOpen,jdbcType=INTEGER},
created_by = #{createdBy,jdbcType=VARCHAR},
created_at = #{createdAt,jdbcType=TIMESTAMP},
updated_by = #{updatedBy,jdbcType=VARCHAR},
updated_at = #{updatedAt,jdbcType=TIMESTAMP},
drill_down_dimensions = #{drillDownDimensions,jdbcType=VARCHAR},
status = #{status,jdbcType=INTEGER}
where id = #{id,jdbcType=BIGINT}
</update>
</mapper>

View File

@@ -5,7 +5,6 @@
<resultMap id="BaseResultMap" type="com.tencent.supersonic.semantic.model.domain.dataobject.DimensionDO">
<id column="id" jdbcType="BIGINT" property="id" />
<result column="model_id" jdbcType="BIGINT" property="modelId" />
<result column="datasource_id" jdbcType="BIGINT" property="datasourceId" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="biz_name" jdbcType="VARCHAR" property="bizName" />
<result column="description" jdbcType="VARCHAR" property="description" />
@@ -67,8 +66,7 @@
<insert id="batchInsert" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="id">
insert into s2_dimension (name, biz_name,
description, status, model_id,
type, type_params, expr,
datasource_id, created_at, created_by,
type, type_params, expr,created_at, created_by,
updated_by, updated_at, semantic_type,sensitive_level, is_tag)
values
<foreach collection="list" item="dimension" separator=",">
@@ -76,8 +74,7 @@
#{dimension.description,jdbcType=VARCHAR}, #{dimension.status,jdbcType=INTEGER},
#{dimension.modelId,jdbcType=BIGINT},
#{dimension.type,jdbcType=VARCHAR}, #{dimension.typeParams,jdbcType=VARCHAR},
#{dimension.expr,jdbcType=VARCHAR},
#{dimension.datasourceId,jdbcType=BIGINT}, #{dimension.createdAt,jdbcType=TIMESTAMP},
#{dimension.expr,jdbcType=VARCHAR}, #{dimension.createdAt,jdbcType=TIMESTAMP},
#{dimension.createdBy,jdbcType=VARCHAR},
#{dimension.updatedBy,jdbcType=VARCHAR}, #{dimension.updatedAt,jdbcType=TIMESTAMP},
#{dimension.semanticType,jdbcType=VARCHAR},
@@ -161,9 +158,6 @@
<if test="createdBy != null">
and created_by = #{createdBy}
</if>
<if test="datasourceId != null">
and datasource_id = #{datasourceId}
</if>
<if test="isTag != null and isTag == 1">
and is_tag = 1
</if>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tencent.supersonic.semantic.model.infrastructure.mapper.ModelDOCustomMapper">
<update id="batchUpdateStatus" parameterType="java.util.List">
<foreach collection="list" item="dimension" separator=";">
update s2_model
set
status = #{model.status,jdbcType=INTEGER},
updated_by = #{model.updatedBy,jdbcType=VARCHAR},
updated_at = #{model.updatedAt,jdbcType=TIMESTAMP}
where id = #{model.id,jdbcType=BIGINT}
</foreach>
</update>
</mapper>

View File

@@ -1,218 +0,0 @@
package com.tencent.supersonic.semantic.model.application;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
import com.tencent.supersonic.semantic.api.model.enums.DimensionTypeEnum;
import com.tencent.supersonic.semantic.api.model.enums.IdentifyTypeEnum;
import com.tencent.supersonic.semantic.api.model.pojo.DatasourceDetail;
import com.tencent.supersonic.semantic.api.model.pojo.Dim;
import com.tencent.supersonic.semantic.api.model.pojo.DimensionTimeTypeParams;
import com.tencent.supersonic.semantic.api.model.pojo.Identify;
import com.tencent.supersonic.semantic.api.model.pojo.Measure;
import com.tencent.supersonic.semantic.api.model.request.DatasourceReq;
import com.tencent.supersonic.semantic.api.model.response.DatasourceResp;
import com.tencent.supersonic.semantic.model.domain.DatabaseService;
import com.tencent.supersonic.semantic.model.domain.DimensionService;
import com.tencent.supersonic.semantic.model.domain.MetricService;
import com.tencent.supersonic.semantic.model.domain.dataobject.DatasourceDO;
import com.tencent.supersonic.semantic.model.domain.repository.DatasourceRepository;
import com.tencent.supersonic.semantic.model.domain.repository.DateInfoRepository;
import com.tencent.supersonic.semantic.model.domain.utils.DatasourceConverter;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.List;
import static org.mockito.Mockito.when;
class DatasourceServiceImplTest {
@Test
void createDatasource() throws Exception {
MetricService metricService = Mockito.mock(MetricService.class);
DimensionService dimensionService = Mockito.mock(DimensionService.class);
DatasourceRepository datasourceRepository = Mockito.mock(DatasourceRepository.class);
DatabaseService databaseService = Mockito.mock(DatabaseService.class);
DateInfoRepository dateInfoRepository = Mockito.mock(DateInfoRepository.class);
DatasourceServiceImpl datasourceService = new DatasourceServiceImpl(datasourceRepository, databaseService,
dimensionService, metricService, dateInfoRepository);
DatasourceResp actualDatasourceResp = datasourceService.createDatasource(
mockDatasourceReq(), User.getFakeUser());
DatasourceResp expectedDatasourceResp = buildExpectedDatasourceResp();
Assertions.assertEquals(expectedDatasourceResp, actualDatasourceResp);
}
@Test
void updateDatasource() throws Exception {
MetricService metricService = Mockito.mock(MetricService.class);
DimensionService dimensionService = Mockito.mock(DimensionService.class);
DatasourceRepository datasourceRepository = Mockito.mock(DatasourceRepository.class);
DatabaseService databaseService = Mockito.mock(DatabaseService.class);
DateInfoRepository dateInfoRepository = Mockito.mock(DateInfoRepository.class);
DatasourceServiceImpl datasourceService = new DatasourceServiceImpl(datasourceRepository, databaseService,
dimensionService, metricService, dateInfoRepository);
DatasourceReq datasourceReq = mockDatasourceReq_update();
DatasourceDO datasourceDO = DatasourceConverter.convert(mockDatasourceReq(), User.getFakeUser());
when(datasourceRepository.getDatasourceById(datasourceReq.getId())).thenReturn(datasourceDO);
User user = User.getFakeUser();
user.setName("alice");
DatasourceResp actualDatasourceResp = datasourceService.updateDatasource(mockDatasourceReq_update(), user);
DatasourceResp expectedDatasourceResp = buildExpectedDatasourceResp_update();
Assertions.assertEquals(expectedDatasourceResp, actualDatasourceResp);
Assertions.assertEquals("admin", actualDatasourceResp.getCreatedBy());
Assertions.assertEquals("alice", actualDatasourceResp.getUpdatedBy());
}
private DatasourceReq mockDatasourceReq() {
DatasourceReq datasourceReq = new DatasourceReq();
datasourceReq.setName("PVUV统计");
datasourceReq.setBizName("s2_pv_uv_statis");
datasourceReq.setDescription("PVUV统计");
datasourceReq.setDatabaseId(1L);
List<Identify> identifiers = new ArrayList<>();
identifiers.add(new Identify("用户名", IdentifyTypeEnum.primary.name(), "user_name"));
datasourceReq.setIdentifiers(identifiers);
List<Dim> dimensions = new ArrayList<>();
Dim dimension1 = new Dim("", "imp_date", DimensionTypeEnum.time.name(), 0);
dimension1.setTypeParams(new DimensionTimeTypeParams());
dimensions.add(dimension1);
Dim dimension2 = new Dim("", "page", DimensionTypeEnum.categorical.name(), 0);
dimension2.setExpr("page");
dimensions.add(dimension2);
datasourceReq.setDimensions(dimensions);
List<Measure> measures = new ArrayList<>();
Measure measure1 = new Measure("访问次数", "pv", AggOperatorEnum.SUM.name(), 1);
measures.add(measure1);
Measure measure2 = new Measure("访问人数", "uv", AggOperatorEnum.COUNT_DISTINCT.name(), 1);
measures.add(measure2);
datasourceReq.setMeasures(measures);
datasourceReq.setSqlQuery("SELECT imp_date, user_name, page, 1 as pv, user_name as uv FROM s2_pv_uv_statis");
datasourceReq.setQueryType("sql_query");
datasourceReq.setModelId(1L);
datasourceReq.setFilterSql("where user_name = 'alice'");
return datasourceReq;
}
private DatasourceReq mockDatasourceReq_update() {
DatasourceReq datasourceReq = new DatasourceReq();
datasourceReq.setId(1L);
datasourceReq.setName("PVUV统计_a");
datasourceReq.setBizName("s2_pv_uv_statis_a");
datasourceReq.setDescription("PVUV统计_a");
datasourceReq.setDatabaseId(2L);
List<Identify> identifiers = new ArrayList<>();
identifiers.add(new Identify("用户名_a", IdentifyTypeEnum.primary.name(), "user_name_a"));
datasourceReq.setIdentifiers(identifiers);
List<Dim> dimensions = new ArrayList<>();
Dim dimension1 = new Dim("", "imp_date_a", DimensionTypeEnum.time.name(), 0);
dimension1.setTypeParams(new DimensionTimeTypeParams());
dimensions.add(dimension1);
Dim dimension2 = new Dim("", "page_a", DimensionTypeEnum.categorical.name(), 0);
dimension2.setExpr("page_a");
dimensions.add(dimension2);
datasourceReq.setDimensions(dimensions);
List<Measure> measures = new ArrayList<>();
Measure measure1 = new Measure("访问次数_a", "pv_a", AggOperatorEnum.SUM.name(), 1);
measures.add(measure1);
Measure measure2 = new Measure("访问人数_a", "uv_a", AggOperatorEnum.COUNT_DISTINCT.name(), 1);
measures.add(measure2);
datasourceReq.setMeasures(measures);
datasourceReq.setSqlQuery("SELECT imp_date_a, user_name_a, page_a, 1 as pv_a, user_name "
+ "as uv_a FROM s2_pv_uv_statis");
datasourceReq.setQueryType("sql_query");
datasourceReq.setModelId(1L);
datasourceReq.setFilterSql("where user_name = 'tom'");
return datasourceReq;
}
private DatasourceResp buildExpectedDatasourceResp() {
DatasourceResp datasourceResp = new DatasourceResp();
datasourceResp.setName("PVUV统计");
datasourceResp.setBizName("s2_pv_uv_statis");
datasourceResp.setDescription("PVUV统计");
datasourceResp.setDatabaseId(1L);
DatasourceDetail datasourceDetail = new DatasourceDetail();
List<Identify> identifiers = new ArrayList<>();
identifiers.add(new Identify("用户名", IdentifyTypeEnum.primary.name(), "user_name"));
datasourceDetail.setIdentifiers(identifiers);
List<Dim> dimensions = new ArrayList<>();
Dim dimension1 = new Dim("", "imp_date", DimensionTypeEnum.time.name(), 0);
dimension1.setTypeParams(new DimensionTimeTypeParams());
dimensions.add(dimension1);
Dim dimension2 = new Dim("", "page", DimensionTypeEnum.categorical.name(), 0);
dimension2.setExpr("page");
dimensions.add(dimension2);
datasourceDetail.setDimensions(dimensions);
List<Measure> measures = new ArrayList<>();
Measure measure1 = new Measure("访问次数", "s2_pv_uv_statis_pv", AggOperatorEnum.SUM.name(), 1);
measure1.setExpr("pv");
measures.add(measure1);
Measure measure2 = new Measure("访问人数", "s2_pv_uv_statis_uv", AggOperatorEnum.COUNT_DISTINCT.name(), 1);
measure2.setExpr("uv");
measures.add(measure2);
datasourceDetail.setMeasures(measures);
datasourceDetail.setSqlQuery("SELECT imp_date, user_name, page, 1 as pv, user_name as uv FROM s2_pv_uv_statis");
datasourceDetail.setQueryType("sql_query");
datasourceResp.setDatasourceDetail(datasourceDetail);
datasourceResp.setModelId(1L);
datasourceResp.setFilterSql("where user_name = 'alice'");
return datasourceResp;
}
private DatasourceResp buildExpectedDatasourceResp_update() {
DatasourceResp datasourceResp = new DatasourceResp();
datasourceResp.setName("PVUV统计_a");
datasourceResp.setBizName("s2_pv_uv_statis_a");
datasourceResp.setDescription("PVUV统计_a");
datasourceResp.setDatabaseId(2L);
DatasourceDetail datasourceDetail = new DatasourceDetail();
List<Identify> identifiers = new ArrayList<>();
identifiers.add(new Identify("用户名_a", IdentifyTypeEnum.primary.name(), "user_name_a"));
datasourceDetail.setIdentifiers(identifiers);
List<Dim> dimensions = new ArrayList<>();
Dim dimension1 = new Dim("", "imp_date_a", DimensionTypeEnum.time.name(), 0);
dimension1.setTypeParams(new DimensionTimeTypeParams());
dimensions.add(dimension1);
Dim dimension2 = new Dim("", "page_a", DimensionTypeEnum.categorical.name(), 0);
dimension2.setExpr("page_a");
dimensions.add(dimension2);
datasourceDetail.setDimensions(dimensions);
List<Measure> measures = new ArrayList<>();
Measure measure1 = new Measure("访问次数_a", "s2_pv_uv_statis_a_pv_a",
AggOperatorEnum.SUM.name(), 1);
measure1.setExpr("pv_a");
measures.add(measure1);
Measure measure2 = new Measure("访问人数_a", "s2_pv_uv_statis_a_uv_a",
AggOperatorEnum.COUNT_DISTINCT.name(), 1);
measure2.setExpr("uv_a");
measures.add(measure2);
datasourceDetail.setMeasures(measures);
datasourceDetail.setSqlQuery("SELECT imp_date_a, user_name_a, page_a, 1 as pv_a, "
+ "user_name as uv_a FROM s2_pv_uv_statis");
datasourceDetail.setQueryType("sql_query");
datasourceResp.setDatasourceDetail(datasourceDetail);
datasourceResp.setModelId(1L);
datasourceResp.setFilterSql("where user_name = 'tom'");
return datasourceResp;
}
}

View File

@@ -0,0 +1,241 @@
package com.tencent.supersonic.semantic.model.application;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authentication.service.UserService;
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
import com.tencent.supersonic.semantic.api.model.enums.DimensionTypeEnum;
import com.tencent.supersonic.semantic.api.model.enums.IdentifyTypeEnum;
import com.tencent.supersonic.semantic.api.model.pojo.Dim;
import com.tencent.supersonic.semantic.api.model.pojo.DimensionTimeTypeParams;
import com.tencent.supersonic.semantic.api.model.pojo.Identify;
import com.tencent.supersonic.semantic.api.model.pojo.Measure;
import com.tencent.supersonic.semantic.api.model.pojo.ModelDetail;
import com.tencent.supersonic.semantic.api.model.request.ModelReq;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.model.domain.DatabaseService;
import com.tencent.supersonic.semantic.model.domain.DimensionService;
import com.tencent.supersonic.semantic.model.domain.DomainService;
import com.tencent.supersonic.semantic.model.domain.MetricService;
import com.tencent.supersonic.semantic.model.domain.ModelRelaService;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import com.tencent.supersonic.semantic.model.domain.dataobject.ModelDO;
import com.tencent.supersonic.semantic.model.domain.repository.DateInfoRepository;
import com.tencent.supersonic.semantic.model.domain.repository.ModelRepository;
import com.tencent.supersonic.semantic.model.domain.utils.ModelConverter;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.List;
import static org.mockito.Mockito.when;
class ModelServiceImplTest {
@Test
void createModel() throws Exception {
ModelRepository modelRepository = Mockito.mock(ModelRepository.class);
ModelService modelService = mockModelService(modelRepository);
ModelResp actualModelResp = modelService.createModel(
mockModelReq(), User.getFakeUser());
ModelResp expectedModelResp = buildExpectedModelResp();
Assertions.assertEquals(expectedModelResp, actualModelResp);
}
@Test
void updateModel() throws Exception {
ModelRepository modelRepository = Mockito.mock(ModelRepository.class);
ModelService modelService = mockModelService(modelRepository);
ModelReq modelReq = mockModelReq_update();
ModelDO modelDO = ModelConverter.convert(mockModelReq(), User.getFakeUser());
when(modelRepository.getModelById(modelReq.getId())).thenReturn(modelDO);
User user = User.getFakeUser();
user.setName("alice");
ModelResp actualModelResp = modelService.updateModel(modelReq, user);
ModelResp expectedModelResp = buildExpectedModelResp_update();
Assertions.assertEquals(expectedModelResp, actualModelResp);
Assertions.assertEquals("admin", actualModelResp.getCreatedBy());
Assertions.assertEquals("alice", actualModelResp.getUpdatedBy());
}
private ModelService mockModelService(ModelRepository modelRepository) {
MetricService metricService = Mockito.mock(MetricService.class);
DimensionService dimensionService = Mockito.mock(DimensionService.class);
DatabaseService databaseService = Mockito.mock(DatabaseService.class);
DomainService domainService = Mockito.mock(DomainService.class);
UserService userService = Mockito.mock(UserService.class);
ModelRelaService modelRelaService = Mockito.mock(ModelRelaService.class);
DateInfoRepository dateInfoRepository = Mockito.mock(DateInfoRepository.class);
return new ModelServiceImpl(modelRepository, databaseService,
dimensionService, metricService, modelRelaService, domainService, userService, dateInfoRepository);
}
private ModelReq mockModelReq() {
ModelReq modelReq = new ModelReq();
modelReq.setId(1L);
modelReq.setName("PVUV统计");
modelReq.setBizName("s2_pv_uv_statis");
modelReq.setDescription("PVUV统计");
modelReq.setDatabaseId(1L);
modelReq.setAlias("访问次数统计,PVUV统计");
modelReq.setAdmins(Lists.newArrayList("admin", "tom"));
modelReq.setViewers(Lists.newArrayList("alice", "lucy"));
ModelDetail modelDetail = new ModelDetail();
List<Identify> identifiers = new ArrayList<>();
identifiers.add(new Identify("用户名", IdentifyTypeEnum.primary.name(), "user_name"));
modelDetail.setIdentifiers(identifiers);
List<Dim> dimensions = new ArrayList<>();
Dim dimension1 = new Dim("", "imp_date", DimensionTypeEnum.time.name(), 0);
dimension1.setTypeParams(new DimensionTimeTypeParams());
dimensions.add(dimension1);
Dim dimension2 = new Dim("", "page", DimensionTypeEnum.categorical.name(), 0);
dimension2.setExpr("page");
dimensions.add(dimension2);
modelDetail.setDimensions(dimensions);
List<Measure> measures = new ArrayList<>();
Measure measure1 = new Measure("访问次数", "pv", AggOperatorEnum.SUM.name(), 1);
measures.add(measure1);
Measure measure2 = new Measure("访问人数", "uv", AggOperatorEnum.COUNT_DISTINCT.name(), 1);
measures.add(measure2);
modelDetail.setMeasures(measures);
modelDetail.setSqlQuery("SELECT imp_date, user_name, page, 1 as pv, user_name as uv FROM s2_pv_uv_statis");
modelDetail.setQueryType("sql_query");
modelReq.setDomainId(1L);
modelReq.setFilterSql("where user_name = 'alice'");
modelReq.setModelDetail(modelDetail);
return modelReq;
}
private ModelReq mockModelReq_update() {
ModelReq modelReq = new ModelReq();
modelReq.setId(1L);
modelReq.setName("PVUV统计_a");
modelReq.setBizName("s2_pv_uv_statis_a");
modelReq.setDescription("PVUV统计_a");
modelReq.setDatabaseId(2L);
modelReq.setDomainId(1L);
modelReq.setAlias("访问次数统计,PVUV统计");
modelReq.setAdmins(Lists.newArrayList("admin"));
modelReq.setViewers(Lists.newArrayList("alice"));
ModelDetail modelDetail = new ModelDetail();
List<Identify> identifiers = new ArrayList<>();
identifiers.add(new Identify("用户名_a", IdentifyTypeEnum.primary.name(), "user_name_a"));
modelDetail.setIdentifiers(identifiers);
List<Dim> dimensions = new ArrayList<>();
Dim dimension1 = new Dim("", "imp_date_a", DimensionTypeEnum.time.name(), 0);
dimension1.setTypeParams(new DimensionTimeTypeParams());
dimensions.add(dimension1);
Dim dimension2 = new Dim("", "page_a", DimensionTypeEnum.categorical.name(), 0);
dimension2.setExpr("page_a");
dimensions.add(dimension2);
modelDetail.setDimensions(dimensions);
List<Measure> measures = new ArrayList<>();
Measure measure1 = new Measure("访问次数_a", "pv_a", AggOperatorEnum.SUM.name(), 1);
measures.add(measure1);
Measure measure2 = new Measure("访问人数_a", "uv_a", AggOperatorEnum.COUNT_DISTINCT.name(), 1);
measures.add(measure2);
modelDetail.setMeasures(measures);
modelDetail.setSqlQuery("SELECT imp_date_a, user_name_a, page_a, 1 as pv_a, user_name "
+ "as uv_a FROM s2_pv_uv_statis");
modelDetail.setQueryType("sql_query");
modelReq.setDomainId(1L);
modelReq.setFilterSql("where user_name = 'tom'");
modelReq.setModelDetail(modelDetail);
return modelReq;
}
private ModelResp buildExpectedModelResp() {
ModelResp modelResp = new ModelResp();
modelResp.setName("PVUV统计");
modelResp.setBizName("s2_pv_uv_statis");
modelResp.setDescription("PVUV统计");
modelResp.setDatabaseId(1L);
modelResp.setDomainId(1L);
modelResp.setAlias("访问次数统计,PVUV统计");
modelResp.setAdmins(Lists.newArrayList("admin", "tom"));
modelResp.setViewers(Lists.newArrayList("alice", "lucy"));
ModelDetail modelDetail = new ModelDetail();
List<Identify> identifiers = new ArrayList<>();
identifiers.add(new Identify("用户名", IdentifyTypeEnum.primary.name(), "user_name"));
modelDetail.setIdentifiers(identifiers);
List<Dim> dimensions = new ArrayList<>();
Dim dimension1 = new Dim("", "imp_date", DimensionTypeEnum.time.name(), 0);
dimension1.setTypeParams(new DimensionTimeTypeParams());
dimensions.add(dimension1);
Dim dimension2 = new Dim("", "page", DimensionTypeEnum.categorical.name(), 0);
dimension2.setExpr("page");
dimensions.add(dimension2);
modelDetail.setDimensions(dimensions);
List<Measure> measures = new ArrayList<>();
Measure measure1 = new Measure("访问次数", "s2_pv_uv_statis_pv", AggOperatorEnum.SUM.name(), 1);
measure1.setExpr("pv");
measures.add(measure1);
Measure measure2 = new Measure("访问人数", "s2_pv_uv_statis_uv", AggOperatorEnum.COUNT_DISTINCT.name(), 1);
measure2.setExpr("uv");
measures.add(measure2);
modelDetail.setMeasures(measures);
modelDetail.setSqlQuery("SELECT imp_date, user_name, page, 1 as pv, user_name as uv FROM s2_pv_uv_statis");
modelDetail.setQueryType("sql_query");
modelResp.setModelDetail(modelDetail);
modelResp.setId(1L);
modelResp.setFilterSql("where user_name = 'alice'");
return modelResp;
}
private ModelResp buildExpectedModelResp_update() {
ModelResp modelResp = new ModelResp();
modelResp.setName("PVUV统计_a");
modelResp.setBizName("s2_pv_uv_statis_a");
modelResp.setDescription("PVUV统计_a");
modelResp.setDatabaseId(2L);
modelResp.setDomainId(1L);
modelResp.setAlias("访问次数统计,PVUV统计");
modelResp.setAdmins(Lists.newArrayList("admin"));
modelResp.setViewers(Lists.newArrayList("alice"));
ModelDetail modelDetail = new ModelDetail();
List<Identify> identifiers = new ArrayList<>();
identifiers.add(new Identify("用户名_a", IdentifyTypeEnum.primary.name(), "user_name_a"));
modelDetail.setIdentifiers(identifiers);
List<Dim> dimensions = new ArrayList<>();
Dim dimension1 = new Dim("", "imp_date_a", DimensionTypeEnum.time.name(), 0);
dimension1.setTypeParams(new DimensionTimeTypeParams());
dimensions.add(dimension1);
Dim dimension2 = new Dim("", "page_a", DimensionTypeEnum.categorical.name(), 0);
dimension2.setExpr("page_a");
dimensions.add(dimension2);
modelDetail.setDimensions(dimensions);
List<Measure> measures = new ArrayList<>();
Measure measure1 = new Measure("访问次数_a", "s2_pv_uv_statis_a_pv_a",
AggOperatorEnum.SUM.name(), 1);
measure1.setExpr("pv_a");
measures.add(measure1);
Measure measure2 = new Measure("访问人数_a", "s2_pv_uv_statis_a_uv_a",
AggOperatorEnum.COUNT_DISTINCT.name(), 1);
measure2.setExpr("uv_a");
measures.add(measure2);
modelDetail.setMeasures(measures);
modelDetail.setSqlQuery("SELECT imp_date_a, user_name_a, page_a, 1 as pv_a, "
+ "user_name as uv_a FROM s2_pv_uv_statis");
modelDetail.setQueryType("sql_query");
modelResp.setModelDetail(modelDetail);
modelResp.setId(1L);
modelResp.setFilterSql("where user_name = 'tom'");
return modelResp;
}
}

View File

@@ -85,8 +85,9 @@ public class MaterializationQuery implements QueryOptimizer {
return;
}
try {
if (Objects.isNull(queryStructCmd) || Objects.isNull(queryStatement) || Objects.isNull(
queryStructCmd.getModelId()) || Objects.isNull(
if (Objects.isNull(queryStructCmd) || Objects.isNull(queryStatement)
|| CollectionUtils.isEmpty(queryStructCmd.getModelIds())
|| Objects.isNull(
queryStructCmd.getDateInfo())) {
return;
}
@@ -172,10 +173,11 @@ public class MaterializationQuery implements QueryOptimizer {
ImmutablePair<String, String> timeRange = queryStructUtils.getBeginEndTime(queryStructReq);
String start = timeRange.left;
String end = timeRange.right;
Long modelId = queryStructReq.getModelId();
//todo
Long modelId = 1L;
List<MaterializationResp> materializationResps = materializationConfService.getMaterializationByModel(modelId);
List<DimensionResp> dimensionResps = catalog.getDimensions(modelId);
List<MetricResp> metrics = catalog.getMetrics(modelId);
List<DimensionResp> dimensionResps = catalog.getDimensions(queryStructReq.getModelIds());
List<MetricResp> metrics = catalog.getMetrics(queryStructReq.getModelIds());
Set<String> fields = new HashSet<>();
if (Objects.nonNull(metricReq.getWhere()) && !metricReq.getWhere().isEmpty()) {

View File

@@ -41,6 +41,7 @@ public class CalciteSqlParser implements SqlParser {
semanticSchema.setDatasource(semanticModel.getDatasourceMap());
semanticSchema.setDimension(semanticModel.getDimensionMap());
semanticSchema.setMetric(semanticModel.getMetrics());
semanticSchema.setJoinRelations(semanticModel.getJoinRelations());
return semanticSchema;
}
}

View File

@@ -3,7 +3,9 @@ package com.tencent.supersonic.semantic.query.parser.calcite;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.tencent.supersonic.semantic.api.model.yaml.DatasourceYamlTpl;
import com.tencent.supersonic.common.pojo.ModelRela;
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
import com.tencent.supersonic.semantic.api.model.yaml.DataModelYamlTpl;
import com.tencent.supersonic.semantic.api.model.yaml.DimensionTimeTypeParamsTpl;
import com.tencent.supersonic.semantic.api.model.yaml.DimensionYamlTpl;
import com.tencent.supersonic.semantic.api.model.yaml.IdentifyYamlTpl;
@@ -17,12 +19,14 @@ import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.DataType;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Dimension;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.DimensionTimeTypeParams;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Identify;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.JoinRelation;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Measure;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Metric;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.MetricTypeParams;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.SemanticModel;
import com.tencent.supersonic.semantic.query.parser.calcite.schema.SemanticSchema;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -34,6 +38,7 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.EnableCaching;
@@ -57,20 +62,27 @@ public class SemanticSchemaManager {
public SemanticModel reload(String rootPath) {
SemanticModel semanticModel = new SemanticModel();
semanticModel.setRootPath(rootPath);
Map<Long, String> modelFullPathMap = catalog.getModelFullPath();
log.info("modelFullPathMap {}", modelFullPathMap);
Set<Long> modelIds = modelFullPathMap.entrySet().stream().filter(e -> e.getValue().startsWith(rootPath))
.map(Entry::getKey).collect(Collectors.toSet());
//Map<Long, String> modelFullPathMap = catalog.getModelFullPath();
//log.info("modelFullPathMap {}", modelFullPathMap);
//Set<Long> modelIds = modelFullPathMap.entrySet().stream().filter(e -> e.getValue().startsWith(rootPath))
// .map(Entry::getKey).collect(Collectors.toSet());
Set<Long> modelIds = Arrays.stream(rootPath.split(",")).map(s -> Long.parseLong(s.trim()))
.collect(Collectors.toSet());
if (modelIds.isEmpty()) {
log.error("get modelIds empty {}", rootPath);
return semanticModel;
}
Map<String, List<DimensionYamlTpl>> dimensionYamlTpls = new HashMap<>();
List<DatasourceYamlTpl> datasourceYamlTpls = new ArrayList<>();
List<DataModelYamlTpl> dataModelYamlTpls = new ArrayList<>();
List<MetricYamlTpl> metricYamlTpls = new ArrayList<>();
catalog.getModelYamlTplByModelIds(modelIds, dimensionYamlTpls, datasourceYamlTpls, metricYamlTpls);
if (!datasourceYamlTpls.isEmpty()) {
Map<String, DataSource> dataSourceMap = datasourceYamlTpls.stream().map(d -> getDatasource(d))
Map<Long, String> modelIdName = new HashMap<>();
catalog.getModelYamlTplByModelIds(modelIds, dimensionYamlTpls, dataModelYamlTpls, metricYamlTpls, modelIdName);
List<ModelRela> modelRelas = catalog.getModelRela(new ArrayList<>(modelIds));
if (!CollectionUtils.isEmpty(modelRelas)) {
semanticModel.setJoinRelations(getJoinRelation(modelRelas, modelIdName));
}
if (!dataModelYamlTpls.isEmpty()) {
Map<String, DataSource> dataSourceMap = dataModelYamlTpls.stream().map(d -> getDatasource(d))
.collect(Collectors.toMap(DataSource::getName, item -> item, (k1, k2) -> k1));
semanticModel.setDatasourceMap(dataSourceMap);
}
@@ -107,7 +119,7 @@ public class SemanticSchemaManager {
}
public static DataSource getDatasource(final DatasourceYamlTpl d) {
public static DataSource getDatasource(final DataModelYamlTpl d) {
DataSource datasource = DataSource.builder().sourceId(d.getSourceId()).sqlQuery(d.getSqlQuery())
.name(d.getName()).tableQuery(d.getTableQuery()).identifiers(getIdentify(d.getIdentifiers()))
.measures(getMeasures(d.getMeasures())).dimensions(getDimensions(d.getDimensions())).build();
@@ -200,6 +212,25 @@ public class SemanticSchemaManager {
return identifies;
}
private static List<JoinRelation> getJoinRelation(List<ModelRela> modelRelas, Map<Long, String> modelIdName) {
List<JoinRelation> joinRelations = new ArrayList<>();
modelRelas.stream().forEach(r -> {
if (modelIdName.containsKey(r.getFromModelId()) && modelIdName.containsKey(r.getToModelId())) {
JoinRelation joinRelation = JoinRelation.builder().left(modelIdName.get(r.getFromModelId()))
.right(modelIdName.get(r.getToModelId())).joinType(r.getJoinType()).build();
List<Triple<String, String, String>> conditions = new ArrayList<>();
r.getJoinConditions().stream().forEach(rr -> {
if (FilterOperatorEnum.isValueCompare(rr.getOperator())) {
conditions.add(Triple.of(rr.getLeftField(), rr.getOperator().getValue(), rr.getRightField()));
}
});
joinRelation.setJoinCondition(conditions);
joinRelations.add(joinRelation);
}
});
return joinRelations;
}
public static void update(SemanticSchema schema, List<Metric> metric) throws Exception {
if (schema != null) {

View File

@@ -15,18 +15,19 @@ import com.tencent.supersonic.semantic.query.parser.calcite.sql.render.FilterRen
import com.tencent.supersonic.semantic.query.parser.calcite.sql.render.OutputRender;
import com.tencent.supersonic.semantic.query.parser.calcite.sql.render.SourceRender;
import com.tencent.supersonic.semantic.query.persistence.pojo.QueryStatement;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.validate.SqlValidatorScope;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import java.util.Stack;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.validate.SqlValidatorScope;
public class AggPlanner implements Planner {
private MetricReq metricCommand;
private MetricReq metricReq;
private SemanticSchema schema;
private SqlValidatorScope scope;
private Stack<TableView> dataSets = new Stack<>();
@@ -61,13 +62,13 @@ public class AggPlanner implements Planner {
while (it.hasNext()) {
Renderer renderer = it.next();
if (previous != null) {
previous.render(metricCommand, datasource, scope, schema, !isAgg);
previous.render(metricReq, datasource, scope, schema, !isAgg);
renderer.setTable(previous.builderAs(DataSourceNode.getNames(datasource) + "_" + String.valueOf(i)));
i++;
}
previous = renderer;
}
builders.getLast().render(metricCommand, datasource, scope, schema, !isAgg);
builders.getLast().render(metricReq, datasource, scope, schema, !isAgg);
parserNode = builders.getLast().builder();
@@ -75,7 +76,7 @@ public class AggPlanner implements Planner {
private List<DataSource> getMatchDataSource(SqlValidatorScope scope) throws Exception {
return DataSourceNode.getMatchDataSources(scope, schema, metricCommand);
return DataSourceNode.getMatchDataSources(scope, schema, metricReq);
}
private boolean getAgg(DataSource dataSource) {
@@ -85,7 +86,7 @@ public class AggPlanner implements Planner {
// default by dataSource time aggregation
if (Objects.nonNull(dataSource.getAggTime()) && !dataSource.getAggTime().equalsIgnoreCase(
Constants.DIMENSION_TYPE_TIME_GRANULARITY_NONE)) {
if (!metricCommand.isNativeQuery()) {
if (!metricReq.isNativeQuery()) {
return true;
}
}
@@ -95,15 +96,15 @@ public class AggPlanner implements Planner {
@Override
public void explain(QueryStatement queryStatement, AggOption aggOption) throws Exception {
this.metricCommand = queryStatement.getMetricReq();
if (metricCommand.getMetrics() == null) {
metricCommand.setMetrics(new ArrayList<>());
this.metricReq = queryStatement.getMetricReq();
if (metricReq.getMetrics() == null) {
metricReq.setMetrics(new ArrayList<>());
}
if (metricCommand.getDimensions() == null) {
metricCommand.setDimensions(new ArrayList<>());
if (metricReq.getDimensions() == null) {
metricReq.setDimensions(new ArrayList<>());
}
if (metricCommand.getLimit() == null) {
metricCommand.setLimit(0L);
if (metricReq.getLimit() == null) {
metricReq.setLimit(0L);
}
this.aggOption = aggOption;
// build a parse Node

View File

@@ -0,0 +1,17 @@
package com.tencent.supersonic.semantic.query.parser.calcite.s2sql;
import java.util.List;
import lombok.Builder;
import lombok.Data;
import org.apache.commons.lang3.tuple.Triple;
@Data
@Builder
public class JoinRelation {
private String left;
private String right;
private String joinType;
private List<Triple<String, String, String>> joinCondition;
}

View File

@@ -14,4 +14,5 @@ public class SemanticModel {
private Map<String, DataSource> datasourceMap = new HashMap<>();
private Map<String, List<Dimension>> dimensionMap = new HashMap<>();
private List<Materialization> materializationList = new ArrayList<>();
private List<JoinRelation> joinRelations;
}

View File

@@ -3,17 +3,19 @@ package com.tencent.supersonic.semantic.query.parser.calcite.schema;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.DataSource;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Dimension;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.JoinRelation;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Materialization;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Metric;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.SemanticModel;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.calcite.schema.Schema;
import org.apache.calcite.schema.SchemaVersion;
import org.apache.calcite.schema.Table;
import org.apache.calcite.schema.impl.AbstractSchema;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SemanticSchema extends AbstractSchema {
private final String rootPath;
@@ -21,6 +23,8 @@ public class SemanticSchema extends AbstractSchema {
private SemanticModel semanticModel = new SemanticModel();
private List<JoinRelation> joinRelations;
private SemanticSchema(String rootPath, Map<String, Table> tableMap) {
this.rootPath = rootPath;
@@ -84,6 +88,14 @@ public class SemanticSchema extends AbstractSchema {
return semanticModel.getMaterializationList();
}
public void setJoinRelations(List<JoinRelation> joinRelations) {
this.joinRelations = joinRelations;
}
public List<JoinRelation> getJoinRelations() {
return joinRelations;
}
public static final class Builder {

View File

@@ -1,13 +1,26 @@
package com.tencent.supersonic.semantic.query.parser.calcite.sql.node;
import com.google.common.collect.Lists;
import com.tencent.supersonic.semantic.api.query.request.MetricReq;
import com.tencent.supersonic.semantic.query.parser.calcite.Configuration;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Constants;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.DataSource;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Dimension;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.JoinRelation;
import com.tencent.supersonic.semantic.query.parser.calcite.schema.SemanticSchema;
import com.tencent.supersonic.semantic.query.parser.calcite.sql.node.extend.LateralViewExplodeNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.calcite.sql.SqlBasicCall;
import org.apache.calcite.sql.SqlDataTypeSpec;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.sql.SqlUserDefinedTypeNameSpec;
import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.validate.SqlValidatorScope;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@@ -19,16 +32,6 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.calcite.sql.SqlBasicCall;
import org.apache.calcite.sql.SqlDataTypeSpec;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.sql.SqlUserDefinedTypeNameSpec;
import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.validate.SqlValidatorScope;
import org.springframework.util.CollectionUtils;
@Slf4j
public class DataSourceNode extends SemanticNode {
@@ -159,21 +162,26 @@ public class DataSourceNode extends SemanticNode {
return dataSources;
}
// find all dataSource has the same identifiers
Set<String> baseIdentifiers = baseDataSource.getIdentifiers().stream().map(i -> i.getName())
.collect(Collectors.toSet());
if (baseIdentifiers.isEmpty()) {
throw new Exception("datasource error : " + baseDataSource.getName() + " miss identifier");
}
List<DataSource> linkDataSources = getLinkDataSources(baseIdentifiers, queryDimension, measures,
List<DataSource> linkDataSources = getLinkDataSourcesByJoinRelation(queryDimension, measures,
baseDataSource, schema);
if (linkDataSources.isEmpty()) {
throw new Exception(
String.format("not find the match datasource : dimension[%s],measure[%s]", queryDimension,
measures));
if (CollectionUtils.isEmpty(linkDataSources)) {
log.info("baseDataSource get by identifiers ");
Set<String> baseIdentifiers = baseDataSource.getIdentifiers().stream().map(i -> i.getName())
.collect(Collectors.toSet());
if (baseIdentifiers.isEmpty()) {
throw new Exception("datasource error : " + baseDataSource.getName() + " miss identifier");
}
linkDataSources = getLinkDataSources(baseIdentifiers, queryDimension, measures,
baseDataSource, schema);
if (linkDataSources.isEmpty()) {
throw new Exception(
String.format("not find the match datasource : dimension[%s],measure[%s]", queryDimension,
measures));
}
}
log.debug("linkDataSources {}", linkDataSources);
dataSources.addAll(linkDataSources);
return linkDataSources;
//dataSources.addAll(linkDataSources);
}
return dataSources;
@@ -208,6 +216,69 @@ public class DataSourceNode extends SemanticNode {
return isAllMatch;
}
private static List<DataSource> getLinkDataSourcesByJoinRelation(Set<String> queryDimension, List<String> measures,
DataSource baseDataSource, SemanticSchema schema) {
Set<String> linkDataSourceName = new HashSet<>();
List<DataSource> linkDataSources = new ArrayList<>();
Set<String> before = new HashSet<>();
before.add(baseDataSource.getName());
if (!CollectionUtils.isEmpty(schema.getJoinRelations())) {
for (JoinRelation joinRelation : schema.getJoinRelations()) {
if (!before.contains(joinRelation.getLeft()) && !before.contains(joinRelation.getRight())) {
continue;
}
boolean isMatch = false;
boolean isRight = before.contains(joinRelation.getLeft());
DataSource other = isRight ? schema.getDatasource().get(joinRelation.getRight())
: schema.getDatasource().get(joinRelation.getLeft());
if (!queryDimension.isEmpty()) {
Set<String> linkDimension = other.getDimensions().stream().map(dd -> dd.getName())
.collect(Collectors.toSet());
other.getIdentifiers().stream().forEach(i -> linkDimension.add(i.getName()));
linkDimension.retainAll(queryDimension);
if (!linkDimension.isEmpty()) {
isMatch = true;
}
}
Set<String> linkMeasure = other.getMeasures().stream().map(mm -> mm.getName())
.collect(Collectors.toSet());
linkMeasure.retainAll(measures);
if (!linkMeasure.isEmpty()) {
isMatch = true;
}
if (!isMatch && schema.getDimension().containsKey(other.getName())) {
Set<String> linkDimension = schema.getDimension().get(other.getName()).stream()
.map(dd -> dd.getName())
.collect(Collectors.toSet());
linkDimension.retainAll(queryDimension);
if (!linkDimension.isEmpty()) {
isMatch = true;
}
}
if (isMatch) {
linkDataSourceName.add(other.getName());
before.add(other.getName());
}
}
}
if (!CollectionUtils.isEmpty(linkDataSourceName)) {
Map<String, Long> orders = new HashMap<>();
linkDataSourceName.add(baseDataSource.getName());
orders.put(baseDataSource.getName(), 0L);
for (JoinRelation joinRelation : schema.getJoinRelations()) {
if (linkDataSourceName.contains(joinRelation.getLeft()) && linkDataSourceName.contains(
joinRelation.getRight())) {
orders.put(joinRelation.getLeft(), 0L);
orders.put(joinRelation.getRight(), 1L);
}
}
orders.entrySet().stream().sorted(Map.Entry.comparingByValue()).forEach(d -> {
linkDataSources.add(schema.getDatasource().get(d.getKey()));
});
}
return linkDataSources;
}
private static List<DataSource> getLinkDataSources(Set<String> baseIdentifiers,
Set<String> queryDimension,
List<String> measures,
@@ -258,6 +329,12 @@ public class DataSourceNode extends SemanticNode {
for (String linkName : linkDataSourceName) {
linkDataSources.add(schema.getDatasource().get(linkName));
}
return linkDataSources;
if (!CollectionUtils.isEmpty(linkDataSources)) {
List<DataSource> all = new ArrayList<>();
all.add(baseDataSource);
all.addAll(linkDataSources);
return all;
}
return Lists.newArrayList();
}
}

View File

@@ -2,24 +2,21 @@ package com.tencent.supersonic.semantic.query.parser.calcite.sql.node;
import com.tencent.supersonic.semantic.query.parser.calcite.Configuration;
import com.tencent.supersonic.semantic.query.parser.calcite.sql.Optimization;
import com.tencent.supersonic.semantic.query.parser.calcite.schema.SemanticSqlDialect;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import com.tencent.supersonic.semantic.query.parser.calcite.sql.Optimization;
import org.apache.calcite.jdbc.CalciteSchema;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.sql.JoinType;
import org.apache.calcite.sql.SqlAsOperator;
import org.apache.calcite.sql.SqlBasicCall;
import org.apache.calcite.sql.SqlBinaryOperator;
import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlLiteral;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlSelect;
import org.apache.calcite.sql.SqlWriterConfig;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.parser.SqlParserPos;
@@ -29,6 +26,15 @@ import org.apache.calcite.sql.validate.SqlValidatorScope;
import org.apache.calcite.sql2rel.SqlToRelConverter;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
public abstract class SemanticNode {
public static SqlNode parse(String expression, SqlValidatorScope scope) throws Exception {
@@ -130,6 +136,46 @@ public abstract class SemanticNode {
sqlValidator.validate(SqlParser.create(sql, SqlParser.Config.DEFAULT).parseStmt()), false, true).rel;
}
public static SqlBinaryOperator getBinaryOperator(String val) {
if (val.equals("=")) {
return SqlStdOperatorTable.EQUALS;
}
if (val.equals(">")) {
return SqlStdOperatorTable.GREATER_THAN;
}
if (val.equals(">=")) {
return SqlStdOperatorTable.GREATER_THAN_OR_EQUAL;
}
if (val.equals("<")) {
return SqlStdOperatorTable.LESS_THAN;
}
if (val.equals("<=")) {
return SqlStdOperatorTable.LESS_THAN_OR_EQUAL;
}
if (val.equals("!=")) {
return SqlStdOperatorTable.NOT_EQUALS;
}
return SqlStdOperatorTable.EQUALS;
}
public static SqlLiteral getJoinSqlLiteral(String joinType) {
if (Objects.nonNull(joinType) && !joinType.isEmpty()) {
if (joinType.toLowerCase().contains(JoinType.INNER.lowerName)) {
return SqlLiteral.createSymbol(JoinType.INNER, SqlParserPos.ZERO);
}
if (joinType.toLowerCase().contains(JoinType.LEFT.lowerName)) {
return SqlLiteral.createSymbol(JoinType.LEFT, SqlParserPos.ZERO);
}
if (joinType.toLowerCase().contains(JoinType.RIGHT.lowerName)) {
return SqlLiteral.createSymbol(JoinType.RIGHT, SqlParserPos.ZERO);
}
if (joinType.toLowerCase().contains(JoinType.FULL.lowerName)) {
return SqlLiteral.createSymbol(JoinType.FULL, SqlParserPos.ZERO);
}
}
return SqlLiteral.createSymbol(JoinType.INNER, SqlParserPos.ZERO);
}
public void accept(Optimization optimization) {
optimization.visit(this);
}

View File

@@ -5,10 +5,9 @@ import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Constants;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.DataSource;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Dimension;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Identify;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Identify.Type;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.JoinRelation;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Materialization.TimePartType;
import com.tencent.supersonic.semantic.query.parser.calcite.s2sql.Metric;
import com.tencent.supersonic.semantic.query.parser.calcite.schema.SemanticSchema;
import com.tencent.supersonic.semantic.query.parser.calcite.sql.Renderer;
@@ -19,6 +18,18 @@ import com.tencent.supersonic.semantic.query.parser.calcite.sql.node.FilterNode;
import com.tencent.supersonic.semantic.query.parser.calcite.sql.node.IdentifyNode;
import com.tencent.supersonic.semantic.query.parser.calcite.sql.node.MetricNode;
import com.tencent.supersonic.semantic.query.parser.calcite.sql.node.SemanticNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.calcite.sql.JoinConditionType;
import org.apache.calcite.sql.SqlBasicCall;
import org.apache.calcite.sql.SqlJoin;
import org.apache.calcite.sql.SqlLiteral;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.validate.SqlValidatorScope;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.util.CollectionUtils;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
@@ -28,21 +39,11 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Queue;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.calcite.sql.JoinConditionType;
import org.apache.calcite.sql.JoinType;
import org.apache.calcite.sql.SqlBasicCall;
import org.apache.calcite.sql.SqlJoin;
import org.apache.calcite.sql.SqlLiteral;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.validate.SqlValidatorScope;
import org.springframework.util.CollectionUtils;
@Slf4j
public class JoinRender extends Renderer {
@@ -51,7 +52,7 @@ public class JoinRender extends Renderer {
public void render(MetricReq metricCommand, List<DataSource> dataSources, SqlValidatorScope scope,
SemanticSchema schema, boolean nonAgg) throws Exception {
String queryWhere = metricCommand.getWhere();
dataSources = getOrderSource(dataSources);
//dataSources = getOrderSource(dataSources);
Set<String> whereFields = new HashSet<>();
List<String> fieldWhere = new ArrayList<>();
if (queryWhere != null && !queryWhere.isEmpty()) {
@@ -68,6 +69,7 @@ public class JoinRender extends Renderer {
TableView filterView = new TableView();
Map<String, SqlNode> innerSelect = new HashMap<>();
Set<String> filterDimension = new HashSet<>();
Map<String, String> beforeSources = new HashMap<>();
for (int i = 0; i < dataSources.size(); i++) {
final DataSource dataSource = dataSources.get(i);
@@ -112,18 +114,12 @@ public class JoinRender extends Renderer {
if (left == null) {
leftTable = tableView;
left = SemanticNode.buildAs(tableView.getAlias(), getTable(tableView, scope));
beforeSources.put(dataSource.getName(), leftTable.getAlias());
continue;
}
left = new SqlJoin(
SqlParserPos.ZERO,
left,
SqlLiteral.createBoolean(false, SqlParserPos.ZERO),
SqlLiteral.createSymbol(JoinType.INNER, SqlParserPos.ZERO),
SemanticNode.buildAs(tableView.getAlias(), getTable(tableView, scope)),
SqlLiteral.createSymbol(JoinConditionType.ON, SqlParserPos.ZERO),
getCondition(leftTable, tableView, dataSource, schema, scope));
left = buildJoin(left, leftTable, tableView, beforeSources, dataSource, schema, scope);
leftTable = tableView;
beforeSources.put(dataSource.getName(), tableView.getAlias());
}
for (Map.Entry<String, SqlNode> entry : innerSelect.entrySet()) {
@@ -258,6 +254,76 @@ public class JoinRender extends Renderer {
return SemanticNode.getTable(tableView.getTable());
}
private SqlNode buildJoin(SqlNode left, TableView leftTable, TableView tableView, Map<String, String> before,
DataSource dataSource,
SemanticSchema schema, SqlValidatorScope scope)
throws Exception {
SqlNode condition = getCondition(leftTable, tableView, dataSource, schema, scope);
SqlLiteral sqlLiteral = SemanticNode.getJoinSqlLiteral("");
if (!TimePartType.ZIPPER.equals(leftTable.getDataSource().getTimePartType()) && !TimePartType.ZIPPER.equals(
tableView.getDataSource().getTimePartType())) {
JoinRelation matchJoinRelation = getMatchJoinRelation(before, tableView, schema);
if (!CollectionUtils.isEmpty(matchJoinRelation.getJoinCondition())) {
sqlLiteral = SemanticNode.getJoinSqlLiteral(matchJoinRelation.getJoinType());
condition = getCondition(matchJoinRelation, scope);
}
}
return new SqlJoin(
SqlParserPos.ZERO,
left,
SqlLiteral.createBoolean(false, SqlParserPos.ZERO),
sqlLiteral,
SemanticNode.buildAs(tableView.getAlias(), getTable(tableView, scope)),
SqlLiteral.createSymbol(JoinConditionType.ON, SqlParserPos.ZERO),
condition
);
}
private JoinRelation getMatchJoinRelation(Map<String, String> before, TableView tableView, SemanticSchema schema) {
JoinRelation matchJoinRelation = JoinRelation.builder().build();
if (!CollectionUtils.isEmpty(schema.getJoinRelations())) {
for (JoinRelation joinRelation : schema.getJoinRelations()) {
if (joinRelation.getRight().equalsIgnoreCase(tableView.getDataSource().getName())
&& before.containsKey(joinRelation.getLeft())) {
matchJoinRelation.setJoinCondition(joinRelation.getJoinCondition().stream()
.map(r -> Triple.of(before.get(joinRelation.getLeft()) + "." + r.getLeft(),
r.getMiddle(), tableView.getAlias() + "." + r.getRight())).collect(
Collectors.toList()));
matchJoinRelation.setJoinType(joinRelation.getJoinType());
}
}
}
return matchJoinRelation;
}
private SqlNode getCondition(JoinRelation joinRelation,
SqlValidatorScope scope) throws Exception {
SqlNode condition = null;
for (Triple<String, String, String> con : joinRelation.getJoinCondition()) {
List<SqlNode> ons = new ArrayList<>();
ons.add(SemanticNode.parse(con.getLeft(), scope));
ons.add(SemanticNode.parse(con.getRight(), scope));
if (Objects.isNull(condition)) {
condition = new SqlBasicCall(
SemanticNode.getBinaryOperator(con.getMiddle()),
ons,
SqlParserPos.ZERO, null);
continue;
}
SqlNode addCondition = new SqlBasicCall(
SemanticNode.getBinaryOperator(con.getMiddle()),
ons,
SqlParserPos.ZERO, null);
condition = new SqlBasicCall(
SqlStdOperatorTable.AND,
new ArrayList<>(Arrays.asList(condition, addCondition)),
SqlParserPos.ZERO, null);
}
return condition;
}
private SqlNode getCondition(TableView left, TableView right, DataSource dataSource, SemanticSchema schema,
SqlValidatorScope scope) throws Exception {
if (TimePartType.ZIPPER.equals(left.getDataSource().getTimePartType()) || TimePartType.ZIPPER.equals(
@@ -318,8 +384,7 @@ public class JoinRender extends Renderer {
});
int cnt = dataSources.size();
List<Map.Entry<String, List<Identify>>> dataSourceIdentifyList = dataSourceIdentifies.entrySet().stream()
.collect(
Collectors.toList());
.collect(Collectors.toList());
for (int i = 0; i < cnt; i++) {
for (int j = i + 1; j < cnt; j++) {
Set<String> primaries = IdentifyNode.getIdentifyNames(dataSourceIdentifyList.get(i).getValue(),
@@ -384,6 +449,7 @@ public class JoinRender extends Renderer {
orders.poll();
visited.put(id, false);
}
private void addZipperField(DataSource dataSource, List<String> fields) {
if (TimePartType.ZIPPER.equals(dataSource.getTimePartType())) {
dataSource.getDimensions().stream()

View File

@@ -5,6 +5,7 @@ import com.tencent.supersonic.common.pojo.Aggregator;
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.semantic.api.model.response.DatabaseResp;
import com.tencent.supersonic.semantic.api.query.enums.AggOption;
import com.tencent.supersonic.semantic.api.query.pojo.MetricTable;
@@ -15,20 +16,20 @@ import com.tencent.supersonic.semantic.model.domain.Catalog;
import com.tencent.supersonic.semantic.model.domain.pojo.EngineTypeEnum;
import com.tencent.supersonic.semantic.query.parser.SemanticConverter;
import com.tencent.supersonic.semantic.query.service.SemanticQueryEngine;
import com.tencent.supersonic.common.util.DateModeUtils;
import com.tencent.supersonic.semantic.query.utils.QueryStructUtils;
import com.tencent.supersonic.semantic.query.utils.SqlGenerateUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Component("CalculateAggConverter")
@Slf4j
@@ -66,7 +67,7 @@ public class CalculateAggConverter implements SemanticConverter {
return generateRatioSqlCommand(queryStructCmd, engineTypeEnum, version);
}
ParseSqlReq sqlCommand = new ParseSqlReq();
sqlCommand.setRootPath(catalog.getModelFullPath(queryStructCmd.getModelId()));
sqlCommand.setRootPath(catalog.getModelFullPath(queryStructCmd.getModelIds()));
String metricTableName = "v_metric_tb_tmp";
MetricTable metricTable = new MetricTable();
metricTable.setAlias(metricTableName);
@@ -120,7 +121,7 @@ public class CalculateAggConverter implements SemanticConverter {
@Override
public void converter(Catalog catalog, QueryStructReq queryStructCmd, ParseSqlReq sqlCommend,
MetricReq metricCommand) throws Exception {
DatabaseResp databaseResp = catalog.getDatabaseByModelId(queryStructCmd.getModelId());
DatabaseResp databaseResp = catalog.getDatabaseByModelId(queryStructCmd.getModelIds().get(0));
ParseSqlReq parseSqlReq = generateSqlCommend(queryStructCmd,
EngineTypeEnum.valueOf(databaseResp.getType().toUpperCase()), databaseResp.getVersion());
sqlCommend.setSql(parseSqlReq.getSql());
@@ -150,7 +151,7 @@ public class CalculateAggConverter implements SemanticConverter {
throws Exception {
check(queryStructCmd);
ParseSqlReq sqlCommand = new ParseSqlReq();
sqlCommand.setRootPath(catalog.getModelFullPath(queryStructCmd.getModelId()));
sqlCommand.setRootPath(catalog.getModelFullPath(queryStructCmd.getModelIds()));
String metricTableName = "v_metric_tb_tmp";
MetricTable metricTable = new MetricTable();
metricTable.setAlias(metricTableName);

View File

@@ -26,7 +26,7 @@ public class DefaultDimValueConverter implements SemanticConverter {
@Override
public void converter(Catalog catalog, QueryStructReq queryStructCmd,
ParseSqlReq sqlCommend, MetricReq metricCommand) throws Exception {
List<DimensionResp> dimensionResps = catalog.getDimensions(queryStructCmd.getModelId());
List<DimensionResp> dimensionResps = catalog.getDimensions(queryStructCmd.getModelIds());
//dimension which has default values
dimensionResps = dimensionResps.stream()
.filter(dimensionResp -> !CollectionUtils.isEmpty(dimensionResp.getDefaultValues()))

View File

@@ -33,9 +33,8 @@ public class MetricCheckConverter implements SemanticConverter {
@Override
public void converter(Catalog catalog, QueryStructReq queryStructReq, ParseSqlReq sqlCommend,
MetricReq metricCommand) throws Exception {
Long modelId = queryStructReq.getModelId();
List<MetricResp> metricResps = catalog.getMetrics(modelId);
List<DimensionResp> dimensionResps = catalog.getDimensions(modelId);
List<MetricResp> metricResps = catalog.getMetrics(queryStructReq.getModelIds());
List<DimensionResp> dimensionResps = catalog.getDimensions(queryStructReq.getModelIds());
Map<Long, DimensionResp> dimensionMap = dimensionResps.stream()
.collect(Collectors.toMap(DimensionResp::getId, d -> d));
List<String> metricBizNames = queryStructReq.getMetrics();

View File

@@ -1,135 +0,0 @@
package com.tencent.supersonic.semantic.query.parser.convert;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.tencent.supersonic.common.pojo.Aggregator;
import com.tencent.supersonic.semantic.api.model.pojo.Identify;
import com.tencent.supersonic.semantic.api.model.pojo.Measure;
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.MetricResp;
import com.tencent.supersonic.common.pojo.Filter;
import com.tencent.supersonic.semantic.api.query.request.MetricReq;
import com.tencent.supersonic.semantic.api.query.request.ParseSqlReq;
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
import com.tencent.supersonic.semantic.model.domain.Catalog;
import com.tencent.supersonic.semantic.query.parser.SemanticConverter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@Slf4j
@Component("MultiSourceJoin")
public class MultiSourceJoin implements SemanticConverter {
private final Catalog catalog;
public MultiSourceJoin(Catalog catalog) {
this.catalog = catalog;
}
public void buildJoinPrefix(QueryStructReq queryStructCmd) {
List<String> groups = queryStructCmd.getGroups();
List<Aggregator> aggregators = queryStructCmd.getAggregators();
List<Filter> filters = queryStructCmd.getOriginalFilter();
List<String> fields = Lists.newArrayList();
fields.addAll(groups);
fields.addAll(filters.stream().map(Filter::getBizName).collect(Collectors.toList()));
if (CollectionUtils.isEmpty(groups) || CollectionUtils.isEmpty(aggregators)) {
return;
}
Long modelId = queryStructCmd.getModelId();
List<String> aggs = aggregators.stream().map(Aggregator::getColumn).collect(Collectors.toList());
Map<String, DimensionResp> dimensionMap = catalog.getDimensions(modelId).stream()
.filter(dimensionDesc -> fields.contains(dimensionDesc.getBizName()))
.collect(Collectors.toMap(DimensionResp::getBizName, dimensionDesc -> dimensionDesc));
List<MetricResp> metricDescList = catalog.getMetrics(modelId).stream()
.filter(metricDesc -> aggs.contains(metricDesc.getBizName()))
.collect(Collectors.toList());
Map<Long, DatasourceResp> datasourceMap = catalog.getDatasourceList(modelId)
.stream().collect(Collectors.toMap(DatasourceResp::getId, datasource -> datasource));
//check groups filters and aggs is in same datasource
if (!isInSameDatasource(new ArrayList<>(dimensionMap.values()), metricDescList)) {
List<String> groupsWithPrefix = Lists.newArrayList();
for (String group : groups) {
DimensionResp dimensionDesc = dimensionMap.get(group);
if (dimensionDesc == null) {
groupsWithPrefix.add(group);
continue;
}
String joinKeyName = getJoinKey(datasourceMap, dimensionDesc.getDatasourceId());
if (joinKeyName.equalsIgnoreCase(group)) {
groupsWithPrefix.add(group);
} else {
String groupWithPrefix = String.format("%s__%s", joinKeyName, group);
groupsWithPrefix.add(groupWithPrefix);
}
}
List<Filter> filtersWithPrefix = Lists.newArrayList();
for (Filter filter : filters) {
DimensionResp dimensionDesc = dimensionMap.get(filter.getBizName());
if (dimensionDesc == null) {
filtersWithPrefix.add(filter);
continue;
}
String joinKeyName = getJoinKey(datasourceMap, dimensionDesc.getDatasourceId());
if (joinKeyName.equalsIgnoreCase(filter.getBizName())) {
filtersWithPrefix.add(filter);
} else {
String filterWithPrefix = String.format("%s__%s", joinKeyName, filter.getBizName());
filter.setBizName(filterWithPrefix);
filtersWithPrefix.add(filter);
}
}
queryStructCmd.setGroups(groupsWithPrefix);
queryStructCmd.setDimensionFilters(filtersWithPrefix);
}
}
private String getJoinKey(Map<Long, DatasourceResp> datasourceMap, Long datasourceId) {
DatasourceResp datasourceDesc = datasourceMap.get(datasourceId);
List<Identify> identifies = datasourceDesc.getDatasourceDetail().getIdentifiers();
Optional<Identify> identifyOptional = identifies.stream()
.filter(identify -> identify.getType().equalsIgnoreCase("primary")).findFirst();
if (identifyOptional.isPresent()) {
return identifyOptional.get().getBizName();
}
return "";
}
private boolean isInSameDatasource(List<DimensionResp> dimensionDescs, List<MetricResp> metricDescs) {
Set<Long> datasourceIdSet = Sets.newHashSet();
datasourceIdSet.addAll(dimensionDescs.stream().map(DimensionResp::getDatasourceId).filter(Objects::nonNull)
.collect(Collectors.toSet()));
datasourceIdSet.addAll(
metricDescs.stream().flatMap(metricDesc -> metricDesc.getTypeParams().getMeasures().stream())
.map(Measure::getDatasourceId).filter(Objects::nonNull).collect(Collectors.toList()));
log.info("[multi source join] datasource id:{}", datasourceIdSet);
return datasourceIdSet.size() <= 1;
}
@Override
public boolean accept(QueryStructReq queryStructCmd) {
return true;
}
@Override
public void converter(Catalog catalog, QueryStructReq queryStructCmd, ParseSqlReq sqlCommend,
MetricReq metricCommand) throws Exception {
buildJoinPrefix(queryStructCmd);
}
}

View File

@@ -19,7 +19,6 @@ import org.springframework.util.CollectionUtils;
public class ParserDefaultConverter implements SemanticConverter {
private final CalculateAggConverter calculateCoverterAgg;
private final QueryStructUtils queryStructUtils;
@@ -57,20 +56,21 @@ public class ParserDefaultConverter implements SemanticConverter {
sqlCommend.setVariables(queryStructCmd.getParams().stream()
.collect(Collectors.toMap(Param::getName, Param::getValue, (k1, k2) -> k1)));
sqlCommend.setLimit(queryStructCmd.getLimit());
String rootPath = catalog.getModelFullPath(queryStructCmd.getModelId());
String rootPath = catalog.getModelFullPath(queryStructCmd.getModelIds());
sqlCommend.setRootPath(rootPath);
// todo tmp delete
// support detail query
if (queryStructCmd.getQueryType().isNativeAggQuery() && CollectionUtils.isEmpty(sqlCommend.getMetrics())) {
String internalMetricName = queryStructUtils.generateInternalMetricName(
queryStructCmd.getModelId(), queryStructCmd.getGroups());
sqlCommend.getMetrics().add(internalMetricName);
for (Long modelId : queryStructCmd.getModelIds()) {
String internalMetricName = queryStructUtils.generateInternalMetricName(
modelId, queryStructCmd.getGroups());
sqlCommend.getMetrics().add(internalMetricName);
}
}
return sqlCommend;
}
}

View File

@@ -26,15 +26,6 @@ import com.tencent.supersonic.semantic.model.domain.pojo.EngineTypeEnum;
import com.tencent.supersonic.semantic.query.persistence.pojo.QueryStatement;
import com.tencent.supersonic.semantic.query.service.SemanticQueryEngine;
import com.tencent.supersonic.semantic.query.utils.QueryStructUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
@@ -43,6 +34,15 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Component
@Slf4j
public class QueryReqConverter {
@@ -57,13 +57,13 @@ public class QueryReqConverter {
@Autowired
private Catalog catalog;
public QueryStatement convert(QueryS2SQLReq databaseReq, ModelSchemaResp modelSchemaResp) throws Exception {
public QueryStatement convert(QueryS2SQLReq databaseReq, List<ModelSchemaResp> modelSchemaResps) throws Exception {
if (Objects.isNull(modelSchemaResp)) {
if (CollectionUtils.isEmpty(modelSchemaResps)) {
return new QueryStatement();
}
//1.convert name to bizName
convertNameToBizName(databaseReq, modelSchemaResp);
convertNameToBizName(databaseReq, modelSchemaResps);
//2.functionName corrector
functionNameCorrector(databaseReq);
//3.correct tableName
@@ -75,21 +75,23 @@ public class QueryReqConverter {
}
//4.build MetricTables
List<String> allFields = SqlParserSelectHelper.getAllFields(databaseReq.getSql());
List<String> metrics = getMetrics(modelSchemaResp, allFields);
List<String> metrics = getMetrics(modelSchemaResps, allFields);
QueryStructReq queryStructCmd = new QueryStructReq();
MetricTable metricTable = new MetricTable();
metricTable.setMetrics(metrics);
Set<String> dimensions = getDimensions(modelSchemaResp, allFields);
Set<String> dimensions = getDimensions(modelSchemaResps, allFields);
metricTable.setDimensions(new ArrayList<>(dimensions));
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()))));
metricTable.setMetrics(new ArrayList<>());
for (Long modelId : databaseReq.getModelIds()) {
metricTable.getMetrics().add(queryStructUtils.generateInternalMetricName(modelId,
metricTable.getDimensions()));
}
} else {
queryStructCmd.setAggregators(
metricTable.getMetrics().stream().map(m -> new Aggregator(m, AggOperatorEnum.UNKNOWN)).collect(
@@ -102,9 +104,10 @@ public class QueryReqConverter {
//4.build ParseSqlReq
ParseSqlReq result = new ParseSqlReq();
BeanUtils.copyProperties(databaseReq, result);
result.setRootPath(domainService.getModelFullPathMap().get(databaseReq.getModelId()));
result.setRootPath(catalog.getModelFullPath(databaseReq.getModelIds()));
result.setTables(tables);
DatabaseResp database = catalog.getDatabaseByModelId(databaseReq.getModelId());
DatabaseResp database = catalog.getDatabaseByModelId(databaseReq.getModelIds().get(0));
if (!queryStructUtils.isSupportWith(EngineTypeEnum.valueOf(database.getType().toUpperCase()),
database.getVersion())) {
result.setSupportWith(false);
@@ -112,7 +115,7 @@ public class QueryReqConverter {
}
//5.physicalSql by ParseSqlReq
queryStructCmd.setDateInfo(queryStructUtils.getDateConfBySql(databaseReq.getSql()));
queryStructCmd.setModelId(databaseReq.getModelId());
queryStructCmd.setModelIds(databaseReq.getModelIds().stream().collect(Collectors.toSet()));
queryStructCmd.setQueryType(getQueryType(aggOption));
log.info("QueryReqConverter queryStructCmd[{}]", queryStructCmd);
QueryStatement queryStatement = parserService.physicalSql(queryStructCmd, result);
@@ -132,8 +135,8 @@ public class QueryReqConverter {
return AggOption.DEFAULT;
}
private void convertNameToBizName(QueryS2SQLReq databaseReq, ModelSchemaResp modelSchemaResp) {
Map<String, String> fieldNameToBizNameMap = getFieldNameToBizNameMap(modelSchemaResp);
private void convertNameToBizName(QueryS2SQLReq databaseReq, List<ModelSchemaResp> modelSchemaResps) {
Map<String, String> fieldNameToBizNameMap = getFieldNameToBizNameMap(modelSchemaResps);
String sql = databaseReq.getSql();
log.info("convert name to bizName before:{}", sql);
String replaceFields = SqlParserReplaceHelper.replaceFields(sql, fieldNameToBizNameMap, true);
@@ -141,26 +144,28 @@ public class QueryReqConverter {
databaseReq.setSql(replaceFields);
}
private Set<String> getDimensions(ModelSchemaResp modelSchemaResp, List<String> allFields) {
Map<String, String> dimensionLowerToNameMap = modelSchemaResp.getDimensions().stream()
.collect(Collectors.toMap(entry -> entry.getBizName().toLowerCase(), entry -> entry.getBizName()));
private Set<String> getDimensions(List<ModelSchemaResp> modelSchemaResps, List<String> allFields) {
Map<String, String> dimensionLowerToNameMap = modelSchemaResps.stream().flatMap(modelSchemaResp
-> modelSchemaResp.getDimensions().stream())
.collect(Collectors.toMap(entry -> entry.getBizName().toLowerCase(), SchemaItem::getBizName));
Map<String, String> internalLowerToNameMap = QueryStructUtils.internalCols.stream()
.collect(Collectors.toMap(a -> a.toLowerCase(), a -> a));
.collect(Collectors.toMap(String::toLowerCase, a -> a));
dimensionLowerToNameMap.putAll(internalLowerToNameMap);
return allFields.stream()
.filter(entry -> dimensionLowerToNameMap.containsKey(entry.toLowerCase()))
.map(entry -> dimensionLowerToNameMap.get(entry.toLowerCase())).collect(Collectors.toSet());
}
private List<String> getMetrics(ModelSchemaResp modelSchemaResp, List<String> allFields) {
Map<String, String> metricLowerToNameMap = modelSchemaResp.getMetrics().stream()
.collect(Collectors.toMap(entry -> entry.getBizName().toLowerCase(), entry -> entry.getBizName()));
private List<String> getMetrics(List<ModelSchemaResp> modelSchemaResps, List<String> allFields) {
Map<String, String> metricLowerToNameMap = modelSchemaResps.stream()
.flatMap(modelSchemaResp -> modelSchemaResp.getMetrics().stream())
.collect(Collectors.toMap(entry -> entry.getBizName().toLowerCase(), SchemaItem::getBizName));
return allFields.stream().filter(entry -> metricLowerToNameMap.containsKey(entry.toLowerCase()))
.map(entry -> metricLowerToNameMap.get(entry.toLowerCase())).collect(Collectors.toList());
}
private void functionNameCorrector(QueryS2SQLReq databaseReq) {
DatabaseResp database = catalog.getDatabaseByModelId(databaseReq.getModelId());
DatabaseResp database = catalog.getDatabaseByModelId(databaseReq.getModelIds().get(0));
if (Objects.isNull(database) || Objects.isNull(database.getType())) {
return;
}
@@ -174,16 +179,17 @@ public class QueryReqConverter {
}
}
protected Map<String, String> getFieldNameToBizNameMap(ModelSchemaResp modelSchemaResp) {
protected Map<String, String> getFieldNameToBizNameMap(List<ModelSchemaResp> modelSchemaResps) {
// support fieldName and field alias to bizName
Map<String, String> dimensionResults = modelSchemaResp.getDimensions().stream()
Map<String, String> dimensionResults = modelSchemaResps.stream().flatMap(modelSchemaResp
-> modelSchemaResp.getDimensions().stream())
.flatMap(entry -> getPairStream(entry.getAlias(), entry.getName(), entry.getBizName()))
.collect(Collectors.toMap(a -> a.getLeft(), a -> a.getRight(), (k1, k2) -> k1));
.collect(Collectors.toMap(Pair::getLeft, Pair::getRight, (k1, k2) -> k1));
Map<String, String> metricResults = modelSchemaResp.getMetrics().stream()
Map<String, String> metricResults = modelSchemaResps.stream().flatMap(modelSchemaResp
-> modelSchemaResp.getMetrics().stream())
.flatMap(entry -> getPairStream(entry.getAlias(), entry.getName(), entry.getBizName()))
.collect(Collectors.toMap(a -> a.getLeft(), a -> a.getRight(), (k1, k2) -> k1));
.collect(Collectors.toMap(Pair::getLeft, Pair::getRight, (k1, k2) -> k1));
dimensionResults.putAll(TimeDimensionEnum.getChNameToNameMap());
dimensionResults.putAll(TimeDimensionEnum.getNameToNameMap());
@@ -204,8 +210,10 @@ public class QueryReqConverter {
}
public void correctTableName(QueryS2SQLReq databaseReq) {
String sql = SqlParserReplaceHelper.replaceTable(databaseReq.getSql(),
Constants.TABLE_PREFIX + databaseReq.getModelId());
String sql = databaseReq.getSql();
for (Long modelId : databaseReq.getModelIds()) {
sql = SqlParserReplaceHelper.replaceTable(sql, Constants.TABLE_PREFIX + modelId);
}
databaseReq.setSql(sql);
}

View File

@@ -2,14 +2,15 @@ package com.tencent.supersonic.semantic.query.persistence.pojo;
import com.tencent.supersonic.semantic.api.query.request.MetricReq;
import com.tencent.supersonic.semantic.api.query.request.ParseSqlReq;
import java.util.List;
import lombok.Data;
import org.apache.commons.lang3.tuple.ImmutablePair;
import java.util.List;
@Data
public class QueryStatement {
private Long modelId = 0L;
private List<Long> modelIds;
private String sql = "";
private String sourceId = "";
private String errMsg = "";

View File

@@ -9,23 +9,24 @@ import com.tencent.supersonic.semantic.api.materialization.response.Materializat
import com.tencent.supersonic.semantic.api.model.request.ModelSchemaFilterReq;
import com.tencent.supersonic.semantic.api.model.request.PageDimensionReq;
import com.tencent.supersonic.semantic.api.model.request.PageMetricReq;
import com.tencent.supersonic.semantic.api.model.response.ModelSchemaResp;
import com.tencent.supersonic.semantic.api.model.response.DomainResp;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
import com.tencent.supersonic.semantic.api.model.response.DomainResp;
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.ModelSchemaResp;
import com.tencent.supersonic.semantic.query.service.MaterializationService;
import com.tencent.supersonic.semantic.query.service.SchemaService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@RestController
@RequestMapping("/api/semantic/schema")

View File

@@ -2,7 +2,7 @@ package com.tencent.supersonic.semantic.query.service;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authorization.pojo.AuthRes;
import com.tencent.supersonic.auth.api.authorization.pojo.AuthResGrp;
@@ -16,7 +16,6 @@ import com.tencent.supersonic.common.pojo.QueryColumn;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.common.pojo.enums.SensitiveLevelEnum;
import com.tencent.supersonic.common.pojo.exception.InvalidPermissionException;
import com.tencent.supersonic.semantic.api.model.pojo.SchemaItem;
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.ModelResp;
@@ -26,20 +25,18 @@ import com.tencent.supersonic.semantic.model.domain.MetricService;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import com.tencent.supersonic.semantic.model.domain.pojo.MetaFilter;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Sets;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@Service
@@ -57,64 +54,62 @@ public class AuthCommonService {
@Autowired
private ModelService modelService;
public boolean doModelAdmin(User user, Long modelId) {
public boolean doModelAdmin(User user, List<Long> modelIds) {
List<ModelResp> modelListAdmin = modelService.getModelListWithAuth(user, 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);
Set<Long> modelAdmins = modelListAdmin.stream().map(ModelResp::getId).collect(Collectors.toSet());
return !CollectionUtils.isEmpty(modelAdmins) && modelAdmins.containsAll(modelIds);
}
}
public void doModelVisible(User user, Long modelId) {
public void doModelVisible(User user, List<Long> modelIds) {
Boolean visible = true;
List<ModelResp> modelListVisible = modelService.getModelListWithAuth(user, null, AuthType.VISIBLE);
if (CollectionUtils.isEmpty(modelListVisible)) {
visible = false;
} else {
Map<Long, List<ModelResp>> id2domainDesc = modelListVisible.stream()
.collect(Collectors.groupingBy(SchemaItem::getId));
if (!CollectionUtils.isEmpty(id2domainDesc) && !id2domainDesc.containsKey(modelId)) {
Set<Long> modelVisibles = modelListVisible.stream().map(ModelResp::getId).collect(Collectors.toSet());
if (!CollectionUtils.isEmpty(modelVisibles) && !modelVisibles.containsAll(modelIds)) {
visible = false;
}
}
if (!visible) {
ModelResp modelResp = modelService.getModel(modelId);
ModelResp modelResp = modelService.getModel(modelIds.get(0));
String modelName = modelResp.getName();
List<String> admins = modelService.getModelAdmin(modelResp.getId());
String message = String.format("您没有主题域[%s]权限,请联系管理员%s开通", modelName, admins);
String message = String.format("您没有模型[%s]权限,请联系管理员%s开通", modelName, admins);
throw new InvalidPermissionException(message);
}
}
public Set<String> getHighSensitiveColsByModelId(Long modelId) {
public Set<String> getHighSensitiveColsByModelId(List<Long> modelIds) {
Set<String> highSensitiveCols = new HashSet<>();
MetaFilter metaFilter = new MetaFilter();
metaFilter.setModelIds(Lists.newArrayList(modelId));
metaFilter.setModelIds(modelIds);
metaFilter.setSensitiveLevel(SensitiveLevelEnum.HIGH.getCode());
List<DimensionResp> highSensitiveDimensions = dimensionService.getDimensions(metaFilter);
List<MetricResp> highSensitiveMetrics = metricService.getMetrics(metaFilter);
if (!CollectionUtils.isEmpty(highSensitiveDimensions)) {
highSensitiveDimensions.stream().forEach(dim -> highSensitiveCols.add(dim.getBizName()));
highSensitiveDimensions.forEach(dim -> highSensitiveCols.add(dim.getBizName()));
}
if (!CollectionUtils.isEmpty(highSensitiveMetrics)) {
highSensitiveMetrics.stream().forEach(metric -> highSensitiveCols.add(metric.getBizName()));
highSensitiveMetrics.forEach(metric -> highSensitiveCols.add(metric.getBizName()));
}
return highSensitiveCols;
}
public AuthorizedResourceResp getAuthorizedResource(User user, Long modelId,
public AuthorizedResourceResp getAuthorizedResource(User user, List<Long> modelIds,
Set<String> sensitiveResReq) {
List<AuthRes> resourceReqList = new ArrayList<>();
sensitiveResReq.forEach(res -> resourceReqList.add(new AuthRes(modelId, res)));
sensitiveResReq.forEach(res -> resourceReqList.add(new AuthRes(modelIds.get(0), res)));
QueryAuthResReq queryAuthResReq = new QueryAuthResReq();
queryAuthResReq.setResources(resourceReqList);
queryAuthResReq.setModelId(modelId);
queryAuthResReq.setModelIds(modelIds);
AuthorizedResourceResp authorizedResource = fetchAuthRes(queryAuthResReq, user);
log.info("user:{}, domainId:{}, after queryAuthorizedResources:{}", user.getName(), modelId,
log.info("user:{}, domainId:{}, after queryAuthorizedResources:{}", user.getName(), modelIds,
authorizedResource);
return authorizedResource;
}
@@ -124,13 +119,13 @@ public class AuthCommonService {
return authService.queryAuthorizedResources(queryAuthResReq, user);
}
public Set<String> getAuthResNameSet(AuthorizedResourceResp authorizedResource, Long modelId) {
public Set<String> getAuthResNameSet(AuthorizedResourceResp authorizedResource, List<Long> modelIds) {
Set<String> resAuthName = new HashSet<>();
List<AuthResGrp> authResGrpList = authorizedResource.getResources();
authResGrpList.stream().forEach(authResGrp -> {
List<AuthRes> cols = authResGrp.getGroup();
if (!CollectionUtils.isEmpty(cols)) {
cols.stream().filter(col -> modelId.equals(col.getModelId()))
cols.stream().filter(col -> modelIds.contains(col.getModelId()))
.forEach(col -> resAuthName.add(col.getName()));
}
@@ -148,8 +143,9 @@ public class AuthCommonService {
}
public QueryResultWithSchemaResp getQueryResultWithColumns(QueryResultWithSchemaResp resultWithColumns,
Long domainId, AuthorizedResourceResp authResource) {
addPromptInfoInfo(domainId, resultWithColumns, authResource, Sets.newHashSet());
List<Long> modelIds,
AuthorizedResourceResp authResource) {
addPromptInfoInfo(modelIds, resultWithColumns, authResource, Sets.newHashSet());
return resultWithColumns;
}
@@ -245,20 +241,20 @@ public class AuthCommonService {
return queryResultWithColumns;
}
public void addPromptInfoInfo(Long modelId, QueryResultWithSchemaResp queryResultWithColumns,
public void addPromptInfoInfo(List<Long> modelIds, QueryResultWithSchemaResp queryResultWithColumns,
AuthorizedResourceResp authorizedResource, Set<String> need2Apply) {
List<DimensionFilter> filters = authorizedResource.getFilters();
if (CollectionUtils.isEmpty(need2Apply) && CollectionUtils.isEmpty(filters)) {
return;
}
List<String> admins = modelService.getModelAdmin(modelId);
List<String> admins = modelService.getModelAdmin(modelIds.get(0));
if (!CollectionUtils.isEmpty(need2Apply)) {
String promptInfo = String.format("当前结果已经过脱敏处理, 申请权限请联系管理员%s", admins);
queryResultWithColumns.setQueryAuthorization(new QueryAuthorization(promptInfo));
}
if (!CollectionUtils.isEmpty(filters)) {
log.debug("dimensionFilters:{}", filters);
ModelResp modelResp = modelService.getModel(modelId);
ModelResp modelResp = modelService.getModel(modelIds.get(0));
List<String> exprList = new ArrayList<>();
List<String> descList = new ArrayList<>();
filters.stream().forEach(filter -> {

View File

@@ -12,10 +12,13 @@ import com.tencent.supersonic.semantic.api.model.response.ModelSchemaResp;
import com.tencent.supersonic.semantic.api.query.request.MetricReq;
import com.tencent.supersonic.semantic.materialization.domain.MaterializationConfService;
import com.tencent.supersonic.semantic.model.domain.Catalog;
import com.tencent.supersonic.semantic.model.domain.DatasourceService;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import com.tencent.supersonic.semantic.query.persistence.pojo.QueryStatement;
import com.tencent.supersonic.semantic.query.utils.QueryStructUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -24,9 +27,6 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
@Service("MaterializationService")
@Slf4j
@@ -34,19 +34,17 @@ public class MaterializationServiceImpl implements MaterializationService {
protected final MaterializationConfService materializationConfService;
protected final ModelService modelService;
protected final DatasourceService datasourceService;
protected final Catalog catalog;
protected final QueryStructUtils queryStructUtils;
protected final QueryService queryService;
public MaterializationServiceImpl(
MaterializationConfService materializationConfService,
ModelService modelService, DatasourceService datasourceService,
ModelService modelService,
Catalog catalog, QueryStructUtils queryStructUtils,
QueryService queryService) {
this.materializationConfService = materializationConfService;
this.modelService = modelService;
this.datasourceService = datasourceService;
this.catalog = catalog;
this.queryStructUtils = queryStructUtils;
this.queryService = queryService;
@@ -72,11 +70,12 @@ public class MaterializationServiceImpl implements MaterializationService {
ModelSchemaFilterReq modelFilter = new ModelSchemaFilterReq();
modelFilter.setModelIds(Arrays.asList(materializationSourceResp.getModelId()));
List<ModelSchemaResp> modelSchemaRespList = modelService.fetchModelSchema(modelFilter);
List<MeasureResp> measureRespList = datasourceService.getMeasureListOfModel(
//todo
List<MeasureResp> measureRespList = modelService.getMeasureListOfModel(
Lists.newArrayList(materializationSourceResp.getModelId()));
modelSchemaRespList.stream().forEach(m -> {
m.getDimensions().stream()
.filter(mm -> mm.getDatasourceId().equals(materializationSourceReq.getDataSourceId())
.filter(mm -> mm.getModelId().equals(materializationSourceReq.getDataSourceId())
&& materializationSourceResp.getDimensions().keySet().contains(mm.getId())
).forEach(mm -> {
dimensionFields.add(mm.getBizName());

View File

@@ -4,42 +4,43 @@ import com.google.common.cache.CacheBuilder;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.Aggregator;
import com.tencent.supersonic.common.pojo.DateConf;
import com.tencent.supersonic.common.pojo.Filter;
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
import com.tencent.supersonic.common.pojo.enums.TaskStatusEnum;
import com.tencent.supersonic.common.util.ContextUtils;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.common.util.cache.CacheUtils;
import com.tencent.supersonic.common.util.ContextUtils;
import com.tencent.supersonic.semantic.api.model.enums.QueryTypeEnum;
import com.tencent.supersonic.semantic.api.model.request.ModelSchemaFilterReq;
import com.tencent.supersonic.semantic.api.model.response.ExplainResp;
import com.tencent.supersonic.semantic.api.model.response.ModelSchemaResp;
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
import com.tencent.supersonic.semantic.api.query.pojo.Cache;
import com.tencent.supersonic.common.pojo.Filter;
import com.tencent.supersonic.semantic.api.query.request.ExplainSqlReq;
import com.tencent.supersonic.semantic.api.query.request.ItemUseReq;
import com.tencent.supersonic.semantic.api.query.request.MetricReq;
import com.tencent.supersonic.semantic.api.query.request.QueryDimValueReq;
import com.tencent.supersonic.semantic.api.query.request.QueryS2SQLReq;
import com.tencent.supersonic.semantic.api.query.request.QueryMultiStructReq;
import com.tencent.supersonic.semantic.api.query.request.QueryS2SQLReq;
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
import com.tencent.supersonic.semantic.api.query.response.ItemUseResp;
import com.tencent.supersonic.semantic.query.utils.S2SQLPermissionAnnotation;
import com.tencent.supersonic.semantic.query.executor.QueryExecutor;
import com.tencent.supersonic.semantic.query.parser.convert.QueryReqConverter;
import com.tencent.supersonic.semantic.query.persistence.pojo.QueryStatement;
import com.tencent.supersonic.semantic.query.utils.QueryUtils;
import com.tencent.supersonic.semantic.query.utils.S2SQLPermissionAnnotation;
import com.tencent.supersonic.semantic.query.utils.StatUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Service
@@ -75,11 +76,11 @@ public class QueryServiceImpl implements QueryService {
@Override
@S2SQLPermissionAnnotation
@SneakyThrows
public Object queryBySql(QueryS2SQLReq querySqlCmd, User user) {
statUtils.initStatInfo(querySqlCmd, user);
public Object queryBySql(QueryS2SQLReq queryS2SQLReq, User user) {
statUtils.initStatInfo(queryS2SQLReq, user);
QueryStatement queryStatement = new QueryStatement();
try {
queryStatement = convertToQueryStatement(querySqlCmd, user);
queryStatement = convertToQueryStatement(queryS2SQLReq, user);
} catch (Exception e) {
log.info("convertToQueryStatement has a exception:{}", e.toString());
}
@@ -95,18 +96,11 @@ public class QueryServiceImpl implements QueryService {
private QueryStatement convertToQueryStatement(QueryS2SQLReq querySqlCmd, User user) throws Exception {
ModelSchemaFilterReq filter = new ModelSchemaFilterReq();
List<Long> modelIds = new ArrayList<>();
modelIds.add(querySqlCmd.getModelId());
filter.setModelIds(modelIds);
filter.setModelIds(querySqlCmd.getModelIds());
SchemaService schemaService = ContextUtils.getBean(SchemaService.class);
List<ModelSchemaResp> domainSchemas = schemaService.fetchModelSchema(filter, user);
ModelSchemaResp domainSchema = null;
if (CollectionUtils.isNotEmpty(domainSchemas)) {
domainSchema = domainSchemas.get(0);
}
QueryStatement queryStatement = queryReqConverter.convert(querySqlCmd, domainSchema);
queryStatement.setModelId(querySqlCmd.getModelId());
List<ModelSchemaResp> modelSchemaResps = schemaService.fetchModelSchema(filter, user);
QueryStatement queryStatement = queryReqConverter.convert(querySqlCmd, modelSchemaResps);
queryStatement.setModelIds(querySqlCmd.getModelIds());
return queryStatement;
}
@@ -116,7 +110,7 @@ public class QueryServiceImpl implements QueryService {
log.info("[queryStructCmd:{}]", queryStructCmd);
try {
statUtils.initStatInfo(queryStructCmd, user);
String cacheKey = cacheUtils.generateCacheKey(queryStructCmd.getModelId().toString(),
String cacheKey = cacheUtils.generateCacheKey(getKeyByModelIds(queryStructCmd.getModelIds()),
queryStructCmd.generateCommandMd5());
handleGlobalCacheDisable(queryStructCmd);
boolean isCache = isCache(queryStructCmd);
@@ -160,7 +154,7 @@ public class QueryServiceImpl implements QueryService {
throws Exception {
statUtils.initStatInfo(queryMultiStructReq.getQueryStructReqs().get(0), user);
String cacheKey = cacheUtils.generateCacheKey(
queryMultiStructReq.getQueryStructReqs().get(0).getModelId().toString(),
getKeyByModelIds(queryMultiStructReq.getQueryStructReqs().get(0).getModelIds()),
queryMultiStructReq.generateCommandMd5());
boolean isCache = isCache(queryMultiStructReq);
QueryResultWithSchemaResp queryResultWithColumns;
@@ -323,5 +317,9 @@ public class QueryServiceImpl implements QueryService {
return queryStructReq;
}
private String getKeyByModelIds(List<Long> modelIds) {
return String.join(",", modelIds.stream().map(Object::toString).collect(Collectors.toList()));
}
}

View File

@@ -6,11 +6,11 @@ import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.semantic.api.model.request.ModelSchemaFilterReq;
import com.tencent.supersonic.semantic.api.model.request.PageDimensionReq;
import com.tencent.supersonic.semantic.api.model.request.PageMetricReq;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.api.model.response.ModelSchemaResp;
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.DomainResp;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import java.util.List;

View File

@@ -1,34 +1,35 @@
package com.tencent.supersonic.semantic.query.service;
import static com.tencent.supersonic.common.pojo.Constants.AT_SYMBOL;
import com.github.pagehelper.PageInfo;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.common.pojo.enums.TypeEnums;
import com.tencent.supersonic.semantic.api.model.request.ModelSchemaFilterReq;
import com.tencent.supersonic.semantic.api.model.request.PageDimensionReq;
import com.tencent.supersonic.semantic.api.model.request.PageMetricReq;
import com.tencent.supersonic.semantic.api.model.response.ModelSchemaResp;
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.DimensionResp;
import com.tencent.supersonic.semantic.api.model.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.model.response.MetricSchemaResp;
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
import com.tencent.supersonic.semantic.api.model.response.DomainResp;
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
import com.tencent.supersonic.semantic.api.model.response.MetricSchemaResp;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.api.model.response.ModelSchemaResp;
import com.tencent.supersonic.semantic.api.query.request.ItemUseReq;
import com.tencent.supersonic.semantic.api.query.response.ItemUseResp;
import com.tencent.supersonic.common.pojo.enums.TypeEnums;
import com.tencent.supersonic.semantic.model.domain.DimensionService;
import com.tencent.supersonic.semantic.model.domain.DomainService;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import com.tencent.supersonic.semantic.model.domain.MetricService;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.tencent.supersonic.common.pojo.Constants.AT_SYMBOL;
@Slf4j
@Service
public class SchemaServiceImpl implements SchemaService {

View File

@@ -13,6 +13,7 @@ import com.tencent.supersonic.semantic.query.utils.ComponentFactory;
import com.tencent.supersonic.semantic.query.utils.QueryUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@Slf4j
@Component
@@ -36,8 +37,8 @@ public class SemanticQueryEngineImpl implements SemanticQueryEngine {
if (queryExecutor != null) {
queryResultWithColumns = queryExecutor.execute(catalog, queryStatement);
queryResultWithColumns.setSql(queryStatement.getSql());
if (queryStatement.getModelId() > 0) {
queryUtils.fillItemNameInfo(queryResultWithColumns, queryStatement.getModelId());
if (!CollectionUtils.isEmpty(queryStatement.getModelIds())) {
queryUtils.fillItemNameInfo(queryResultWithColumns, queryStatement.getModelIds());
}
}
return queryResultWithColumns;
@@ -46,7 +47,7 @@ public class SemanticQueryEngineImpl implements SemanticQueryEngine {
public QueryStatement plan(QueryStructReq queryStructCmd) throws Exception {
QueryStatement queryStatement = queryParser.logicSql(queryStructCmd);
queryUtils.checkSqlParse(queryStatement);
queryStatement.setModelId(queryStructCmd.getModelId());
queryStatement.setModelIds(queryStructCmd.getModelIds());
log.info("queryStatement:{}", queryStatement);
return optimize(queryStructCmd, queryStatement);
}

View File

@@ -12,7 +12,6 @@ import com.tencent.supersonic.semantic.query.parser.calcite.CalciteSqlParser;
import com.tencent.supersonic.semantic.query.parser.convert.CalculateAggConverter;
import com.tencent.supersonic.semantic.query.parser.convert.DefaultDimValueConverter;
import com.tencent.supersonic.semantic.query.parser.convert.MetricCheckConverter;
import com.tencent.supersonic.semantic.query.parser.convert.MultiSourceJoin;
import com.tencent.supersonic.semantic.query.parser.convert.ParserDefaultConverter;
import java.util.ArrayList;
import java.util.HashMap;
@@ -83,7 +82,6 @@ public class ComponentFactory {
semanticConverters.add(getBean("DefaultDimValueConverter", DefaultDimValueConverter.class));
semanticConverters.add(getBean("CalculateAggConverter", CalculateAggConverter.class));
semanticConverters.add(getBean("ParserDefaultConverter", ParserDefaultConverter.class));
semanticConverters.add(getBean("MultiSourceJoin", MultiSourceJoin.class));
}
private static void initQueryExecutors() {

View File

@@ -1,35 +1,32 @@
package com.tencent.supersonic.semantic.query.utils;
import static com.tencent.supersonic.common.pojo.Constants.MINUS;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authorization.pojo.AuthRes;
import com.tencent.supersonic.auth.api.authorization.pojo.AuthResGrp;
import com.tencent.supersonic.auth.api.authorization.pojo.DimensionFilter;
import com.tencent.supersonic.auth.api.authorization.request.QueryAuthResReq;
import com.tencent.supersonic.auth.api.authorization.response.AuthorizedResourceResp;
import com.tencent.supersonic.auth.api.authorization.service.AuthService;
import com.tencent.supersonic.common.pojo.QueryAuthorization;
import com.tencent.supersonic.common.pojo.QueryColumn;
import com.tencent.supersonic.common.pojo.enums.AuthType;
import com.tencent.supersonic.common.pojo.enums.SensitiveLevelEnum;
import com.tencent.supersonic.semantic.api.model.pojo.SchemaItem;
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
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.FilterOperatorEnum;
import com.tencent.supersonic.common.pojo.exception.InvalidPermissionException;
import java.text.SimpleDateFormat;
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
import com.tencent.supersonic.semantic.api.model.response.ModelResp;
import com.tencent.supersonic.semantic.api.model.response.QueryResultWithSchemaResp;
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
import com.tencent.supersonic.semantic.model.domain.DimensionService;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import com.tencent.supersonic.semantic.model.domain.pojo.MetaFilter;
import com.tencent.supersonic.semantic.query.service.AuthCommonService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -37,40 +34,21 @@ import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;
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.pojo.MetaFilter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.assertj.core.util.Sets;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import static com.tencent.supersonic.common.pojo.Constants.MINUS;
@Component
@Aspect
@Slf4j
public class DataPermissionAOP {
private static final ObjectMapper MAPPER = new ObjectMapper().setDateFormat(
new SimpleDateFormat(Constants.DAY_FORMAT));
@Autowired
private QueryStructUtils queryStructUtils;
@Autowired
private AuthService authService;
@Autowired
private DimensionService dimensionService;
@Autowired
private MetricService metricService;
@Autowired
private ModelService modelService;
@Autowired
private AuthCommonService authCommonService;
@Value("${permission.data.enable:true}")
private Boolean permissionDataEnable;
@@ -93,27 +71,29 @@ public class DataPermissionAOP {
throw new RuntimeException("lease provide user information");
}
//1. determine whether admin of the model
if (doModelAdmin(user, queryStructReq)) {
if (authCommonService.doModelAdmin(user, queryStructReq.getModelIds())) {
return point.proceed();
}
// 2. determine whether the subject field is visible
doModelVisible(user, queryStructReq);
authCommonService.doModelVisible(user, queryStructReq.getModelIds());
// 3. fetch data permission meta information
Long modelId = queryStructReq.getModelId();
List<Long> modelIds = queryStructReq.getModelIds();
Set<String> res4Privilege = queryStructUtils.getResNameEnExceptInternalCol(queryStructReq);
log.info("modelId:{}, res4Privilege:{}", modelId, res4Privilege);
log.info("modelId:{}, res4Privilege:{}", modelIds, res4Privilege);
Set<String> sensitiveResByModel = getHighSensitiveColsByModelId(modelId);
Set<String> sensitiveResByModel = authCommonService.getHighSensitiveColsByModelId(modelIds);
Set<String> sensitiveResReq = res4Privilege.parallelStream()
.filter(sensitiveResByModel::contains).collect(Collectors.toSet());
log.info("this query domainId:{}, sensitiveResReq:{}", modelId, sensitiveResReq);
log.info("this query domainId:{}, sensitiveResReq:{}", modelIds, sensitiveResReq);
// query user privilege info
AuthorizedResourceResp authorizedResource = getAuthorizedResource(user, modelId, sensitiveResReq);
AuthorizedResourceResp authorizedResource = authCommonService.getAuthorizedResource(user,
modelIds, sensitiveResReq);
// get sensitiveRes that user has privilege
Set<String> resAuthSet = getAuthResNameSet(authorizedResource, queryStructReq.getModelId());
Set<String> resAuthSet = authCommonService.getAuthResNameSet(authorizedResource,
queryStructReq.getModelIds());
// 4.if sensitive fields without permission are involved in filter, thrown an exception
doFilterCheckLogic(queryStructReq, resAuthSet, sensitiveResReq);
@@ -127,115 +107,20 @@ public class DataPermissionAOP {
if (CollectionUtils.isEmpty(sensitiveResReq) || allSensitiveResReqIsOk(sensitiveResReq, resAuthSet)) {
// if sensitiveRes is empty
log.info("sensitiveResReq is empty");
return getQueryResultWithColumns(queryResultWithColumns, modelId, authorizedResource);
return authCommonService.getQueryResultWithColumns(queryResultWithColumns, modelIds, authorizedResource);
}
// 6.if the column has no permission, hit *
Set<String> need2Apply = sensitiveResReq.stream().filter(req -> !resAuthSet.contains(req))
.collect(Collectors.toSet());
QueryResultWithSchemaResp queryResultAfterDesensitization = desensitizationData(queryResultWithColumns,
need2Apply);
addPromptInfoInfo(modelId, queryResultAfterDesensitization, authorizedResource, need2Apply);
QueryResultWithSchemaResp queryResultAfterDesensitization =
authCommonService.desensitizationData(queryResultWithColumns, need2Apply);
authCommonService.addPromptInfoInfo(modelIds, queryResultAfterDesensitization, authorizedResource, need2Apply);
return queryResultAfterDesensitization;
}
private boolean doModelAdmin(User user, QueryStructReq queryStructReq) {
Long modelId = queryStructReq.getModelId();
List<ModelResp> modelListAdmin = modelService.getModelListWithAuth(user, 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 queryStructReq) {
Boolean visible = true;
Long modelId = queryStructReq.getModelId();
List<ModelResp> modelListVisible = modelService.getModelListWithAuth(user, null, AuthType.VISIBLE);
if (CollectionUtils.isEmpty(modelListVisible)) {
visible = false;
} else {
Map<Long, List<ModelResp>> id2domainDesc = modelListVisible.stream()
.collect(Collectors.groupingBy(SchemaItem::getId));
if (!CollectionUtils.isEmpty(id2domainDesc) && !id2domainDesc.containsKey(modelId)) {
visible = false;
}
}
if (!visible) {
ModelResp modelResp = modelService.getModel(modelId);
String modelName = modelResp.getName();
List<String> admins = modelService.getModelAdmin(modelResp.getId());
String message = String.format("您没有主题域[%s]权限,请联系管理员%s开通", modelName, admins);
throw new InvalidPermissionException(message);
}
}
private QueryResultWithSchemaResp getQueryResultWithColumns(QueryResultWithSchemaResp resultWithColumns,
Long domainId, AuthorizedResourceResp authResource) {
addPromptInfoInfo(domainId, resultWithColumns, authResource, Sets.newHashSet());
return resultWithColumns;
}
private void addPromptInfoInfo(Long modelId, QueryResultWithSchemaResp queryResultWithColumns,
AuthorizedResourceResp authorizedResource, Set<String> need2Apply) {
List<DimensionFilter> filters = authorizedResource.getFilters();
if (CollectionUtils.isEmpty(need2Apply) && CollectionUtils.isEmpty(filters)) {
return;
}
List<String> admins = modelService.getModelAdmin(modelId);
if (!CollectionUtils.isEmpty(need2Apply)) {
String promptInfo = String.format("当前结果已经过脱敏处理, 申请权限请联系管理员%s", admins);
queryResultWithColumns.setQueryAuthorization(new QueryAuthorization(promptInfo));
}
if (!CollectionUtils.isEmpty(filters)) {
log.debug("dimensionFilters:{}", filters);
ModelResp modelResp = modelService.getModel(modelId);
List<String> exprList = new ArrayList<>();
List<String> descList = new ArrayList<>();
filters.stream().forEach(filter -> {
descList.add(filter.getDescription());
exprList.add(filter.getExpressions().toString());
});
String promptInfo = "当前结果已经过行权限过滤,详细过滤条件如下:%s, 申请权限请联系管理员%s";
String message = String.format(promptInfo, CollectionUtils.isEmpty(descList) ? exprList : descList, admins);
queryResultWithColumns.setQueryAuthorization(
new QueryAuthorization(modelResp.getName(), exprList, descList, message));
log.info("queryResultWithColumns:{}", queryResultWithColumns);
}
}
private QueryResultWithSchemaResp deepCopyResult(QueryResultWithSchemaResp raw) throws Exception {
QueryResultWithSchemaResp queryResultWithColumns = new QueryResultWithSchemaResp();
BeanUtils.copyProperties(raw, queryResultWithColumns);
List<QueryColumn> columns = new ArrayList<>();
if (!CollectionUtils.isEmpty(raw.getColumns())) {
String columnsStr = MAPPER.writeValueAsString(raw.getColumns());
columns = MAPPER.readValue(columnsStr, new TypeReference<List<QueryColumn>>() {
});
queryResultWithColumns.setColumns(columns);
}
queryResultWithColumns.setColumns(columns);
List<Map<String, Object>> resultData = new ArrayList<>();
if (!CollectionUtils.isEmpty(raw.getResultList())) {
for (Map<String, Object> line : raw.getResultList()) {
Map<String, Object> newLine = new HashMap<>();
newLine.putAll(line);
resultData.add(newLine);
}
}
queryResultWithColumns.setResultList(resultData);
return queryResultWithColumns;
}
private boolean allSensitiveResReqIsOk(Set<String> sensitiveResReq, Set<String> resAuthSet) {
if (resAuthSet.containsAll(sensitiveResReq)) {
return true;
@@ -244,50 +129,6 @@ public class DataPermissionAOP {
return false;
}
private Set<String> getAuthResNameSet(AuthorizedResourceResp authorizedResource, Long modelId) {
Set<String> resAuthName = new HashSet<>();
List<AuthResGrp> authResGrpList = authorizedResource.getResources();
authResGrpList.stream().forEach(authResGrp -> {
List<AuthRes> cols = authResGrp.getGroup();
if (!CollectionUtils.isEmpty(cols)) {
cols.stream().filter(col -> modelId.equals(col.getModelId()))
.forEach(col -> resAuthName.add(col.getName()));
}
});
log.info("resAuthName:{}", resAuthName);
return resAuthName;
}
private AuthorizedResourceResp getAuthorizedResource(User user, Long domainId,
Set<String> sensitiveResReq) {
List<AuthRes> resourceReqList = new ArrayList<>();
sensitiveResReq.forEach(res -> resourceReqList.add(new AuthRes(domainId, res)));
QueryAuthResReq queryAuthResReq = new QueryAuthResReq();
queryAuthResReq.setResources(resourceReqList);
queryAuthResReq.setModelId(domainId);
AuthorizedResourceResp authorizedResource = fetchAuthRes(queryAuthResReq, user);
log.info("user:{}, domainId:{}, after queryAuthorizedResources:{}", user.getName(), domainId,
authorizedResource);
return authorizedResource;
}
private Set<String> getHighSensitiveColsByModelId(Long modelId) {
Set<String> highSensitiveCols = new HashSet<>();
MetaFilter metaFilter = new MetaFilter();
metaFilter.setModelIds(Lists.newArrayList(modelId));
metaFilter.setSensitiveLevel(SensitiveLevelEnum.HIGH.getCode());
List<DimensionResp> highSensitiveDimensions = dimensionService.getDimensions(metaFilter);
List<MetricResp> highSensitiveMetrics = metricService.getMetrics(metaFilter);
if (!CollectionUtils.isEmpty(highSensitiveDimensions)) {
highSensitiveDimensions.stream().forEach(dim -> highSensitiveCols.add(dim.getBizName()));
}
if (!CollectionUtils.isEmpty(highSensitiveMetrics)) {
highSensitiveMetrics.stream().forEach(metric -> highSensitiveCols.add(metric.getBizName()));
}
return highSensitiveCols;
}
private void doRowPermission(QueryStructReq queryStructReq, AuthorizedResourceResp authorizedResource) {
log.debug("start doRowPermission logic");
StringJoiner joiner = new StringJoiner(" OR ");
@@ -320,64 +161,6 @@ public class DataPermissionAOP {
}
private QueryResultWithSchemaResp desensitizationData(QueryResultWithSchemaResp raw, Set<String> need2Apply) {
log.debug("start desensitizationData logic");
if (CollectionUtils.isEmpty(need2Apply)) {
log.info("user has all sensitiveRes");
return raw;
}
List<QueryColumn> columns = raw.getColumns();
boolean doDesensitization = false;
for (QueryColumn queryColumn : columns) {
if (need2Apply.contains(queryColumn.getNameEn())) {
doDesensitization = true;
break;
}
}
if (!doDesensitization) {
return raw;
}
QueryResultWithSchemaResp queryResultWithColumns = raw;
try {
queryResultWithColumns = deepCopyResult(raw);
} catch (Exception e) {
log.warn("deepCopyResult: ", e);
}
addAuthorizedSchemaInfo(queryResultWithColumns.getColumns(), need2Apply);
desensitizationInternal(queryResultWithColumns.getResultList(), need2Apply);
return queryResultWithColumns;
}
private void addAuthorizedSchemaInfo(List<QueryColumn> columns, Set<String> need2Apply) {
if (CollectionUtils.isEmpty(need2Apply)) {
return;
}
columns.stream().forEach(col -> {
if (need2Apply.contains(col.getNameEn())) {
col.setAuthorized(false);
}
});
}
private void desensitizationInternal(List<Map<String, Object>> result, Set<String> need2Apply) {
log.info("start desensitizationInternal logic");
for (int i = 0; i < result.size(); i++) {
Map<String, Object> row = result.get(i);
Map<String, Object> newRow = new HashMap<>();
for (String col : row.keySet()) {
if (need2Apply.contains(col)) {
newRow.put(col, "****");
} else {
newRow.put(col, row.get(col));
}
}
result.set(i, newRow);
}
}
private void doFilterCheckLogic(QueryStructReq queryStructReq, Set<String> resAuthName,
Set<String> sensitiveResReq) {
Set<String> resFilterSet = queryStructUtils.getFilterResNameEnExceptInternalCol(queryStructReq);
@@ -385,32 +168,18 @@ public class DataPermissionAOP {
.filter(res -> !resAuthName.contains(res) && sensitiveResReq.contains(res)).collect(Collectors.toSet());
Set<String> nameCnSet = new HashSet<>();
List<Long> modelIds = new ArrayList<>();
modelIds.add(queryStructReq.getModelId());
List<ModelResp> modelInfos = modelService.getModelList(modelIds);
String modelNameCn = Constants.EMPTY;
if (!CollectionUtils.isEmpty(modelInfos)) {
modelNameCn = modelInfos.get(0).getName();
}
Map<Long, ModelResp> modelRespMap = modelService.getModelMap();
List<Long> modelIds = Lists.newArrayList(queryStructReq.getModelIds());
List<DimensionResp> dimensionDescList = dimensionService.getDimensions(new MetaFilter(modelIds));
String finalDomainNameCn = modelNameCn;
dimensionDescList.stream().filter(dim -> need2Apply.contains(dim.getBizName()))
.forEach(dim -> nameCnSet.add(finalDomainNameCn + MINUS + dim.getName()));
.forEach(dim -> nameCnSet.add(modelRespMap.get(dim.getModelId()).getName() + MINUS + dim.getName()));
if (!CollectionUtils.isEmpty(need2Apply)) {
ModelResp modelResp = modelInfos.get(0);
List<String> admins = modelService.getModelAdmin(modelResp.getId());
List<String> admins = modelService.getModelAdmin(modelIds.get(0));
log.info("in doFilterLogic, need2Apply:{}", need2Apply);
String message = String.format("您没有以下维度%s权限, 请联系管理员%s开通", nameCnSet, admins);
throw new InvalidPermissionException(message);
}
}
private AuthorizedResourceResp fetchAuthRes(QueryAuthResReq queryAuthResReq, User user) {
log.info("queryAuthResReq:{}", queryAuthResReq);
return authService.queryAuthorizedResources(queryAuthResReq, user);
}
}

View File

@@ -1,7 +1,9 @@
package com.tencent.supersonic.semantic.query.utils;
import com.google.common.collect.Lists;
import com.tencent.supersonic.common.pojo.Filter;
import com.tencent.supersonic.common.pojo.QueryColumn;
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum;
import com.tencent.supersonic.common.util.JsonUtil;
import com.tencent.supersonic.common.util.jsqlparser.FieldExpression;
import com.tencent.supersonic.common.util.jsqlparser.SqlParserReplaceHelper;
@@ -9,19 +11,9 @@ import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectHelper;
import com.tencent.supersonic.semantic.api.model.pojo.DimValueMap;
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
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.QueryS2SQLReq;
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
import com.tencent.supersonic.semantic.model.domain.DimensionService;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Objects;
import java.util.stream.Collectors;
import com.tencent.supersonic.semantic.model.domain.pojo.MetaFilter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@@ -34,6 +26,14 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@Aspect
@Component
@Slf4j
@@ -56,7 +56,7 @@ public class DimValueAspect {
}
Object[] args = joinPoint.getArgs();
QueryS2SQLReq queryS2SQLReq = (QueryS2SQLReq) args[0];
MetaFilter metaFilter = new MetaFilter(Lists.newArrayList(queryS2SQLReq.getModelId()));
MetaFilter metaFilter = new MetaFilter(Lists.newArrayList(queryS2SQLReq.getModelIds()));
String sql = queryS2SQLReq.getSql();
log.info("correctorSql before replacing:{}", sql);
// if dimensionvalue is alias,consider the true dimensionvalue.
@@ -147,8 +147,7 @@ public class DimValueAspect {
Object[] args = joinPoint.getArgs();
QueryStructReq queryStructReq = (QueryStructReq) args[0];
Long modelId = queryStructReq.getModelId();
MetaFilter metaFilter = new MetaFilter(Lists.newArrayList(modelId));
MetaFilter metaFilter = new MetaFilter(Lists.newArrayList(queryStructReq.getModelIds()));
List<DimensionResp> dimensions = dimensionService.getDimensions(metaFilter);
Map<String, Map<String, String>> dimAndAliasAndTechNamePair = getAliasAndBizNameToTechName(dimensions);
Map<String, Map<String, String>> dimAndTechNameAndBizNamePair = getTechNameToBizName(dimensions);

View File

@@ -1,15 +1,11 @@
package com.tencent.supersonic.semantic.query.utils;
import static com.tencent.supersonic.common.pojo.Constants.DAY;
import static com.tencent.supersonic.common.pojo.Constants.DAY_FORMAT;
import static com.tencent.supersonic.common.pojo.Constants.MONTH;
import static com.tencent.supersonic.common.pojo.Constants.UNDERLINE;
import static com.tencent.supersonic.common.pojo.Constants.WEEK;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.Aggregator;
import com.tencent.supersonic.common.pojo.DateConf;
import com.tencent.supersonic.common.pojo.DateConf.DateMode;
import com.tencent.supersonic.common.pojo.ItemDateResp;
import com.tencent.supersonic.common.pojo.enums.TypeEnums;
import com.tencent.supersonic.common.util.DateModeUtils;
import com.tencent.supersonic.common.util.SqlFilterUtils;
@@ -23,7 +19,6 @@ import com.tencent.supersonic.semantic.api.model.pojo.SchemaItem;
import com.tencent.supersonic.semantic.api.model.request.ModelSchemaFilterReq;
import com.tencent.supersonic.semantic.api.model.response.DimSchemaResp;
import com.tencent.supersonic.semantic.api.model.response.DimensionResp;
import com.tencent.supersonic.common.pojo.ItemDateResp;
import com.tencent.supersonic.semantic.api.model.response.MetricResp;
import com.tencent.supersonic.semantic.api.model.response.MetricSchemaResp;
import com.tencent.supersonic.semantic.api.model.response.ModelSchemaResp;
@@ -33,6 +28,14 @@ import com.tencent.supersonic.semantic.model.domain.Catalog;
import com.tencent.supersonic.semantic.model.domain.pojo.EngineTypeEnum;
import com.tencent.supersonic.semantic.query.persistence.pojo.QueryStatement;
import com.tencent.supersonic.semantic.query.service.SchemaService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
@@ -46,14 +49,12 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.logging.log4j.util.Strings;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import static com.tencent.supersonic.common.pojo.Constants.DAY;
import static com.tencent.supersonic.common.pojo.Constants.DAY_FORMAT;
import static com.tencent.supersonic.common.pojo.Constants.MONTH;
import static com.tencent.supersonic.common.pojo.Constants.UNDERLINE;
import static com.tencent.supersonic.common.pojo.Constants.WEEK;
@Slf4j
@@ -95,7 +96,7 @@ public class QueryStructUtils {
private List<Long> getDimensionIds(QueryStructReq queryStructCmd) {
List<Long> dimensionIds = new ArrayList<>();
List<DimensionResp> dimensions = catalog.getDimensions(queryStructCmd.getModelId());
List<DimensionResp> dimensions = catalog.getDimensions(queryStructCmd.getModelIds());
Map<String, List<DimensionResp>> pair = dimensions.stream()
.collect(Collectors.groupingBy(DimensionResp::getBizName));
for (String group : queryStructCmd.getGroups()) {
@@ -116,7 +117,7 @@ public class QueryStructUtils {
private List<Long> getMetricIds(QueryStructReq queryStructCmd) {
List<Long> metricIds = new ArrayList<>();
List<MetricResp> metrics = catalog.getMetrics(queryStructCmd.getModelId());
List<MetricResp> metrics = catalog.getMetrics(queryStructCmd.getModelIds());
Map<String, List<MetricResp>> pair = metrics.stream().collect(Collectors.groupingBy(SchemaItem::getBizName));
for (Aggregator agg : queryStructCmd.getAggregators()) {
if (pair.containsKey(agg.getColumn())) {
@@ -214,7 +215,7 @@ public class QueryStructUtils {
Set<String> resNameSet = getResName(queryS2SQLReq);
Set<String> resNameEnSet = new HashSet<>();
ModelSchemaFilterReq filter = new ModelSchemaFilterReq();
List<Long> modelIds = Lists.newArrayList(queryS2SQLReq.getModelId());
List<Long> modelIds = Lists.newArrayList(queryS2SQLReq.getModelIds());
filter.setModelIds(modelIds);
List<ModelSchemaResp> modelSchemaRespList = schemaService.fetchModelSchema(filter, user);
if (!CollectionUtils.isEmpty(modelSchemaRespList)) {
@@ -256,14 +257,16 @@ public class QueryStructUtils {
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;
for (int i = 0; i < groups.size(); i++) {
if (groups.get(i).equalsIgnoreCase("sys_imp_date")) {
continue;
}
DimensionResp dimension = catalog.getDimension(groups.get(i), modelId);
if (Objects.nonNull(dimension) && Strings.isNotEmpty(dimension.getModelBizName())) {
internalMetricNamePrefix = dimension.getModelBizName() + UNDERLINE;
break;
}
}
}
String internalMetricName = internalMetricNamePrefix + internalMetricNameSuffix;
return internalMetricName;

View File

@@ -1,20 +1,24 @@
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.enums.TimeDimensionEnum;
import com.tencent.supersonic.common.util.cache.CacheUtils;
import com.tencent.supersonic.semantic.api.model.enums.SemanticTypeEnum;
import com.tencent.supersonic.common.pojo.enums.TimeDimensionEnum;
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;
import com.tencent.supersonic.semantic.api.query.request.QueryMultiStructReq;
import com.tencent.supersonic.semantic.model.domain.Catalog;
import com.tencent.supersonic.semantic.query.persistence.pojo.QueryStatement;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
@@ -26,12 +30,9 @@ import java.util.concurrent.CompletableFuture;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import static com.tencent.supersonic.common.pojo.Constants.JOIN_UNDERLINE;
import static com.tencent.supersonic.common.pojo.Constants.UNIONALL;
@Slf4j
@@ -67,9 +68,9 @@ public class QueryUtils {
}
}
public void fillItemNameInfo(QueryResultWithSchemaResp queryResultWithColumns, Long modelId) {
List<MetricResp> metricDescList = catalog.getMetrics(modelId);
List<DimensionResp> dimensionDescList = catalog.getDimensions(modelId);
public void fillItemNameInfo(QueryResultWithSchemaResp queryResultWithColumns, List<Long> modelIds) {
List<MetricResp> metricDescList = catalog.getMetrics(modelIds);
List<DimensionResp> dimensionDescList = catalog.getDimensions(modelIds);
Map<String, MetricResp> metricRespMap =
metricDescList.stream().collect(Collectors.toMap(MetricResp::getBizName, a -> a, (k1, k2) -> k1));
Map<String, String> namePair = new HashMap<>();

View File

@@ -1,8 +1,7 @@
package com.tencent.supersonic.semantic.query.utils;
import static com.tencent.supersonic.common.pojo.Constants.MINUS;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.auth.api.authorization.response.AuthorizedResourceResp;
import com.tencent.supersonic.common.pojo.Constants;
@@ -15,14 +14,8 @@ import com.tencent.supersonic.semantic.api.query.request.QueryS2SQLReq;
import com.tencent.supersonic.semantic.model.domain.DimensionService;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import com.tencent.supersonic.semantic.model.domain.pojo.MetaFilter;
import com.tencent.supersonic.semantic.model.domain.pojo.ModelFilter;
import com.tencent.supersonic.semantic.query.service.AuthCommonService;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
@@ -38,6 +31,16 @@ import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import static com.tencent.supersonic.common.pojo.Constants.MINUS;
@Component
@Aspect
@Order(1)
@@ -72,29 +75,29 @@ public class S2SQLDataAspect {
if (Objects.isNull(user) || Strings.isNullOrEmpty(user.getName())) {
throw new RuntimeException("please provide user information");
}
Long modelId = queryS2SQLReq.getModelId();
List<Long> modelIds = queryS2SQLReq.getModelIds();
//1. determine whether admin of the model
if (authCommonService.doModelAdmin(user, modelId)) {
if (authCommonService.doModelAdmin(user, modelIds)) {
log.info("determine whether admin of the model!");
return joinPoint.proceed();
}
// 2. determine whether the subject field is visible
authCommonService.doModelVisible(user, modelId);
authCommonService.doModelVisible(user, modelIds);
// 3. fetch data permission meta information
Set<String> res4Privilege = queryStructUtils.getResNameEnExceptInternalCol(queryS2SQLReq, user);
log.info("modelId:{}, res4Privilege:{}", modelId, res4Privilege);
log.info("modelId:{}, res4Privilege:{}", modelIds, res4Privilege);
Set<String> sensitiveResByModel = authCommonService.getHighSensitiveColsByModelId(modelId);
Set<String> sensitiveResByModel = authCommonService.getHighSensitiveColsByModelId(modelIds);
Set<String> sensitiveResReq = res4Privilege.parallelStream()
.filter(sensitiveResByModel::contains).collect(Collectors.toSet());
log.info("this query domainId:{}, sensitiveResReq:{}", modelId, sensitiveResReq);
log.info("this query domainId:{}, sensitiveResReq:{}", modelIds, sensitiveResReq);
// query user privilege info
AuthorizedResourceResp authorizedResource = authCommonService
.getAuthorizedResource(user, modelId, sensitiveResReq);
.getAuthorizedResource(user, modelIds, sensitiveResReq);
// get sensitiveRes that user has privilege
Set<String> resAuthSet = authCommonService.getAuthResNameSet(authorizedResource, modelId);
Set<String> resAuthSet = authCommonService.getAuthResNameSet(authorizedResource, modelIds);
// 4.if sensitive fields without permission are involved in filter, thrown an exception
doFilterCheckLogic(queryS2SQLReq, resAuthSet, sensitiveResReq);
@@ -109,7 +112,7 @@ public class S2SQLDataAspect {
.allSensitiveResReqIsOk(sensitiveResReq, resAuthSet)) {
// if sensitiveRes is empty
log.info("sensitiveResReq is empty");
return authCommonService.getQueryResultWithColumns(queryResultWithColumns, modelId, authorizedResource);
return authCommonService.getQueryResultWithColumns(queryResultWithColumns, modelIds, authorizedResource);
}
// 6.if the column has no permission, hit *
@@ -118,7 +121,7 @@ public class S2SQLDataAspect {
log.info("need2Apply:{},sensitiveResReq:{},resAuthSet:{}", need2Apply, sensitiveResReq, resAuthSet);
QueryResultWithSchemaResp queryResultAfterDesensitization = authCommonService
.desensitizationData(queryResultWithColumns, need2Apply);
authCommonService.addPromptInfoInfo(modelId, queryResultAfterDesensitization, authorizedResource, need2Apply);
authCommonService.addPromptInfoInfo(modelIds, queryResultAfterDesensitization, authorizedResource, need2Apply);
return queryResultAfterDesensitization;
}
@@ -163,9 +166,10 @@ public class S2SQLDataAspect {
.filter(res -> !resAuthName.contains(res) && sensitiveResReq.contains(res)).collect(Collectors.toSet());
Set<String> nameCnSet = new HashSet<>();
List<Long> modelIds = new ArrayList<>();
modelIds.add(queryS2SQLReq.getModelId());
List<ModelResp> modelInfos = modelService.getModelList(modelIds);
List<Long> modelIds = Lists.newArrayList(queryS2SQLReq.getModelIds());
ModelFilter modelFilter = new ModelFilter();
modelFilter.setModelIds(modelIds);
List<ModelResp> modelInfos = modelService.getModelList(modelFilter);
String modelNameCn = Constants.EMPTY;
if (!CollectionUtils.isEmpty(modelInfos)) {
modelNameCn = modelInfos.get(0).getName();

View File

@@ -7,6 +7,7 @@ import com.tencent.supersonic.auth.api.authentication.pojo.User;
import com.tencent.supersonic.common.pojo.enums.TaskStatusEnum;
import com.tencent.supersonic.common.util.SqlFilterUtils;
import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectHelper;
import com.tencent.supersonic.semantic.api.model.enums.QueryOptMode;
import com.tencent.supersonic.semantic.api.model.enums.QueryTypeBackEnum;
import com.tencent.supersonic.semantic.api.model.enums.QueryTypeEnum;
import com.tencent.supersonic.semantic.api.model.pojo.QueryStat;
@@ -17,23 +18,20 @@ import com.tencent.supersonic.semantic.api.query.request.QueryS2SQLReq;
import com.tencent.supersonic.semantic.api.query.request.QueryStructReq;
import com.tencent.supersonic.semantic.api.query.response.ItemUseResp;
import com.tencent.supersonic.semantic.model.domain.ModelService;
import com.tencent.supersonic.semantic.api.model.enums.QueryOptMode;
import com.tencent.supersonic.semantic.query.persistence.repository.StatRepository;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@Component
@Slf4j
@@ -91,23 +89,20 @@ public class StatUtils {
public void initStatInfo(QueryS2SQLReq queryS2SQLReq, User facadeUser) {
QueryStat queryStatInfo = new QueryStat();
List<String> allFields = SqlParserSelectHelper.getAllFields(queryS2SQLReq.getSql());
queryStatInfo.setModelId(queryS2SQLReq.getModelId());
ModelSchemaResp modelSchemaResp = modelService.fetchSingleModelSchema(queryS2SQLReq.getModelId());
queryStatInfo.setModelId(queryS2SQLReq.getModelIds().get(0));
ModelSchemaResp modelSchemaResp = modelService.fetchSingleModelSchema(queryS2SQLReq.getModelIds().get(0));
List<String> dimensions = new ArrayList<>();
if (Objects.nonNull(modelSchemaResp)) {
dimensions = getFieldNames(allFields, modelSchemaResp.getDimensions());
}
List<String> metrics = new ArrayList<>();
if (Objects.nonNull(modelSchemaResp)) {
dimensions = getFieldNames(allFields, modelSchemaResp.getDimensions());
metrics = getFieldNames(allFields, modelSchemaResp.getMetrics());
}
String userName = getUserName(facadeUser);
try {
queryStatInfo.setTraceId("")
.setModelId(queryS2SQLReq.getModelId())
.setModelId(queryS2SQLReq.getModelIds().get(0))
.setUser(userName)
.setQueryType(QueryTypeEnum.SQL.getValue())
.setQueryTypeBack(QueryTypeBackEnum.NORMAL.getState())
@@ -137,7 +132,7 @@ public class StatUtils {
try {
queryStatInfo.setTraceId(traceId)
.setModelId(queryStructCmd.getModelId())
.setModelId(1L)
.setUser(user)
.setQueryType(QueryTypeEnum.STRUCT.getValue())
.setQueryTypeBack(QueryTypeBackEnum.NORMAL.getState())

View File

@@ -10,9 +10,10 @@ import com.tencent.supersonic.semantic.query.parser.QueryParser;
import com.tencent.supersonic.semantic.query.persistence.pojo.QueryStatement;
import com.tencent.supersonic.semantic.query.utils.ComponentFactory;
import com.tencent.supersonic.semantic.query.utils.QueryUtils;
import java.util.Arrays;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
@Slf4j
public class MaterializationQueryTest {
@@ -43,7 +44,7 @@ public class MaterializationQueryTest {
try {
QueryStatement queryStatement = queryParser.logicSql(queryStructReq);
queryUtils.checkSqlParse(queryStatement);
queryStatement.setModelId(queryStructReq.getModelId());
queryStatement.setModelIds(queryStructReq.getModelIds());
log.info("queryStatement:{}", queryStatement);
for (QueryOptimizer queryOptimizer : ComponentFactory.getQueryOptimizers()) {
queryOptimizer.rewrite(queryStructReq, queryStatement);

Some files were not shown because too many files have changed in this diff Show More