10 Commits

Author SHA1 Message Date
zyclove
36b2b4c4db Merge 668f872743 into a3293e6788 2025-03-09 17:35:30 +08:00
zyclove
a3293e6788 fix:java.lang.NullPointerException: Cannot invoke "com.tencent.supersonic.common.pojo.DateConf.getDateField()" because "dateConf" is null (#2142)
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled
2025-03-09 13:44:07 +08:00
jerryjzhang
a99f5985f5 (improvement)(headless)Set fields of model detail when restoring model.
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-09 10:58:49 +08:00
jerryjzhang
91243005bc (fix)(launcher)Change join_condition to type text to avoid "value too long for column". 2025-03-09 09:18:29 +08:00
jerryjzhang
a76b5a4300 (improvement)(headless)Add unit to measure. 2025-03-09 09:15:13 +08:00
jerryjzhang
c1f9df963c (improvement)(headless)Add expr to semantic column. 2025-03-09 08:31:48 +08:00
Shaofeng Shi
954aa4eea5 fix: https://github.com/tencentmusic/supersonic/issues/2132 for Trino syntax (#2144)
Some checks are pending
supersonic CentOS CI / build (21) (push) Waiting to run
supersonic mac CI / build (21) (push) Waiting to run
supersonic ubuntu CI / build (21) (push) Waiting to run
supersonic windows CI / build (21) (push) Waiting to run
2025-03-08 21:41:35 +08:00
jerryjzhang
33bd0de604 (improvement)(headless)Set fields of model detail when creating model. 2025-03-08 21:16:10 +08:00
zhaoyingchao
668f872743 Merge remote-tracking branch 'origin/master' into jsqlparser-fix 2025-03-05 10:01:57 +08:00
zhaoyingchao
acb9cef64e feat:upgrade jsqlparser 4.9 and add timeout 2025-02-27 17:30:48 +08:00
19 changed files with 66 additions and 62 deletions

View File

@@ -225,7 +225,7 @@ public class SqlSelectHelper {
public static Select getSelect(String sql) { public static Select getSelect(String sql) {
Statement statement = null; Statement statement = null;
try { try {
statement = CCJSqlParserUtil.parse(sql); statement = CCJSqlParserUtil.parse(sql, parser -> parser.withTimeOut(20000));
} catch (JSQLParserException e) { } catch (JSQLParserException e) {
log.error("parse error, sql:{}", sql, e); log.error("parse error, sql:{}", sql, e);
throw new RuntimeException(e); throw new RuntimeException(e);

View File

@@ -23,12 +23,16 @@ public class Measure {
private String alias; private String alias;
public Measure(String name, String bizName, String expr, String agg, Integer isCreateMetric) { private String unit;
public Measure(String name, String bizName, String expr, String agg, String unit,
Integer isCreateMetric) {
this.name = name; this.name = name;
this.agg = agg; this.agg = agg;
this.isCreateMetric = isCreateMetric; this.isCreateMetric = isCreateMetric;
this.bizName = bizName; this.bizName = bizName;
this.expr = expr; this.expr = expr;
this.unit = unit;
} }
public Measure(String name, String bizName, String agg, Integer isCreateMetric) { public Measure(String name, String bizName, String agg, Integer isCreateMetric) {

View File

@@ -49,27 +49,4 @@ public class ModelDetail {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public List<Field> getFields() {
if (!CollectionUtils.isEmpty(fields)) {
return fields;
}
List<Field> fieldList = Lists.newArrayList();
// Compatible with older versions
if (!CollectionUtils.isEmpty(identifiers)) {
fieldList.addAll(identifiers.stream()
.map(identify -> Field.builder().fieldName(identify.getFieldName()).build())
.collect(Collectors.toSet()));
}
if (!CollectionUtils.isEmpty(dimensions)) {
fieldList.addAll(dimensions.stream()
.map(dim -> Field.builder().fieldName(dim.getFieldName()).build())
.collect(Collectors.toSet()));
}
if (!CollectionUtils.isEmpty(measures)) {
fieldList.addAll(measures.stream()
.map(measure -> Field.builder().fieldName(measure.getFieldName()).build())
.collect(Collectors.toSet()));
}
return fieldList;
}
} }

View File

@@ -14,11 +14,11 @@ public class ModelSchema {
private String description; private String description;
private List<ColumnSchema> columnSchemas; private List<SemanticColumn> semanticColumns;
@JsonIgnore @JsonIgnore
public ColumnSchema getColumnByName(String columnName) { public SemanticColumn getColumnByName(String columnName) {
for (ColumnSchema fieldSchema : columnSchemas) { for (SemanticColumn fieldSchema : semanticColumns) {
if (fieldSchema.getColumnName().equalsIgnoreCase(columnName)) { if (fieldSchema.getColumnName().equalsIgnoreCase(columnName)) {
return fieldSchema; return fieldSchema;
} }

View File

@@ -5,7 +5,7 @@ import com.tencent.supersonic.headless.api.pojo.enums.FieldType;
import lombok.Data; import lombok.Data;
@Data @Data
public class ColumnSchema { public class SemanticColumn {
private String columnName; private String columnName;
@@ -19,4 +19,8 @@ public class ColumnSchema {
private String name; private String name;
private String expr;
private String unit;
} }

View File

@@ -83,6 +83,7 @@ public class PrestoAdaptor extends BaseDbAdaptor {
@Override @Override
public String rewriteSql(String sql) { public String rewriteSql(String sql) {
sql = sql.replaceAll("`", "\"");
return sql; return sql;
} }
} }

View File

@@ -100,6 +100,7 @@ public class SemanticSchemaManager {
modelDetail.getIdentifiers().addAll(getIdentify(d.getIdentifiers())); modelDetail.getIdentifiers().addAll(getIdentify(d.getIdentifiers()));
modelDetail.getMeasures().addAll(getMeasureParams(d.getMeasures())); modelDetail.getMeasures().addAll(getMeasureParams(d.getMeasures()));
modelDetail.getDimensions().addAll(getDimensions(d.getDimensions())); modelDetail.getDimensions().addAll(getDimensions(d.getDimensions()));
modelDetail.getFields().addAll(d.getFields());
return dataModel; return dataModel;
} }

View File

@@ -75,6 +75,7 @@ public class LLMSemanticModeller implements SemanticModeller {
if (!chatApp.isPresent() || !chatApp.get().isEnable()) { if (!chatApp.isPresent() || !chatApp.get().isEnable()) {
return; return;
} }
List<DbSchema> otherDbSchema = getOtherDbSchema(dbSchema, dbSchemas); List<DbSchema> otherDbSchema = getOtherDbSchema(dbSchema, dbSchemas);
ModelSchemaExtractor extractor = ModelSchemaExtractor extractor =
AiServices.create(ModelSchemaExtractor.class, getChatModel(modelBuildReq)); AiServices.create(ModelSchemaExtractor.class, getChatModel(modelBuildReq));

View File

@@ -1,9 +1,9 @@
package com.tencent.supersonic.headless.server.modeller; package com.tencent.supersonic.headless.server.modeller;
import com.tencent.supersonic.headless.api.pojo.ColumnSchema;
import com.tencent.supersonic.headless.api.pojo.DBColumn; import com.tencent.supersonic.headless.api.pojo.DBColumn;
import com.tencent.supersonic.headless.api.pojo.DbSchema; import com.tencent.supersonic.headless.api.pojo.DbSchema;
import com.tencent.supersonic.headless.api.pojo.ModelSchema; import com.tencent.supersonic.headless.api.pojo.ModelSchema;
import com.tencent.supersonic.headless.api.pojo.SemanticColumn;
import com.tencent.supersonic.headless.api.pojo.request.ModelBuildReq; import com.tencent.supersonic.headless.api.pojo.request.ModelBuildReq;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -16,19 +16,20 @@ public class RuleSemanticModeller implements SemanticModeller {
@Override @Override
public void build(DbSchema dbSchema, List<DbSchema> dbSchemas, ModelSchema modelSchema, public void build(DbSchema dbSchema, List<DbSchema> dbSchemas, ModelSchema modelSchema,
ModelBuildReq modelBuildReq) { ModelBuildReq modelBuildReq) {
List<ColumnSchema> columnSchemas = List<SemanticColumn> semanticColumns =
dbSchema.getDbColumns().stream().map(this::convert).collect(Collectors.toList()); dbSchema.getDbColumns().stream().map(this::convert).collect(Collectors.toList());
modelSchema.setColumnSchemas(columnSchemas); modelSchema.setSemanticColumns(semanticColumns);
} }
private ColumnSchema convert(DBColumn dbColumn) { private SemanticColumn convert(DBColumn dbColumn) {
ColumnSchema columnSchema = new ColumnSchema(); SemanticColumn semanticColumn = new SemanticColumn();
columnSchema.setName(dbColumn.getColumnName()); semanticColumn.setName(dbColumn.getColumnName());
columnSchema.setColumnName(dbColumn.getColumnName()); semanticColumn.setColumnName(dbColumn.getColumnName());
columnSchema.setComment(dbColumn.getComment()); semanticColumn.setExpr(dbColumn.getColumnName());
columnSchema.setDataType(dbColumn.getDataType()); semanticColumn.setComment(dbColumn.getComment());
columnSchema.setFiledType(dbColumn.getFieldType()); semanticColumn.setDataType(dbColumn.getDataType());
return columnSchema; semanticColumn.setFiledType(dbColumn.getFieldType());
return semanticColumn;
} }
} }

View File

@@ -7,6 +7,9 @@ import com.tencent.supersonic.headless.api.pojo.request.ModelBuildReq;
import java.util.List; import java.util.List;
/**
* A semantic modeler builds semantic-layer schemas from database-layer schemas.
*/
public interface SemanticModeller { public interface SemanticModeller {
void build(DbSchema dbSchema, List<DbSchema> otherDbSchema, ModelSchema modelSchema, void build(DbSchema dbSchema, List<DbSchema> otherDbSchema, ModelSchema modelSchema,

View File

@@ -277,8 +277,8 @@ public class ModelServiceImpl implements ModelService {
dimensionService.createDimensionBatch(dimensionReqs, user); dimensionService.createDimensionBatch(dimensionReqs, user);
} }
private void batchCreateMetric(ModelDO datasourceDO, User user) throws Exception { private void batchCreateMetric(ModelDO modelDO, User user) throws Exception {
List<MetricReq> metricReqs = ModelConverter.convertMetricList(datasourceDO); List<MetricReq> metricReqs = ModelConverter.convertMetricList(modelDO);
metricService.createMetricBatch(metricReqs, user); metricService.createMetricBatch(metricReqs, user);
} }

View File

@@ -425,8 +425,12 @@ public class DictUtils {
.format(DateTimeFormatter.ofPattern(format)); .format(DateTimeFormatter.ofPattern(format));
String end = LocalDate.now().minusDays(itemValueDateEnd) String end = LocalDate.now().minusDays(itemValueDateEnd)
.format(DateTimeFormatter.ofPattern(format)); .format(DateTimeFormatter.ofPattern(format));
return String.format("( %s >= '%s' and %s <= '%s' )", dateConf.getDateField(), start, if (Objects.nonNull(dateConf)) {
dateConf.getDateField(), end); return String.format("( %s >= '%s' and %s <= '%s' )", dateConf.getDateField(), start,
dateConf.getDateField(), end);
} else {
return String.format("( %s >= '%s' and %s <= '%s' )", "dt", start, "dt", end);
}
} }
private String generateDictDateFilter(DictItemResp dictItemResp) { private String generateDictDateFilter(DictItemResp dictItemResp) {
@@ -440,7 +444,7 @@ public class DictUtils {
} }
// 未进行设置 // 未进行设置
if (Objects.isNull(config) || Objects.isNull(config.getDateConf())) { if (Objects.isNull(config) || Objects.isNull(config.getDateConf())) {
return defaultDateFilter(config.getDateConf()); return defaultDateFilter(null);
} }
// 全表扫描 // 全表扫描
if (DateConf.DateMode.ALL.equals(config.getDateConf().getDateMode())) { if (DateConf.DateMode.ALL.equals(config.getDateConf().getDateMode())) {

View File

@@ -157,23 +157,28 @@ public class ModelConverter {
modelDetail.setQueryType(ModelDefineType.TABLE_QUERY.getName()); modelDetail.setQueryType(ModelDefineType.TABLE_QUERY.getName());
modelDetail.setTableQuery(String.format("%s.%s", modelBuildReq.getDb(), tableName)); modelDetail.setTableQuery(String.format("%s.%s", modelBuildReq.getDb(), tableName));
} }
for (ColumnSchema columnSchema : modelSchema.getColumnSchemas()) { List<Field> fields = new ArrayList<>();
FieldType fieldType = columnSchema.getFiledType(); for (SemanticColumn semanticColumn : modelSchema.getSemanticColumns()) {
FieldType fieldType = semanticColumn.getFiledType();
fields.add(new Field(semanticColumn.getName(), semanticColumn.getDataType()));
if (getIdentifyType(fieldType) != null) { if (getIdentifyType(fieldType) != null) {
Identify identify = new Identify(columnSchema.getName(), Identify identify = new Identify(semanticColumn.getName(),
getIdentifyType(fieldType).name(), columnSchema.getColumnName(), 1); getIdentifyType(fieldType).name(), semanticColumn.getColumnName(), 1);
modelDetail.getIdentifiers().add(identify); modelDetail.getIdentifiers().add(identify);
} else if (FieldType.measure.equals(fieldType)) { } else if (FieldType.measure.equals(fieldType)) {
Measure measure = new Measure(columnSchema.getName(), columnSchema.getColumnName(), Measure measure = new Measure(semanticColumn.getName(),
columnSchema.getColumnName(), columnSchema.getAgg().getOperator(), 1); semanticColumn.getColumnName(), semanticColumn.getExpr(),
semanticColumn.getAgg().getOperator(), semanticColumn.getUnit(), 1);
modelDetail.getMeasures().add(measure); modelDetail.getMeasures().add(measure);
} else { } else {
Dimension dim = new Dimension(columnSchema.getName(), columnSchema.getColumnName(), Dimension dim = new Dimension(semanticColumn.getName(),
columnSchema.getColumnName(), semanticColumn.getColumnName(), semanticColumn.getExpr(),
DimensionType.valueOf(columnSchema.getFiledType().name()), 1); DimensionType.valueOf(semanticColumn.getFiledType().name()), 1);
modelDetail.getDimensions().add(dim); modelDetail.getDimensions().add(dim);
} }
} }
modelDetail.setFields(fields);
modelReq.setModelDetail(modelDetail); modelReq.setModelDetail(modelDetail);
return modelReq; return modelReq;
} }

View File

@@ -410,4 +410,7 @@ ALTER TABLE s2_query_stat_info RENAME COLUMN `sql` TO `query_sql`;
--20250224 --20250224
ALTER TABLE s2_agent add column `admin_org` varchar(3000) DEFAULT NULL COMMENT '管理员组织'; ALTER TABLE s2_agent add column `admin_org` varchar(3000) DEFAULT NULL COMMENT '管理员组织';
ALTER TABLE s2_agent add column `view_org` varchar(3000) DEFAULT NULL COMMENT '可用组织'; ALTER TABLE s2_agent add column `view_org` varchar(3000) DEFAULT NULL COMMENT '可用组织';
ALTER TABLE s2_agent add column `is_open` tinyint DEFAULT NULL COMMENT '是否公开'; ALTER TABLE s2_agent add column `is_open` tinyint DEFAULT NULL COMMENT '是否公开';
--20250309
ALTER TABLE s2_model_rela alter column join_condition type text;

View File

@@ -268,7 +268,7 @@ CREATE TABLE IF NOT EXISTS s2_model_rela
from_model_id BIGINT, from_model_id BIGINT,
to_model_id BIGINT, to_model_id BIGINT,
join_type VARCHAR(255), join_type VARCHAR(255),
join_condition VARCHAR(255), join_condition TEXT,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
); );

View File

@@ -404,7 +404,7 @@ CREATE TABLE IF NOT EXISTS s2_model_rela
from_model_id bigint, from_model_id bigint,
to_model_id bigint, to_model_id bigint,
join_type VARCHAR(255), join_type VARCHAR(255),
join_condition VARCHAR(255) join_condition text
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; )ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `s2_collect` ( CREATE TABLE IF NOT EXISTS `s2_collect` (

View File

@@ -465,7 +465,7 @@ CREATE TABLE IF NOT EXISTS s2_model_rela (
from_model_id bigint, from_model_id bigint,
to_model_id bigint, to_model_id bigint,
join_type VARCHAR(255), join_type VARCHAR(255),
join_condition VARCHAR(255) join_condition text
); );
CREATE TABLE IF NOT EXISTS s2_collect ( CREATE TABLE IF NOT EXISTS s2_collect (

View File

@@ -39,14 +39,14 @@ public class SemanticModellerTest extends BaseTest {
Map<String, ModelSchema> modelSchemaMap = modelService.buildModelSchema(modelSchemaReq); Map<String, ModelSchema> modelSchemaMap = modelService.buildModelSchema(modelSchemaReq);
ModelSchema userModelSchema = modelSchemaMap.get("s2_user_department"); ModelSchema userModelSchema = modelSchemaMap.get("s2_user_department");
Assertions.assertEquals(2, userModelSchema.getColumnSchemas().size()); Assertions.assertEquals(2, userModelSchema.getSemanticColumns().size());
Assertions.assertEquals(FieldType.primary_key, Assertions.assertEquals(FieldType.primary_key,
userModelSchema.getColumnByName("user_name").getFiledType()); userModelSchema.getColumnByName("user_name").getFiledType());
Assertions.assertEquals(FieldType.categorical, Assertions.assertEquals(FieldType.categorical,
userModelSchema.getColumnByName("department").getFiledType()); userModelSchema.getColumnByName("department").getFiledType());
ModelSchema stayTimeModelSchema = modelSchemaMap.get("s2_stay_time_statis"); ModelSchema stayTimeModelSchema = modelSchemaMap.get("s2_stay_time_statis");
Assertions.assertEquals(4, stayTimeModelSchema.getColumnSchemas().size()); Assertions.assertEquals(4, stayTimeModelSchema.getSemanticColumns().size());
Assertions.assertEquals(FieldType.foreign_key, Assertions.assertEquals(FieldType.foreign_key,
stayTimeModelSchema.getColumnByName("user_name").getFiledType()); stayTimeModelSchema.getColumnByName("user_name").getFiledType());
Assertions.assertEquals(FieldType.partition_time, Assertions.assertEquals(FieldType.partition_time,
@@ -72,7 +72,7 @@ public class SemanticModellerTest extends BaseTest {
Map<String, ModelSchema> modelSchemaMap = modelService.buildModelSchema(modelSchemaReq); Map<String, ModelSchema> modelSchemaMap = modelService.buildModelSchema(modelSchemaReq);
ModelSchema pvModelSchema = modelSchemaMap.values().iterator().next(); ModelSchema pvModelSchema = modelSchemaMap.values().iterator().next();
Assertions.assertEquals(5, pvModelSchema.getColumnSchemas().size()); Assertions.assertEquals(5, pvModelSchema.getSemanticColumns().size());
Assertions.assertEquals(FieldType.partition_time, Assertions.assertEquals(FieldType.partition_time,
pvModelSchema.getColumnByName("imp_date").getFiledType()); pvModelSchema.getColumnByName("imp_date").getFiledType());
Assertions.assertEquals(FieldType.categorical, Assertions.assertEquals(FieldType.categorical,

View File

@@ -32,7 +32,7 @@
<maven.compiler.source>21</maven.compiler.source> <maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target> <maven.compiler.target>21</maven.compiler.target>
<file.encoding>UTF-8</file.encoding> <file.encoding>UTF-8</file.encoding>
<jsqlparser.version>4.7</jsqlparser.version> <jsqlparser.version>4.9</jsqlparser.version>
<pagehelper.version>6.1.0</pagehelper.version> <pagehelper.version>6.1.0</pagehelper.version>
<pagehelper.spring.version>2.1.0</pagehelper.spring.version> <pagehelper.spring.version>2.1.0</pagehelper.spring.version>
<mybatis.version>3.5.3</mybatis.version> <mybatis.version>3.5.3</mybatis.version>