diff --git a/common/src/main/java/com/tencent/supersonic/common/pojo/enums/StatusEnum.java b/common/src/main/java/com/tencent/supersonic/common/pojo/enums/StatusEnum.java index 478001c84..b7175cd0f 100644 --- a/common/src/main/java/com/tencent/supersonic/common/pojo/enums/StatusEnum.java +++ b/common/src/main/java/com/tencent/supersonic/common/pojo/enums/StatusEnum.java @@ -6,6 +6,7 @@ public enum StatusEnum { ONLINE("ONLINE", 1), OFFLINE("OFFLINE", 2), DELETED("DELETED", 3), + UNAVAILABLE("UNAVAILABLE", 4), UNKNOWN("UNKNOWN", -1); diff --git a/common/src/main/java/com/tencent/supersonic/common/util/jsqlparser/SqlParserSelectFunctionHelper.java b/common/src/main/java/com/tencent/supersonic/common/util/jsqlparser/SqlParserSelectFunctionHelper.java index a5db686bf..14504259f 100644 --- a/common/src/main/java/com/tencent/supersonic/common/util/jsqlparser/SqlParserSelectFunctionHelper.java +++ b/common/src/main/java/com/tencent/supersonic/common/util/jsqlparser/SqlParserSelectFunctionHelper.java @@ -1,11 +1,5 @@ package com.tencent.supersonic.common.util.jsqlparser; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum; import lombok.extern.slf4j.Slf4j; import net.sf.jsqlparser.expression.Expression; @@ -19,6 +13,12 @@ import net.sf.jsqlparser.statement.select.SelectItem; import org.apache.commons.lang3.StringUtils; import org.springframework.util.CollectionUtils; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + /** * Sql Parser Select function Helper */ @@ -32,6 +32,11 @@ public class SqlParserSelectFunctionHelper { return SqlParserSelectHelper.hasGroupBy(sql); } + public static void main(String[] args) { + String sql = "select a from table"; + System.out.println(hasAggregateFunction(sql)); + } + public static boolean hasFunction(String sql, String functionName) { Set functions = getFunctions(sql); if (!CollectionUtils.isEmpty(functions)) { diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/enums/MetricDefineType.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/enums/MetricDefineType.java new file mode 100644 index 000000000..948dec3a5 --- /dev/null +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/enums/MetricDefineType.java @@ -0,0 +1,9 @@ +package com.tencent.supersonic.headless.api.enums; + +public enum MetricDefineType { + + FIELD, + MEASURE, + METRIC + +} diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/Field.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/Field.java new file mode 100644 index 000000000..6e289f4e8 --- /dev/null +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/Field.java @@ -0,0 +1,10 @@ +package com.tencent.supersonic.headless.api.pojo; + +import lombok.Data; + +@Data +public class Field { + + private String fieldName; + +} diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/FieldParam.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/FieldParam.java new file mode 100644 index 000000000..4e3b6bf0e --- /dev/null +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/FieldParam.java @@ -0,0 +1,10 @@ +package com.tencent.supersonic.headless.api.pojo; + +import lombok.Data; + +@Data +public class FieldParam { + + private String fieldName; + +} diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/Measure.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/Measure.java index 96503109f..d61299c2b 100644 --- a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/Measure.java +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/Measure.java @@ -32,6 +32,11 @@ public class Measure { this.bizName = bizName; } + public Measure(String bizName, String constraint) { + this.bizName = bizName; + this.constraint = constraint; + } + public String getFieldName() { return expr; } diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MeasureParam.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MeasureParam.java new file mode 100644 index 000000000..aaa0e276d --- /dev/null +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MeasureParam.java @@ -0,0 +1,23 @@ +package com.tencent.supersonic.headless.api.pojo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class MeasureParam { + + private String bizName; + + private String constraint; + + private String agg; + + public MeasureParam(String bizName, String constraint) { + this.bizName = bizName; + this.constraint = constraint; + } + +} diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricTypeParams.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricDefineByFieldParams.java similarity index 53% rename from headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricTypeParams.java rename to headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricDefineByFieldParams.java index 8bebe8cbb..002c4fc10 100644 --- a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricTypeParams.java +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricDefineByFieldParams.java @@ -1,14 +1,13 @@ package com.tencent.supersonic.headless.api.pojo; -import java.util.List; import com.google.common.collect.Lists; import lombok.Data; +import java.util.List; + @Data -public class MetricTypeParams { +public class MetricDefineByFieldParams extends MetricDefineParams { - private List measures = Lists.newArrayList(); - - private String expr; + private List fields = Lists.newArrayList(); } diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricDefineByMeasureParams.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricDefineByMeasureParams.java new file mode 100644 index 000000000..a2df4d756 --- /dev/null +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricDefineByMeasureParams.java @@ -0,0 +1,12 @@ +package com.tencent.supersonic.headless.api.pojo; + +import com.google.common.collect.Lists; +import lombok.Data; +import java.util.List; + +@Data +public class MetricDefineByMeasureParams extends MetricDefineParams { + + private List measures = Lists.newArrayList(); + +} diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricDefineByMetricParams.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricDefineByMetricParams.java new file mode 100644 index 000000000..d0058033b --- /dev/null +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricDefineByMetricParams.java @@ -0,0 +1,13 @@ +package com.tencent.supersonic.headless.api.pojo; + +import com.google.common.collect.Lists; +import lombok.Data; + +import java.util.List; + +@Data +public class MetricDefineByMetricParams extends MetricDefineParams { + + private List metrics = Lists.newArrayList(); + +} diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricDefineParams.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricDefineParams.java new file mode 100644 index 000000000..257f73d0e --- /dev/null +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricDefineParams.java @@ -0,0 +1,10 @@ +package com.tencent.supersonic.headless.api.pojo; + +import lombok.Data; + +@Data +public abstract class MetricDefineParams { + + private String expr; + +} diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricParam.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricParam.java new file mode 100644 index 000000000..2e2b696bb --- /dev/null +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/MetricParam.java @@ -0,0 +1,12 @@ +package com.tencent.supersonic.headless.api.pojo; + +import lombok.Data; + +@Data +public class MetricParam { + + private Long id; + + private String bizName; + +} diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/ModelDetail.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/ModelDetail.java index b35c403f6..3d1bc5094 100644 --- a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/ModelDetail.java +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/ModelDetail.java @@ -25,6 +25,8 @@ public class ModelDetail { private List measures; + private List fields; + public String getSqlQuery() { if (StringUtils.isNotBlank(sqlQuery) && sqlQuery.endsWith(";")) { sqlQuery = sqlQuery.substring(0, sqlQuery.length() - 1); @@ -32,7 +34,7 @@ public class ModelDetail { return sqlQuery; } - public List getTimeDims() { + public List filterTimeDims() { if (CollectionUtils.isEmpty(dimensions)) { return Lists.newArrayList(); } diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/SchemaItem.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/SchemaItem.java index cb14afc74..532a17be6 100644 --- a/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/SchemaItem.java +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/pojo/SchemaItem.java @@ -4,13 +4,14 @@ import com.google.common.base.Objects; import com.tencent.supersonic.common.pojo.RecordInfo; import com.tencent.supersonic.common.pojo.enums.SensitiveLevelEnum; import com.tencent.supersonic.common.pojo.enums.TypeEnums; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import lombok.Data; import lombok.ToString; import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + @Data @ToString(callSuper = true) public class SchemaItem extends RecordInfo { @@ -38,9 +39,6 @@ public class SchemaItem extends RecordInfo { if (o == null || getClass() != o.getClass()) { return false; } - if (!super.equals(o)) { - return false; - } SchemaItem that = (SchemaItem) o; return Objects.equal(id, that.id) && Objects.equal(name, that.name) && Objects.equal(bizName, that.bizName) && Objects.equal( @@ -50,7 +48,7 @@ public class SchemaItem extends RecordInfo { @Override public int hashCode() { - return Objects.hashCode(super.hashCode(), id, name, bizName, description, status, typeEnum, sensitiveLevel); + return Objects.hashCode(id, name, bizName, description, status, typeEnum, sensitiveLevel); } public static List getAliasList(String alias) { diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/request/MetricBaseReq.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/request/MetricBaseReq.java index 50f314904..22b33412b 100644 --- a/headless/api/src/main/java/com/tencent/supersonic/headless/api/request/MetricBaseReq.java +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/request/MetricBaseReq.java @@ -30,6 +30,9 @@ public class MetricBaseReq extends SchemaItem { private Map ext = new HashMap<>(); public String getTag() { + if (tags == null) { + return null; + } if (CollectionUtils.isEmpty(tags)) { return ""; } diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/request/MetricReq.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/request/MetricReq.java index cf2355c17..50cd6f8b9 100644 --- a/headless/api/src/main/java/com/tencent/supersonic/headless/api/request/MetricReq.java +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/request/MetricReq.java @@ -1,30 +1,49 @@ package com.tencent.supersonic.headless.api.request; - +import com.alibaba.fastjson.JSONObject; +import com.tencent.supersonic.headless.api.enums.MetricDefineType; import com.tencent.supersonic.headless.api.enums.MetricType; -import com.tencent.supersonic.headless.api.pojo.Measure; -import com.tencent.supersonic.headless.api.pojo.MetricTypeParams; +import com.tencent.supersonic.headless.api.pojo.MeasureParam; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByFieldParams; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByMeasureParams; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByMetricParams; import lombok.Data; import java.util.List; @Data public class MetricReq extends MetricBaseReq { - private MetricType metricType; + private MetricDefineType metricDefineType = MetricDefineType.MEASURE; + private MetricDefineByMeasureParams typeParams; + private MetricDefineByFieldParams metricDefineByFieldParams; + private MetricDefineByMetricParams metricDefineByMetricParams; - private MetricTypeParams typeParams; + public String getTypeParamsJson() { + if (metricDefineByFieldParams != null) { + return JSONObject.toJSONString(metricDefineByFieldParams); + } else if (typeParams != null) { + return JSONObject.toJSONString(typeParams); + } else if (metricDefineByMetricParams != null) { + return JSONObject.toJSONString(metricDefineByMetricParams); + } + return null; + } public MetricType getMetricType() { - if (metricType != null) { - return metricType; - } - List measureList = typeParams.getMeasures(); - if (measureList.size() == 1 && typeParams.getExpr().trim().equalsIgnoreCase(measureList.get(0).getBizName())) { - return MetricType.ATOMIC; - } else if (measureList.size() >= 1) { + if (MetricDefineType.METRIC.equals(metricDefineType)) { return MetricType.DERIVED; } - throw new RuntimeException("measure can not be none"); + if (MetricDefineType.MEASURE.equals(metricDefineType)) { + List measures = typeParams.getMeasures(); + if (measures.size() > 1) { + return MetricType.DERIVED; + } + if (measures.size() == 1 && measures.get(0).getBizName() + .equalsIgnoreCase(typeParams.getExpr())) { + return MetricType.ATOMIC; + } + } + return MetricType.ATOMIC; } } diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/request/ModelReq.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/request/ModelReq.java index 691f72a3a..f6be9aa92 100644 --- a/headless/api/src/main/java/com/tencent/supersonic/headless/api/request/ModelReq.java +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/request/ModelReq.java @@ -42,7 +42,7 @@ public class ModelReq extends SchemaItem { if (modelDetail == null) { return Lists.newArrayList(); } - return modelDetail.getTimeDims(); + return modelDetail.filterTimeDims(); } public String getViewer() { diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/response/DomainResp.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/response/DomainResp.java index 5a1573736..01e5a6353 100644 --- a/headless/api/src/main/java/com/tencent/supersonic/headless/api/response/DomainResp.java +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/response/DomainResp.java @@ -1,6 +1,5 @@ package com.tencent.supersonic.headless.api.response; -import com.tencent.supersonic.headless.api.pojo.Entity; import com.tencent.supersonic.headless.api.pojo.SchemaItem; import lombok.Data; import lombok.ToString; @@ -26,12 +25,6 @@ public class DomainResp extends SchemaItem { private Integer isOpen = 0; - private Integer dimensionCnt; - - private Integer metricCnt; - - private Entity entity; - private boolean hasEditPermission = false; @Override diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/response/MetricResp.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/response/MetricResp.java index 23fdec369..145a93a81 100644 --- a/headless/api/src/main/java/com/tencent/supersonic/headless/api/response/MetricResp.java +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/response/MetricResp.java @@ -2,21 +2,23 @@ package com.tencent.supersonic.headless.api.response; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import com.tencent.supersonic.common.pojo.DataFormat; +import com.tencent.supersonic.headless.api.enums.MetricDefineType; import com.tencent.supersonic.headless.api.pojo.DrillDownDimension; -import com.tencent.supersonic.headless.api.pojo.MetricTypeParams; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByFieldParams; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByMeasureParams; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByMetricParams; import com.tencent.supersonic.headless.api.pojo.RelateDimension; import com.tencent.supersonic.headless.api.pojo.SchemaItem; import lombok.Data; import lombok.ToString; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; + import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; @@ -33,8 +35,6 @@ public class MetricResp extends SchemaItem { //ATOMIC DERIVED private String type; - private MetricTypeParams typeParams; - private String dataFormatType; private DataFormat dataFormat; @@ -51,6 +51,14 @@ public class MetricResp extends SchemaItem { private Map ext = new HashMap<>(); + private MetricDefineType metricDefineType = MetricDefineType.MEASURE; + + private MetricDefineByMeasureParams typeParams; + + private MetricDefineByFieldParams metricDefineByFieldParams; + + private MetricDefineByMetricParams metricDefineByMetricParams; + public void setTag(String tag) { if (StringUtils.isBlank(tag)) { tags = Lists.newArrayList(); @@ -59,14 +67,6 @@ public class MetricResp extends SchemaItem { } } - public Set getNecessaryDimensionIds() { - if (relateDimension == null || CollectionUtils.isEmpty(relateDimension.getDrillDownDimensions())) { - return Sets.newHashSet(); - } - return relateDimension.getDrillDownDimensions().stream().filter(DrillDownDimension::isNecessary) - .map(DrillDownDimension::getDimensionId).collect(Collectors.toSet()); - } - public String getRelaDimensionIdKey() { if (relateDimension == null || CollectionUtils.isEmpty(relateDimension.getDrillDownDimensions())) { return ""; @@ -78,6 +78,11 @@ public class MetricResp extends SchemaItem { } public String getDefaultAgg() { - return typeParams.getMeasures().get(0).getAgg(); + if (typeParams != null + && CollectionUtils.isNotEmpty(typeParams.getMeasures())) { + return typeParams.getMeasures().get(0).getAgg(); + } + return ""; } + } diff --git a/headless/api/src/main/java/com/tencent/supersonic/headless/api/response/ModelResp.java b/headless/api/src/main/java/com/tencent/supersonic/headless/api/response/ModelResp.java index 18d4c6e62..42df76cd1 100644 --- a/headless/api/src/main/java/com/tencent/supersonic/headless/api/response/ModelResp.java +++ b/headless/api/src/main/java/com/tencent/supersonic/headless/api/response/ModelResp.java @@ -3,16 +3,22 @@ package com.tencent.supersonic.headless.api.response; import com.google.common.collect.Lists; import com.tencent.supersonic.headless.api.pojo.Dim; import com.tencent.supersonic.headless.api.pojo.DrillDownDimension; +import com.tencent.supersonic.headless.api.pojo.Identify; +import com.tencent.supersonic.headless.api.pojo.Measure; import com.tencent.supersonic.headless.api.pojo.ModelDetail; import com.tencent.supersonic.headless.api.pojo.SchemaItem; -import com.tencent.supersonic.headless.api.pojo.Identify; import lombok.Data; +import lombok.ToString; import org.springframework.util.CollectionUtils; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; @Data +@ToString(callSuper = true) public class ModelResp extends SchemaItem { private Long domainId; @@ -66,7 +72,27 @@ public class ModelResp extends SchemaItem { if (modelDetail == null) { return Lists.newArrayList(); } - return modelDetail.getTimeDims(); + return modelDetail.filterTimeDims(); + } + + public Set getFieldList() { + Set fieldSet = new HashSet<>(); + if (modelDetail == null) { + return fieldSet; + } + if (!CollectionUtils.isEmpty(modelDetail.getIdentifiers())) { + fieldSet.addAll(modelDetail.getIdentifiers().stream() + .map(Identify::getFieldName).collect(Collectors.toSet())); + } + if (!CollectionUtils.isEmpty(modelDetail.getDimensions())) { + fieldSet.addAll(modelDetail.getDimensions().stream() + .map(Dim::getFieldName).collect(Collectors.toSet())); + } + if (!CollectionUtils.isEmpty(modelDetail.getMeasures())) { + fieldSet.addAll(modelDetail.getMeasures().stream() + .map(Measure::getFieldName).collect(Collectors.toSet())); + } + return fieldSet; } } diff --git a/headless/core/src/main/java/com/tencent/supersonic/headless/core/manager/MetricYamlManager.java b/headless/core/src/main/java/com/tencent/supersonic/headless/core/manager/MetricYamlManager.java index 1b0a71080..4a753be7a 100644 --- a/headless/core/src/main/java/com/tencent/supersonic/headless/core/manager/MetricYamlManager.java +++ b/headless/core/src/main/java/com/tencent/supersonic/headless/core/manager/MetricYamlManager.java @@ -1,8 +1,8 @@ package com.tencent.supersonic.headless.core.manager; import com.google.common.collect.Lists; -import com.tencent.supersonic.headless.api.pojo.Measure; -import com.tencent.supersonic.headless.api.pojo.MetricTypeParams; +import com.tencent.supersonic.headless.api.pojo.MeasureParam; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByMeasureParams; import com.tencent.supersonic.headless.api.response.MetricResp; import com.tencent.supersonic.headless.core.pojo.yaml.MeasureYamlTpl; import com.tencent.supersonic.headless.core.pojo.yaml.MetricTypeParamsYamlTpl; @@ -37,21 +37,21 @@ public class MetricYamlManager { BeanUtils.copyProperties(metric, metricYamlTpl); metricYamlTpl.setName(metric.getBizName()); metricYamlTpl.setOwners(Lists.newArrayList(metric.getCreatedBy())); - MetricTypeParams exprMetricTypeParams = metric.getTypeParams(); + MetricDefineByMeasureParams metricDefineParams = metric.getTypeParams(); MetricTypeParamsYamlTpl metricTypeParamsYamlTpl = new MetricTypeParamsYamlTpl(); - metricTypeParamsYamlTpl.setExpr(exprMetricTypeParams.getExpr()); - List measures = exprMetricTypeParams.getMeasures(); + metricTypeParamsYamlTpl.setExpr(metricDefineParams.getExpr()); + List measures = metricDefineParams.getMeasures(); metricTypeParamsYamlTpl.setMeasures( measures.stream().map(MetricYamlManager::convert).collect(Collectors.toList())); metricYamlTpl.setTypeParams(metricTypeParamsYamlTpl); return metricYamlTpl; } - public static MeasureYamlTpl convert(Measure measure) { + public static MeasureYamlTpl convert(MeasureParam measure) { MeasureYamlTpl measureYamlTpl = new MeasureYamlTpl(); measureYamlTpl.setName(measure.getBizName()); measureYamlTpl.setConstraint(measure.getConstraint()); - measureYamlTpl.setAgg(measure.getAlias()); + measureYamlTpl.setAgg(measure.getAgg()); return measureYamlTpl; } diff --git a/headless/core/src/main/java/com/tencent/supersonic/headless/core/manager/ModelYamlManager.java b/headless/core/src/main/java/com/tencent/supersonic/headless/core/manager/ModelYamlManager.java index 0c8983a5a..28c1b940d 100644 --- a/headless/core/src/main/java/com/tencent/supersonic/headless/core/manager/ModelYamlManager.java +++ b/headless/core/src/main/java/com/tencent/supersonic/headless/core/manager/ModelYamlManager.java @@ -94,7 +94,7 @@ public class ModelYamlManager { } measure.setAgg("count"); measure.setBizName(String.format("%s_%s", datasourceEnName, "internal_cnt")); - measure.setCreateMetric("true"); + measure.setIsCreateMetric(1); datasourceDetail.getMeasures().add(measure); } diff --git a/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/render/SourceRender.java b/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/render/SourceRender.java index 08edb7776..ab5e325de 100644 --- a/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/render/SourceRender.java +++ b/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/render/SourceRender.java @@ -316,9 +316,9 @@ public class SourceRender extends Renderer { } } - public void render(MetricQueryReq metricCommand, List dataSources, SqlValidatorScope scope, + public void render(MetricQueryReq metricQueryReq, List dataSources, SqlValidatorScope scope, HeadlessSchema schema, boolean nonAgg) throws Exception { - String queryWhere = metricCommand.getWhere(); + String queryWhere = metricQueryReq.getWhere(); Set whereFields = new HashSet<>(); List fieldWhere = new ArrayList<>(); if (queryWhere != null && !queryWhere.isEmpty()) { @@ -328,13 +328,13 @@ public class SourceRender extends Renderer { } if (dataSources.size() == 1) { DataSource dataSource = dataSources.get(0); - super.tableView = renderOne("", fieldWhere, metricCommand.getMetrics(), - metricCommand.getDimensions(), - metricCommand.getWhere(), dataSource, scope, schema, nonAgg); + super.tableView = renderOne("", fieldWhere, metricQueryReq.getMetrics(), + metricQueryReq.getDimensions(), + metricQueryReq.getWhere(), dataSource, scope, schema, nonAgg); return; } JoinRender joinRender = new JoinRender(); - joinRender.render(metricCommand, dataSources, scope, schema, nonAgg); + joinRender.render(metricQueryReq, dataSources, scope, schema, nonAgg); super.tableView = joinRender.getTableView(); } diff --git a/headless/server/src/main/java/com/tencent/supersonic/headless/server/persistence/dataobject/MetricDO.java b/headless/server/src/main/java/com/tencent/supersonic/headless/server/persistence/dataobject/MetricDO.java index fb424b2a0..73b693e7e 100644 --- a/headless/server/src/main/java/com/tencent/supersonic/headless/server/persistence/dataobject/MetricDO.java +++ b/headless/server/src/main/java/com/tencent/supersonic/headless/server/persistence/dataobject/MetricDO.java @@ -101,4 +101,6 @@ public class MetricDO { private String ext; + private String defineType; + } \ No newline at end of file diff --git a/headless/server/src/main/java/com/tencent/supersonic/headless/server/persistence/mapper/MetricDOCustomMapper.java b/headless/server/src/main/java/com/tencent/supersonic/headless/server/persistence/mapper/MetricDOCustomMapper.java index ab186aeba..0c785847e 100644 --- a/headless/server/src/main/java/com/tencent/supersonic/headless/server/persistence/mapper/MetricDOCustomMapper.java +++ b/headless/server/src/main/java/com/tencent/supersonic/headless/server/persistence/mapper/MetricDOCustomMapper.java @@ -11,8 +11,6 @@ public interface MetricDOCustomMapper { void batchInsert(List metricDOS); - void batchUpdate(List metricDOS); - void batchUpdateStatus(List metricDOS); List query(MetricFilter metricFilter); diff --git a/headless/server/src/main/java/com/tencent/supersonic/headless/server/rest/MetricController.java b/headless/server/src/main/java/com/tencent/supersonic/headless/server/rest/MetricController.java index 88cdcfb4f..ced5eb206 100644 --- a/headless/server/src/main/java/com/tencent/supersonic/headless/server/rest/MetricController.java +++ b/headless/server/src/main/java/com/tencent/supersonic/headless/server/rest/MetricController.java @@ -9,6 +9,7 @@ import com.tencent.supersonic.common.pojo.enums.SensitiveLevelEnum; import com.tencent.supersonic.headless.api.pojo.DrillDownDimension; import com.tencent.supersonic.headless.api.pojo.MetricQueryDefaultConfig; import com.tencent.supersonic.headless.api.request.MetaBatchReq; +import com.tencent.supersonic.headless.api.request.MetricBaseReq; import com.tencent.supersonic.headless.api.request.MetricReq; import com.tencent.supersonic.headless.api.request.PageMetricReq; import com.tencent.supersonic.headless.api.response.MetricResp; @@ -33,30 +34,26 @@ import java.util.Set; @RequestMapping("/api/semantic/metric") public class MetricController { - private MetricService metricService; - public MetricController(MetricService metricService) { this.metricService = metricService; } @PostMapping("/creatExprMetric") - public Boolean creatExprMetric(@RequestBody MetricReq metricReq, - HttpServletRequest request, - HttpServletResponse response) throws Exception { + public MetricResp createMetric(@RequestBody MetricReq metricReq, + HttpServletRequest request, + HttpServletResponse response) throws Exception { User user = UserHolder.findUser(request, response); - metricService.createMetric(metricReq, user); - return true; + return metricService.createMetric(metricReq, user); } @PostMapping("/updateExprMetric") - public Boolean updateExprMetric(@RequestBody MetricReq metricReq, - HttpServletRequest request, - HttpServletResponse response) throws Exception { + public MetricResp updateMetric(@RequestBody MetricReq metricReq, + HttpServletRequest request, + HttpServletResponse response) throws Exception { User user = UserHolder.findUser(request, response); - metricService.updateExprMetric(metricReq, user); - return true; + return metricService.updateMetric(metricReq, user); } @PostMapping("/batchUpdateStatus") @@ -69,7 +66,7 @@ public class MetricController { } @PostMapping("/mockMetricAlias") - public List mockMetricAlias(@RequestBody MetricReq metricReq, + public List mockMetricAlias(@RequestBody MetricBaseReq metricReq, HttpServletRequest request, HttpServletResponse response) { User user = UserHolder.findUser(request, response); @@ -82,6 +79,11 @@ public class MetricController { return metricService.getMetrics(metaFilter); } + @GetMapping("/getMetricsToCreateNewMetric/{modelId}") + public List getMetricsToCreateNewMetric(@PathVariable("modelId") Long modelId) { + return metricService.getMetricsToCreateNewMetric(modelId); + } + @PostMapping("/queryMetric") public PageInfo queryMetric(@RequestBody PageMetricReq pageMetricReq, HttpServletRequest request, @@ -92,13 +94,15 @@ public class MetricController { @Deprecated @GetMapping("getMetric/{modelId}/{bizName}") - public MetricResp getMetric(@PathVariable("modelId") Long modelId, @PathVariable("bizName") String bizName) { + public MetricResp getMetric(@PathVariable("modelId") Long modelId, + @PathVariable("bizName") String bizName) { return metricService.getMetric(modelId, bizName); } @GetMapping("getMetric/{id}") public MetricResp getMetric(@PathVariable("id") Long id, - HttpServletRequest request, HttpServletResponse response) { + HttpServletRequest request, + HttpServletResponse response) { User user = UserHolder.findUser(request, response); return metricService.getMetric(id, user); } diff --git a/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/MetricService.java b/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/MetricService.java index b39db622d..51aae99ed 100644 --- a/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/MetricService.java +++ b/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/MetricService.java @@ -2,11 +2,11 @@ package com.tencent.supersonic.headless.server.service; import com.github.pagehelper.PageInfo; import com.tencent.supersonic.auth.api.authentication.pojo.User; -import com.tencent.supersonic.common.pojo.DataItem; import com.tencent.supersonic.common.pojo.enums.EventType; import com.tencent.supersonic.headless.api.pojo.DrillDownDimension; import com.tencent.supersonic.headless.api.pojo.MetricQueryDefaultConfig; import com.tencent.supersonic.headless.api.request.MetaBatchReq; +import com.tencent.supersonic.headless.api.request.MetricBaseReq; import com.tencent.supersonic.headless.api.request.MetricReq; import com.tencent.supersonic.headless.api.request.PageMetricReq; import com.tencent.supersonic.headless.api.response.MetricResp; @@ -17,11 +17,11 @@ import java.util.Set; public interface MetricService { - void createMetric(MetricReq metricReq, User user) throws Exception; + MetricResp createMetric(MetricReq metricReq, User user) throws Exception; void createMetricBatch(List metricReqs, User user) throws Exception; - void updateExprMetric(MetricReq metricReq, User user) throws Exception; + MetricResp updateMetric(MetricReq metricReq, User user) throws Exception; void batchUpdateStatus(MetaBatchReq metaBatchReq, User user); @@ -31,20 +31,20 @@ public interface MetricService { List getMetrics(MetaFilter metaFilter); + List getMetricsToCreateNewMetric(Long modelId); + MetricResp getMetric(Long modelId, String bizName); MetricResp getMetric(Long id, User user); MetricResp getMetric(Long id); - List mockAlias(MetricReq metricReq, String mockType, User user); + List mockAlias(MetricBaseReq metricReq, String mockType, User user); Set getMetricTags(); List getDrillDownDimension(Long metricId); - List getDataItems(Long modelId); - void saveMetricQueryDefaultConfig(MetricQueryDefaultConfig defaultConfig, User user); MetricQueryDefaultConfig getMetricQueryDefaultConfig(Long metricId, User user); diff --git a/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/impl/MetricServiceImpl.java b/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/impl/MetricServiceImpl.java index 0a46c76fe..27b1fed2b 100644 --- a/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/impl/MetricServiceImpl.java +++ b/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/impl/MetricServiceImpl.java @@ -12,14 +12,13 @@ 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.pojo.enums.TypeEnums; -import com.tencent.supersonic.common.pojo.exception.InvalidArgumentException; import com.tencent.supersonic.common.util.BeanMapper; import com.tencent.supersonic.common.util.ChatGptHelper; +import com.tencent.supersonic.headless.api.enums.MetricDefineType; import com.tencent.supersonic.headless.api.pojo.DrillDownDimension; -import com.tencent.supersonic.headless.api.pojo.Measure; import com.tencent.supersonic.headless.api.pojo.MetricQueryDefaultConfig; -import com.tencent.supersonic.headless.api.pojo.MetricTypeParams; import com.tencent.supersonic.headless.api.request.MetaBatchReq; +import com.tencent.supersonic.headless.api.request.MetricBaseReq; import com.tencent.supersonic.headless.api.request.MetricReq; import com.tencent.supersonic.headless.api.request.PageMetricReq; import com.tencent.supersonic.headless.api.response.DomainResp; @@ -35,10 +34,9 @@ import com.tencent.supersonic.headless.server.service.CollectService; import com.tencent.supersonic.headless.server.service.DomainService; import com.tencent.supersonic.headless.server.service.MetricService; import com.tencent.supersonic.headless.server.service.ModelService; +import com.tencent.supersonic.headless.server.utils.MetricCheckUtils; import com.tencent.supersonic.headless.server.utils.MetricConverter; -import com.tencent.supersonic.headless.server.utils.NameCheckUtils; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; @@ -83,13 +81,14 @@ public class MetricServiceImpl implements MetricService { } @Override - public void createMetric(MetricReq metricReq, User user) { + public MetricResp createMetric(MetricReq metricReq, User user) { checkExist(Lists.newArrayList(metricReq)); - checkParam(metricReq); + MetricCheckUtils.checkParam(metricReq); metricReq.createdBy(user.getName()); MetricDO metricDO = MetricConverter.convert2MetricDO(metricReq); metricRepository.createMetric(metricDO); sendEventBatch(Lists.newArrayList(metricDO), EventType.ADD); + return MetricConverter.convert2MetricResp(metricDO); } @Override @@ -116,8 +115,8 @@ public class MetricServiceImpl implements MetricService { } @Override - public void updateExprMetric(MetricReq metricReq, User user) { - checkParam(metricReq); + public MetricResp updateMetric(MetricReq metricReq, User user) { + MetricCheckUtils.checkParam(metricReq); checkExist(Lists.newArrayList(metricReq)); metricReq.updatedBy(user.getName()); MetricDO metricDO = metricRepository.getMetricById(metricReq.getId()); @@ -130,6 +129,7 @@ public class MetricServiceImpl implements MetricService { dataItem.setNewName(metricDO.getName()); sendEvent(getDataItem(metricDO), EventType.UPDATE); } + return MetricConverter.convert2MetricResp(metricDO); } @Override @@ -209,6 +209,17 @@ public class MetricServiceImpl implements MetricService { return convertList(queryMetric(metricFilter), Lists.newArrayList()); } + @Override + public List getMetricsToCreateNewMetric(Long modelId) { + MetricFilter metricFilter = new MetricFilter(); + metricFilter.setModelIds(Lists.newArrayList(modelId)); + List metricResps = getMetrics(metricFilter); + return metricResps.stream().filter(metricResp -> + MetricDefineType.FIELD.equals(metricResp.getMetricDefineType()) + || MetricDefineType.MEASURE.equals(metricResp.getMetricDefineType())) + .collect(Collectors.toList()); + } + private void fillAdminRes(List metricResps, User user) { List modelResps = modelService.getModelListWithAuth(user, null, AuthType.ADMIN); if (CollectionUtils.isEmpty(modelResps)) { @@ -260,7 +271,7 @@ public class MetricServiceImpl implements MetricService { } @Override - public List mockAlias(MetricReq metricReq, String mockType, User user) { + public List mockAlias(MetricBaseReq metricReq, String mockType, User user) { String mockAlias = chatGptHelper.mockAlias(mockType, metricReq.getName(), metricReq.getBizName(), "", metricReq.getDescription(), !"".equals(metricReq.getDataFormatType())); @@ -292,17 +303,6 @@ public class MetricServiceImpl implements MetricService { return modelResp.getDrillDownDimensions(); } - @Override - public List getDataItems(Long modelId) { - MetricFilter metaFilter = new MetricFilter(); - metaFilter.setModelIds(Lists.newArrayList(modelId)); - List metricDOS = queryMetric(metaFilter); - if (CollectionUtils.isEmpty(metricDOS)) { - return Lists.newArrayList(); - } - return metricDOS.stream().map(this::getDataItem).collect(Collectors.toList()); - } - @Override public void saveMetricQueryDefaultConfig(MetricQueryDefaultConfig defaultConfig, User user) { MetricQueryDefaultConfigDO defaultConfigDO = @@ -329,31 +329,14 @@ public class MetricServiceImpl implements MetricService { return metricQueryDefaultConfig; } - private void checkParam(MetricReq metricReq) { - MetricTypeParams typeParams = metricReq.getTypeParams(); - List measures = typeParams.getMeasures(); - if (CollectionUtils.isEmpty(measures)) { - throw new InvalidArgumentException("不可缺少度量"); - } - if (StringUtils.isBlank(typeParams.getExpr())) { - throw new InvalidArgumentException("表达式不可为空"); - } - if (NameCheckUtils.containsSpecialCharacters(metricReq.getName())) { - throw new InvalidArgumentException("名称包含特殊字符, 请修改"); - } - } - - private void checkExist(List metricReqs) { + private void checkExist(List metricReqs) { Long modelId = metricReqs.get(0).getModelId(); List metricResps = getMetricInSameDomain(modelId); Map bizNameMap = metricResps.stream() .collect(Collectors.toMap(MetricResp::getBizName, a -> a, (k1, k2) -> k1)); Map nameMap = metricResps.stream() .collect(Collectors.toMap(MetricResp::getName, a -> a, (k1, k2) -> k1)); - for (MetricReq metricReq : metricReqs) { - if (NameCheckUtils.containsSpecialCharacters(metricReq.getName())) { - throw new InvalidArgumentException("名称包含特殊字符, 请修改"); - } + for (MetricBaseReq metricReq : metricReqs) { if (bizNameMap.containsKey(metricReq.getBizName())) { MetricResp metricResp = bizNameMap.get(metricReq.getBizName()); if (!metricResp.getId().equals(metricReq.getId())) { diff --git a/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/impl/ModelServiceImpl.java b/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/impl/ModelServiceImpl.java index 41a1ba0d0..bf9a9677f 100644 --- a/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/impl/ModelServiceImpl.java +++ b/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/impl/ModelServiceImpl.java @@ -30,12 +30,12 @@ import com.tencent.supersonic.headless.api.response.MetricResp; import com.tencent.supersonic.headless.api.response.MetricSchemaResp; import com.tencent.supersonic.headless.api.response.ModelResp; import com.tencent.supersonic.headless.api.response.ModelSchemaResp; -import com.tencent.supersonic.headless.core.pojo.yaml.DataModelYamlTpl; -import com.tencent.supersonic.headless.core.pojo.yaml.DimensionYamlTpl; -import com.tencent.supersonic.headless.core.pojo.yaml.MetricYamlTpl; import com.tencent.supersonic.headless.core.manager.DimensionYamlManager; import com.tencent.supersonic.headless.core.manager.MetricYamlManager; import com.tencent.supersonic.headless.core.manager.ModelYamlManager; +import com.tencent.supersonic.headless.core.pojo.yaml.DataModelYamlTpl; +import com.tencent.supersonic.headless.core.pojo.yaml.DimensionYamlTpl; +import com.tencent.supersonic.headless.core.pojo.yaml.MetricYamlTpl; import com.tencent.supersonic.headless.server.persistence.dataobject.DateInfoDO; import com.tencent.supersonic.headless.server.persistence.dataobject.ModelDO; import com.tencent.supersonic.headless.server.persistence.repository.DateInfoRepository; @@ -211,8 +211,8 @@ public class ModelServiceImpl implements ModelService { } private void batchCreateMetric(ModelDO datasourceDO, User user) throws Exception { - List exprMetricReqs = ModelConverter.convertMetricList(datasourceDO); - metricService.createMetricBatch(exprMetricReqs, user); + List metricReqs = ModelConverter.convertMetricList(datasourceDO); + metricService.createMetricBatch(metricReqs, user); } private void checkName(ModelReq modelReq) { diff --git a/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/DomainConvert.java b/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/DomainConvert.java index 27339dfcc..8cbaf816b 100644 --- a/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/DomainConvert.java +++ b/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/DomainConvert.java @@ -4,15 +4,12 @@ package com.tencent.supersonic.headless.server.utils; import com.google.common.collect.Lists; import com.tencent.supersonic.auth.api.authentication.pojo.User; import com.tencent.supersonic.headless.api.request.DomainReq; -import com.tencent.supersonic.headless.api.response.DimensionResp; import com.tencent.supersonic.headless.api.response.DomainResp; -import com.tencent.supersonic.headless.api.response.MetricResp; import com.tencent.supersonic.headless.server.persistence.dataobject.DomainDO; 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 { @@ -43,13 +40,4 @@ public class DomainConvert { return domainResp; } - public static DomainResp convert(DomainDO domainDO, Map domainFullPathMap, - Map> dimensionMap, - Map> metricMap) { - DomainResp domainResp = convert(domainDO, domainFullPathMap); - domainResp.setDimensionCnt(dimensionMap.getOrDefault(domainResp.getId(), Lists.newArrayList()).size()); - domainResp.setMetricCnt(metricMap.getOrDefault(domainResp.getId(), Lists.newArrayList()).size()); - return domainResp; - } - } diff --git a/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/MetricCheckUtils.java b/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/MetricCheckUtils.java new file mode 100644 index 000000000..41fefd551 --- /dev/null +++ b/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/MetricCheckUtils.java @@ -0,0 +1,69 @@ +package com.tencent.supersonic.headless.server.utils; + +import com.tencent.supersonic.common.pojo.exception.InvalidArgumentException; +import com.tencent.supersonic.common.util.jsqlparser.SqlParserSelectFunctionHelper; +import com.tencent.supersonic.headless.api.enums.MetricDefineType; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByFieldParams; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByMeasureParams; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByMetricParams; +import com.tencent.supersonic.headless.api.request.MetricReq; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.CollectionUtils; + +public class MetricCheckUtils { + + public static void checkParam(MetricReq metricReq) { + String expr = ""; + if (MetricDefineType.METRIC.equals(metricReq.getMetricDefineType())) { + MetricDefineByMetricParams typeParams = metricReq.getMetricDefineByMetricParams(); + if (typeParams == null) { + throw new InvalidArgumentException("指标定义参数不可为空"); + } + expr = typeParams.getExpr(); + if (CollectionUtils.isEmpty(typeParams.getMetrics())) { + throw new InvalidArgumentException("定义指标的指标列表参数不可为空"); + } + if (hasAggregateFunction(expr)) { + throw new InvalidArgumentException("基于指标来创建指标,表达式中不可再包含聚合函数"); + } + } + if (MetricDefineType.MEASURE.equals(metricReq.getMetricDefineType())) { + MetricDefineByMeasureParams typeParams = metricReq.getTypeParams(); + if (typeParams == null) { + throw new InvalidArgumentException("指标定义参数不可为空"); + } + expr = typeParams.getExpr(); + if (CollectionUtils.isEmpty(typeParams.getMeasures())) { + throw new InvalidArgumentException("定义指标的度量列表参数不可为空"); + } + if (hasAggregateFunction(expr)) { + throw new InvalidArgumentException("基于度量来创建指标,表达式中不可再包含聚合函数"); + } + } + if (MetricDefineType.FIELD.equals(metricReq.getMetricDefineType())) { + MetricDefineByFieldParams typeParams = metricReq.getMetricDefineByFieldParams(); + if (typeParams == null) { + throw new InvalidArgumentException("指标定义参数不可为空"); + } + expr = typeParams.getExpr(); + if (CollectionUtils.isEmpty(typeParams.getFields())) { + throw new InvalidArgumentException("定义指标的字段列表参数不可为空"); + } + if (!hasAggregateFunction(expr)) { + throw new InvalidArgumentException("基于字段来创建指标,表达式中必须包含聚合函数"); + } + } + if (StringUtils.isBlank(expr)) { + throw new InvalidArgumentException("表达式不可为空"); + } + if (NameCheckUtils.containsSpecialCharacters(metricReq.getName())) { + throw new InvalidArgumentException("名称包含特殊字符, 请修改"); + } + } + + private static boolean hasAggregateFunction(String expr) { + String sql = String.format("select %s from table", expr); + return SqlParserSelectFunctionHelper.hasAggregateFunction(sql); + } + +} diff --git a/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/MetricConverter.java b/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/MetricConverter.java index 79c874996..2b5bed642 100644 --- a/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/MetricConverter.java +++ b/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/MetricConverter.java @@ -1,11 +1,15 @@ package com.tencent.supersonic.headless.server.utils; 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.pojo.enums.TypeEnums; import com.tencent.supersonic.common.util.BeanMapper; -import com.tencent.supersonic.headless.api.pojo.MetricTypeParams; +import com.tencent.supersonic.headless.api.enums.MetricDefineType; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByFieldParams; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByMeasureParams; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByMetricParams; import com.tencent.supersonic.headless.api.pojo.RelateDimension; import com.tencent.supersonic.headless.api.request.MetricReq; import com.tencent.supersonic.headless.api.response.MetricResp; @@ -13,6 +17,7 @@ import com.tencent.supersonic.headless.api.response.ModelResp; import com.tencent.supersonic.headless.server.persistence.dataobject.MetricDO; import org.springframework.beans.BeanUtils; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -22,44 +27,52 @@ public class MetricConverter { MetricDO metricDO = new MetricDO(); BeanMapper.mapper(metricReq, metricDO); metricDO.setType(metricReq.getMetricType().name()); - metricDO.setTypeParams(JSONObject.toJSONString(metricReq.getTypeParams())); + metricDO.setTypeParams(metricReq.getTypeParamsJson()); metricDO.setDataFormat(JSONObject.toJSONString(metricReq.getDataFormat())); metricDO.setTags(metricReq.getTag()); metricDO.setRelateDimensions(JSONObject.toJSONString(metricReq.getRelateDimension())); metricDO.setStatus(StatusEnum.ONLINE.getCode()); metricDO.setExt(JSONObject.toJSONString(metricReq.getExt())); + metricDO.setDefineType(metricReq.getMetricDefineType().name()); return metricDO; } public static MetricDO convert(MetricDO metricDO, MetricReq metricReq) { BeanMapper.mapper(metricReq, metricDO); - metricDO.setTypeParams(JSONObject.toJSONString(metricReq.getTypeParams())); + metricDO.setDefineType(metricReq.getMetricDefineType().name()); if (metricReq.getDataFormat() != null) { metricDO.setDataFormat(JSONObject.toJSONString(metricReq.getDataFormat())); } if (metricReq.getRelateDimension() != null) { metricDO.setRelateDimensions(JSONObject.toJSONString(metricReq.getRelateDimension())); } - metricDO.setTags(metricReq.getTag()); - metricDO.setExt(JSONObject.toJSONString(metricReq.getExt())); + if (metricReq.getTag() != null) { + metricDO.setTags(metricReq.getTag()); + } + if (metricReq.getExt() != null) { + metricDO.setExt(JSONObject.toJSONString(metricReq.getExt())); + } + if (metricReq.getTypeParamsJson() != null) { + metricDO.setTypeParams(metricReq.getTypeParamsJson()); + } return metricDO; } + public static MetricResp convert2MetricResp(MetricDO metricDO) { + return convert2MetricResp(metricDO, new HashMap<>(), Lists.newArrayList()); + } + public static MetricResp convert2MetricResp(MetricDO metricDO, Map modelMap, List collect) { MetricResp metricResp = new MetricResp(); BeanUtils.copyProperties(metricDO, metricResp); - metricResp.setTypeParams(JSONObject.parseObject(metricDO.getTypeParams(), MetricTypeParams.class)); + metricResp.setDataFormat(JSONObject.parseObject(metricDO.getDataFormat(), DataFormat.class)); ModelResp modelResp = modelMap.get(metricDO.getModelId()); if (modelResp != null) { metricResp.setModelName(modelResp.getName()); metricResp.setDomainId(modelResp.getDomainId()); } - if (collect != null && collect.contains(metricDO.getId())) { - metricResp.setIsCollect(true); - } else { - metricResp.setIsCollect(false); - } + metricResp.setIsCollect(collect != null && collect.contains(metricDO.getId())); metricResp.setTag(metricDO.getTags()); metricResp.setRelateDimension(JSONObject.parseObject(metricDO.getRelateDimensions(), RelateDimension.class)); @@ -67,6 +80,19 @@ public class MetricConverter { metricResp.setExt(JSONObject.parseObject(metricDO.getExt(), Map.class)); } metricResp.setTypeEnum(TypeEnums.METRIC); + if (MetricDefineType.MEASURE.name().equalsIgnoreCase(metricDO.getDefineType())) { + metricResp.setTypeParams(JSONObject.parseObject(metricDO.getTypeParams(), + MetricDefineByMeasureParams.class)); + } else if (MetricDefineType.METRIC.name().equalsIgnoreCase(metricDO.getDefineType())) { + metricResp.setMetricDefineByMetricParams(JSONObject.parseObject(metricDO.getTypeParams(), + MetricDefineByMetricParams.class)); + } else if (MetricDefineType.FIELD.name().equalsIgnoreCase(metricDO.getDefineType())) { + metricResp.setMetricDefineByFieldParams(JSONObject.parseObject(metricDO.getTypeParams(), + MetricDefineByFieldParams.class)); + } + if (metricDO.getDefineType() != null) { + metricResp.setMetricDefineType(MetricDefineType.valueOf(metricDO.getDefineType())); + } return metricResp; } diff --git a/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/ModelConverter.java b/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/ModelConverter.java index a31b3cde8..9b0e78ed2 100644 --- a/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/ModelConverter.java +++ b/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/ModelConverter.java @@ -8,13 +8,14 @@ import com.tencent.supersonic.common.util.BeanMapper; import com.tencent.supersonic.common.util.JsonUtil; import com.tencent.supersonic.headless.api.enums.DimensionType; import com.tencent.supersonic.headless.api.enums.IdentifyType; -import com.tencent.supersonic.headless.api.enums.MetricType; +import com.tencent.supersonic.headless.api.enums.MetricDefineType; import com.tencent.supersonic.headless.api.enums.SemanticType; import com.tencent.supersonic.headless.api.pojo.Dim; import com.tencent.supersonic.headless.api.pojo.DrillDownDimension; import com.tencent.supersonic.headless.api.pojo.Identify; import com.tencent.supersonic.headless.api.pojo.Measure; -import com.tencent.supersonic.headless.api.pojo.MetricTypeParams; +import com.tencent.supersonic.headless.api.pojo.MeasureParam; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByMeasureParams; import com.tencent.supersonic.headless.api.pojo.ModelDetail; import com.tencent.supersonic.headless.api.request.DimensionReq; import com.tencent.supersonic.headless.api.request.MetricReq; @@ -116,11 +117,13 @@ public class ModelConverter { metricReq.setBizName(measure.getBizName().replaceFirst(modelDO.getBizName() + "_", "")); metricReq.setDescription(measure.getName()); metricReq.setModelId(modelDO.getId()); - metricReq.setMetricType(MetricType.ATOMIC); - MetricTypeParams exprTypeParams = new MetricTypeParams(); + MetricDefineByMeasureParams exprTypeParams = new MetricDefineByMeasureParams(); exprTypeParams.setExpr(measure.getBizName()); - exprTypeParams.setMeasures(Lists.newArrayList(measure)); + MeasureParam measureParam = new MeasureParam(); + BeanMapper.mapper(measure, measureParam); + exprTypeParams.setMeasures(Lists.newArrayList(measureParam)); metricReq.setTypeParams(exprTypeParams); + metricReq.setMetricDefineType(MetricDefineType.MEASURE); return metricReq; } diff --git a/headless/server/src/main/resources/mapper/custom/MetricDOCustomMapper.xml b/headless/server/src/main/resources/mapper/custom/MetricDOCustomMapper.xml index 4b7098aae..3a8fca6b6 100644 --- a/headless/server/src/main/resources/mapper/custom/MetricDOCustomMapper.xml +++ b/headless/server/src/main/resources/mapper/custom/MetricDOCustomMapper.xml @@ -19,6 +19,7 @@ + @@ -56,7 +57,7 @@ id, model_id, name, biz_name, description, status, sensitive_level, type, created_at, - created_by, updated_at, updated_by, data_format_type, data_format, alias, tags + created_by, updated_at, updated_by, data_format_type, data_format, alias, tags, define_type type_params @@ -66,7 +67,7 @@ insert into s2_metric (model_id, name, biz_name, description, type,status,sensitive_level, created_at, created_by, updated_at, - updated_by, type_params + updated_by, type_params, define_type ) values @@ -76,30 +77,12 @@ #{metric.status,jdbcType=VARCHAR},#{metric.sensitiveLevel,jdbcType=VARCHAR}, #{metric.createdAt,jdbcType=TIMESTAMP}, #{metric.createdBy,jdbcType=VARCHAR}, #{metric.updatedAt,jdbcType=TIMESTAMP}, - #{metric.updatedBy,jdbcType=VARCHAR}, #{metric.typeParams,jdbcType=LONGVARCHAR} + #{metric.updatedBy,jdbcType=VARCHAR}, #{metric.typeParams,jdbcType=LONGVARCHAR}, + #{metric.defineType,jdbcType=VARCHAR} ) - - - update s2_metric - set model_id = #{metric.modelId,jdbcType=BIGINT}, - name = #{metric.name,jdbcType=VARCHAR}, - biz_name = #{metric.bizName,jdbcType=VARCHAR}, - description = #{metric.description,jdbcType=VARCHAR}, - type = #{metric.type,jdbcType=VARCHAR}, - status = #{metric.status,jdbcType=VARCHAR}, - created_at = #{metric.createdAt,jdbcType=TIMESTAMP}, - created_by = #{metric.createdBy,jdbcType=VARCHAR}, - updated_at = #{metric.updatedAt,jdbcType=TIMESTAMP}, - updated_by = #{metric.updatedBy,jdbcType=VARCHAR}, - sensitive_level = #{metric.sensitiveLevel,jdbcType=INTEGER}, - type_params = #{metric.typeParams,jdbcType=LONGVARCHAR} - where id = #{metric.id,jdbcType=BIGINT} - - - update s2_metric diff --git a/headless/server/src/test/java/com/tencent/supersonic/headless/server/service/MetricServiceImplTest.java b/headless/server/src/test/java/com/tencent/supersonic/headless/server/service/MetricServiceImplTest.java new file mode 100644 index 000000000..72a5af37e --- /dev/null +++ b/headless/server/src/test/java/com/tencent/supersonic/headless/server/service/MetricServiceImplTest.java @@ -0,0 +1,160 @@ +package com.tencent.supersonic.headless.server.service; + +import com.google.common.collect.Lists; +import com.tencent.supersonic.auth.api.authentication.pojo.User; +import com.tencent.supersonic.common.pojo.DataFormat; +import com.tencent.supersonic.common.pojo.enums.DataFormatTypeEnum; +import com.tencent.supersonic.common.pojo.enums.SensitiveLevelEnum; +import com.tencent.supersonic.common.pojo.enums.StatusEnum; +import com.tencent.supersonic.common.pojo.enums.TypeEnums; +import com.tencent.supersonic.common.util.ChatGptHelper; +import com.tencent.supersonic.headless.api.enums.MetricDefineType; +import com.tencent.supersonic.headless.api.enums.MetricType; +import com.tencent.supersonic.headless.api.pojo.DrillDownDimension; +import com.tencent.supersonic.headless.api.pojo.MeasureParam; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByMeasureParams; +import com.tencent.supersonic.headless.api.pojo.RelateDimension; +import com.tencent.supersonic.headless.api.request.MetricReq; +import com.tencent.supersonic.headless.api.response.MetricResp; +import com.tencent.supersonic.headless.api.response.ModelResp; +import com.tencent.supersonic.headless.server.persistence.dataobject.MetricDO; +import com.tencent.supersonic.headless.server.persistence.repository.MetricRepository; +import com.tencent.supersonic.headless.server.service.impl.MetricServiceImpl; +import com.tencent.supersonic.headless.server.utils.MetricConverter; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.context.ApplicationEventPublisher; +import java.util.HashMap; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +public class MetricServiceImplTest { + + @Test + void createMetric() throws Exception { + MetricRepository metricRepository = Mockito.mock(MetricRepository.class); + ModelService modelService = Mockito.mock(ModelService.class); + MetricService metricService = mockMetricService(metricRepository, modelService); + MetricReq metricReq = buildMetricReq(); + when(modelService.getModel(metricReq.getModelId())).thenReturn(mockModelResp()); + when(modelService.getModelByDomainIds(any())).thenReturn(Lists.newArrayList()); + MetricResp actualMetricResp = metricService.createMetric(metricReq, User.getFakeUser()); + MetricResp expectedMetricResp = buildExpectedMetricResp(); + Assertions.assertEquals(expectedMetricResp, actualMetricResp); + } + + @Test + void updateMetric() throws Exception { + MetricRepository metricRepository = Mockito.mock(MetricRepository.class); + ModelService modelService = Mockito.mock(ModelService.class); + MetricService metricService = mockMetricService(metricRepository, modelService); + MetricReq metricReq = buildMetricUpdateReq(); + when(modelService.getModel(metricReq.getModelId())).thenReturn(mockModelResp()); + when(modelService.getModelByDomainIds(any())).thenReturn(Lists.newArrayList()); + MetricDO metricDO = MetricConverter.convert2MetricDO(buildMetricReq()); + when(metricRepository.getMetricById(metricDO.getId())).thenReturn(metricDO); + MetricResp actualMetricResp = metricService.updateMetric(metricReq, User.getFakeUser()); + MetricResp expectedMetricResp = buildExpectedMetricResp(); + Assertions.assertEquals(expectedMetricResp, actualMetricResp); + } + + private MetricService mockMetricService(MetricRepository metricRepository, + ModelService modelService) { + DomainService domainService = Mockito.mock(DomainService.class); + ChatGptHelper chatGptHelper = Mockito.mock(ChatGptHelper.class); + CollectService collectService = Mockito.mock(CollectService.class); + ApplicationEventPublisher eventPublisher = Mockito.mock(ApplicationEventPublisher.class); + return new MetricServiceImpl(metricRepository, modelService, domainService, + chatGptHelper, collectService, eventPublisher); + } + + private MetricReq buildMetricReq() { + MetricReq metricReq = new MetricReq(); + metricReq.setId(1L); + metricReq.setName("hr部门的访问次数"); + metricReq.setBizName("pv"); + metricReq.setDescription("SuperSonic的访问情况"); + metricReq.setAlias("pv"); + metricReq.setMetricDefineType(MetricDefineType.MEASURE); + metricReq.setModelId(2L); + metricReq.setDataFormatType(DataFormatTypeEnum.PERCENT.getName()); + DataFormat dataFormat = new DataFormat(); + dataFormat.setDecimalPlaces(3); + dataFormat.setNeedMultiply100(false); + metricReq.setDataFormat(dataFormat); + MetricDefineByMeasureParams typeParams = new MetricDefineByMeasureParams(); + typeParams.setMeasures(Lists.newArrayList( + new MeasureParam("s2_pv", "department='hr'"), + new MeasureParam("s2_uv", "department='hr'"))); + typeParams.setExpr("s2_pv/s2_uv"); + metricReq.setMetricDefineByMeasureParams(typeParams); + metricReq.setTags(Lists.newArrayList("核心指标")); + metricReq.setRelateDimension( + RelateDimension.builder().drillDownDimensions(Lists.newArrayList( + new DrillDownDimension(1L), + new DrillDownDimension(1L, false)) + ).build()); + metricReq.setSensitiveLevel(SensitiveLevelEnum.LOW.getCode()); + metricReq.setExt(new HashMap<>()); + return metricReq; + } + + private MetricResp buildExpectedMetricResp() { + MetricResp metricResp = new MetricResp(); + metricResp.setId(1L); + metricResp.setName("hr部门的访问次数"); + metricResp.setBizName("pv"); + metricResp.setDescription("SuperSonic的访问情况"); + metricResp.setAlias("pv"); + metricResp.setMetricDefineType(MetricDefineType.MEASURE); + metricResp.setModelId(2L); + metricResp.setDataFormatType(DataFormatTypeEnum.PERCENT.getName()); + DataFormat dataFormat = new DataFormat(); + dataFormat.setDecimalPlaces(3); + dataFormat.setNeedMultiply100(false); + metricResp.setDataFormat(dataFormat); + MetricDefineByMeasureParams typeParams = new MetricDefineByMeasureParams(); + typeParams.setMeasures(Lists.newArrayList( + new MeasureParam("s2_pv", "department='hr'"), + new MeasureParam("s2_uv", "department='hr'"))); + typeParams.setExpr("s2_pv/s2_uv"); + metricResp.setMetricDefineByMeasureParams(typeParams); + metricResp.setTags(Lists.newArrayList("核心指标")); + metricResp.setRelateDimension( + RelateDimension.builder().drillDownDimensions(Lists.newArrayList( + new DrillDownDimension(1L), + new DrillDownDimension(1L, false)) + ).build()); + metricResp.setSensitiveLevel(SensitiveLevelEnum.LOW.getCode()); + metricResp.setExt(new HashMap<>()); + metricResp.setTypeEnum(TypeEnums.METRIC); + metricResp.setIsCollect(false); + metricResp.setType(MetricType.DERIVED.name()); + metricResp.setStatus(StatusEnum.ONLINE.getCode()); + return metricResp; + } + + private MetricReq buildMetricUpdateReq() { + MetricReq metricReq = new MetricReq(); + metricReq.setId(1L); + metricReq.setName("hr部门的访问次数"); + metricReq.setBizName("pv"); + metricReq.setMetricDefineType(MetricDefineType.MEASURE); + MetricDefineByMeasureParams typeParams = new MetricDefineByMeasureParams(); + typeParams.setMeasures(Lists.newArrayList( + new MeasureParam("s2_pv", "department='hr'"), + new MeasureParam("s2_uv", "department='hr'"))); + typeParams.setExpr("s2_pv/s2_uv"); + metricReq.setMetricDefineByMeasureParams(typeParams); + return metricReq; + } + + private ModelResp mockModelResp() { + ModelResp modelResp = new ModelResp(); + modelResp.setId(2L); + modelResp.setDomainId(1L); + return modelResp; + } + +} diff --git a/headless/server/src/test/java/com/tencent/supersonic/headless/server/service/ModelServiceImplTest.java b/headless/server/src/test/java/com/tencent/supersonic/headless/server/service/ModelServiceImplTest.java index 3bc586c8f..8901d16df 100644 --- a/headless/server/src/test/java/com/tencent/supersonic/headless/server/service/ModelServiceImplTest.java +++ b/headless/server/src/test/java/com/tencent/supersonic/headless/server/service/ModelServiceImplTest.java @@ -56,6 +56,18 @@ class ModelServiceImplTest { Assertions.assertEquals("alice", actualModelResp.getUpdatedBy()); } + @Test + void updateModel_updateAdmin() throws Exception { + ModelRepository modelRepository = Mockito.mock(ModelRepository.class); + ModelService modelService = mockModelService(modelRepository); + ModelReq modelReq = mockModelReq_updateAdmin(); + ModelDO modelDO = ModelConverter.convert(mockModelReq(), User.getFakeUser()); + when(modelRepository.getModelById(modelReq.getId())).thenReturn(modelDO); + ModelResp actualModelResp = modelService.updateModel(modelReq, User.getFakeUser()); + ModelResp expectedModelResp = buildExpectedModelResp(); + Assertions.assertEquals(expectedModelResp, actualModelResp); + } + private ModelService mockModelService(ModelRepository modelRepository) { MetricService metricService = Mockito.mock(MetricService.class); DimensionService dimensionService = Mockito.mock(DimensionService.class); @@ -137,8 +149,8 @@ class ModelServiceImplTest { 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.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'"); @@ -146,6 +158,36 @@ class ModelServiceImplTest { return modelReq; } + private ModelReq mockModelReq_updateAdmin() { + ModelReq modelReq = new ModelReq(); + modelReq.setId(1L); + modelReq.setName("PVUV统计"); + modelReq.setBizName("s2_pv_uv_statis"); + ModelDetail modelDetail = new ModelDetail(); + List identifiers = new ArrayList<>(); + identifiers.add(new Identify("用户名", IdentifyType.primary.name(), "user_name")); + modelDetail.setIdentifiers(identifiers); + List dimensions = new ArrayList<>(); + Dim dimension1 = new Dim("", "imp_date", DimensionType.time.name(), 0); + dimension1.setTypeParams(new DimensionTimeTypeParams()); + dimensions.add(dimension1); + Dim dimension2 = new Dim("", "page", DimensionType.categorical.name(), 0); + dimension2.setExpr("page"); + dimensions.add(dimension2); + modelDetail.setDimensions(dimensions); + List 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.setModelDetail(modelDetail); + return modelReq; + } + private ModelResp buildExpectedModelResp() { ModelResp modelResp = new ModelResp(); modelResp.setName("PVUV统计"); @@ -197,6 +239,7 @@ class ModelServiceImplTest { modelResp.setDescription("PVUV统计_a"); modelResp.setDatabaseId(2L); modelResp.setDomainId(1L); + modelResp.setStatus(StatusEnum.ONLINE.getCode()); modelResp.setAlias("访问次数统计,PVUV统计"); modelResp.setAdmins(Lists.newArrayList("admin")); modelResp.setViewers(Lists.newArrayList("alice")); diff --git a/launchers/standalone/src/main/java/com/tencent/supersonic/ModelDemoDataLoader.java b/launchers/standalone/src/main/java/com/tencent/supersonic/ModelDemoDataLoader.java index ac6172079..41d838469 100644 --- a/launchers/standalone/src/main/java/com/tencent/supersonic/ModelDemoDataLoader.java +++ b/launchers/standalone/src/main/java/com/tencent/supersonic/ModelDemoDataLoader.java @@ -15,12 +15,14 @@ import com.tencent.supersonic.common.pojo.enums.StatusEnum; import com.tencent.supersonic.headless.api.enums.DataType; import com.tencent.supersonic.headless.api.enums.DimensionType; import com.tencent.supersonic.headless.api.enums.IdentifyType; +import com.tencent.supersonic.headless.api.enums.MetricDefineType; import com.tencent.supersonic.headless.api.enums.SemanticType; import com.tencent.supersonic.headless.api.pojo.Dim; import com.tencent.supersonic.headless.api.pojo.DimensionTimeTypeParams; import com.tencent.supersonic.headless.api.pojo.Identify; import com.tencent.supersonic.headless.api.pojo.Measure; -import com.tencent.supersonic.headless.api.pojo.MetricTypeParams; +import com.tencent.supersonic.headless.api.pojo.MeasureParam; +import com.tencent.supersonic.headless.api.pojo.MetricDefineByMeasureParams; import com.tencent.supersonic.headless.api.pojo.ModelDetail; import com.tencent.supersonic.headless.api.request.DatabaseReq; import com.tencent.supersonic.headless.api.request.DimensionReq; @@ -329,15 +331,16 @@ public class ModelDemoDataLoader { metricReq.setDescription("停留时长"); metricReq.setTags(Collections.singletonList("核心指标")); metricReq.setAlias("访问时长"); - MetricTypeParams metricTypeParams = new MetricTypeParams(); + MetricDefineByMeasureParams metricTypeParams = new MetricDefineByMeasureParams(); metricTypeParams.setExpr("s2_stay_time_statis_stay_hours"); - List measures = new ArrayList<>(); - Measure measure = new Measure("停留时长", - "s2_stay_time_statis_stay_hours", AggOperatorEnum.SUM.getOperator(), 1); + List measures = new ArrayList<>(); + MeasureParam measure = new MeasureParam("s2_stay_time_statis_stay_hours", + "", AggOperatorEnum.SUM.getOperator()); measures.add(measure); metricTypeParams.setMeasures(measures); metricReq.setTypeParams(metricTypeParams); - metricService.updateExprMetric(metricReq, user); + metricReq.setMetricDefineType(MetricDefineType.MEASURE); + metricService.updateMetric(metricReq, user); } public void addAuthGroup_1() { diff --git a/launchers/standalone/src/main/resources/db/schema-h2.sql b/launchers/standalone/src/main/resources/db/schema-h2.sql index 76a5e40fa..b1ff86027 100644 --- a/launchers/standalone/src/main/resources/db/schema-h2.sql +++ b/launchers/standalone/src/main/resources/db/schema-h2.sql @@ -174,9 +174,9 @@ CREATE TABLE IF NOT EXISTS `s2_metric` ( `name` varchar(255) NOT NULL , `biz_name` varchar(255) NOT NULL , `description` varchar(500) DEFAULT NULL , - `status` INT NOT NULL , -- status, 0 is off the shelf, 1 is normal + `status` INT NOT NULL , `sensitive_level` INT NOT NULL , - `type` varchar(50) NOT NULL , -- type proxy,expr + `type` varchar(50) NOT NULL , -- ATOMIC, DERIVED `type_params` LONGVARCHAR DEFAULT NULL , `created_at` TIMESTAMP NOT NULL , `created_by` varchar(100) NOT NULL , @@ -188,6 +188,7 @@ CREATE TABLE IF NOT EXISTS `s2_metric` ( `tags` varchar(500) DEFAULT NULL, `relate_dimensions` varchar(500) DEFAULT NULL, `ext` LONGVARCHAR DEFAULT NULL , + `define_type` varchar(50) NOT NULL, -- MEASURE, FIELD, METRIC PRIMARY KEY (`id`) ); COMMENT ON TABLE s2_metric IS 'metric information table'; diff --git a/launchers/standalone/src/main/resources/db/schema-mysql.sql b/launchers/standalone/src/main/resources/db/schema-mysql.sql index a7b67491a..0ca5c9542 100644 --- a/launchers/standalone/src/main/resources/db/schema-mysql.sql +++ b/launchers/standalone/src/main/resources/db/schema-mysql.sql @@ -279,28 +279,31 @@ CREATE TABLE `s2_domain` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='主题域基础信息表'; -CREATE TABLE `s2_metric` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `model_id` bigint(20) DEFAULT NULL, - `name` varchar(255) NOT NULL COMMENT '指标名称', - `biz_name` varchar(255) NOT NULL COMMENT '字段名称', - `description` varchar(500) DEFAULT NULL COMMENT '描述', - `status` int(10) NOT NULL COMMENT '指标状态,0未启用,1启用', - `sensitive_level` int(10) NOT NULL COMMENT '敏感级别', - `type` varchar(50) NOT NULL COMMENT '指标类型', - `type_params` text NOT NULL COMMENT '类型参数', - `created_at` datetime NOT NULL COMMENT '创建时间', - `created_by` varchar(100) NOT NULL COMMENT '创建人', - `updated_at` datetime NOT NULL COMMENT '更新时间', - `updated_by` varchar(100) NOT NULL COMMENT '更新人', - `data_format_type` varchar(50) DEFAULT NULL COMMENT '数值类型', - `data_format` varchar(500) DEFAULT NULL COMMENT '数值类型参数', - `alias` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL, - `tags` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL, - `relate_dimensions` varchar(500) DEFAULT NULL COMMENT '指标相关维度', - `ext` text DEFAULT NULL , - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='指标表'; +CREATE TABLE `s2_metric` +( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `model_id` bigint(20) DEFAULT NULL, + `name` varchar(255) NOT NULL COMMENT '指标名称', + `biz_name` varchar(255) NOT NULL COMMENT '字段名称', + `description` varchar(500) DEFAULT NULL COMMENT '描述', + `status` int(10) NOT NULL COMMENT '指标状态', + `sensitive_level` int(10) NOT NULL COMMENT '敏感级别', + `type` varchar(50) NOT NULL COMMENT '指标类型', + `type_params` text NOT NULL COMMENT '类型参数', + `created_at` datetime NOT NULL COMMENT '创建时间', + `created_by` varchar(100) NOT NULL COMMENT '创建人', + `updated_at` datetime NOT NULL COMMENT '更新时间', + `updated_by` varchar(100) NOT NULL COMMENT '更新人', + `data_format_type` varchar(50) DEFAULT NULL COMMENT '数值类型', + `data_format` varchar(500) DEFAULT NULL COMMENT '数值类型参数', + `alias` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL, + `tags` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL, + `relate_dimensions` varchar(500) DEFAULT NULL COMMENT '指标相关维度', + `ext` text DEFAULT NULL, + `define_type` varchar(50) DEFAULT NULL, -- MEASURE, FIELD, METRIC + PRIMARY KEY (`id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8 COMMENT ='指标表'; CREATE TABLE `s2_model` ( diff --git a/launchers/standalone/src/main/resources/db/sql-update.sql b/launchers/standalone/src/main/resources/db/sql-update.sql index d9aa92d46..2288b7f0d 100644 --- a/launchers/standalone/src/main/resources/db/sql-update.sql +++ b/launchers/standalone/src/main/resources/db/sql-update.sql @@ -163,4 +163,9 @@ CREATE TABLE `s2_app` `updated_at` datetime null, `created_by` varchar(255) null, `updated_by` varchar(255) null -)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; \ No newline at end of file +)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + +--20240115 +alter table s2_metric add column `define_type` varchar(50) DEFAULT NULL; -- MEASURE, FIELD, METRIC +update s2_metric set define_type = 'MEASURE'; \ No newline at end of file