mirror of
https://github.com/tencentmusic/supersonic.git
synced 2026-04-28 20:04:27 +08:00
Merge remote-tracking branch 'origin/master' into jsqlparser-fix
This commit is contained in:
@@ -55,8 +55,8 @@ if "%command%"=="restart" (
|
|||||||
set "webDir=%baseDir%\webapp"
|
set "webDir=%baseDir%\webapp"
|
||||||
set "logDir=%baseDir%\logs"
|
set "logDir=%baseDir%\logs"
|
||||||
set "classpath=%baseDir%;%webDir%;%libDir%\*;%confDir%"
|
set "classpath=%baseDir%;%webDir%;%libDir%\*;%confDir%"
|
||||||
set "java-command=-Dfile.encoding=UTF-8 -Duser.language=Zh -Duser.region=CN -Duser.timezone=GMT+08 -Dspring.profiles.active=%profile% -Xms1024m
|
set "property=-Dfile.encoding=UTF-8 -Duser.language=Zh -Duser.region=CN -Duser.timezone=GMT+08 -Dspring.profiles.active=%profile%"
|
||||||
-Xmx1024m -cp %CLASSPATH% %MAIN_CLASS%"
|
set "java-command=%property% -Xms1024m -Xmx1024m -cp %CLASSPATH% %MAIN_CLASS%"
|
||||||
if not exist %logDir% mkdir %logDir%
|
if not exist %logDir% mkdir %logDir%
|
||||||
start /B java %java-command% >nul 2>&1
|
start /B java %java-command% >nul 2>&1
|
||||||
timeout /t 10 >nul
|
timeout /t 10 >nul
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.tencent.supersonic.auth.authentication.interceptor;
|
package com.tencent.supersonic.auth.authentication.interceptor;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
||||||
import com.tencent.supersonic.auth.authentication.service.UserServiceImpl;
|
import com.tencent.supersonic.auth.api.authentication.service.UserService;
|
||||||
import com.tencent.supersonic.auth.authentication.utils.TokenService;
|
import com.tencent.supersonic.auth.authentication.utils.TokenService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -16,7 +16,7 @@ public abstract class AuthenticationInterceptor implements HandlerInterceptor {
|
|||||||
|
|
||||||
protected AuthenticationConfig authenticationConfig;
|
protected AuthenticationConfig authenticationConfig;
|
||||||
|
|
||||||
protected UserServiceImpl userServiceImpl;
|
protected UserService userService;
|
||||||
|
|
||||||
protected TokenService tokenService;
|
protected TokenService tokenService;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package com.tencent.supersonic.auth.authentication.interceptor;
|
|||||||
import com.tencent.supersonic.auth.api.authentication.annotation.AuthenticationIgnore;
|
import com.tencent.supersonic.auth.api.authentication.annotation.AuthenticationIgnore;
|
||||||
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
||||||
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
|
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
|
||||||
import com.tencent.supersonic.auth.authentication.service.UserServiceImpl;
|
import com.tencent.supersonic.auth.api.authentication.service.UserService;
|
||||||
import com.tencent.supersonic.auth.authentication.utils.TokenService;
|
import com.tencent.supersonic.auth.authentication.utils.TokenService;
|
||||||
import com.tencent.supersonic.common.pojo.exception.AccessException;
|
import com.tencent.supersonic.common.pojo.exception.AccessException;
|
||||||
import com.tencent.supersonic.common.util.ContextUtils;
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
@@ -16,12 +16,7 @@ import org.springframework.web.method.HandlerMethod;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_IS_ADMIN;
|
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.*;
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_DISPLAY_NAME;
|
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_EMAIL;
|
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_ID;
|
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_NAME;
|
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_PASSWORD;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor {
|
public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor {
|
||||||
@@ -30,7 +25,7 @@ public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor
|
|||||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
||||||
Object handler) throws AccessException {
|
Object handler) throws AccessException {
|
||||||
authenticationConfig = ContextUtils.getBean(AuthenticationConfig.class);
|
authenticationConfig = ContextUtils.getBean(AuthenticationConfig.class);
|
||||||
userServiceImpl = ContextUtils.getBean(UserServiceImpl.class);
|
userService = ContextUtils.getBean(UserService.class);
|
||||||
tokenService = ContextUtils.getBean(TokenService.class);
|
tokenService = ContextUtils.getBean(TokenService.class);
|
||||||
if (!authenticationConfig.isEnabled()) {
|
if (!authenticationConfig.isEnabled()) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -4,10 +4,13 @@ import com.google.common.base.Objects;
|
|||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
import static com.tencent.supersonic.common.pojo.Constants.ASC_UPPER;
|
import static com.tencent.supersonic.common.pojo.Constants.ASC_UPPER;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class Order {
|
public class Order implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@NotBlank(message = "Invalid order column")
|
@NotBlank(message = "Invalid order column")
|
||||||
private String column;
|
private String column;
|
||||||
|
|||||||
@@ -1,25 +1,15 @@
|
|||||||
# Use an official OpenJDK runtime as a parent image
|
FROM supersonicbi/supersonic:0.9.10-SNAPSHOT
|
||||||
FROM openjdk:21-jdk-bullseye
|
|
||||||
|
|
||||||
# Set the working directory in the container
|
# Set the working directory in the container
|
||||||
WORKDIR /usr/src/app
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
# Delete old supersonic installation directory and the symbolic link
|
||||||
|
RUN rm -rf /usr/src/app/supersonic-standalone-0.9.10-SNAPSHOT
|
||||||
|
RUN rm -f /usr/src/app/supersonic-standalone-latest
|
||||||
|
|
||||||
# Argument to pass in the supersonic version at build time
|
# Argument to pass in the supersonic version at build time
|
||||||
ARG SUPERSONIC_VERSION
|
ARG SUPERSONIC_VERSION
|
||||||
|
|
||||||
# Install necessary packages, including Postgres client
|
|
||||||
RUN apt-get update && apt-get install -y postgresql-client
|
|
||||||
|
|
||||||
# Install the vim editor.
|
|
||||||
RUN apt-get update && apt-get install -y vim && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Update the package list and install iputils-ping.
|
|
||||||
RUN apt-get update && apt-get install -y iputils-ping
|
|
||||||
|
|
||||||
# 更新包列表并安装 dnsutils 包
|
|
||||||
RUN apt-get update && apt-get install -y dnsutils
|
|
||||||
|
|
||||||
# Copy the supersonic standalone zip file into the container
|
# Copy the supersonic standalone zip file into the container
|
||||||
COPY assembly/build/supersonic-standalone-${SUPERSONIC_VERSION}.zip .
|
COPY assembly/build/supersonic-standalone-${SUPERSONIC_VERSION}.zip .
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "15432:5432"
|
- "15432:5432"
|
||||||
# volumes:
|
# volumes:
|
||||||
# - postgres_data:/var/lib/postgresql
|
# - postgres_data:/var/lib/postgresql/data
|
||||||
networks:
|
networks:
|
||||||
- supersonic_network
|
- supersonic_network
|
||||||
dns:
|
dns:
|
||||||
@@ -21,7 +21,7 @@ services:
|
|||||||
- 8.8.4.4
|
- 8.8.4.4
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "sh -c 'pg_isready -U supersonic_user -d postgres'"]
|
test: ["CMD-SHELL", "sh -c 'pg_isready -U supersonic_user -d postgres'"]
|
||||||
interval: 30s
|
interval: 10s
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
|
||||||
@@ -62,4 +62,4 @@ services:
|
|||||||
# supersonic_data:
|
# supersonic_data:
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
supersonic_network:
|
supersonic_network:
|
||||||
|
|||||||
@@ -133,6 +133,10 @@
|
|||||||
<groupId>io.trino</groupId>
|
<groupId>io.trino</groupId>
|
||||||
<artifactId>trino-jdbc</artifactId>
|
<artifactId>trino-jdbc</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jgrapht</groupId>
|
||||||
|
<artifactId>jgrapht-core</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.tencent.supersonic.headless.core.translator;
|
package com.tencent.supersonic.headless.core.translator;
|
||||||
|
|
||||||
import com.tencent.supersonic.common.calcite.SqlMergeWithUtils;
|
import com.tencent.supersonic.common.calcite.SqlMergeWithUtils;
|
||||||
|
import com.tencent.supersonic.common.jsqlparser.SqlSelectHelper;
|
||||||
import com.tencent.supersonic.common.pojo.enums.EngineType;
|
import com.tencent.supersonic.common.pojo.enums.EngineType;
|
||||||
import com.tencent.supersonic.headless.api.pojo.response.QueryState;
|
import com.tencent.supersonic.headless.api.pojo.response.QueryState;
|
||||||
import com.tencent.supersonic.headless.core.pojo.OntologyQuery;
|
import com.tencent.supersonic.headless.core.pojo.OntologyQuery;
|
||||||
@@ -73,7 +74,7 @@ public class DefaultSemanticTranslator implements SemanticTranslator {
|
|||||||
String finalSql = null;
|
String finalSql = null;
|
||||||
if (sqlQuery.isSupportWith()) {
|
if (sqlQuery.isSupportWith()) {
|
||||||
EngineType engineType = queryStatement.getOntology().getDatabaseType();
|
EngineType engineType = queryStatement.getOntology().getDatabaseType();
|
||||||
if (!SqlMergeWithUtils.hasWith(engineType, ontologyOuterSql)) {
|
if (!SqlSelectHelper.hasWith(ontologyOuterSql)) {
|
||||||
finalSql = "with " + tables.stream()
|
finalSql = "with " + tables.stream()
|
||||||
.map(t -> String.format("%s as (%s)", t.getLeft(), t.getRight()))
|
.map(t -> String.format("%s as (%s)", t.getLeft(), t.getRight()))
|
||||||
.collect(Collectors.joining(",")) + "\n" + ontologyOuterSql;
|
.collect(Collectors.joining(",")) + "\n" + ontologyOuterSql;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.tencent.supersonic.headless.core.translator.parser.calcite;
|
package com.tencent.supersonic.headless.core.translator.parser.calcite;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import com.tencent.supersonic.common.calcite.Configuration;
|
import com.tencent.supersonic.common.calcite.Configuration;
|
||||||
import com.tencent.supersonic.common.pojo.enums.EngineType;
|
import com.tencent.supersonic.common.pojo.enums.EngineType;
|
||||||
import com.tencent.supersonic.headless.api.pojo.Dimension;
|
import com.tencent.supersonic.headless.api.pojo.Dimension;
|
||||||
@@ -9,17 +10,26 @@ import com.tencent.supersonic.headless.api.pojo.response.DatabaseResp;
|
|||||||
import com.tencent.supersonic.headless.api.pojo.response.DimSchemaResp;
|
import com.tencent.supersonic.headless.api.pojo.response.DimSchemaResp;
|
||||||
import com.tencent.supersonic.headless.api.pojo.response.MetricSchemaResp;
|
import com.tencent.supersonic.headless.api.pojo.response.MetricSchemaResp;
|
||||||
import com.tencent.supersonic.headless.api.pojo.response.ModelResp;
|
import com.tencent.supersonic.headless.api.pojo.response.ModelResp;
|
||||||
import com.tencent.supersonic.headless.core.pojo.*;
|
import com.tencent.supersonic.headless.core.pojo.JoinRelation;
|
||||||
|
import com.tencent.supersonic.headless.core.pojo.Ontology;
|
||||||
|
import com.tencent.supersonic.headless.core.pojo.OntologyQuery;
|
||||||
|
import com.tencent.supersonic.headless.core.pojo.QueryStatement;
|
||||||
import com.tencent.supersonic.headless.core.translator.parser.Constants;
|
import com.tencent.supersonic.headless.core.translator.parser.Constants;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.calcite.sql.*;
|
import org.apache.calcite.sql.*;
|
||||||
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
|
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
|
||||||
|
import org.apache.calcite.sql.parser.SqlParseException;
|
||||||
import org.apache.calcite.sql.parser.SqlParser;
|
import org.apache.calcite.sql.parser.SqlParser;
|
||||||
import org.apache.calcite.sql.parser.SqlParserPos;
|
import org.apache.calcite.sql.parser.SqlParserPos;
|
||||||
import org.apache.calcite.sql.validate.SqlValidatorScope;
|
import org.apache.calcite.sql.validate.SqlValidatorScope;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Triple;
|
import org.apache.commons.lang3.tuple.Triple;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.jgrapht.Graph;
|
||||||
|
import org.jgrapht.GraphPath;
|
||||||
|
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
|
||||||
|
import org.jgrapht.graph.DefaultEdge;
|
||||||
|
import org.jgrapht.graph.DefaultUndirectedGraph;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -37,6 +47,8 @@ public class SqlBuilder {
|
|||||||
|
|
||||||
public String buildOntologySql(QueryStatement queryStatement) throws Exception {
|
public String buildOntologySql(QueryStatement queryStatement) throws Exception {
|
||||||
OntologyQuery ontologyQuery = queryStatement.getOntologyQuery();
|
OntologyQuery ontologyQuery = queryStatement.getOntologyQuery();
|
||||||
|
Ontology ontology = queryStatement.getOntology();
|
||||||
|
|
||||||
if (ontologyQuery.getLimit() == null) {
|
if (ontologyQuery.getLimit() == null) {
|
||||||
ontologyQuery.setLimit(0L);
|
ontologyQuery.setLimit(0L);
|
||||||
}
|
}
|
||||||
@@ -46,7 +58,14 @@ public class SqlBuilder {
|
|||||||
throw new Exception("data model not found");
|
throw new Exception("data model not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
TableView tableView = render(ontologyQuery, new ArrayList<>(dataModels), scope, schema);
|
TableView tableView;
|
||||||
|
if (!CollectionUtils.isEmpty(ontology.getJoinRelations()) && dataModels.size() > 1) {
|
||||||
|
Set<ModelResp> models = probeRelatedModels(dataModels, queryStatement.getOntology());
|
||||||
|
tableView = render(ontologyQuery, models, scope, schema);
|
||||||
|
} else {
|
||||||
|
tableView = render(ontologyQuery, dataModels, scope, schema);
|
||||||
|
}
|
||||||
|
|
||||||
SqlNode parserNode = tableView.build();
|
SqlNode parserNode = tableView.build();
|
||||||
DatabaseResp database = queryStatement.getOntology().getDatabase();
|
DatabaseResp database = queryStatement.getOntology().getDatabase();
|
||||||
EngineType engineType = EngineType.fromString(database.getType());
|
EngineType engineType = EngineType.fromString(database.getType());
|
||||||
@@ -54,7 +73,61 @@ public class SqlBuilder {
|
|||||||
return SemanticNode.getSql(parserNode, engineType);
|
return SemanticNode.getSql(parserNode, engineType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SqlNode optimizeParseNode(SqlNode parserNode, EngineType engineType) {
|
private Set<ModelResp> probeRelatedModels(Set<ModelResp> dataModels, Ontology ontology) {
|
||||||
|
List<JoinRelation> joinRelations = ontology.getJoinRelations();
|
||||||
|
Graph<String, DefaultEdge> graph = buildGraph(joinRelations);
|
||||||
|
DijkstraShortestPath<String, DefaultEdge> dijkstraAlg = new DijkstraShortestPath<>(graph);
|
||||||
|
Set<String> queryModels =
|
||||||
|
dataModels.stream().map(ModelResp::getName).collect(Collectors.toSet());
|
||||||
|
GraphPath<String, DefaultEdge> selectedGraphPath = null;
|
||||||
|
for (String fromModel : queryModels) {
|
||||||
|
for (String toModel : queryModels) {
|
||||||
|
if (fromModel != toModel) {
|
||||||
|
GraphPath<String, DefaultEdge> path = dijkstraAlg.getPath(fromModel, toModel);
|
||||||
|
if (isGraphPathContainsAll(path, queryModels)) {
|
||||||
|
selectedGraphPath = path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selectedGraphPath == null) {
|
||||||
|
return dataModels;
|
||||||
|
}
|
||||||
|
Set<String> modelNames = Sets.newHashSet();
|
||||||
|
for (DefaultEdge edge : selectedGraphPath.getEdgeList()) {
|
||||||
|
modelNames.add(selectedGraphPath.getGraph().getEdgeSource(edge));
|
||||||
|
modelNames.add(selectedGraphPath.getGraph().getEdgeTarget(edge));
|
||||||
|
}
|
||||||
|
return modelNames.stream().map(m -> ontology.getModelMap().get(m))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isGraphPathContainsAll(GraphPath<String, DefaultEdge> graphPath,
|
||||||
|
Set<String> vertex) {
|
||||||
|
Set<String> allVertex = Sets.newHashSet();
|
||||||
|
for (DefaultEdge edge : graphPath.getEdgeList()) {
|
||||||
|
allVertex.add(graphPath.getGraph().getEdgeSource(edge));
|
||||||
|
allVertex.add(graphPath.getGraph().getEdgeTarget(edge));
|
||||||
|
}
|
||||||
|
Collection<String> intersect =
|
||||||
|
org.apache.commons.collections.CollectionUtils.intersection(vertex, allVertex);
|
||||||
|
|
||||||
|
return intersect.size() == vertex.size() ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Graph<String, DefaultEdge> buildGraph(List<JoinRelation> joinRelations) {
|
||||||
|
Graph<String, DefaultEdge> directedGraph = new DefaultUndirectedGraph<>(DefaultEdge.class);
|
||||||
|
for (JoinRelation joinRelation : joinRelations) {
|
||||||
|
directedGraph.addVertex(joinRelation.getLeft());
|
||||||
|
directedGraph.addVertex(joinRelation.getRight());
|
||||||
|
directedGraph.addEdge(joinRelation.getLeft(), joinRelation.getRight());
|
||||||
|
}
|
||||||
|
return directedGraph;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqlNode optimizeParseNode(SqlNode parserNode, EngineType engineType)
|
||||||
|
throws SqlParseException {
|
||||||
if (Objects.isNull(schema.getRuntimeOptions())
|
if (Objects.isNull(schema.getRuntimeOptions())
|
||||||
|| Objects.isNull(schema.getRuntimeOptions().getEnableOptimize())
|
|| Objects.isNull(schema.getRuntimeOptions().getEnableOptimize())
|
||||||
|| !schema.getRuntimeOptions().getEnableOptimize()) {
|
|| !schema.getRuntimeOptions().getEnableOptimize()) {
|
||||||
@@ -62,14 +135,10 @@ public class SqlBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SqlNode optimizeNode = null;
|
SqlNode optimizeNode = null;
|
||||||
try {
|
SqlNode sqlNode = SqlParser.create(SemanticNode.getSql(parserNode, engineType),
|
||||||
SqlNode sqlNode = SqlParser.create(SemanticNode.getSql(parserNode, engineType),
|
Configuration.getParserConfig(engineType)).parseStmt();
|
||||||
Configuration.getParserConfig(engineType)).parseStmt();
|
if (Objects.nonNull(sqlNode)) {
|
||||||
if (Objects.nonNull(sqlNode)) {
|
optimizeNode = SemanticNode.optimize(scope, schema, sqlNode, engineType);
|
||||||
optimizeNode = SemanticNode.optimize(scope, schema, sqlNode, engineType);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("optimize error {}", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Objects.nonNull(optimizeNode)) {
|
if (Objects.nonNull(optimizeNode)) {
|
||||||
@@ -79,7 +148,7 @@ public class SqlBuilder {
|
|||||||
return parserNode;
|
return parserNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TableView render(OntologyQuery ontologyQuery, List<ModelResp> dataModels,
|
private TableView render(OntologyQuery ontologyQuery, Set<ModelResp> dataModels,
|
||||||
SqlValidatorScope scope, S2CalciteSchema schema) throws Exception {
|
SqlValidatorScope scope, S2CalciteSchema schema) throws Exception {
|
||||||
SqlNode left = null;
|
SqlNode left = null;
|
||||||
TableView leftTable = null;
|
TableView leftTable = null;
|
||||||
@@ -88,8 +157,7 @@ public class SqlBuilder {
|
|||||||
Map<String, String> beforeModels = new HashMap<>();
|
Map<String, String> beforeModels = new HashMap<>();
|
||||||
EngineType engineType = EngineType.fromString(schema.getOntology().getDatabase().getType());
|
EngineType engineType = EngineType.fromString(schema.getOntology().getDatabase().getType());
|
||||||
|
|
||||||
for (int i = 0; i < dataModels.size(); i++) {
|
for (ModelResp dataModel : dataModels) {
|
||||||
final ModelResp dataModel = dataModels.get(i);
|
|
||||||
final Set<DimSchemaResp> queryDimensions =
|
final Set<DimSchemaResp> queryDimensions =
|
||||||
ontologyQuery.getDimensionsByModel(dataModel.getName());
|
ontologyQuery.getDimensionsByModel(dataModel.getName());
|
||||||
final Set<MetricSchemaResp> queryMetrics =
|
final Set<MetricSchemaResp> queryMetrics =
|
||||||
@@ -141,7 +209,8 @@ public class SqlBuilder {
|
|||||||
SqlLiteral sqlLiteral = SemanticNode.getJoinSqlLiteral("");
|
SqlLiteral sqlLiteral = SemanticNode.getJoinSqlLiteral("");
|
||||||
JoinRelation matchJoinRelation = getMatchJoinRelation(before, rightTable, schema);
|
JoinRelation matchJoinRelation = getMatchJoinRelation(before, rightTable, schema);
|
||||||
SqlNode joinRelationCondition;
|
SqlNode joinRelationCondition;
|
||||||
if (!CollectionUtils.isEmpty(matchJoinRelation.getJoinCondition())) {
|
if (!org.apache.commons.collections.CollectionUtils
|
||||||
|
.isEmpty(matchJoinRelation.getJoinCondition())) {
|
||||||
sqlLiteral = SemanticNode.getJoinSqlLiteral(matchJoinRelation.getJoinType());
|
sqlLiteral = SemanticNode.getJoinSqlLiteral(matchJoinRelation.getJoinType());
|
||||||
joinRelationCondition = getCondition(matchJoinRelation, scope, engineType);
|
joinRelationCondition = getCondition(matchJoinRelation, scope, engineType);
|
||||||
condition = joinRelationCondition;
|
condition = joinRelationCondition;
|
||||||
@@ -170,12 +239,19 @@ public class SqlBuilder {
|
|||||||
} else if (joinRelation.getLeft()
|
} else if (joinRelation.getLeft()
|
||||||
.equalsIgnoreCase(tableView.getDataModel().getName())
|
.equalsIgnoreCase(tableView.getDataModel().getName())
|
||||||
&& before.containsKey(joinRelation.getRight())) {
|
&& before.containsKey(joinRelation.getRight())) {
|
||||||
matchJoinRelation.setJoinCondition(joinRelation.getJoinCondition().stream()
|
List<Triple<String, String, String>> candidateJoinCon = joinRelation
|
||||||
|
.getJoinCondition().stream()
|
||||||
.map(r -> Triple.of(
|
.map(r -> Triple.of(
|
||||||
before.get(joinRelation.getRight()) + "." + r.getRight(),
|
before.get(joinRelation.getRight()) + "." + r.getRight(),
|
||||||
r.getMiddle(), tableView.getAlias() + "." + r.getLeft()))
|
r.getMiddle(), tableView.getAlias() + "." + r.getLeft()))
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList());
|
||||||
matchJoinRelation.setJoinType(joinRelation.getJoinType());
|
// added by jerryjzhang on 20250214
|
||||||
|
// use the one with the most conditions to join left and right tables
|
||||||
|
if (matchJoinRelation.getJoinCondition() == null || candidateJoinCon
|
||||||
|
.size() > matchJoinRelation.getJoinCondition().size()) {
|
||||||
|
matchJoinRelation.setJoinCondition(candidateJoinCon);
|
||||||
|
matchJoinRelation.setJoinType(joinRelation.getJoinType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.tencent.supersonic.headless.server.rest;
|
|||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
|
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
|
||||||
import com.tencent.supersonic.common.pojo.User;
|
import com.tencent.supersonic.common.pojo.User;
|
||||||
|
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
|
||||||
import com.tencent.supersonic.headless.api.pojo.MetaFilter;
|
import com.tencent.supersonic.headless.api.pojo.MetaFilter;
|
||||||
import com.tencent.supersonic.headless.api.pojo.request.DataSetReq;
|
import com.tencent.supersonic.headless.api.pojo.request.DataSetReq;
|
||||||
import com.tencent.supersonic.headless.api.pojo.response.DataSetResp;
|
import com.tencent.supersonic.headless.api.pojo.response.DataSetResp;
|
||||||
@@ -51,6 +52,7 @@ public class DataSetController {
|
|||||||
public List<DataSetResp> getDataSetList(@RequestParam("domainId") Long domainId) {
|
public List<DataSetResp> getDataSetList(@RequestParam("domainId") Long domainId) {
|
||||||
MetaFilter metaFilter = new MetaFilter();
|
MetaFilter metaFilter = new MetaFilter();
|
||||||
metaFilter.setDomainId(domainId);
|
metaFilter.setDomainId(domainId);
|
||||||
|
metaFilter.setStatus(StatusEnum.ONLINE.getCode());
|
||||||
return dataSetService.getDataSetList(metaFilter);
|
return dataSetService.getDataSetList(metaFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,9 +56,9 @@ public class DataSetServiceImpl extends ServiceImpl<DataSetDOMapper, DataSetDO>
|
|||||||
public DataSetResp save(DataSetReq dataSetReq, User user) {
|
public DataSetResp save(DataSetReq dataSetReq, User user) {
|
||||||
dataSetReq.createdBy(user.getName());
|
dataSetReq.createdBy(user.getName());
|
||||||
DataSetDO dataSetDO = convert(dataSetReq);
|
DataSetDO dataSetDO = convert(dataSetReq);
|
||||||
dataSetDO.setStatus(StatusEnum.ONLINE.getCode());
|
dataSetDO.setStatus(dataSetReq.getStatus() != null ? dataSetReq.getStatus()
|
||||||
|
: StatusEnum.ONLINE.getCode());
|
||||||
DataSetResp dataSetResp = convert(dataSetDO);
|
DataSetResp dataSetResp = convert(dataSetDO);
|
||||||
// conflictCheck(dataSetResp);
|
|
||||||
save(dataSetDO);
|
save(dataSetDO);
|
||||||
dataSetResp.setId(dataSetDO.getId());
|
dataSetResp.setId(dataSetDO.getId());
|
||||||
return dataSetResp;
|
return dataSetResp;
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ spring:
|
|||||||
url: jdbc:postgresql://${DB_HOST}:${DB_PORT:5432}/${DB_NAME}?stringtype=unspecified
|
url: jdbc:postgresql://${DB_HOST}:${DB_PORT:5432}/${DB_NAME}?stringtype=unspecified
|
||||||
username: ${DB_USERNAME}
|
username: ${DB_USERNAME}
|
||||||
password: ${DB_PASSWORD}
|
password: ${DB_PASSWORD}
|
||||||
|
|
||||||
sql:
|
sql:
|
||||||
init:
|
init:
|
||||||
|
continue-on-error: true
|
||||||
mode: always
|
mode: always
|
||||||
username: ${DB_USERNAME}
|
username: ${DB_USERNAME}
|
||||||
password: ${DB_PASSWORD}
|
password: ${DB_PASSWORD}
|
||||||
|
|||||||
@@ -5,21 +5,21 @@ CREATE TABLE IF NOT EXISTS `s2_agent` (
|
|||||||
`examples` TEXT COLLATE utf8_unicode_ci DEFAULT NULL,
|
`examples` TEXT COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
`status` tinyint DEFAULT NULL,
|
`status` tinyint DEFAULT NULL,
|
||||||
`model` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
`model` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
`tool_config` varchar(6000) COLLATE utf8_unicode_ci DEFAULT NULL,
|
`tool_config` TEXT COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
`llm_config` varchar(2000) COLLATE utf8_unicode_ci DEFAULT NULL,
|
`llm_config` TEXT COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
`chat_model_config` text COLLATE utf8_unicode_ci DEFAULT NULL,
|
`chat_model_config` text COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
`visual_config` varchar(2000) COLLATE utf8_unicode_ci DEFAULT NULL,
|
`visual_config` TEXT COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
`enable_search` tinyint DEFAULT 1,
|
`enable_search` tinyint DEFAULT 1,
|
||||||
`enable_feedback` tinyint DEFAULT 1,
|
`enable_feedback` tinyint DEFAULT 1,
|
||||||
`created_by` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
`created_by` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
`created_at` datetime DEFAULT NULL,
|
`created_at` datetime DEFAULT NULL,
|
||||||
`updated_by` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
`updated_by` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||||
`updated_at` datetime DEFAULT NULL,
|
`updated_at` datetime DEFAULT NULL,
|
||||||
`admin` varchar(3000) DEFAULT NULL COMMENT '管理员',
|
`admin` varchar(1000) DEFAULT NULL COMMENT '管理员',
|
||||||
`admin_org` varchar(3000) DEFAULT NULL COMMENT '管理员组织',
|
`admin_org` varchar(1000) DEFAULT NULL COMMENT '管理员组织',
|
||||||
`is_open` tinyint DEFAULT NULL COMMENT '是否公开',
|
`is_open` tinyint DEFAULT NULL COMMENT '是否公开',
|
||||||
`viewer` varchar(3000) DEFAULT NULL COMMENT '可用用户',
|
`viewer` varchar(1000) DEFAULT NULL COMMENT '可用用户',
|
||||||
`view_org` varchar(3000) DEFAULT NULL COMMENT '可用组织',
|
`view_org` varchar(1000) DEFAULT NULL COMMENT '可用组织',
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||||
|
|
||||||
|
|||||||
8
pom.xml
8
pom.xml
@@ -26,7 +26,7 @@
|
|||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>0.9.10-SNAPSHOT</revision>
|
<revision>1.0.0-SNAPSHOT</revision>
|
||||||
<java.source.version>21</java.source.version>
|
<java.source.version>21</java.source.version>
|
||||||
<java.target.version>21</java.target.version>
|
<java.target.version>21</java.target.version>
|
||||||
<maven.compiler.source>21</maven.compiler.source>
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
@@ -82,6 +82,7 @@
|
|||||||
<spotless.skip>false</spotless.skip>
|
<spotless.skip>false</spotless.skip>
|
||||||
<stax2.version>4.2.1</stax2.version>
|
<stax2.version>4.2.1</stax2.version>
|
||||||
<aws-java-sdk.version>1.12.780</aws-java-sdk.version>
|
<aws-java-sdk.version>1.12.780</aws-java-sdk.version>
|
||||||
|
<jgrapht.version>1.5.2</jgrapht.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
@@ -236,6 +237,11 @@
|
|||||||
<artifactId>aws-java-sdk</artifactId>
|
<artifactId>aws-java-sdk</artifactId>
|
||||||
<version>${aws-java-sdk.version}</version>
|
<version>${aws-java-sdk.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jgrapht</groupId>
|
||||||
|
<artifactId>jgrapht-core</artifactId>
|
||||||
|
<version>${jgrapht.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
|||||||
@@ -155,29 +155,8 @@ export default defineConfig({
|
|||||||
|
|
||||||
//================ pro 插件配置 =================
|
//================ pro 插件配置 =================
|
||||||
presets: ['umi-presets-pro'],
|
presets: ['umi-presets-pro'],
|
||||||
/**
|
|
||||||
* @name openAPI 插件的配置
|
|
||||||
* @description 基于 openapi 的规范生成serve 和mock,能减少很多样板代码
|
|
||||||
* @doc https://pro.ant.design/zh-cn/docs/openapi/
|
|
||||||
*/
|
|
||||||
// openAPI: [
|
|
||||||
// {
|
|
||||||
// requestLibPath: "import { request } from '@umijs/max'",
|
|
||||||
// // 或者使用在线的版本
|
|
||||||
// // schemaPath: "https://gw.alipayobjects.com/os/antfincdn/M%24jrzTTYJN/oneapi.json"
|
|
||||||
// schemaPath: join(__dirname, 'oneapi.json'),
|
|
||||||
// mock: false,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// requestLibPath: "import { request } from '@umijs/max'",
|
|
||||||
// schemaPath: 'https://gw.alipayobjects.com/os/antfincdn/CA1dOm%2631B/openapi.json',
|
|
||||||
// projectName: 'swagger',
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// 将insights-flow相关包排除出mfsu编译,在pnpm link 模式下保持热更新
|
|
||||||
mfsu: {
|
mfsu: {
|
||||||
strategy: 'normal',
|
strategy: 'normal',
|
||||||
// exclude: ['supersonic-insights-flow-components', 'supersonic-insights-flow-core'],
|
|
||||||
},
|
},
|
||||||
requestRecord: {},
|
requestRecord: {},
|
||||||
exportStatic: {},
|
exportStatic: {},
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.0 KiB |
@@ -147,8 +147,8 @@ export const layout: RunTimeLayoutConfig = (params) => {
|
|||||||
height: location.pathname.includes('chat') ? 'calc(100vh - 56px)' : undefined,
|
height: location.pathname.includes('chat') ? 'calc(100vh - 56px)' : undefined,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AppPage dom={dom} />
|
{/* <AppPage dom={dom} /> */}
|
||||||
{/* {dom} */}
|
{dom}
|
||||||
{history.location.pathname !== '/chat' && !isMobile && (
|
{history.location.pathname !== '/chat' && !isMobile && (
|
||||||
<Copilot token={getToken() || ''} isDeveloper />
|
<Copilot token={getToken() || ''} isDeveloper />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
|
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||||
import { Input, message, Popconfirm, Tooltip, Row, Col, Button, Menu } from 'antd';
|
import { Input, message, Popconfirm, Tooltip, Row, Col, Button, Menu, MenuProps } from 'antd';
|
||||||
import type { DataNode } from 'antd/lib/tree';
|
import type { DataNode } from 'antd/lib/tree';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import { useModel } from '@umijs/max';
|
import { useModel, history } from '@umijs/max';
|
||||||
import { createDomain, updateDomain, deleteDomain } from '../service';
|
import { createDomain, updateDomain, deleteDomain } from '../service';
|
||||||
import DomainInfoForm from './DomainInfoForm';
|
import DomainInfoForm from './DomainInfoForm';
|
||||||
import styles from './style.less';
|
import styles from './style.less';
|
||||||
@@ -71,6 +71,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
message.success('编辑分类成功');
|
message.success('编辑分类成功');
|
||||||
setProjectInfoModalVisible(false);
|
setProjectInfoModalVisible(false);
|
||||||
onTreeDataUpdate?.();
|
onTreeDataUpdate?.();
|
||||||
|
window.location.reload();
|
||||||
} else {
|
} else {
|
||||||
message.error(res.msg);
|
message.error(res.msg);
|
||||||
}
|
}
|
||||||
@@ -78,10 +79,13 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
|
|
||||||
const domainSubmit = async (values: any) => {
|
const domainSubmit = async (values: any) => {
|
||||||
if (values.modelType === 'add') {
|
if (values.modelType === 'add') {
|
||||||
const { code, data } = await createDomain(values);
|
const { code, data, msg } = await createDomain(values);
|
||||||
// if (code === 200 && values.type === 'top') {
|
if (code === 200) {
|
||||||
// await createDefaultModelSet(data.id);
|
history.push(`/model/domain/${data.id}`);
|
||||||
// }
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
message.error(msg);
|
||||||
|
}
|
||||||
} else if (values.modelType === 'edit') {
|
} else if (values.modelType === 'edit') {
|
||||||
await editProject(values);
|
await editProject(values);
|
||||||
}
|
}
|
||||||
@@ -95,6 +99,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
message.success('删除成功');
|
message.success('删除成功');
|
||||||
setProjectInfoModalVisible(false);
|
setProjectInfoModalVisible(false);
|
||||||
onTreeDataUpdate?.();
|
onTreeDataUpdate?.();
|
||||||
|
window.location.reload();
|
||||||
} else {
|
} else {
|
||||||
message.error(res.msg);
|
message.error(res.msg);
|
||||||
}
|
}
|
||||||
@@ -104,12 +109,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
const { id, name, path, hasEditPermission, parentId, hasModel } = node as any;
|
const { id, name, path, hasEditPermission, parentId, hasModel } = node as any;
|
||||||
const type = parentId === 0 ? 'top' : 'normal';
|
const type = parentId === 0 ? 'top' : 'normal';
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={styles.projectItem}>
|
||||||
className={styles.projectItem}
|
|
||||||
// onClick={() => {
|
|
||||||
// handleSelect(id);
|
|
||||||
// }}
|
|
||||||
>
|
|
||||||
<span className={styles.projectItemTitle}>{name}</span>
|
<span className={styles.projectItemTitle}>{name}</span>
|
||||||
{createDomainBtnVisible && hasEditPermission && (
|
{createDomainBtnVisible && hasEditPermission && (
|
||||||
<span className={`${styles.operation} ${styles.rowHover} `}>
|
<span className={`${styles.operation} ${styles.rowHover} `}>
|
||||||
@@ -175,13 +175,12 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
return {
|
return {
|
||||||
key: domain.id,
|
key: domain.id,
|
||||||
label: titleRender(domain),
|
label: titleRender(domain),
|
||||||
// icon: <AppstoreOutlined />,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const getLevelKeys = (items1: LevelKeysProps[]) => {
|
const getLevelKeys = (items1: any[]) => {
|
||||||
const key: Record<string, number> = {};
|
const key: Record<string, number> = {};
|
||||||
const func = (items2: LevelKeysProps[], level = 1) => {
|
const func = (items2: any[], level = 1) => {
|
||||||
items2.forEach((item) => {
|
items2.forEach((item) => {
|
||||||
if (item.key) {
|
if (item.key) {
|
||||||
key[item.key] = level;
|
key[item.key] = level;
|
||||||
@@ -194,7 +193,7 @@ const DomainListTree: FC<DomainListProps> = ({
|
|||||||
func(items1);
|
func(items1);
|
||||||
return key;
|
return key;
|
||||||
};
|
};
|
||||||
const levelKeys = getLevelKeys(items as LevelKeysProps[]);
|
const levelKeys = getLevelKeys(items as any[]);
|
||||||
const [stateOpenKeys, setStateOpenKeys] = useState(['2', '23']);
|
const [stateOpenKeys, setStateOpenKeys] = useState(['2', '23']);
|
||||||
|
|
||||||
const onOpenChange: MenuProps['onOpenChange'] = (openKeys) => {
|
const onOpenChange: MenuProps['onOpenChange'] = (openKeys) => {
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ const ModelTable: React.FC<Props> = ({ modelList, disabledEdit = false, onModelC
|
|||||||
});
|
});
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
onModelChange?.();
|
onModelChange?.();
|
||||||
|
window.location.reload();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
message.error(msg);
|
message.error(msg);
|
||||||
@@ -198,6 +199,7 @@ const ModelTable: React.FC<Props> = ({ modelList, disabledEdit = false, onModelC
|
|||||||
const { code, msg } = await deleteModel(record.id);
|
const { code, msg } = await deleteModel(record.id);
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
onModelChange?.();
|
onModelChange?.();
|
||||||
|
window.location.reload();
|
||||||
} else {
|
} else {
|
||||||
message.error(msg);
|
message.error(msg);
|
||||||
}
|
}
|
||||||
@@ -292,6 +294,7 @@ const ModelTable: React.FC<Props> = ({ modelList, disabledEdit = false, onModelC
|
|||||||
onModelChange?.();
|
onModelChange?.();
|
||||||
setIsEditing(false);
|
setIsEditing(false);
|
||||||
setCreateDataSourceModalOpen(false);
|
setCreateDataSourceModalOpen(false);
|
||||||
|
window.location.reload();
|
||||||
}}
|
}}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
setIsEditing(false);
|
setIsEditing(false);
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
import { message } from 'antd';
|
import { message } from 'antd';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { history, useParams, useModel, Outlet } from '@umijs/max';
|
import { useParams, useModel, Outlet } from '@umijs/max';
|
||||||
import DomainListTree from './components/DomainList';
|
|
||||||
import styles from './components/style.less';
|
|
||||||
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
|
|
||||||
import { ISemantic } from './data';
|
import { ISemantic } from './data';
|
||||||
import { getDomainList, getDataSetList, getModelDetail } from './service';
|
import { getDomainList, getModelDetail } from './service';
|
||||||
import PageBreadcrumb from './PageBreadcrumb';
|
import PageBreadcrumb from './PageBreadcrumb';
|
||||||
|
|
||||||
type Props = {};
|
type Props = {};
|
||||||
@@ -17,20 +14,10 @@ const SemanticModel: React.FC<Props> = ({}) => {
|
|||||||
const domainModel = useModel('SemanticModel.domainData');
|
const domainModel = useModel('SemanticModel.domainData');
|
||||||
const modelModel = useModel('SemanticModel.modelData');
|
const modelModel = useModel('SemanticModel.modelData');
|
||||||
const databaseModel = useModel('SemanticModel.databaseData');
|
const databaseModel = useModel('SemanticModel.databaseData');
|
||||||
const metricModel = useModel('SemanticModel.metricData');
|
const { setSelectDomain, setDomainList } = domainModel;
|
||||||
const { setSelectDomain, setDomainList, selectDomainId } = domainModel;
|
const { selectModel, setSelectModel } = modelModel;
|
||||||
const { selectModel, setSelectModel, setModelTableHistoryParams, MrefreshModelList } = modelModel;
|
|
||||||
const { MrefreshDatabaseList } = databaseModel;
|
const { MrefreshDatabaseList } = databaseModel;
|
||||||
|
|
||||||
const { selectMetric, setSelectMetric } = metricModel;
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
|
|
||||||
// return () => {
|
|
||||||
// setSelectMetric(undefined);
|
|
||||||
// }
|
|
||||||
// }, [])
|
|
||||||
|
|
||||||
const initSelectedDomain = (domainList: ISemantic.IDomainItem[]) => {
|
const initSelectedDomain = (domainList: ISemantic.IDomainItem[]) => {
|
||||||
const targetNode = domainList.filter((item: any) => {
|
const targetNode = domainList.filter((item: any) => {
|
||||||
return `${item.id}` === domainId;
|
return `${item.id}` === domainId;
|
||||||
@@ -40,9 +27,7 @@ const SemanticModel: React.FC<Props> = ({}) => {
|
|||||||
return item.parentId === 0;
|
return item.parentId === 0;
|
||||||
})[0];
|
})[0];
|
||||||
if (firstRootNode) {
|
if (firstRootNode) {
|
||||||
const { id } = firstRootNode;
|
|
||||||
setSelectDomain(firstRootNode);
|
setSelectDomain(firstRootNode);
|
||||||
// pushUrlMenu(id, menuKey);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setSelectDomain(targetNode);
|
setSelectDomain(targetNode);
|
||||||
@@ -87,7 +72,6 @@ const SemanticModel: React.FC<Props> = ({}) => {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
{/* <OverviewContainer /> */}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useState, useEffect } from 'react';
|
|||||||
import { useModel } from '@umijs/max';
|
import { useModel } from '@umijs/max';
|
||||||
|
|
||||||
export default function Domain() {
|
export default function Domain() {
|
||||||
const [selectDomain, setSelectDomain] = useState<ISemantic.IDomainItem>(
|
const [selectDomain, setSelectDomain] = useState<ISemantic.IDomainItem | undefined>(
|
||||||
{} as ISemantic.IDomainItem,
|
{} as ISemantic.IDomainItem,
|
||||||
);
|
);
|
||||||
const [selectDataSet, setSelectDataSet] = useState<ISemantic.IDatasetItem>();
|
const [selectDataSet, setSelectDataSet] = useState<ISemantic.IDatasetItem>();
|
||||||
|
|||||||
Reference in New Issue
Block a user