mirror of
https://github.com/tencentmusic/supersonic.git
synced 2026-04-19 13:04:21 +08:00
Compare commits
45 Commits
v0.9.10
...
d2a43a99c8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2a43a99c8 | ||
|
|
db8f340e2d | ||
|
|
2e81b190a4 | ||
|
|
81cd60d2da | ||
|
|
3ffc8c3d9e | ||
|
|
18db24c011 | ||
|
|
cd698ac367 | ||
|
|
58b640b087 | ||
|
|
1f28aaeaed | ||
|
|
35b835172b | ||
|
|
1c85bcecc5 | ||
|
|
c3483ae340 | ||
|
|
a5051c7225 | ||
|
|
12f6cfa42d | ||
|
|
4c94f2b816 | ||
|
|
c81aa5859d | ||
|
|
21e213fb19 | ||
|
|
f67bf3eeac | ||
|
|
9d13038599 | ||
|
|
0c8c2d4804 | ||
|
|
f05a4b523c | ||
|
|
b7369abcca | ||
|
|
b40cb13740 | ||
|
|
6f8cf9853b | ||
|
|
75906037ac | ||
|
|
b58e041e8d | ||
|
|
93d585c0d5 | ||
|
|
0dbf56d357 | ||
|
|
a3293e6788 | ||
|
|
a99f5985f5 | ||
|
|
91243005bc | ||
|
|
a76b5a4300 | ||
|
|
c1f9df963c | ||
|
|
954aa4eea5 | ||
|
|
33bd0de604 | ||
|
|
881d891d70 | ||
|
|
d9db455dab | ||
|
|
e0dc3fbf1a | ||
|
|
efddf4cacf | ||
|
|
732222ab98 | ||
|
|
5b994c4f8f | ||
|
|
5d2ebdf680 | ||
|
|
f1bc18ef65 | ||
|
|
8f361f9932 | ||
|
|
f532088e38 |
2
.github/workflows/centos-ci.yml
vendored
2
.github/workflows/centos-ci.yml
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
mvn -version
|
||||
|
||||
- name: Cache Maven packages
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.m2
|
||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||||
|
||||
2
.github/workflows/mac-ci.yml
vendored
2
.github/workflows/mac-ci.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
distribution: 'adopt'
|
||||
|
||||
- name: Cache Maven packages
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/Library/Caches/Maven # macOS Maven cache path
|
||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||||
|
||||
2
.github/workflows/ubuntu-ci.yml
vendored
2
.github/workflows/ubuntu-ci.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
distribution: 'adopt'
|
||||
|
||||
- name: Cache Maven packages
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.m2
|
||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||||
|
||||
2
.github/workflows/windows-ci.yml
vendored
2
.github/workflows/windows-ci.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
distribution: 'adopt' # You might need to change this if 'adopt' doesn't support JDK 21
|
||||
|
||||
- name: Cache Maven packages
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~\.m2 # Windows uses a backslash for paths
|
||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -14,7 +14,7 @@ code and logo.
|
||||
b. a commercial license must be obtained from the author if you want to develop and distribute a derivative work based
|
||||
on SuperSonic.
|
||||
|
||||
Please contact zhangjun2915@163.com by email to inquire about licensing matters.
|
||||
Please contact supersonicbi@qq.com by email to inquire about licensing matters.
|
||||
|
||||
|
||||
2. As a contributor, you should agree that:
|
||||
|
||||
@@ -75,7 +75,7 @@ SuperSonic comes with sample semantic models as well as chat conversations that
|
||||
|
||||
## Build and Development
|
||||
|
||||
Please refer to project [Docs](https://supersonicbi.github.io/docs/%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2/%E7%BC%96%E8%AF%91%E6%9E%84%E5%BB%BA/).
|
||||
Please refer to project [Docs](https://supersonicbi.github.io/docs/%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2/%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91%E9%83%A8%E7%BD%B2/).
|
||||
|
||||
## WeChat Contact
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ SuperSonic自带样例的语义模型和问答对话,只需以下三步即可
|
||||
|
||||
## 如何构建和部署
|
||||
|
||||
请参考项目[文档](https://supersonicbi.github.io/docs/%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2/%E7%BC%96%E8%AF%91%E6%9E%84%E5%BB%BA/)。
|
||||
请参考项目[文档](https://supersonicbi.github.io/docs/%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2/%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91%E9%83%A8%E7%BD%B2/)。
|
||||
|
||||
## 微信联系方式
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ SuperSonicには、サンプルのセマンティックモデルとチャット
|
||||
|
||||
## ビルドと開発
|
||||
|
||||
プロジェクト[ドキュメント](https://supersonicbi.github.io/docs/%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2/%E7%BC%96%E8%AF%91%E6%9E%84%E5%BB%BA/)を参照してください。
|
||||
プロジェクト[ドキュメント](https://supersonicbi.github.io/docs/%E7%B3%BB%E7%BB%9F%E9%83%A8%E7%BD%B2/%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91%E9%83%A8%E7%BD%B2/)を参照してください。
|
||||
|
||||
## WeChat連絡先
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ if "%command%"=="restart" (
|
||||
set "logDir=%baseDir%\logs"
|
||||
set "classpath=%baseDir%;%webDir%;%libDir%\*;%confDir%"
|
||||
set "property=-Dfile.encoding=UTF-8 -Duser.language=Zh -Duser.region=CN -Duser.timezone=GMT+08 -Dspring.profiles.active=%profile%"
|
||||
set "java-command=%property% -Xms1024m -Xmx1024m -cp %CLASSPATH% %MAIN_CLASS%"
|
||||
set "java-command=%property% -Xms1024m -Xmx2048m -cp %CLASSPATH% %MAIN_CLASS%"
|
||||
if not exist %logDir% mkdir %logDir%
|
||||
start /B java %java-command% >nul 2>&1
|
||||
timeout /t 10 >nul
|
||||
|
||||
@@ -60,7 +60,8 @@ function runJavaService {
|
||||
JAVA_HOME=$(ls /usr/jdk64/jdk* -d 2>/dev/null | xargs | awk '{print "'$local_app_name'"}')
|
||||
fi
|
||||
export PATH=$JAVA_HOME/bin:$PATH
|
||||
command="-Dfile.encoding=UTF-8 -Duser.language=Zh -Duser.region=CN -Duser.timezone=GMT+08 -Dapp_name=${local_app_name} -Xms1024m -Xmx1024m $main_class"
|
||||
command="-Dfile.encoding=UTF-8 -Duser.language=Zh -Duser.region=CN -Duser.timezone=GMT+08
|
||||
-Dapp_name=${local_app_name} -Xms1024m -Xmx2048m $main_class"
|
||||
|
||||
mkdir -p $javaRunDir/logs
|
||||
java -Dspring.profiles.active="$profile" $command >/dev/null 2>$javaRunDir/logs/error.log &
|
||||
|
||||
5
assembly/bin/supersonic-docker-compose.sh
Normal file
5
assembly/bin/supersonic-docker-compose.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
export SUPERSONIC_VERSION=latest
|
||||
|
||||
docker-compose -f docker-compose.yml -p supersonic up
|
||||
23
assembly/bin/supersonic-docker-run.sh
Normal file
23
assembly/bin/supersonic-docker-run.sh
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
export SUPERSONIC_VERSION=latest
|
||||
|
||||
#### Set below DB configs to connect to your own database
|
||||
# Supported DB_TYPE: h2, mysql, postgres
|
||||
export S2_DB_TYPE=h2
|
||||
export S2_DB_HOST=
|
||||
export S2_DB_PORT=
|
||||
export S2_DB_USER=
|
||||
export S2_DB_PASSWORD=
|
||||
export S2_DB_DATABASE=
|
||||
|
||||
docker run --rm -it -d \
|
||||
--name supersonic_standalone \
|
||||
-p 9080:9080 \
|
||||
-e S2_DB_TYPE=${S2_DB_TYPE} \
|
||||
-e S2_DB_HOST=${S2_DB_HOST} \
|
||||
-e S2_DB_PORT=${S2_DB_PORT} \
|
||||
-e S2_DB_USER=${S2_DB_USER} \
|
||||
-e S2_DB_PASSWORD=${S2_DB_PASSWORD} \
|
||||
-e S2_DB_DATABASE=${S2_DB_DATABASE} \
|
||||
supersonicbi/supersonic:${SUPERSONIC_VERSION}
|
||||
@@ -1,10 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#### Set below DB configs to connect to your own database
|
||||
# Comment out below exports to config your DB connection
|
||||
# Supported DB_TYPE: h2, mysql, postgres
|
||||
export S2_DB_TYPE=h2
|
||||
export S2_DB_HOST=
|
||||
export S2_DB_PORT=
|
||||
export S2_DB_USER=
|
||||
export S2_DB_PASSWORD=
|
||||
export S2_DB_DATABASE=
|
||||
#export S2_DB_TYPE=h2
|
||||
#export S2_DB_HOST=
|
||||
#export S2_DB_PORT=
|
||||
#export S2_DB_USER=
|
||||
#export S2_DB_PASSWORD=
|
||||
#export S2_DB_DATABASE=
|
||||
@@ -24,7 +24,7 @@ public class UserWithPassword extends User {
|
||||
|
||||
public UserWithPassword(Long id, String name, String displayName, String email, String password,
|
||||
Integer isAdmin) {
|
||||
super(id, name, displayName, email, isAdmin);
|
||||
super(id, name, displayName, email, isAdmin, null);
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@@ -102,7 +103,9 @@ public class DefaultUserAdaptor implements UserAdaptor {
|
||||
TokenService tokenService = ContextUtils.getBean(TokenService.class);
|
||||
try {
|
||||
UserWithPassword user = getUserWithPassword(userReq);
|
||||
return tokenService.generateToken(UserWithPassword.convert(user), appKey);
|
||||
String token = tokenService.generateToken(UserWithPassword.convert(user), appKey);
|
||||
updateLastLogin(userReq.getName());
|
||||
return token;
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
throw new RuntimeException("password encrypt error, please try again");
|
||||
@@ -267,4 +270,11 @@ public class DefaultUserAdaptor implements UserAdaptor {
|
||||
userToken.setExpireDate(userTokenDO.getExpireDateTime());
|
||||
return userToken;
|
||||
}
|
||||
|
||||
private void updateLastLogin(String userName) {
|
||||
UserRepository userRepository = ContextUtils.getBean(UserRepository.class);
|
||||
UserDO userDO = userRepository.getUser(userName);
|
||||
userDO.setLastLogin(new Timestamp(System.currentTimeMillis()));
|
||||
userRepository.updateUser(userDO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.tencent.supersonic.auth.authentication.interceptor;
|
||||
|
||||
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 lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -16,7 +16,7 @@ public abstract class AuthenticationInterceptor implements HandlerInterceptor {
|
||||
|
||||
protected AuthenticationConfig authenticationConfig;
|
||||
|
||||
protected UserServiceImpl userServiceImpl;
|
||||
protected UserService userService;
|
||||
|
||||
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.config.AuthenticationConfig;
|
||||
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.common.pojo.exception.AccessException;
|
||||
import com.tencent.supersonic.common.util.ContextUtils;
|
||||
@@ -16,12 +16,7 @@ import org.springframework.web.method.HandlerMethod;
|
||||
import java.lang.reflect.Method;
|
||||
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.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;
|
||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.*;
|
||||
|
||||
@Slf4j
|
||||
public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor {
|
||||
@@ -30,7 +25,7 @@ public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler) throws AccessException {
|
||||
authenticationConfig = ContextUtils.getBean(AuthenticationConfig.class);
|
||||
userServiceImpl = ContextUtils.getBean(UserServiceImpl.class);
|
||||
userService = ContextUtils.getBean(UserService.class);
|
||||
tokenService = ContextUtils.getBean(TokenService.class);
|
||||
if (!authenticationConfig.isEnabled()) {
|
||||
return true;
|
||||
|
||||
@@ -3,7 +3,11 @@ package com.tencent.supersonic.auth.authentication.persistence.dataobject;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
@Data
|
||||
@TableName("s2_user")
|
||||
public class UserDO {
|
||||
|
||||
@@ -27,71 +31,25 @@ public class UserDO {
|
||||
/** */
|
||||
private Integer isAdmin;
|
||||
|
||||
/** @return id */
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/** @param id */
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/** @return name */
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
private Timestamp lastLogin;
|
||||
|
||||
/** @param name */
|
||||
public void setName(String name) {
|
||||
this.name = name == null ? null : name.trim();
|
||||
}
|
||||
|
||||
/** @return password */
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/** @param password */
|
||||
public void setPassword(String password) {
|
||||
this.password = password == null ? null : password.trim();
|
||||
}
|
||||
|
||||
public String getSalt() {
|
||||
return salt;
|
||||
}
|
||||
|
||||
public void setSalt(String salt) {
|
||||
this.salt = salt == null ? null : salt.trim();
|
||||
}
|
||||
|
||||
/** @return display_name */
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/** @param displayName */
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName == null ? null : displayName.trim();
|
||||
}
|
||||
|
||||
/** @return email */
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
/** @param email */
|
||||
public void setEmail(String email) {
|
||||
this.email = email == null ? null : email.trim();
|
||||
}
|
||||
|
||||
/** @return is_admin */
|
||||
public Integer getIsAdmin() {
|
||||
return isAdmin;
|
||||
}
|
||||
|
||||
/** @param isAdmin */
|
||||
public void setIsAdmin(Integer isAdmin) {
|
||||
this.isAdmin = isAdmin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,6 +136,9 @@
|
||||
<if test="isAdmin != null">
|
||||
is_admin = #{isAdmin,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="lastLogin != null">
|
||||
last_login = #{lastLogin,jdbcType=TIMESTAMP},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</update>
|
||||
|
||||
@@ -5,5 +5,7 @@ import com.tencent.supersonic.chat.server.pojo.ExecuteContext;
|
||||
|
||||
public interface ChatQueryExecutor {
|
||||
|
||||
boolean accept(ExecuteContext executeContext);
|
||||
|
||||
QueryResult execute(ExecuteContext executeContext);
|
||||
}
|
||||
|
||||
@@ -37,11 +37,12 @@ public class PlainTextExecutor implements ChatQueryExecutor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResult execute(ExecuteContext executeContext) {
|
||||
if (!"PLAIN_TEXT".equals(executeContext.getParseInfo().getQueryMode())) {
|
||||
return null;
|
||||
}
|
||||
public boolean accept(ExecuteContext executeContext) {
|
||||
return "PLAIN_TEXT".equals(executeContext.getParseInfo().getQueryMode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResult execute(ExecuteContext executeContext) {
|
||||
AgentService agentService = ContextUtils.getBean(AgentService.class);
|
||||
Agent chatAgent = agentService.getAgent(executeContext.getAgent().getId());
|
||||
ChatApp chatApp = chatAgent.getChatAppConfig().get(APP_KEY);
|
||||
|
||||
@@ -8,6 +8,11 @@ import com.tencent.supersonic.headless.api.pojo.SemanticParseInfo;
|
||||
|
||||
public class PluginExecutor implements ChatQueryExecutor {
|
||||
|
||||
@Override
|
||||
public boolean accept(ExecuteContext executeContext) {
|
||||
return PluginQueryManager.isPluginQuery(executeContext.getParseInfo().getQueryMode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResult execute(ExecuteContext executeContext) {
|
||||
SemanticParseInfo parseInfo = executeContext.getParseInfo();
|
||||
|
||||
@@ -25,6 +25,11 @@ import java.util.Objects;
|
||||
|
||||
public class SqlExecutor implements ChatQueryExecutor {
|
||||
|
||||
@Override
|
||||
public boolean accept(ExecuteContext executeContext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public QueryResult execute(ExecuteContext executeContext) {
|
||||
@@ -80,9 +85,9 @@ public class SqlExecutor implements ChatQueryExecutor {
|
||||
queryResult.setQueryId(executeContext.getRequest().getQueryId());
|
||||
queryResult.setChatContext(parseInfo);
|
||||
queryResult.setQueryMode(parseInfo.getQueryMode());
|
||||
queryResult.setQueryTimeCost(System.currentTimeMillis() - startTime);
|
||||
SemanticQueryResp queryResp =
|
||||
semanticLayer.queryByReq(sqlReq, executeContext.getRequest().getUser());
|
||||
queryResult.setQueryTimeCost(System.currentTimeMillis() - startTime);
|
||||
if (queryResp != null) {
|
||||
queryResult.setQueryAuthorization(queryResp.getQueryAuthorization());
|
||||
queryResult.setQuerySql(queryResp.getSql());
|
||||
|
||||
@@ -4,5 +4,7 @@ import com.tencent.supersonic.chat.server.pojo.ParseContext;
|
||||
|
||||
public interface ChatQueryParser {
|
||||
|
||||
boolean accept(ParseContext parseContext);
|
||||
|
||||
void parse(ParseContext parseContext);
|
||||
}
|
||||
|
||||
@@ -14,12 +14,12 @@ public class NL2PluginParser implements ChatQueryParser {
|
||||
private final List<PluginRecognizer> pluginRecognizers =
|
||||
ComponentFactory.getPluginRecognizers();
|
||||
|
||||
public boolean accept(ParseContext parseContext) {
|
||||
return parseContext.getAgent().containsPluginTool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parse(ParseContext parseContext) {
|
||||
if (!parseContext.getAgent().containsPluginTool()) {
|
||||
return;
|
||||
}
|
||||
|
||||
pluginRecognizers.forEach(pluginRecognizer -> {
|
||||
pluginRecognizer.recognize(parseContext);
|
||||
log.info("{} recallResult:{}", pluginRecognizer.getClass().getSimpleName(),
|
||||
|
||||
@@ -73,12 +73,12 @@ public class NL2SQLParser implements ChatQueryParser {
|
||||
.build());
|
||||
}
|
||||
|
||||
public boolean accept(ParseContext parseContext) {
|
||||
return parseContext.enableNL2SQL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parse(ParseContext parseContext) {
|
||||
if (!parseContext.enableNL2SQL()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// first go with rule-based parsers unless the user has already selected one parse.
|
||||
if (Objects.isNull(parseContext.getRequest().getSelectedParse())) {
|
||||
QueryNLReq queryNLReq = QueryReqConverter.buildQueryNLReq(parseContext);
|
||||
|
||||
@@ -6,12 +6,12 @@ import com.tencent.supersonic.headless.api.pojo.response.ParseResp;
|
||||
|
||||
public class PlainTextParser implements ChatQueryParser {
|
||||
|
||||
public boolean accept(ParseContext parseContext) {
|
||||
return !parseContext.getAgent().containsAnyTool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parse(ParseContext parseContext) {
|
||||
if (parseContext.getAgent().containsAnyTool()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SemanticParseInfo parseInfo = new SemanticParseInfo();
|
||||
parseInfo.setQueryMode("PLAIN_TEXT");
|
||||
parseInfo.setId(1);
|
||||
|
||||
@@ -66,8 +66,10 @@ public class ChatConfigController {
|
||||
}
|
||||
|
||||
@GetMapping("/getDomainDataSetTree")
|
||||
public List<ItemResp> getDomainDataSetTree() {
|
||||
return semanticLayerService.getDomainDataSetTree();
|
||||
public List<ItemResp> getDomainDataSetTree(HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
User user = UserHolder.findUser(request, response);
|
||||
return semanticLayerService.getDomainDataSetTree(user);
|
||||
}
|
||||
|
||||
@GetMapping("/getDataSetSchema/{id}")
|
||||
|
||||
@@ -161,9 +161,11 @@ public class AgentServiceImpl extends ServiceImpl<AgentDOMapper, AgentDO> implem
|
||||
JsonUtil.toMap(agentDO.getChatModelConfig(), String.class, ChatApp.class));
|
||||
agent.setVisualConfig(JsonUtil.toObject(agentDO.getVisualConfig(), VisualConfig.class));
|
||||
agent.getChatAppConfig().values().forEach(c -> {
|
||||
ChatModel chatModel = chatModelService.getChatModel(c.getChatModelId());
|
||||
if (Objects.nonNull(chatModel)) {
|
||||
c.setChatModelConfig(chatModelService.getChatModel(c.getChatModelId()).getConfig());
|
||||
if (c.isEnable()) {// 优化,减少访问数据库的次数
|
||||
ChatModel chatModel = chatModelService.getChatModel(c.getChatModelId());
|
||||
if (Objects.nonNull(chatModel)) {
|
||||
c.setChatModelConfig(chatModel.getConfig());
|
||||
}
|
||||
}
|
||||
});
|
||||
agent.setAdmins(JsonUtil.toList(agentDO.getAdmin(), String.class));
|
||||
|
||||
@@ -95,7 +95,11 @@ public class ChatQueryServiceImpl implements ChatQueryService {
|
||||
}
|
||||
|
||||
ParseContext parseContext = buildParseContext(chatParseReq, new ChatParseResp(queryId));
|
||||
chatQueryParsers.forEach(p -> p.parse(parseContext));
|
||||
for (ChatQueryParser parser : chatQueryParsers) {
|
||||
if (parser.accept(parseContext)) {
|
||||
parser.parse(parseContext);
|
||||
}
|
||||
}
|
||||
|
||||
for (ParseResultProcessor processor : parseResultProcessors) {
|
||||
if (processor.accept(parseContext)) {
|
||||
@@ -116,9 +120,11 @@ public class ChatQueryServiceImpl implements ChatQueryService {
|
||||
QueryResult queryResult = new QueryResult();
|
||||
ExecuteContext executeContext = buildExecuteContext(chatExecuteReq);
|
||||
for (ChatQueryExecutor chatQueryExecutor : chatQueryExecutors) {
|
||||
queryResult = chatQueryExecutor.execute(executeContext);
|
||||
if (queryResult != null) {
|
||||
break;
|
||||
if (chatQueryExecutor.accept(executeContext)) {
|
||||
queryResult = chatQueryExecutor.execute(executeContext);
|
||||
if (queryResult != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,19 +18,23 @@ import com.tencent.supersonic.common.config.EmbeddingConfig;
|
||||
import com.tencent.supersonic.common.pojo.Text2SQLExemplar;
|
||||
import com.tencent.supersonic.common.pojo.User;
|
||||
import com.tencent.supersonic.common.service.ExemplarService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class MemoryServiceImpl implements MemoryService {
|
||||
@Slf4j
|
||||
public class MemoryServiceImpl implements MemoryService, CommandLineRunner {
|
||||
|
||||
@Autowired
|
||||
private ChatMemoryRepository chatMemoryRepository;
|
||||
@@ -187,4 +191,25 @@ public class MemoryServiceImpl implements MemoryService {
|
||||
return memory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String... args) { // 优化,启动时检查,向量数据,将记忆放到向量数据库
|
||||
loadSysExemplars();
|
||||
}
|
||||
|
||||
public void loadSysExemplars() {
|
||||
try {
|
||||
List<ChatMemory> memories = this
|
||||
.getMemories(ChatMemoryFilter.builder().status(MemoryStatus.ENABLED).build());
|
||||
for (ChatMemory memory : memories) {
|
||||
exemplarService.storeExemplar(
|
||||
embeddingConfig.getMemoryCollectionName(memory.getAgentId()),
|
||||
Text2SQLExemplar.builder().question(memory.getQuestion())
|
||||
.sideInfo(memory.getSideInfo()).dbSchema(memory.getDbSchema())
|
||||
.sql(memory.getS2sql()).build());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to load system exemplars", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,16 @@ public class SqlDialectFactory {
|
||||
.withLiteralQuoteString("'").withIdentifierQuoteString("\"")
|
||||
.withLiteralEscapedQuoteString("''").withUnquotedCasing(Casing.UNCHANGED)
|
||||
.withQuotedCasing(Casing.UNCHANGED).withCaseSensitive(true);
|
||||
public static final Context PRESTO_CONTEXT =
|
||||
SqlDialect.EMPTY_CONTEXT.withDatabaseProduct(DatabaseProduct.PRESTO)
|
||||
.withLiteralQuoteString("'").withIdentifierQuoteString("\"")
|
||||
.withLiteralEscapedQuoteString("''").withUnquotedCasing(Casing.UNCHANGED)
|
||||
.withQuotedCasing(Casing.UNCHANGED).withCaseSensitive(true);
|
||||
public static final Context KYUUBI_CONTEXT =
|
||||
SqlDialect.EMPTY_CONTEXT.withDatabaseProduct(DatabaseProduct.BIG_QUERY)
|
||||
.withLiteralQuoteString("'").withIdentifierQuoteString("`")
|
||||
.withLiteralEscapedQuoteString("''").withUnquotedCasing(Casing.UNCHANGED)
|
||||
.withQuotedCasing(Casing.UNCHANGED).withCaseSensitive(false);
|
||||
private static Map<EngineType, SemanticSqlDialect> sqlDialectMap;
|
||||
|
||||
static {
|
||||
@@ -35,6 +45,10 @@ public class SqlDialectFactory {
|
||||
sqlDialectMap.put(EngineType.H2, new SemanticSqlDialect(DEFAULT_CONTEXT));
|
||||
sqlDialectMap.put(EngineType.POSTGRESQL, new SemanticSqlDialect(POSTGRESQL_CONTEXT));
|
||||
sqlDialectMap.put(EngineType.HANADB, new SemanticSqlDialect(HANADB_CONTEXT));
|
||||
sqlDialectMap.put(EngineType.STARROCKS, new SemanticSqlDialect(DEFAULT_CONTEXT));
|
||||
sqlDialectMap.put(EngineType.KYUUBI, new SemanticSqlDialect(KYUUBI_CONTEXT));
|
||||
sqlDialectMap.put(EngineType.PRESTO, new SemanticSqlDialect(PRESTO_CONTEXT));
|
||||
sqlDialectMap.put(EngineType.TRINO, new SemanticSqlDialect(PRESTO_CONTEXT));
|
||||
}
|
||||
|
||||
public static SemanticSqlDialect getSqlDialect(EngineType engineType) {
|
||||
|
||||
@@ -2,19 +2,11 @@ package com.tencent.supersonic.common.calcite;
|
||||
|
||||
import com.tencent.supersonic.common.pojo.enums.EngineType;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.calcite.sql.SqlIdentifier;
|
||||
import org.apache.calcite.sql.SqlLiteral;
|
||||
import org.apache.calcite.sql.SqlNode;
|
||||
import org.apache.calcite.sql.SqlNodeList;
|
||||
import org.apache.calcite.sql.SqlOrderBy;
|
||||
import org.apache.calcite.sql.SqlSelect;
|
||||
import org.apache.calcite.sql.SqlWith;
|
||||
import org.apache.calcite.sql.SqlWithItem;
|
||||
import org.apache.calcite.sql.SqlWriterConfig;
|
||||
import org.apache.calcite.sql.parser.SqlParseException;
|
||||
import org.apache.calcite.sql.parser.SqlParser;
|
||||
import org.apache.calcite.sql.parser.SqlParserPos;
|
||||
import org.apache.calcite.sql.pretty.SqlPrettyWriter;
|
||||
import net.sf.jsqlparser.expression.Alias;
|
||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||
import net.sf.jsqlparser.statement.select.ParenthesedSelect;
|
||||
import net.sf.jsqlparser.statement.select.Select;
|
||||
import net.sf.jsqlparser.statement.select.WithItem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -22,85 +14,37 @@ import java.util.List;
|
||||
@Slf4j
|
||||
public class SqlMergeWithUtils {
|
||||
public static String mergeWith(EngineType engineType, String sql, List<String> parentSqlList,
|
||||
List<String> parentWithNameList) throws SqlParseException {
|
||||
SqlParser.Config parserConfig = Configuration.getParserConfig(engineType);
|
||||
List<String> parentWithNameList) throws Exception {
|
||||
|
||||
// Parse the main SQL statement
|
||||
SqlParser parser = SqlParser.create(sql, parserConfig);
|
||||
SqlNode sqlNode1 = parser.parseQuery();
|
||||
Select selectStatement = (Select) CCJSqlParserUtil.parse(sql);
|
||||
List<WithItem> withItemList = new ArrayList<>();
|
||||
|
||||
// List to hold all WITH items
|
||||
List<SqlNode> withItemList = new ArrayList<>();
|
||||
|
||||
// Iterate over each parentSql and parentWithName pair
|
||||
for (int i = 0; i < parentSqlList.size(); i++) {
|
||||
String parentSql = parentSqlList.get(i);
|
||||
String parentWithName = parentWithNameList.get(i);
|
||||
|
||||
// Parse the parent SQL statement
|
||||
parser = SqlParser.create(parentSql, parserConfig);
|
||||
SqlNode sqlNode2 = parser.parseQuery();
|
||||
Select parentSelect = (Select) CCJSqlParserUtil.parse(parentSql);
|
||||
ParenthesedSelect select = new ParenthesedSelect();
|
||||
select.setSelect(parentSelect);
|
||||
|
||||
// Create a new WITH item for parentWithName without quotes
|
||||
SqlWithItem withItem = new SqlWithItem(SqlParserPos.ZERO,
|
||||
new SqlIdentifier(parentWithName, SqlParserPos.ZERO), null, sqlNode2,
|
||||
SqlLiteral.createBoolean(false, SqlParserPos.ZERO));
|
||||
WithItem withItem = new WithItem();
|
||||
withItem.setAlias(new Alias(parentWithName));
|
||||
withItem.setSelect(select);
|
||||
|
||||
// Add the new WITH item to the list
|
||||
withItemList.add(withItem);
|
||||
}
|
||||
|
||||
// Check if the main SQL node contains an ORDER BY or LIMIT clause
|
||||
SqlNode limitNode = null;
|
||||
SqlNodeList orderByList = null;
|
||||
if (sqlNode1 instanceof SqlOrderBy) {
|
||||
SqlOrderBy sqlOrderBy = (SqlOrderBy) sqlNode1;
|
||||
limitNode = sqlOrderBy.fetch;
|
||||
orderByList = sqlOrderBy.orderList;
|
||||
sqlNode1 = sqlOrderBy.query;
|
||||
} else if (sqlNode1 instanceof SqlSelect) {
|
||||
SqlSelect sqlSelect = (SqlSelect) sqlNode1;
|
||||
limitNode = sqlSelect.getFetch();
|
||||
sqlSelect.setFetch(null);
|
||||
sqlNode1 = sqlSelect;
|
||||
// Extract existing WITH items from mainSelectBody if it has any
|
||||
if (selectStatement.getWithItemsList() != null) {
|
||||
withItemList.addAll(selectStatement.getWithItemsList());
|
||||
}
|
||||
|
||||
// Extract existing WITH items from sqlNode1 if it is a SqlWith
|
||||
if (sqlNode1 instanceof SqlWith) {
|
||||
SqlWith sqlWith = (SqlWith) sqlNode1;
|
||||
withItemList.addAll(sqlWith.withList.getList());
|
||||
sqlNode1 = sqlWith.body;
|
||||
}
|
||||
// Set the new WITH items list to the main select body
|
||||
selectStatement.setWithItemsList(withItemList);
|
||||
|
||||
// Create a new SqlWith node
|
||||
SqlWith finalSqlNode = new SqlWith(SqlParserPos.ZERO,
|
||||
new SqlNodeList(withItemList, SqlParserPos.ZERO), sqlNode1);
|
||||
|
||||
// If there was an ORDER BY or LIMIT clause, wrap the finalSqlNode in a SqlOrderBy
|
||||
SqlNode resultNode = finalSqlNode;
|
||||
if (orderByList != null || limitNode != null) {
|
||||
resultNode = new SqlOrderBy(SqlParserPos.ZERO, finalSqlNode,
|
||||
orderByList != null ? orderByList : SqlNodeList.EMPTY, null, limitNode);
|
||||
}
|
||||
|
||||
// Custom SqlPrettyWriter configuration to avoid quoting identifiers
|
||||
SqlWriterConfig config = Configuration.getSqlWriterConfig(engineType);
|
||||
// Pretty print the final SQL
|
||||
SqlPrettyWriter writer = new SqlPrettyWriter(config);
|
||||
return writer.format(resultNode);
|
||||
}
|
||||
|
||||
public static boolean hasWith(EngineType engineType, String sql) throws SqlParseException {
|
||||
SqlParser.Config parserConfig = Configuration.getParserConfig(engineType);
|
||||
SqlParser parser = SqlParser.create(sql, parserConfig);
|
||||
SqlNode sqlNode = parser.parseQuery();
|
||||
SqlNode sqlSelect = sqlNode;
|
||||
if (sqlNode instanceof SqlOrderBy) {
|
||||
SqlOrderBy sqlOrderBy = (SqlOrderBy) sqlNode;
|
||||
sqlSelect = sqlOrderBy.query;
|
||||
} else if (sqlNode instanceof SqlSelect) {
|
||||
sqlSelect = (SqlSelect) sqlNode;
|
||||
}
|
||||
return sqlSelect instanceof SqlWith;
|
||||
return selectStatement.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.tencent.supersonic.common.config;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.tencent.supersonic.common.pojo.ChatModelConfig;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ChatModel {
|
||||
@@ -25,5 +27,11 @@ public class ChatModel {
|
||||
|
||||
private String admin;
|
||||
|
||||
private String viewer;
|
||||
private List<String> viewers = Lists.newArrayList();
|
||||
|
||||
private Integer isOpen = 0;
|
||||
|
||||
public boolean isPublic() {
|
||||
return isOpen != null && isOpen == 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,8 @@ public class FiledFilterReplaceVisitor extends ExpressionVisitorAdapter {
|
||||
}
|
||||
|
||||
ExpressionList<?> leftFunctionParams = leftFunction.getParameters();
|
||||
if (CollectionUtils.isEmpty(leftFunctionParams)) {
|
||||
if (CollectionUtils.isEmpty(leftFunctionParams)
|
||||
|| !(leftFunctionParams.get(0) instanceof Column)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +146,10 @@ public class SqlReplaceHelper {
|
||||
public static String replaceFields(String sql, Map<String, String> fieldNameMap,
|
||||
boolean exactReplace) {
|
||||
Select selectStatement = SqlSelectHelper.getSelect(sql);
|
||||
// alias field should not be replaced
|
||||
Set<String> aliases = SqlSelectHelper.getAliasFields(sql);
|
||||
aliases.forEach(alias -> fieldNameMap.put(alias, alias));
|
||||
|
||||
Set<Select> plainSelectList = SqlSelectHelper.getAllSelect(selectStatement);
|
||||
for (Select plainSelect : plainSelectList) {
|
||||
if (plainSelect instanceof PlainSelect) {
|
||||
|
||||
@@ -989,6 +989,15 @@ public class SqlSelectHelper {
|
||||
for (SelectItem selectItem : selectItems) {
|
||||
selectItem.accept(visitor);
|
||||
}
|
||||
if (plainSelect.getHaving() != null) {
|
||||
plainSelect.getHaving().accept(visitor);
|
||||
}
|
||||
if (!CollectionUtils.isEmpty(plainSelect.getOrderByElements())) {
|
||||
for (OrderByElement orderByElement : plainSelect.getOrderByElements()) {
|
||||
orderByElement.getExpression().accept(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
return !visitor.getFunctionNames().isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,4 +30,6 @@ public class ChatModelDO {
|
||||
private String admin;
|
||||
|
||||
private String viewer;
|
||||
|
||||
private Integer isOpen;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.tencent.supersonic.common.pojo;
|
||||
import com.google.common.base.Objects;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import static com.tencent.supersonic.common.pojo.Constants.ASC_UPPER;
|
||||
|
||||
@@ -6,6 +6,7 @@ import lombok.NoArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@@ -22,26 +23,28 @@ public class User implements Serializable {
|
||||
|
||||
private Integer isAdmin;
|
||||
|
||||
private Timestamp lastLogin;
|
||||
|
||||
public static User get(Long id, String name, String displayName, String email,
|
||||
Integer isAdmin) {
|
||||
return new User(id, name, displayName, email, isAdmin);
|
||||
return new User(id, name, displayName, email, isAdmin, null);
|
||||
}
|
||||
|
||||
public static User get(Long id, String name) {
|
||||
return new User(id, name, name, name, 0);
|
||||
return new User(id, name, name, name, 0, null);
|
||||
}
|
||||
|
||||
public static User getDefaultUser() {
|
||||
return new User(1L, "admin", "admin", "admin@email", 1);
|
||||
return new User(1L, "admin", "admin", "admin@email", 1, null);
|
||||
}
|
||||
|
||||
public static User getVisitUser() {
|
||||
return new User(1L, "visit", "visit", "visit@email", 0);
|
||||
return new User(1L, "visit", "visit", "visit@email", 0, null);
|
||||
}
|
||||
|
||||
public static User getAppUser(int appId) {
|
||||
String name = String.format("app_%s", appId);
|
||||
return new User(1L, name, name, "", 1);
|
||||
return new User(1L, name, name, "", 1, null);
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.tencent.supersonic.common.pojo.User;
|
||||
import java.util.List;
|
||||
|
||||
public interface ChatModelService {
|
||||
List<ChatModel> getChatModels();
|
||||
List<ChatModel> getChatModels(User user);
|
||||
|
||||
ChatModel getChatModel(Integer id);
|
||||
|
||||
|
||||
@@ -23,8 +23,15 @@ import java.util.stream.Collectors;
|
||||
public class ChatModelServiceImpl extends ServiceImpl<ChatModelMapper, ChatModelDO>
|
||||
implements ChatModelService {
|
||||
@Override
|
||||
public List<ChatModel> getChatModels() {
|
||||
return list().stream().map(this::convert).collect(Collectors.toList());
|
||||
public List<ChatModel> getChatModels(User user) {
|
||||
return list().stream().map(this::convert).filter(chatModel -> {
|
||||
if (chatModel.isPublic() || user.isSuperAdmin()
|
||||
|| chatModel.getCreatedBy().equals(user.getName())
|
||||
|| chatModel.getViewers().contains(user.getName())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -41,10 +48,14 @@ public class ChatModelServiceImpl extends ServiceImpl<ChatModelMapper, ChatModel
|
||||
chatModelDO.setCreatedBy(user.getName());
|
||||
chatModelDO.setCreatedAt(new Date());
|
||||
chatModelDO.setUpdatedBy(user.getName());
|
||||
chatModelDO.setUpdatedAt(new Date());
|
||||
chatModelDO.setUpdatedAt(chatModelDO.getCreatedAt());
|
||||
chatModelDO.setIsOpen(chatModel.getIsOpen());
|
||||
if (StringUtils.isBlank(chatModel.getAdmin())) {
|
||||
chatModelDO.setAdmin(user.getName());
|
||||
}
|
||||
if (!chatModel.getViewers().isEmpty()) {
|
||||
chatModelDO.setViewer(JsonUtil.toString(chatModel.getViewers()));
|
||||
}
|
||||
save(chatModelDO);
|
||||
chatModel.setId(chatModelDO.getId());
|
||||
return chatModel;
|
||||
@@ -55,9 +66,13 @@ public class ChatModelServiceImpl extends ServiceImpl<ChatModelMapper, ChatModel
|
||||
ChatModelDO chatModelDO = convert(chatModel);
|
||||
chatModelDO.setUpdatedBy(user.getName());
|
||||
chatModelDO.setUpdatedAt(new Date());
|
||||
chatModelDO.setIsOpen(chatModel.getIsOpen());
|
||||
if (StringUtils.isBlank(chatModel.getAdmin())) {
|
||||
chatModel.setAdmin(user.getName());
|
||||
}
|
||||
if (!chatModel.getViewers().isEmpty()) {
|
||||
chatModelDO.setViewer(JsonUtil.toString(chatModel.getViewers()));
|
||||
}
|
||||
updateById(chatModelDO);
|
||||
return chatModel;
|
||||
}
|
||||
@@ -74,6 +89,7 @@ public class ChatModelServiceImpl extends ServiceImpl<ChatModelMapper, ChatModel
|
||||
ChatModel chatModel = new ChatModel();
|
||||
BeanUtils.copyProperties(chatModelDO, chatModel);
|
||||
chatModel.setConfig(JsonUtil.toObject(chatModelDO.getConfig(), ChatModelConfig.class));
|
||||
chatModel.setViewers(JsonUtil.toList(chatModelDO.getViewer(), String.class));
|
||||
return chatModel;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,8 @@ public class EmbeddingServiceImpl implements EmbeddingService {
|
||||
try {
|
||||
EmbeddingModel embeddingModel = ModelProvider.getEmbeddingModel();
|
||||
Embedding embedding = embeddingModel.embed(question).content();
|
||||
boolean existSegment = existSegment(embeddingStore, query, embedding);
|
||||
boolean existSegment =
|
||||
existSegment(collectionName, embeddingStore, query, embedding);
|
||||
if (existSegment) {
|
||||
continue;
|
||||
}
|
||||
@@ -62,14 +63,14 @@ public class EmbeddingServiceImpl implements EmbeddingService {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean existSegment(EmbeddingStore embeddingStore, TextSegment query,
|
||||
Embedding embedding) {
|
||||
private boolean existSegment(String collectionName, EmbeddingStore embeddingStore,
|
||||
TextSegment query, Embedding embedding) {
|
||||
String queryId = TextSegmentConvert.getQueryId(query);
|
||||
if (queryId == null) {
|
||||
return false;
|
||||
}
|
||||
// Check cache first
|
||||
Boolean cachedResult = cache.getIfPresent(queryId);
|
||||
Boolean cachedResult = cache.getIfPresent(collectionName + queryId);
|
||||
if (cachedResult != null) {
|
||||
return cachedResult;
|
||||
}
|
||||
@@ -82,7 +83,7 @@ public class EmbeddingServiceImpl implements EmbeddingService {
|
||||
EmbeddingSearchResult result = embeddingStore.search(request);
|
||||
List<EmbeddingMatch<TextSegment>> relevant = result.matches();
|
||||
boolean exists = CollectionUtils.isNotEmpty(relevant);
|
||||
cache.put(queryId, exists);
|
||||
cache.put(collectionName + queryId, exists);
|
||||
return exists;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.tencent.supersonic.common.calcite;
|
||||
|
||||
import com.tencent.supersonic.common.pojo.enums.EngineType;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.calcite.sql.parser.SqlParseException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -12,7 +11,7 @@ import java.util.Collections;
|
||||
class SqlWithMergerTest {
|
||||
|
||||
@Test
|
||||
void test1() throws SqlParseException {
|
||||
void test1() throws Exception {
|
||||
String sql1 = "WITH DepartmentVisits AS (\n" + " SELECT department, SUM(pv) AS 总访问次数\n"
|
||||
+ " FROM t_1\n"
|
||||
+ " WHERE sys_imp_date >= '2024-09-01' AND sys_imp_date <= '2024-09-29'\n"
|
||||
@@ -38,7 +37,7 @@ class SqlWithMergerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void test2() throws SqlParseException {
|
||||
void test2() throws Exception {
|
||||
|
||||
String sql1 =
|
||||
"WITH DepartmentVisits AS (SELECT department, SUM(pv) AS 总访问次数 FROM t_1 WHERE sys_imp_date >= '2024-08-28' "
|
||||
@@ -65,7 +64,7 @@ class SqlWithMergerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void test3() throws SqlParseException {
|
||||
void test3() throws Exception {
|
||||
|
||||
String sql1 = "SELECT COUNT(*) FROM DepartmentVisits WHERE 总访问次数 > 100 LIMIT 1000";
|
||||
|
||||
@@ -89,7 +88,7 @@ class SqlWithMergerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void test4() throws SqlParseException {
|
||||
void test4() throws Exception {
|
||||
String sql1 = "SELECT COUNT(*) FROM DepartmentVisits WHERE 总访问次数 > 100";
|
||||
|
||||
String sql2 =
|
||||
@@ -112,7 +111,7 @@ class SqlWithMergerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void test5() throws SqlParseException {
|
||||
void test5() throws Exception {
|
||||
|
||||
String sql1 = "SELECT COUNT(*) FROM Department join Visits WHERE 总访问次数 > 100";
|
||||
|
||||
@@ -132,13 +131,13 @@ class SqlWithMergerTest {
|
||||
"WITH t_1 AS (SELECT `t3`.`sys_imp_date`, `t2`.`department`, `t3`.`s2_pv_uv_statis_pv` AS `pv` "
|
||||
+ "FROM (SELECT `user_name`, `department` FROM `s2_user_department`) AS `t2` LEFT JOIN "
|
||||
+ "(SELECT 1 AS `s2_pv_uv_statis_pv`, `imp_date` AS `sys_imp_date`, `user_name` FROM `s2_pv_uv_statis`) "
|
||||
+ "AS `t3` ON `t2`.`user_name` = `t3`.`user_name`) SELECT COUNT(*) FROM Department INNER JOIN Visits "
|
||||
+ "AS `t3` ON `t2`.`user_name` = `t3`.`user_name`) SELECT COUNT(*) FROM Department JOIN Visits "
|
||||
+ "WHERE 总访问次数 > 100");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void test6() throws SqlParseException {
|
||||
void test6() throws Exception {
|
||||
|
||||
String sql1 =
|
||||
"SELECT COUNT(*) FROM Department join Visits WHERE 总访问次数 > 100 ORDER BY 总访问次数 LIMIT 10";
|
||||
@@ -159,7 +158,36 @@ class SqlWithMergerTest {
|
||||
"WITH t_1 AS (SELECT `t3`.`sys_imp_date`, `t2`.`department`, `t3`.`s2_pv_uv_statis_pv` AS `pv` FROM "
|
||||
+ "(SELECT `user_name`, `department` FROM `s2_user_department`) AS `t2` LEFT JOIN (SELECT 1 AS `s2_pv_uv_statis_pv`,"
|
||||
+ " `imp_date` AS `sys_imp_date`, `user_name` FROM `s2_pv_uv_statis`) AS `t3` ON `t2`.`user_name` = `t3`.`user_name`) "
|
||||
+ "SELECT COUNT(*) FROM Department INNER JOIN Visits WHERE 总访问次数 > 100 ORDER BY 总访问次数 LIMIT 10");
|
||||
+ "SELECT COUNT(*) FROM Department JOIN Visits WHERE 总访问次数 > 100 ORDER BY 总访问次数 LIMIT 10");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test7() throws Exception {
|
||||
|
||||
String sql1 =
|
||||
"SELECT COUNT(*) FROM Department join Visits WHERE 总访问次数 > 100 AND imp_date >= CURRENT_DATE - "
|
||||
+ "INTERVAL '1 year' AND sys_imp_date < CURRENT_DATE ORDER"
|
||||
+ " BY 总访问次数 LIMIT 10";
|
||||
|
||||
String sql2 =
|
||||
"SELECT `t3`.`sys_imp_date`, `t2`.`department`, `t3`.`s2_pv_uv_statis_pv` AS `pv`\n"
|
||||
+ "FROM\n" + "(SELECT `user_name`, `department`\n" + "FROM\n"
|
||||
+ "`s2_user_department`) AS `t2`\n"
|
||||
+ "LEFT JOIN (SELECT 1 AS `s2_pv_uv_statis_pv`, `imp_date` AS `sys_imp_date`, `user_name`\n"
|
||||
+ "FROM\n"
|
||||
+ "`s2_pv_uv_statis`) AS `t3` ON `t2`.`user_name` = `t3`.`user_name`";
|
||||
|
||||
String mergeSql = SqlMergeWithUtils.mergeWith(EngineType.MYSQL, sql1,
|
||||
Collections.singletonList(sql2), Collections.singletonList("t_1"));
|
||||
|
||||
|
||||
Assert.assertEquals(format(mergeSql),
|
||||
"WITH t_1 AS (SELECT `t3`.`sys_imp_date`, `t2`.`department`, `t3`.`s2_pv_uv_statis_pv` AS `pv` FROM "
|
||||
+ "(SELECT `user_name`, `department` FROM `s2_user_department`) AS `t2` LEFT JOIN (SELECT 1 AS `s2_pv_uv_statis_pv`,"
|
||||
+ " `imp_date` AS `sys_imp_date`, `user_name` FROM `s2_pv_uv_statis`) AS `t3` ON `t2`.`user_name` = `t3`.`user_name`) "
|
||||
+ "SELECT COUNT(*) FROM Department JOIN Visits WHERE 总访问次数 > 100 AND imp_date >= "
|
||||
+ "CURRENT_DATE - INTERVAL '1 year' AND sys_imp_date < CURRENT_DATE ORDER BY 总访问次数 "
|
||||
+ "LIMIT 10");
|
||||
}
|
||||
|
||||
private static String format(String mergeSql) {
|
||||
|
||||
@@ -27,4 +27,4 @@ WORKDIR /usr/src/app/supersonic-standalone-${SUPERSONIC_VERSION}
|
||||
EXPOSE 9080
|
||||
# Command to run the supersonic daemon
|
||||
RUN chmod +x bin/supersonic-daemon.sh
|
||||
CMD ["bash", "-c", "bin/supersonic-daemon.sh restart standalone docker && tail -f /dev/null"]
|
||||
CMD ["bash", "-c", "bin/supersonic-daemon.sh restart standalone ${S2_DB_TYPE} && tail -f /dev/null"]
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
# Function to execute the build script
|
||||
execute_build_script() {
|
||||
echo "Executing build script: assembly/bin/supersonic-build.sh"
|
||||
assembly/bin/supersonic-build.sh
|
||||
echo "Executing build script: sh assembly/bin/supersonic-build.sh"
|
||||
sh assembly/bin/supersonic-build.sh
|
||||
}
|
||||
|
||||
# Function to build the Docker image
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SUPERSONIC_VERSION=latest docker-compose -f docker-compose.yml -p supersonic up
|
||||
@@ -11,8 +11,8 @@ services:
|
||||
POSTGRES_PASSWORD: supersonic_password
|
||||
ports:
|
||||
- "15432:5432"
|
||||
# volumes:
|
||||
# - postgres_data:/var/lib/postgresql
|
||||
volumes:
|
||||
- ./supersonic_pg/data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- supersonic_network
|
||||
dns:
|
||||
@@ -30,12 +30,19 @@ services:
|
||||
privileged: true
|
||||
container_name: supersonic_standalone
|
||||
environment:
|
||||
DB_HOST: supersonic_postgres
|
||||
DB_NAME: postgres
|
||||
DB_USERNAME: supersonic_user
|
||||
DB_PASSWORD: supersonic_password
|
||||
S2_DB_TYPE: postgres
|
||||
S2_DB_HOST: supersonic_postgres
|
||||
S2_DB_PORT: 5432
|
||||
S2_DB_DATABASE: postgres
|
||||
S2_DB_USER: supersonic_user
|
||||
S2_DB_PASSWORD: supersonic_password
|
||||
ports:
|
||||
- "9080:9080"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: "2.0"
|
||||
memory: 2048M
|
||||
depends_on:
|
||||
supersonic_postgres:
|
||||
condition: service_healthy
|
||||
@@ -58,8 +65,7 @@ services:
|
||||
# propagation: rprivate
|
||||
# create_host_path: true
|
||||
#volumes:
|
||||
# postgres_data:
|
||||
# supersonic_data:
|
||||
|
||||
networks:
|
||||
supersonic_network:
|
||||
supersonic_network:
|
||||
|
||||
@@ -3,10 +3,12 @@ package com.tencent.supersonic.headless.api.pojo;
|
||||
import com.tencent.supersonic.common.pojo.Constants;
|
||||
import com.tencent.supersonic.headless.api.pojo.enums.DimensionType;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Dimension {
|
||||
|
||||
@@ -23,12 +23,16 @@ public class Measure {
|
||||
|
||||
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.agg = agg;
|
||||
this.isCreateMetric = isCreateMetric;
|
||||
this.bizName = bizName;
|
||||
this.expr = expr;
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
public Measure(String name, String bizName, String agg, Integer isCreateMetric) {
|
||||
|
||||
@@ -24,6 +24,8 @@ public class ModelDetail {
|
||||
|
||||
private String tableQuery;
|
||||
|
||||
private String filterSql;
|
||||
|
||||
private List<Identify> identifiers = Lists.newArrayList();
|
||||
|
||||
private List<Dimension> dimensions = Lists.newArrayList();
|
||||
@@ -49,27 +51,4 @@ public class ModelDetail {
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ public class ModelSchema {
|
||||
|
||||
private String description;
|
||||
|
||||
private List<ColumnSchema> columnSchemas;
|
||||
private List<SemanticColumn> semanticColumns;
|
||||
|
||||
@JsonIgnore
|
||||
public ColumnSchema getColumnByName(String columnName) {
|
||||
for (ColumnSchema fieldSchema : columnSchemas) {
|
||||
public SemanticColumn getColumnByName(String columnName) {
|
||||
for (SemanticColumn fieldSchema : semanticColumns) {
|
||||
if (fieldSchema.getColumnName().equalsIgnoreCase(columnName)) {
|
||||
return fieldSchema;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.tencent.supersonic.headless.api.pojo.enums.FieldType;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ColumnSchema {
|
||||
public class SemanticColumn {
|
||||
|
||||
private String columnName;
|
||||
|
||||
@@ -19,4 +19,8 @@ public class ColumnSchema {
|
||||
|
||||
private String name;
|
||||
|
||||
private String expr;
|
||||
|
||||
private String unit;
|
||||
|
||||
}
|
||||
@@ -32,9 +32,12 @@ public class DatabaseReq extends RecordInfo {
|
||||
private String description;
|
||||
|
||||
private String schema;
|
||||
|
||||
private String url;
|
||||
|
||||
private List<String> admins = Lists.newArrayList();
|
||||
|
||||
private List<String> viewers = Lists.newArrayList();
|
||||
|
||||
private Integer isOpen = 0;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ public class ModelBuildReq {
|
||||
|
||||
private String sql;
|
||||
|
||||
private String filterSql;
|
||||
|
||||
private String catalog;
|
||||
|
||||
private String db;
|
||||
|
||||
@@ -30,6 +30,7 @@ public class QueryDataSetReq {
|
||||
private List<Filter> metricFilters = new ArrayList<>();
|
||||
private DateConf dateInfo;
|
||||
private Long limit = 2000L;
|
||||
private Long offset = 0L;
|
||||
private QueryType queryType = QueryType.DETAIL;
|
||||
private boolean innerLayerNative = false;
|
||||
}
|
||||
|
||||
@@ -3,11 +3,7 @@ package com.tencent.supersonic.headless.api.pojo.request;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.tencent.supersonic.common.jsqlparser.SqlAddHelper;
|
||||
import com.tencent.supersonic.common.jsqlparser.SqlReplaceHelper;
|
||||
import com.tencent.supersonic.common.pojo.Aggregator;
|
||||
import com.tencent.supersonic.common.pojo.Constants;
|
||||
import com.tencent.supersonic.common.pojo.DateConf;
|
||||
import com.tencent.supersonic.common.pojo.Filter;
|
||||
import com.tencent.supersonic.common.pojo.Order;
|
||||
import com.tencent.supersonic.common.pojo.*;
|
||||
import com.tencent.supersonic.common.pojo.enums.AggOperatorEnum;
|
||||
import com.tencent.supersonic.common.pojo.enums.QueryType;
|
||||
import com.tencent.supersonic.common.util.ContextUtils;
|
||||
@@ -25,12 +21,7 @@ import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
|
||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
import net.sf.jsqlparser.schema.Table;
|
||||
import net.sf.jsqlparser.statement.select.GroupByElement;
|
||||
import net.sf.jsqlparser.statement.select.Limit;
|
||||
import net.sf.jsqlparser.statement.select.OrderByElement;
|
||||
import net.sf.jsqlparser.statement.select.ParenthesedSelect;
|
||||
import net.sf.jsqlparser.statement.select.PlainSelect;
|
||||
import net.sf.jsqlparser.statement.select.SelectItem;
|
||||
import net.sf.jsqlparser.statement.select.*;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@@ -52,6 +43,7 @@ public class QueryStructReq extends SemanticQueryReq {
|
||||
private List<Filter> metricFilters = new ArrayList<>();
|
||||
private DateConf dateInfo;
|
||||
private long limit = Constants.DEFAULT_DETAIL_LIMIT;
|
||||
private long offset;
|
||||
private QueryType queryType = QueryType.DETAIL;
|
||||
private boolean convertToSql = true;
|
||||
|
||||
@@ -170,9 +162,15 @@ public class QueryStructReq extends SemanticQueryReq {
|
||||
// 5. Set the limit clause
|
||||
plainSelect.setLimit(buildLimit(queryStructReq));
|
||||
|
||||
// 6. Set the offset clause
|
||||
plainSelect.setOffset(buildOffset(queryStructReq));
|
||||
|
||||
// 7. Set the having clause
|
||||
plainSelect.setHaving(buildHavingClause(queryStructReq));
|
||||
|
||||
select.setSelect(plainSelect);
|
||||
|
||||
// 6. Set where clause
|
||||
// 8. Set the where clause
|
||||
return addWhereClauses(select.toString(), queryStructReq, isBizName);
|
||||
}
|
||||
|
||||
@@ -239,7 +237,8 @@ public class QueryStructReq extends SemanticQueryReq {
|
||||
|
||||
private GroupByElement buildGroupByElement(QueryStructReq queryStructReq) {
|
||||
List<String> groups = queryStructReq.getGroups();
|
||||
if (!CollectionUtils.isEmpty(groups) && !queryStructReq.getAggregators().isEmpty()) {
|
||||
if ((!CollectionUtils.isEmpty(groups) && !queryStructReq.getAggregators().isEmpty())
|
||||
|| !queryStructReq.getMetricFilters().isEmpty()) {
|
||||
GroupByElement groupByElement = new GroupByElement();
|
||||
for (String group : groups) {
|
||||
groupByElement.addGroupByExpression(new Column(group));
|
||||
@@ -258,6 +257,15 @@ public class QueryStructReq extends SemanticQueryReq {
|
||||
return limit;
|
||||
}
|
||||
|
||||
private Offset buildOffset(QueryStructReq queryStructReq) {
|
||||
if (Objects.isNull(queryStructReq.getOffset())) {
|
||||
return null;
|
||||
}
|
||||
Offset offset = new Offset();
|
||||
offset.setOffset(new LongValue(queryStructReq.getOffset()));
|
||||
return offset;
|
||||
}
|
||||
|
||||
private String addWhereClauses(String sql, QueryStructReq queryStructReq, boolean isBizName)
|
||||
throws JSQLParserException {
|
||||
SqlFilterUtils sqlFilterUtils = ContextUtils.getBean(SqlFilterUtils.class);
|
||||
@@ -289,4 +297,23 @@ public class QueryStructReq extends SemanticQueryReq {
|
||||
}
|
||||
return Constants.TABLE_PREFIX + StringUtils.join(modelIds, "_");
|
||||
}
|
||||
|
||||
public Expression buildHavingClause(QueryStructReq queryStructReq) {
|
||||
if (queryStructReq.getMetricFilters().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Filter> filters = queryStructReq.getMetricFilters();
|
||||
SqlFilterUtils sqlFilterUtils = ContextUtils.getBean(SqlFilterUtils.class);
|
||||
String havingClause = sqlFilterUtils.getWhereClause(filters, false);
|
||||
if (StringUtils.isNotBlank(havingClause)) {
|
||||
try {
|
||||
return CCJSqlParserUtil.parseCondExpression(havingClause);
|
||||
} catch (JSQLParserException e) {
|
||||
log.error("Failed to parse having clause", e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ public class DatabaseResp extends RecordInfo {
|
||||
|
||||
private List<String> viewers = Lists.newArrayList();
|
||||
|
||||
private Integer isOpen = 0;
|
||||
|
||||
private String type;
|
||||
|
||||
private String url;
|
||||
@@ -48,6 +50,10 @@ public class DatabaseResp extends RecordInfo {
|
||||
|
||||
private boolean hasEditPermission = false;
|
||||
|
||||
public boolean isPublic() {
|
||||
return isOpen != null && isOpen == 1;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
Pattern p = Pattern.compile("jdbc:(?<db>\\w+):.*((//)|@)(?<host>.+):(?<port>\\d+).*");
|
||||
Matcher m = p.matcher(url);
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package com.tencent.supersonic.headless.chat.corrector;
|
||||
|
||||
import com.tencent.supersonic.common.util.ContextUtils;
|
||||
import com.tencent.supersonic.headless.api.pojo.SemanticParseInfo;
|
||||
import com.tencent.supersonic.headless.chat.ChatQueryContext;
|
||||
import com.tencent.supersonic.headless.chat.parser.ParserConfig;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.tencent.supersonic.headless.chat.parser.ParserConfig.PARSER_RULE_CORRECTOR_ENABLE;
|
||||
|
||||
@Slf4j
|
||||
public class RuleSqlCorrector extends BaseSemanticCorrector {
|
||||
private List<BaseSemanticCorrector> correctors;
|
||||
@@ -20,6 +24,11 @@ public class RuleSqlCorrector extends BaseSemanticCorrector {
|
||||
|
||||
@Override
|
||||
public void doCorrect(ChatQueryContext chatQueryContext, SemanticParseInfo semanticParseInfo) {
|
||||
ParserConfig parserConfig = ContextUtils.getBean(ParserConfig.class);
|
||||
if (!Boolean.parseBoolean(parserConfig.getParameterValue(PARSER_RULE_CORRECTOR_ENABLE))) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (BaseSemanticCorrector corrector : correctors) {
|
||||
corrector.correct(chatQueryContext, semanticParseInfo);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.tencent.supersonic.headless.chat.corrector;
|
||||
|
||||
import com.tencent.supersonic.common.jsqlparser.FieldExpression;
|
||||
import com.tencent.supersonic.common.jsqlparser.SqlAddHelper;
|
||||
import com.tencent.supersonic.common.jsqlparser.SqlSelectHelper;
|
||||
import com.tencent.supersonic.common.jsqlparser.SqlValidHelper;
|
||||
@@ -8,10 +9,7 @@ import com.tencent.supersonic.headless.chat.ChatQueryContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/** Perform SQL corrections on the "Select" section in S2SQL. */
|
||||
@Slf4j
|
||||
@@ -46,10 +44,28 @@ public class SelectCorrector extends BaseSemanticCorrector {
|
||||
return correctS2SQL;
|
||||
}
|
||||
needAddFields.removeAll(selectFields);
|
||||
String addFieldsToSelectSql =
|
||||
SqlAddHelper.addFieldsToSelect(correctS2SQL, new ArrayList<>(needAddFields));
|
||||
semanticParseInfo.getSqlInfo().setCorrectedS2SQL(addFieldsToSelectSql);
|
||||
return addFieldsToSelectSql;
|
||||
|
||||
if (!SqlSelectHelper.hasSubSelect(correctS2SQL)) { // 优化内容 , 如果sql 条件包含了这个字段,而且是全等,则不再查询该字段
|
||||
List<FieldExpression> tmp4 = SqlSelectHelper.getWhereExpressions(correctS2SQL);
|
||||
Iterator<String> it = needAddFields.iterator();
|
||||
while (it.hasNext()) {
|
||||
String field = it.next();
|
||||
long size = tmp4.stream()
|
||||
.filter(e -> e.getFieldName().equals(field) && "=".equals(e.getOperator()))
|
||||
.count();
|
||||
if (size == 1) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needAddFields.size() > 0) {
|
||||
String addFieldsToSelectSql =
|
||||
SqlAddHelper.addFieldsToSelect(correctS2SQL, new ArrayList<>(needAddFields));
|
||||
semanticParseInfo.getSqlInfo().setCorrectedS2SQL(addFieldsToSelectSql);
|
||||
return addFieldsToSelectSql;
|
||||
} else {
|
||||
return correctS2SQL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,4 +22,9 @@ public abstract class MapResult implements Serializable {
|
||||
return this.getMapKey().equals(otherResult.getMapKey())
|
||||
&& this.similarity < otherResult.similarity;
|
||||
}
|
||||
|
||||
public Boolean lessOrEqualSimilar(MapResult otherResult) {
|
||||
return this.getMapKey().equals(otherResult.getMapKey())
|
||||
&& this.similarity <= otherResult.similarity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,8 @@ public class MetaEmbeddingService {
|
||||
return dataSetIds.stream().map(dataSetId -> {
|
||||
Retrieval newRetrieval = new Retrieval();
|
||||
BeanUtils.copyProperties(retrieval, newRetrieval);
|
||||
HashMap<String, Object> newMetadata = new HashMap<>(retrieval.getMetadata());
|
||||
newRetrieval.setMetadata(newMetadata);
|
||||
newRetrieval.getMetadata().putIfAbsent("dataSetId",
|
||||
dataSetId + Constants.UNDERLINE);
|
||||
return newRetrieval;
|
||||
|
||||
@@ -56,7 +56,7 @@ public abstract class BaseMatchStrategy<T extends MapResult> implements MatchStr
|
||||
for (T oneRoundResult : oneRoundResults) {
|
||||
if (existResults.contains(oneRoundResult)) {
|
||||
boolean isDeleted = existResults.removeIf(existResult -> {
|
||||
boolean delete = existResult.lessSimilar(oneRoundResult);
|
||||
boolean delete = existResult.lessOrEqualSimilar(oneRoundResult);
|
||||
if (delete) {
|
||||
log.debug("deleted existResult:{}", existResult);
|
||||
}
|
||||
|
||||
@@ -75,6 +75,9 @@ public class KeywordMapper extends BaseMapper {
|
||||
continue;
|
||||
}
|
||||
Long elementID = NatureHelper.getElementID(nature);
|
||||
if (elementID == null) {
|
||||
continue;
|
||||
}
|
||||
SchemaElement element = getSchemaElement(dataSetId, elementType, elementID,
|
||||
chatQueryContext.getSemanticSchema());
|
||||
if (Objects.isNull(element)) {
|
||||
|
||||
@@ -17,6 +17,10 @@ public class ParserConfig extends ParameterConfig {
|
||||
"ONE_PASS_SELF_CONSISTENCY: 通过投票方式一步生成sql", "list", "语义解析配置",
|
||||
Lists.newArrayList("ONE_PASS_SELF_CONSISTENCY"));
|
||||
|
||||
public static final Parameter PARSER_RULE_CORRECTOR_ENABLE =
|
||||
new Parameter("s2.parser.rule.corrector.enable", "false", "是否开启规则修正器",
|
||||
"规则修正器灵活度有限,在大模型能力足够情况下,不必强制做规则修正", "bool", "语义解析配置");
|
||||
|
||||
public static final Parameter PARSER_LINKING_VALUE_ENABLE =
|
||||
new Parameter("s2.parser.linking.value.enable", "true", "是否将Mapper探测识别到的维度值提供给大模型",
|
||||
"为了数据安全考虑, 这里可进行开关选择", "bool", "语义解析配置");
|
||||
@@ -55,7 +59,8 @@ public class ParserConfig extends ParameterConfig {
|
||||
|
||||
@Override
|
||||
public List<Parameter> getSysParameters() {
|
||||
return Lists.newArrayList(PARSER_LINKING_VALUE_ENABLE, PARSER_FEW_SHOT_NUMBER,
|
||||
PARSER_SELF_CONSISTENCY_NUMBER, PARSER_SHOW_COUNT, PARSER_FIELDS_COUNT_THRESHOLD);
|
||||
return Lists.newArrayList(PARSER_LINKING_VALUE_ENABLE, PARSER_RULE_CORRECTOR_ENABLE,
|
||||
PARSER_FEW_SHOT_NUMBER, PARSER_SELF_CONSISTENCY_NUMBER, PARSER_SHOW_COUNT,
|
||||
PARSER_FIELDS_COUNT_THRESHOLD);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,28 @@ class AggCorrectorTest {
|
||||
semanticParseInfo.getSqlInfo().getCorrectedS2SQL());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSchemaCorrector() {
|
||||
SchemaCorrector corrector = new SchemaCorrector();
|
||||
Long dataSetId = 1L;
|
||||
ChatQueryContext chatQueryContext = buildQueryContext(dataSetId);
|
||||
SemanticParseInfo semanticParseInfo = new SemanticParseInfo();
|
||||
SchemaElement dataSet = new SchemaElement();
|
||||
dataSet.setDataSetId(dataSetId);
|
||||
semanticParseInfo.setDataSet(dataSet);
|
||||
SqlInfo sqlInfo = new SqlInfo();
|
||||
String sql =
|
||||
"WITH 总停留时长 AS (SELECT 用户, SUM(停留时长) AS _总停留时长_ FROM 超音数数据集 WHERE 用户 IN ('alice', 'lucy') AND 数据日期 >= '2025-03-01' AND 数据日期 <= '2025-03-12' GROUP BY 用户) SELECT 用户, _总停留时长_ FROM 总停留时长";
|
||||
sqlInfo.setParsedS2SQL(sql);
|
||||
sqlInfo.setCorrectedS2SQL(sql);
|
||||
semanticParseInfo.setSqlInfo(sqlInfo);
|
||||
corrector.correct(chatQueryContext, semanticParseInfo);
|
||||
Assert.assertEquals(
|
||||
"WITH 总停留时长 AS (SELECT 用户名, SUM(停留时长) AS _总停留时长_ FROM 超音数数据集 WHERE 用户名 IN ('alice', 'lucy') AND 数据日期 "
|
||||
+ ">= '2025-03-01' AND 数据日期 <= '2025-03-12' GROUP BY 用户名) SELECT 用户名, _总停留时长_ FROM 总停留时长",
|
||||
semanticParseInfo.getSqlInfo().getCorrectedS2SQL());
|
||||
}
|
||||
|
||||
private ChatQueryContext buildQueryContext(Long dataSetId) {
|
||||
ChatQueryContext chatQueryContext = new ChatQueryContext();
|
||||
List<DataSetSchema> dataSetSchemaList = new ArrayList<>();
|
||||
@@ -51,18 +73,18 @@ class AggCorrectorTest {
|
||||
schemaElement.setDataSetId(dataSetId);
|
||||
dataSetSchema.setDataSet(schemaElement);
|
||||
Set<SchemaElement> dimensions = new HashSet<>();
|
||||
SchemaElement element1 = new SchemaElement();
|
||||
element1.setDataSetId(1L);
|
||||
element1.setName("部门");
|
||||
dimensions.add(element1);
|
||||
|
||||
dimensions.add(SchemaElement.builder().dataSetId(1L).name("部门").build());
|
||||
|
||||
dimensions.add(SchemaElement.builder().dataSetId(1L).name("用户名").build());
|
||||
|
||||
dataSetSchema.setDimensions(dimensions);
|
||||
|
||||
Set<SchemaElement> metrics = new HashSet<>();
|
||||
SchemaElement metric1 = new SchemaElement();
|
||||
metric1.setDataSetId(1L);
|
||||
metric1.setName("访问次数");
|
||||
metrics.add(metric1);
|
||||
|
||||
metrics.add(SchemaElement.builder().dataSetId(1L).name("访问次数").build());
|
||||
|
||||
metrics.add(SchemaElement.builder().dataSetId(1L).name("停留时长").build());
|
||||
|
||||
dataSetSchema.setMetrics(metrics);
|
||||
dataSetSchemaList.add(dataSetSchema);
|
||||
|
||||
@@ -83,6 +83,7 @@ public class PrestoAdaptor extends BaseDbAdaptor {
|
||||
|
||||
@Override
|
||||
public String rewriteSql(String sql) {
|
||||
sql = sql.replaceAll("`", "\"");
|
||||
return sql;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ public class StructQuery {
|
||||
private List<Filter> metricFilters = new ArrayList();
|
||||
private DateConf dateInfo;
|
||||
private Long limit = 2000L;
|
||||
private Long offset = 0L;
|
||||
private QueryType queryType;
|
||||
private List<Param> params = new ArrayList<>();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.tencent.supersonic.headless.core.translator;
|
||||
|
||||
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.headless.api.pojo.response.QueryState;
|
||||
import com.tencent.supersonic.headless.core.pojo.OntologyQuery;
|
||||
@@ -73,7 +74,7 @@ public class DefaultSemanticTranslator implements SemanticTranslator {
|
||||
String finalSql = null;
|
||||
if (sqlQuery.isSupportWith()) {
|
||||
EngineType engineType = queryStatement.getOntology().getDatabaseType();
|
||||
if (!SqlMergeWithUtils.hasWith(engineType, ontologyOuterSql)) {
|
||||
if (!SqlSelectHelper.hasWith(ontologyOuterSql)) {
|
||||
finalSql = "with " + tables.stream()
|
||||
.map(t -> String.format("%s as (%s)", t.getLeft(), t.getRight()))
|
||||
.collect(Collectors.joining(",")) + "\n" + ontologyOuterSql;
|
||||
|
||||
@@ -40,11 +40,23 @@ public class DataModelNode extends SemanticNode {
|
||||
.equalsIgnoreCase(EngineType.POSTGRESQL.getName())) {
|
||||
String fullTableName = String.join(".public.",
|
||||
dataModel.getModelDetail().getTableQuery().split("\\."));
|
||||
sqlTable = "select * from " + fullTableName;
|
||||
sqlTable = "SELECT * FROM " + fullTableName;
|
||||
} else {
|
||||
sqlTable = "select * from " + dataModel.getModelDetail().getTableQuery();
|
||||
sqlTable = "SELECT * FROM " + dataModel.getModelDetail().getTableQuery();
|
||||
}
|
||||
}
|
||||
|
||||
// String filterSql = dataModel.getFilterSql();
|
||||
String filterSql = dataModel.getModelDetail().getFilterSql();
|
||||
if (filterSql != null && !filterSql.isEmpty()) {
|
||||
boolean sqlContainWhere = sqlTable.toUpperCase().matches("(?s).*\\bWHERE\\b.*");
|
||||
if (sqlContainWhere) {
|
||||
sqlTable = String.format("%s AND %s", sqlTable, filterSql);
|
||||
} else {
|
||||
sqlTable = String.format("%s WHERE %s", sqlTable, filterSql);
|
||||
}
|
||||
}
|
||||
|
||||
if (sqlTable.isEmpty()) {
|
||||
throw new Exception("DataModelNode build error [tableSqlNode not found]");
|
||||
}
|
||||
|
||||
@@ -78,7 +78,8 @@ public abstract class SemanticNode {
|
||||
scope.getValidator().getCatalogReader().getRootSchema(), engineType);
|
||||
if (Configuration.getSqlAdvisor(sqlValidatorWithHints, engineType).getReservedAndKeyWords()
|
||||
.contains(expression.toUpperCase())) {
|
||||
if (engineType == EngineType.HANADB) {
|
||||
if (engineType == EngineType.HANADB || engineType == EngineType.PRESTO
|
||||
|| engineType == EngineType.TRINO) {
|
||||
expression = String.format("\"%s\"", expression);
|
||||
} else {
|
||||
expression = String.format("`%s`", expression);
|
||||
@@ -166,9 +167,9 @@ public abstract class SemanticNode {
|
||||
if (sqlNode instanceof SqlBasicCall) {
|
||||
SqlBasicCall sqlBasicCall = (SqlBasicCall) sqlNode;
|
||||
if (sqlBasicCall.getOperator().getKind().equals(SqlKind.AS)) {
|
||||
if (sqlBasicCall.getOperandList().get(0) instanceof SqlSelect) {
|
||||
SqlSelect table = (SqlSelect) sqlBasicCall.getOperandList().get(0);
|
||||
return table;
|
||||
SqlNode innerQuery = sqlBasicCall.getOperandList().get(0);
|
||||
if (innerQuery instanceof SqlCall) {
|
||||
return innerQuery;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,13 @@ public class SqlBuilder {
|
||||
SqlNode parserNode = tableView.build();
|
||||
DatabaseResp database = queryStatement.getOntology().getDatabase();
|
||||
EngineType engineType = EngineType.fromString(database.getType());
|
||||
parserNode = optimizeParseNode(parserNode, engineType);
|
||||
try {
|
||||
parserNode = optimizeParseNode(parserNode, engineType);
|
||||
} catch (Exception e) {
|
||||
// failure in optimization phase doesn't affect the query result,
|
||||
// just ignore it
|
||||
log.error("optimizeParseNode error", e);
|
||||
}
|
||||
return SemanticNode.getSql(parserNode, engineType);
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ public class DimValueAspect {
|
||||
List<String> values = JsonUtil.toList(fieldValue, String.class);
|
||||
List<String> revisedValues = new ArrayList<>();
|
||||
for (int i = 0; i < values.size(); i++) {
|
||||
Boolean flag = new Boolean(false);
|
||||
Boolean flag = false;
|
||||
for (DimValueMap dimValueMap : dimension.getDimValueMaps()) {
|
||||
if (!CollectionUtils.isEmpty(dimValueMap.getAlias())
|
||||
&& dimValueMap.getAlias().contains(values.get(i))) {
|
||||
|
||||
@@ -24,7 +24,7 @@ public interface SemanticLayerService {
|
||||
|
||||
DataSetSchema getDataSetSchema(Long id);
|
||||
|
||||
List<ItemResp> getDomainDataSetTree();
|
||||
List<ItemResp> getDomainDataSetTree(User user);
|
||||
|
||||
List<DimensionResp> getDimensions(MetaFilter metaFilter);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.google.common.collect.Sets;
|
||||
import com.tencent.supersonic.common.pojo.Constants;
|
||||
import com.tencent.supersonic.common.pojo.QueryColumn;
|
||||
import com.tencent.supersonic.common.pojo.User;
|
||||
import com.tencent.supersonic.common.pojo.enums.AuthType;
|
||||
import com.tencent.supersonic.common.pojo.enums.TaskStatusEnum;
|
||||
import com.tencent.supersonic.headless.api.pojo.DataSetSchema;
|
||||
import com.tencent.supersonic.headless.api.pojo.Dimension;
|
||||
@@ -29,10 +30,7 @@ import com.tencent.supersonic.headless.core.utils.ComponentFactory;
|
||||
import com.tencent.supersonic.headless.server.annotation.S2DataPermission;
|
||||
import com.tencent.supersonic.headless.server.facade.service.SemanticLayerService;
|
||||
import com.tencent.supersonic.headless.server.manager.SemanticSchemaManager;
|
||||
import com.tencent.supersonic.headless.server.service.DataSetService;
|
||||
import com.tencent.supersonic.headless.server.service.DimensionService;
|
||||
import com.tencent.supersonic.headless.server.service.MetricService;
|
||||
import com.tencent.supersonic.headless.server.service.SchemaService;
|
||||
import com.tencent.supersonic.headless.server.service.*;
|
||||
import com.tencent.supersonic.headless.server.utils.MetricDrillDownChecker;
|
||||
import com.tencent.supersonic.headless.server.utils.QueryUtils;
|
||||
import com.tencent.supersonic.headless.server.utils.StatUtils;
|
||||
@@ -59,6 +57,7 @@ public class S2SemanticLayerService implements SemanticLayerService {
|
||||
private final MetricDrillDownChecker metricDrillDownChecker;
|
||||
private final KnowledgeBaseService knowledgeBaseService;
|
||||
private final MetricService metricService;
|
||||
private final DomainService domainService;
|
||||
private final DimensionService dimensionService;
|
||||
private final TranslatorConfig translatorConfig;
|
||||
private final QueryCache queryCache = ComponentFactory.getQueryCache();
|
||||
@@ -69,7 +68,8 @@ public class S2SemanticLayerService implements SemanticLayerService {
|
||||
SchemaService schemaService, SemanticTranslator semanticTranslator,
|
||||
MetricDrillDownChecker metricDrillDownChecker,
|
||||
KnowledgeBaseService knowledgeBaseService, MetricService metricService,
|
||||
DimensionService dimensionService, TranslatorConfig translatorConfig) {
|
||||
DimensionService dimensionService, DomainService domainService,
|
||||
TranslatorConfig translatorConfig) {
|
||||
this.statUtils = statUtils;
|
||||
this.queryUtils = queryUtils;
|
||||
this.semanticSchemaManager = semanticSchemaManager;
|
||||
@@ -80,6 +80,7 @@ public class S2SemanticLayerService implements SemanticLayerService {
|
||||
this.knowledgeBaseService = knowledgeBaseService;
|
||||
this.metricService = metricService;
|
||||
this.dimensionService = dimensionService;
|
||||
this.domainService = domainService;
|
||||
this.translatorConfig = translatorConfig;
|
||||
}
|
||||
|
||||
@@ -262,8 +263,11 @@ public class S2SemanticLayerService implements SemanticLayerService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemResp> getDomainDataSetTree() {
|
||||
return schemaService.getDomainDataSetTree();
|
||||
public List<ItemResp> getDomainDataSetTree(User user) {
|
||||
List<Long> domainsWithAuth = domainService.getDomainAuthSet(user, AuthType.VIEWER).stream()
|
||||
.map(DomainResp::getId).toList();
|
||||
return schemaService.getDomainDataSetTree().stream()
|
||||
.filter(item -> domainsWithAuth.contains(item.getId())).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -36,6 +36,7 @@ public class ModelYamlManager {
|
||||
} else {
|
||||
dataModelYamlTpl.setTableQuery(modelDetail.getTableQuery());
|
||||
}
|
||||
dataModelYamlTpl.setFilterSql(modelDetail.getFilterSql());
|
||||
dataModelYamlTpl.setFields(modelResp.getModelDetail().getFields());
|
||||
dataModelYamlTpl.setId(modelResp.getId());
|
||||
return dataModelYamlTpl;
|
||||
|
||||
@@ -97,9 +97,11 @@ public class SemanticSchemaManager {
|
||||
modelDetail.setDbType(d.getType());
|
||||
modelDetail.setSqlQuery(d.getSqlQuery());
|
||||
modelDetail.setTableQuery(d.getTableQuery());
|
||||
modelDetail.setFilterSql(d.getFilterSql());
|
||||
modelDetail.getIdentifiers().addAll(getIdentify(d.getIdentifiers()));
|
||||
modelDetail.getMeasures().addAll(getMeasureParams(d.getMeasures()));
|
||||
modelDetail.getDimensions().addAll(getDimensions(d.getDimensions()));
|
||||
modelDetail.getFields().addAll(d.getFields());
|
||||
|
||||
return dataModel;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ public class LLMSemanticModeller implements SemanticModeller {
|
||||
if (!chatApp.isPresent() || !chatApp.get().isEnable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<DbSchema> otherDbSchema = getOtherDbSchema(dbSchema, dbSchemas);
|
||||
ModelSchemaExtractor extractor =
|
||||
AiServices.create(ModelSchemaExtractor.class, getChatModel(modelBuildReq));
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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.DbSchema;
|
||||
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 lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -16,19 +16,20 @@ public class RuleSemanticModeller implements SemanticModeller {
|
||||
@Override
|
||||
public void build(DbSchema dbSchema, List<DbSchema> dbSchemas, ModelSchema modelSchema,
|
||||
ModelBuildReq modelBuildReq) {
|
||||
List<ColumnSchema> columnSchemas =
|
||||
List<SemanticColumn> semanticColumns =
|
||||
dbSchema.getDbColumns().stream().map(this::convert).collect(Collectors.toList());
|
||||
modelSchema.setColumnSchemas(columnSchemas);
|
||||
modelSchema.setSemanticColumns(semanticColumns);
|
||||
}
|
||||
|
||||
private ColumnSchema convert(DBColumn dbColumn) {
|
||||
ColumnSchema columnSchema = new ColumnSchema();
|
||||
columnSchema.setName(dbColumn.getColumnName());
|
||||
columnSchema.setColumnName(dbColumn.getColumnName());
|
||||
columnSchema.setComment(dbColumn.getComment());
|
||||
columnSchema.setDataType(dbColumn.getDataType());
|
||||
columnSchema.setFiledType(dbColumn.getFieldType());
|
||||
return columnSchema;
|
||||
private SemanticColumn convert(DBColumn dbColumn) {
|
||||
SemanticColumn semanticColumn = new SemanticColumn();
|
||||
semanticColumn.setName(dbColumn.getColumnName());
|
||||
semanticColumn.setColumnName(dbColumn.getColumnName());
|
||||
semanticColumn.setExpr(dbColumn.getColumnName());
|
||||
semanticColumn.setComment(dbColumn.getComment());
|
||||
semanticColumn.setDataType(dbColumn.getDataType());
|
||||
semanticColumn.setFiledType(dbColumn.getFieldType());
|
||||
return semanticColumn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ import com.tencent.supersonic.headless.api.pojo.request.ModelBuildReq;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A semantic modeler builds semantic-layer schemas from database-layer schemas.
|
||||
*/
|
||||
public interface SemanticModeller {
|
||||
|
||||
void build(DbSchema dbSchema, List<DbSchema> otherDbSchema, ModelSchema modelSchema,
|
||||
|
||||
@@ -44,6 +44,8 @@ public class DatabaseDO {
|
||||
/** */
|
||||
private String viewer;
|
||||
|
||||
private Integer isOpen = 0;
|
||||
|
||||
/** 配置信息 */
|
||||
private String config;
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ public class DataModelYamlTpl {
|
||||
|
||||
private String tableQuery;
|
||||
|
||||
private String filterSql;
|
||||
|
||||
private List<IdentifyYamlTpl> identifiers;
|
||||
|
||||
private List<DimensionYamlTpl> dimensions;
|
||||
|
||||
@@ -52,8 +52,10 @@ public class ChatModelController {
|
||||
}
|
||||
|
||||
@RequestMapping("/getModelList")
|
||||
public List<ChatModel> getModelList() {
|
||||
return chatModelService.getChatModels();
|
||||
public List<ChatModel> getModelList(HttpServletRequest httpServletRequest,
|
||||
HttpServletResponse httpServletResponse) {
|
||||
User user = UserHolder.findUser(httpServletRequest, httpServletResponse);
|
||||
return chatModelService.getChatModels(user);
|
||||
}
|
||||
|
||||
@RequestMapping("/getModelAppList")
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.tencent.supersonic.headless.server.rest;
|
||||
|
||||
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
|
||||
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.request.DataSetReq;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.DataSetResp;
|
||||
@@ -51,6 +52,7 @@ public class DataSetController {
|
||||
public List<DataSetResp> getDataSetList(@RequestParam("domainId") Long domainId) {
|
||||
MetaFilter metaFilter = new MetaFilter();
|
||||
metaFilter.setDomainId(domainId);
|
||||
metaFilter.setStatus(StatusEnum.ONLINE.getCode());
|
||||
return dataSetService.getDataSetList(metaFilter);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,11 @@ package com.tencent.supersonic.headless.server.service;
|
||||
import com.tencent.supersonic.common.pojo.ItemDateResp;
|
||||
import com.tencent.supersonic.common.pojo.User;
|
||||
import com.tencent.supersonic.common.pojo.enums.AuthType;
|
||||
import com.tencent.supersonic.headless.api.pojo.Dimension;
|
||||
import com.tencent.supersonic.headless.api.pojo.ItemDateFilter;
|
||||
import com.tencent.supersonic.headless.api.pojo.MetaFilter;
|
||||
import com.tencent.supersonic.headless.api.pojo.ModelSchema;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.FieldRemovedReq;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.MetaBatchReq;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.ModelBuildReq;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.ModelReq;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.*;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.DatabaseResp;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.ModelResp;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.UnAvailableItemResp;
|
||||
@@ -54,4 +52,6 @@ public interface ModelService {
|
||||
DatabaseResp getDatabaseByModelId(Long modelId);
|
||||
|
||||
void batchUpdateStatus(MetaBatchReq metaBatchReq, User user);
|
||||
|
||||
Dimension updateDimension(DimensionReq dimensionReq, User user);
|
||||
}
|
||||
|
||||
@@ -56,9 +56,9 @@ public class DataSetServiceImpl extends ServiceImpl<DataSetDOMapper, DataSetDO>
|
||||
public DataSetResp save(DataSetReq dataSetReq, User user) {
|
||||
dataSetReq.createdBy(user.getName());
|
||||
DataSetDO dataSetDO = convert(dataSetReq);
|
||||
dataSetDO.setStatus(StatusEnum.ONLINE.getCode());
|
||||
dataSetDO.setStatus(dataSetReq.getStatus() != null ? dataSetReq.getStatus()
|
||||
: StatusEnum.ONLINE.getCode());
|
||||
DataSetResp dataSetResp = convert(dataSetDO);
|
||||
// conflictCheck(dataSetResp);
|
||||
save(dataSetDO);
|
||||
dataSetResp.setId(dataSetDO.getId());
|
||||
return dataSetResp;
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.tencent.supersonic.common.pojo.QueryColumn;
|
||||
import com.tencent.supersonic.common.pojo.User;
|
||||
import com.tencent.supersonic.common.pojo.enums.AuthType;
|
||||
import com.tencent.supersonic.common.pojo.enums.EngineType;
|
||||
import com.tencent.supersonic.headless.api.pojo.DBColumn;
|
||||
import com.tencent.supersonic.headless.api.pojo.enums.DataType;
|
||||
@@ -79,8 +80,9 @@ public class DatabaseServiceImpl extends ServiceImpl<DatabaseDOMapper, DatabaseD
|
||||
|
||||
@Override
|
||||
public List<DatabaseResp> getDatabaseList(User user) {
|
||||
List<DatabaseResp> databaseResps =
|
||||
list().stream().map(DatabaseConverter::convert).collect(Collectors.toList());
|
||||
List<DatabaseResp> databaseResps = list().stream().map(DatabaseConverter::convert)
|
||||
.filter(database -> filterByAuth(database, user, AuthType.VIEWER))
|
||||
.collect(Collectors.toList());
|
||||
fillPermission(databaseResps, user);
|
||||
return databaseResps;
|
||||
}
|
||||
@@ -94,12 +96,50 @@ public class DatabaseServiceImpl extends ServiceImpl<DatabaseDOMapper, DatabaseD
|
||||
databaseResp.setHasEditPermission(true);
|
||||
databaseResp.setHasUsePermission(true);
|
||||
}
|
||||
if (databaseResp.getViewers().contains(user.getName())) {
|
||||
if (databaseResp.getViewers().contains(user.getName()) || databaseResp.isPublic()) {
|
||||
databaseResp.setHasUsePermission(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean filterByAuth(DatabaseResp database, User user, AuthType authType) {
|
||||
if (database.isPublic() || user.isSuperAdmin()
|
||||
|| user.getName().equals(database.getCreatedBy())) {
|
||||
return true;
|
||||
}
|
||||
authType = authType == null ? AuthType.VIEWER : authType;
|
||||
switch (authType) {
|
||||
case ADMIN:
|
||||
return checkAdminPermission(user, database);
|
||||
case VIEWER:
|
||||
default:
|
||||
return checkViewPermission(user, database);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkAdminPermission(User user, DatabaseResp database) {
|
||||
List<String> admins = database.getAdmins();
|
||||
if (user.isSuperAdmin()) {
|
||||
return true;
|
||||
}
|
||||
if (admins.contains(user.getName()) || database.getCreatedBy().equals(user.getName())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkViewPermission(User user, DatabaseResp database) {
|
||||
if (checkAdminPermission(user, database)) {
|
||||
return true;
|
||||
}
|
||||
List<String> viewers = database.getViewers();
|
||||
|
||||
if (viewers.contains(user.getName())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDatabase(Long databaseId) {
|
||||
ModelFilter modelFilter = new ModelFilter();
|
||||
|
||||
@@ -84,6 +84,10 @@ public class DimensionServiceImpl extends ServiceImpl<DimensionDOMapper, Dimensi
|
||||
DimensionDO dimensionDO = DimensionConverter.convert2DimensionDO(dimensionReq);
|
||||
dimensionRepository.createDimension(dimensionDO);
|
||||
sendEventBatch(Lists.newArrayList(dimensionDO), EventType.ADD);
|
||||
|
||||
// should update modelDetail
|
||||
modelService.updateDimension(dimensionReq, user);
|
||||
|
||||
return DimensionConverter.convert2DimensionResp(dimensionDO);
|
||||
}
|
||||
|
||||
@@ -136,6 +140,9 @@ public class DimensionServiceImpl extends ServiceImpl<DimensionDOMapper, Dimensi
|
||||
String oldName = dimensionDO.getName();
|
||||
DimensionConverter.convert(dimensionDO, dimensionReq);
|
||||
dimensionRepository.updateDimension(dimensionDO);
|
||||
// should update modelDetail as well
|
||||
modelService.updateDimension(dimensionReq, user);
|
||||
|
||||
if (!oldName.equals(dimensionDO.getName())) {
|
||||
sendEvent(getDataItem(dimensionDO), EventType.UPDATE);
|
||||
}
|
||||
@@ -419,6 +426,9 @@ public class DimensionServiceImpl extends ServiceImpl<DimensionDOMapper, Dimensi
|
||||
dimValueMapList = JsonUtil.toList(dimensionDO.getDimValueMaps(), DimValueMap.class);
|
||||
}
|
||||
DimValueMap dimValueMaps = req.getDimValueMaps();
|
||||
if (StringUtils.isEmpty(dimValueMaps.getTechName())) {
|
||||
dimValueMaps.setTechName(dimValueMaps.getValue());
|
||||
}
|
||||
Map<String, DimValueMap> valeAndMapInfo = dimValueMapList.stream()
|
||||
.collect(Collectors.toMap(DimValueMap::getValue, v -> v, (v1, v2) -> v2));
|
||||
String value = dimValueMaps.getValue();
|
||||
|
||||
@@ -2,52 +2,24 @@ package com.tencent.supersonic.headless.server.service.impl;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.tencent.supersonic.auth.api.authentication.service.UserService;
|
||||
import com.tencent.supersonic.common.pojo.DataEvent;
|
||||
import com.tencent.supersonic.common.pojo.DataItem;
|
||||
import com.tencent.supersonic.common.pojo.ItemDateResp;
|
||||
import com.tencent.supersonic.common.pojo.ModelRela;
|
||||
import com.tencent.supersonic.common.pojo.User;
|
||||
import com.tencent.supersonic.common.pojo.*;
|
||||
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.JsonUtil;
|
||||
import com.tencent.supersonic.headless.api.pojo.DBColumn;
|
||||
import com.tencent.supersonic.headless.api.pojo.DbSchema;
|
||||
import com.tencent.supersonic.headless.api.pojo.Dimension;
|
||||
import com.tencent.supersonic.headless.api.pojo.Identify;
|
||||
import com.tencent.supersonic.headless.api.pojo.ItemDateFilter;
|
||||
import com.tencent.supersonic.headless.api.pojo.Measure;
|
||||
import com.tencent.supersonic.headless.api.pojo.MetaFilter;
|
||||
import com.tencent.supersonic.headless.api.pojo.ModelSchema;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.DateInfoReq;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.DimensionReq;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.FieldRemovedReq;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.MetaBatchReq;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.MetricReq;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.ModelBuildReq;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.ModelReq;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.DataSetResp;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.DatabaseResp;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.DimensionResp;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.DomainResp;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.MetricResp;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.ModelResp;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.UnAvailableItemResp;
|
||||
import com.tencent.supersonic.headless.api.pojo.*;
|
||||
import com.tencent.supersonic.headless.api.pojo.enums.DimensionType;
|
||||
import com.tencent.supersonic.headless.api.pojo.request.*;
|
||||
import com.tencent.supersonic.headless.api.pojo.response.*;
|
||||
import com.tencent.supersonic.headless.server.modeller.SemanticModeller;
|
||||
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;
|
||||
import com.tencent.supersonic.headless.server.persistence.repository.ModelRepository;
|
||||
import com.tencent.supersonic.headless.server.pojo.ModelFilter;
|
||||
import com.tencent.supersonic.headless.server.service.DataSetService;
|
||||
import com.tencent.supersonic.headless.server.service.DatabaseService;
|
||||
import com.tencent.supersonic.headless.server.service.DimensionService;
|
||||
import com.tencent.supersonic.headless.server.service.DomainService;
|
||||
import com.tencent.supersonic.headless.server.service.MetricService;
|
||||
import com.tencent.supersonic.headless.server.service.ModelRelaService;
|
||||
import com.tencent.supersonic.headless.server.service.ModelService;
|
||||
import com.tencent.supersonic.headless.server.service.*;
|
||||
import com.tencent.supersonic.headless.server.utils.CoreComponentFactory;
|
||||
import com.tencent.supersonic.headless.server.utils.ModelConverter;
|
||||
import com.tencent.supersonic.headless.server.utils.NameCheckUtils;
|
||||
@@ -62,12 +34,7 @@ import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@@ -277,8 +244,8 @@ public class ModelServiceImpl implements ModelService {
|
||||
dimensionService.createDimensionBatch(dimensionReqs, user);
|
||||
}
|
||||
|
||||
private void batchCreateMetric(ModelDO datasourceDO, User user) throws Exception {
|
||||
List<MetricReq> metricReqs = ModelConverter.convertMetricList(datasourceDO);
|
||||
private void batchCreateMetric(ModelDO modelDO, User user) throws Exception {
|
||||
List<MetricReq> metricReqs = ModelConverter.convertMetricList(modelDO);
|
||||
metricService.createMetricBatch(metricReqs, user);
|
||||
}
|
||||
|
||||
@@ -553,6 +520,35 @@ public class ModelServiceImpl implements ModelService {
|
||||
modelRepository.batchUpdate(modelDOS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension updateDimension(DimensionReq dimensionReq, User user) {
|
||||
ModelDO modelDO = getModelDO(dimensionReq.getModelId());
|
||||
ModelDetail modelDetail = JsonUtil.toObject(modelDO.getModelDetail(), ModelDetail.class);
|
||||
Optional<Dimension> dimOptional = modelDetail.getDimensions().stream()
|
||||
.filter(dimension -> dimension.getBizName().equals(dimensionReq.getBizName()))
|
||||
.findFirst();
|
||||
Dimension result;
|
||||
if (dimOptional.isPresent()) {
|
||||
Dimension dimension = dimOptional.get();
|
||||
dimension.setExpr(dimensionReq.getExpr());
|
||||
dimension.setName(dimensionReq.getName());
|
||||
dimension.setType(DimensionType.valueOf(dimensionReq.getType()));
|
||||
dimension.setDescription(dimensionReq.getDescription());
|
||||
result = dimension;
|
||||
} else {
|
||||
Dimension dimension = Dimension.builder().name(dimensionReq.getName())
|
||||
.bizName(dimensionReq.getBizName()).expr(dimensionReq.getExpr())
|
||||
.type(DimensionType.valueOf(dimensionReq.getType()))
|
||||
.description(dimensionReq.getDescription()).build();
|
||||
modelDetail.getDimensions().add(dimension);
|
||||
result = dimension;
|
||||
}
|
||||
|
||||
modelDO.setModelDetail(JsonUtil.toString(modelDetail));
|
||||
modelRepository.updateModel(modelDO);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected ModelDO getModelDO(Long id) {
|
||||
return modelRepository.getModelById(id);
|
||||
}
|
||||
|
||||
@@ -425,8 +425,12 @@ public class DictUtils {
|
||||
.format(DateTimeFormatter.ofPattern(format));
|
||||
String end = LocalDate.now().minusDays(itemValueDateEnd)
|
||||
.format(DateTimeFormatter.ofPattern(format));
|
||||
return String.format("( %s >= '%s' and %s <= '%s' )", dateConf.getDateField(), start,
|
||||
dateConf.getDateField(), end);
|
||||
if (Objects.nonNull(dateConf)) {
|
||||
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) {
|
||||
@@ -440,7 +444,7 @@ public class DictUtils {
|
||||
}
|
||||
// 未进行设置
|
||||
if (Objects.isNull(config) || Objects.isNull(config.getDateConf())) {
|
||||
return defaultDateFilter(config.getDateConf());
|
||||
return defaultDateFilter(null);
|
||||
}
|
||||
// 全表扫描
|
||||
if (DateConf.DateMode.ALL.equals(config.getDateConf().getDateMode())) {
|
||||
|
||||
@@ -157,23 +157,29 @@ public class ModelConverter {
|
||||
modelDetail.setQueryType(ModelDefineType.TABLE_QUERY.getName());
|
||||
modelDetail.setTableQuery(String.format("%s.%s", modelBuildReq.getDb(), tableName));
|
||||
}
|
||||
for (ColumnSchema columnSchema : modelSchema.getColumnSchemas()) {
|
||||
FieldType fieldType = columnSchema.getFiledType();
|
||||
List<Field> fields = new ArrayList<>();
|
||||
for (SemanticColumn semanticColumn : modelSchema.getSemanticColumns()) {
|
||||
FieldType fieldType = semanticColumn.getFiledType();
|
||||
fields.add(new Field(semanticColumn.getName(), semanticColumn.getDataType()));
|
||||
|
||||
if (getIdentifyType(fieldType) != null) {
|
||||
Identify identify = new Identify(columnSchema.getName(),
|
||||
getIdentifyType(fieldType).name(), columnSchema.getColumnName(), 1);
|
||||
Identify identify = new Identify(semanticColumn.getName(),
|
||||
getIdentifyType(fieldType).name(), semanticColumn.getColumnName(), 1);
|
||||
modelDetail.getIdentifiers().add(identify);
|
||||
} else if (FieldType.measure.equals(fieldType)) {
|
||||
Measure measure = new Measure(columnSchema.getName(), columnSchema.getColumnName(),
|
||||
columnSchema.getColumnName(), columnSchema.getAgg().getOperator(), 1);
|
||||
Measure measure = new Measure(semanticColumn.getName(),
|
||||
semanticColumn.getColumnName(), semanticColumn.getExpr(),
|
||||
semanticColumn.getAgg().getOperator(), semanticColumn.getUnit(), 1);
|
||||
modelDetail.getMeasures().add(measure);
|
||||
} else {
|
||||
Dimension dim = new Dimension(columnSchema.getName(), columnSchema.getColumnName(),
|
||||
columnSchema.getColumnName(),
|
||||
DimensionType.valueOf(columnSchema.getFiledType().name()), 1);
|
||||
Dimension dim = new Dimension(semanticColumn.getName(),
|
||||
semanticColumn.getColumnName(), semanticColumn.getExpr(),
|
||||
DimensionType.valueOf(semanticColumn.getFiledType().name()), 1);
|
||||
modelDetail.getDimensions().add(dim);
|
||||
}
|
||||
}
|
||||
modelDetail.setFields(fields);
|
||||
modelDetail.setFilterSql(modelBuildReq.getFilterSql());
|
||||
modelReq.setModelDetail(modelDetail);
|
||||
return modelReq;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,19 @@ public class SqlVariableParseUtilsTest {
|
||||
Assertions.assertEquals(expectedSql, actualSql);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseSql_if() {
|
||||
String sql =
|
||||
"select * from t_$interval$ where id = $id$ $if(name)$and name = $name$$endif$";
|
||||
List<SqlVariable> variables = Lists.newArrayList(mockNumSqlVariable(),
|
||||
mockExprSqlVariable(), mockStrSqlVariable());
|
||||
List<Param> params =
|
||||
Lists.newArrayList(mockIdParam(), mockNameParam(), mockIntervalParam());
|
||||
String actualSql = SqlVariableParseUtils.parse(sql, variables, params);
|
||||
String expectedSql = "select * from t_wk where id = 2 and name = 'alice'";
|
||||
Assertions.assertEquals(expectedSql, actualSql);
|
||||
}
|
||||
|
||||
private SqlVariable mockNumSqlVariable() {
|
||||
return mockSqlVariable("id", VariableValueType.NUMBER, 1);
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ public abstract class S2BaseDemo implements CommandLineRunner {
|
||||
}
|
||||
|
||||
protected ChatModel addChatModelIfNotExist() {
|
||||
List<ChatModel> chatModels = chatModelService.getChatModels();
|
||||
List<ChatModel> chatModels = chatModelService.getChatModels(defaultUser);
|
||||
if (!chatModels.isEmpty()) {
|
||||
return chatModels.get(0);
|
||||
} else {
|
||||
|
||||
@@ -333,7 +333,6 @@ public class S2VisitsDemo extends S2BaseDemo {
|
||||
metricReq.setSensitiveLevel(SensitiveLevelEnum.HIGH.getCode());
|
||||
metricReq.setDescription("每个用户平均访问的次数");
|
||||
metricReq.setClassifications(Collections.singletonList("核心指标"));
|
||||
metricReq.setAlias("平均访问次数");
|
||||
MetricDefineByMetricParams metricTypeParams = new MetricDefineByMetricParams();
|
||||
metricTypeParams.setExpr("pv/uv");
|
||||
List<MetricParam> metrics = new ArrayList<>();
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
spring:
|
||||
datasource:
|
||||
driver-class-name: org.postgresql.Driver
|
||||
url: jdbc:postgresql://${DB_HOST}:${DB_PORT:5432}/${DB_NAME}?stringtype=unspecified
|
||||
username: ${DB_USERNAME}
|
||||
password: ${DB_PASSWORD}
|
||||
sql:
|
||||
init:
|
||||
continue-on-error: true
|
||||
mode: always
|
||||
username: ${DB_USERNAME}
|
||||
password: ${DB_PASSWORD}
|
||||
schema-locations: classpath:db/schema-postgres.sql,classpath:db/schema-postgres-demo.sql
|
||||
data-locations: classpath:db/data-postgres.sql,classpath:db/data-postgres-demo.sql
|
||||
|
||||
s2:
|
||||
embedding:
|
||||
store:
|
||||
provider: PGVECTOR
|
||||
base:
|
||||
url: ${DB_HOST}
|
||||
port: ${DB_PORT:5432}
|
||||
databaseName: ${DB_NAME}
|
||||
user: ${DB_USERNAME}
|
||||
password: ${DB_PASSWORD}
|
||||
dimension: 512
|
||||
@@ -410,4 +410,14 @@ ALTER TABLE s2_query_stat_info RENAME COLUMN `sql` TO `query_sql`;
|
||||
--20250224
|
||||
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 `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;
|
||||
|
||||
--20250310
|
||||
ALTER TABLE s2_chat_model add column is_open tinyint DEFAULT NULL COMMENT '是否公开';
|
||||
ALTER TABLE s2_database add column is_open tinyint DEFAULT NULL COMMENT '是否公开';
|
||||
|
||||
--20250321
|
||||
ALTER TABLE s2_user add column last_loin datetime DEFAULT NULL;
|
||||
@@ -116,6 +116,7 @@ CREATE TABLE IF NOT EXISTS `s2_chat_model`
|
||||
`updated_by` varchar(100) NOT NULL,
|
||||
`admin` varchar(500) NOT NULL,
|
||||
`viewer` varchar(500) DEFAULT NULL,
|
||||
`is_open` TINYINT DEFAULT NULL , -- whether public
|
||||
PRIMARY KEY (`id`)
|
||||
); COMMENT ON TABLE s2_chat_model IS 'chat model table';
|
||||
|
||||
@@ -128,6 +129,7 @@ create table IF NOT EXISTS s2_user
|
||||
salt varchar(256) NULL,
|
||||
email varchar(100) null,
|
||||
is_admin INT null,
|
||||
last_login TIMESTAMP NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
COMMENT ON TABLE s2_user IS 'user information table';
|
||||
@@ -197,6 +199,7 @@ CREATE TABLE IF NOT EXISTS `s2_database` (
|
||||
`updated_by` varchar(100) NOT NULL,
|
||||
`admin` varchar(500) NOT NULL,
|
||||
`viewer` varchar(500) DEFAULT NULL,
|
||||
`is_open` TINYINT DEFAULT NULL , -- whether public
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
COMMENT ON TABLE s2_database IS 'database instance table';
|
||||
@@ -268,7 +271,7 @@ CREATE TABLE IF NOT EXISTS s2_model_rela
|
||||
from_model_id BIGINT,
|
||||
to_model_id BIGINT,
|
||||
join_type VARCHAR(255),
|
||||
join_condition VARCHAR(255),
|
||||
join_condition TEXT,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
@@ -379,7 +382,7 @@ CREATE TABLE IF NOT EXISTS s2_agent
|
||||
enable_feedback int null,
|
||||
`admin` varchar(3000) DEFAULT NULL , -- administrator
|
||||
`admin_org` varchar(3000) DEFAULT NULL , -- administrators organization
|
||||
`is_open` TINYINT DEFAULT NULL , -- whether the public
|
||||
`is_open` TINYINT DEFAULT NULL , -- whether public
|
||||
`viewer` varchar(3000) DEFAULT NULL , -- available users
|
||||
`view_org` varchar(3000) DEFAULT NULL , -- available organization
|
||||
PRIMARY KEY (`id`)
|
||||
|
||||
@@ -1,85 +1,85 @@
|
||||
CREATE TABLE IF NOT EXISTS `s2_agent` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`description` TEXT COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`examples` TEXT COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`description` TEXT COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`examples` TEXT COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`status` tinyint DEFAULT NULL,
|
||||
`model` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`tool_config` TEXT 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,
|
||||
`visual_config` TEXT COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`model` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`tool_config` TEXT COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`llm_config` TEXT COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`chat_model_config` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`visual_config` TEXT COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`enable_search` tinyint DEFAULT 1,
|
||||
`enable_feedback` tinyint DEFAULT 1,
|
||||
`created_by` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`created_by` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`created_at` datetime DEFAULT NULL,
|
||||
`updated_by` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`updated_by` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`updated_at` datetime DEFAULT NULL,
|
||||
`admin` varchar(1000) DEFAULT NULL COMMENT '管理员',
|
||||
`admin_org` varchar(1000) DEFAULT NULL COMMENT '管理员组织',
|
||||
`is_open` tinyint DEFAULT NULL COMMENT '是否公开',
|
||||
`viewer` varchar(1000) DEFAULT NULL COMMENT '可用用户',
|
||||
`view_org` varchar(1000) DEFAULT NULL COMMENT '可用组织',
|
||||
`admin` varchar(1000) DEFAULT NULL COMMENT '管理员',
|
||||
`admin_org` varchar(1000) DEFAULT NULL COMMENT '管理员组织',
|
||||
`is_open` tinyint DEFAULT NULL COMMENT '是否公开',
|
||||
`viewer` varchar(1000) DEFAULT NULL COMMENT '可用用户',
|
||||
`view_org` varchar(1000) DEFAULT NULL COMMENT '可用组织',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_auth_groups` (
|
||||
`group_id` int(11) NOT NULL,
|
||||
`config` varchar(2048) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
PRIMARY KEY (`group_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`group_id` int(11) NOT NULL,
|
||||
`config` varchar(2048) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
PRIMARY KEY (`group_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_available_date_info` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`item_id` int(11) NOT NULL,
|
||||
`type` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`date_format` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`date_period` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`start_date` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`end_date` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`unavailable_date` text COLLATE utf8mb4_unicode_ci,
|
||||
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`created_by` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`updated_at` timestamp NULL,
|
||||
`updated_by` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`status` tinyint DEFAULT 0,
|
||||
UNIQUE(`item_id`, `type`),
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`item_id` int(11) NOT NULL,
|
||||
`type` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`date_format` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`date_period` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`start_date` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`end_date` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`unavailable_date` text COLLATE utf8mb4_unicode_ci,
|
||||
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`created_by` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`updated_at` timestamp NULL,
|
||||
`updated_by` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`status` tinyint DEFAULT 0,
|
||||
UNIQUE(`item_id`, `type`),
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_chat` (
|
||||
`chat_id` bigint(8) NOT NULL AUTO_INCREMENT,
|
||||
`agent_id` int(11) DEFAULT NULL,
|
||||
`chat_name` varchar(300) DEFAULT NULL,
|
||||
`create_time` datetime DEFAULT NULL,
|
||||
`last_time` datetime DEFAULT NULL,
|
||||
`creator` varchar(30) DEFAULT NULL,
|
||||
`last_question` varchar(200) DEFAULT NULL,
|
||||
`is_delete` tinyint DEFAULT '0' COMMENT 'is deleted',
|
||||
`is_top` tinyint DEFAULT '0' COMMENT 'is top',
|
||||
PRIMARY KEY (`chat_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
`chat_id` bigint(8) NOT NULL AUTO_INCREMENT,
|
||||
`agent_id` int(11) DEFAULT NULL,
|
||||
`chat_name` varchar(300) DEFAULT NULL,
|
||||
`create_time` datetime DEFAULT NULL,
|
||||
`last_time` datetime DEFAULT NULL,
|
||||
`creator` varchar(30) DEFAULT NULL,
|
||||
`last_question` varchar(200) DEFAULT NULL,
|
||||
`is_delete` tinyint DEFAULT '0' COMMENT 'is deleted',
|
||||
`is_top` tinyint DEFAULT '0' COMMENT 'is top',
|
||||
PRIMARY KEY (`chat_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_chat_config` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`model_id` bigint(20) DEFAULT NULL,
|
||||
`chat_detail_config` mediumtext COMMENT '明细模式配置信息',
|
||||
`chat_agg_config` mediumtext COMMENT '指标模式配置信息',
|
||||
`recommended_questions` mediumtext COMMENT '推荐问题配置',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间',
|
||||
`updated_at` datetime NOT NULL COMMENT '更新时间',
|
||||
`created_by` varchar(100) NOT NULL COMMENT '创建人',
|
||||
`updated_by` varchar(100) NOT NULL COMMENT '更新人',
|
||||
`status` tinyint NOT NULL COMMENT '主题域扩展信息状态, 0-删除,1-生效',
|
||||
`llm_examples` text COMMENT 'llm examples',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='主题域扩展信息表';
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`model_id` bigint(20) DEFAULT NULL,
|
||||
`chat_detail_config` mediumtext COMMENT '明细模式配置信息',
|
||||
`chat_agg_config` mediumtext COMMENT '指标模式配置信息',
|
||||
`recommended_questions` mediumtext COMMENT '推荐问题配置',
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间',
|
||||
`updated_at` datetime NOT NULL COMMENT '更新时间',
|
||||
`created_by` varchar(100) NOT NULL COMMENT '创建人',
|
||||
`updated_by` varchar(100) NOT NULL COMMENT '更新人',
|
||||
`status` tinyint NOT NULL COMMENT '主题域扩展信息状态, 0-删除,1-生效',
|
||||
`llm_examples` text COMMENT 'llm examples',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主题域扩展信息表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_chat_memory` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`question` varchar(655) COMMENT '用户问题' ,
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`question` varchar(655) COMMENT '用户问题' ,
|
||||
`side_info` TEXT COMMENT '辅助信息' ,
|
||||
`query_id` BIGINT COMMENT '问答ID' ,
|
||||
`agent_id` INT COMMENT '助理ID' ,
|
||||
@@ -95,29 +95,29 @@ CREATE TABLE IF NOT EXISTS `s2_chat_memory` (
|
||||
`created_by` varchar(100) DEFAULT NULL ,
|
||||
`updated_by` varchar(100) DEFAULT NULL ,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_chat_context` (
|
||||
`chat_id` bigint(20) NOT NULL COMMENT 'context chat id',
|
||||
`modified_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'row modify time',
|
||||
`query_user` varchar(64) DEFAULT NULL COMMENT 'row modify user',
|
||||
`query_text` text COMMENT 'query text',
|
||||
`semantic_parse` text COMMENT 'parse data',
|
||||
`ext_data` text COMMENT 'extend data',
|
||||
PRIMARY KEY (`chat_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
`chat_id` bigint(20) NOT NULL COMMENT 'context chat id',
|
||||
`modified_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'row modify time',
|
||||
`query_user` varchar(64) DEFAULT NULL COMMENT 'row modify user',
|
||||
`query_text` text COMMENT 'query text',
|
||||
`semantic_parse` text COMMENT 'parse data',
|
||||
`ext_data` text COMMENT 'extend data',
|
||||
PRIMARY KEY (`chat_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_chat_parse` (
|
||||
`question_id` bigint NOT NULL,
|
||||
`chat_id` int(11) NOT NULL,
|
||||
`parse_id` int(11) NOT NULL,
|
||||
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`query_text` varchar(500) DEFAULT NULL,
|
||||
`user_name` varchar(150) DEFAULT NULL,
|
||||
`parse_info` mediumtext NOT NULL,
|
||||
`is_candidate` int(11) DEFAULT '1' COMMENT '1是candidate,0是selected',
|
||||
KEY `commonIndex` (`question_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
`question_id` bigint NOT NULL,
|
||||
`chat_id` int(11) NOT NULL,
|
||||
`parse_id` int(11) NOT NULL,
|
||||
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`query_text` varchar(500) DEFAULT NULL,
|
||||
`user_name` varchar(150) DEFAULT NULL,
|
||||
`parse_info` mediumtext NOT NULL,
|
||||
`is_candidate` int(11) DEFAULT '1' COMMENT '1是candidate,0是selected',
|
||||
KEY `commonIndex` (`question_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_chat_query`
|
||||
@@ -135,81 +135,83 @@ CREATE TABLE IF NOT EXISTS `s2_chat_query`
|
||||
`similar_queries` varchar(1024) DEFAULT '',
|
||||
`parse_time_cost` varchar(1024) DEFAULT '',
|
||||
PRIMARY KEY (`question_id`)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8;
|
||||
) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_chat_statistics` (
|
||||
`question_id` bigint(20) NOT NULL,
|
||||
`chat_id` bigint(20) NOT NULL,
|
||||
`user_name` varchar(150) DEFAULT NULL,
|
||||
`query_text` varchar(200) DEFAULT NULL,
|
||||
`interface_name` varchar(100) DEFAULT NULL,
|
||||
`cost` int(6) DEFAULT '0',
|
||||
`type` int(11) DEFAULT NULL,
|
||||
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
KEY `commonIndex` (`question_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
`question_id` bigint(20) NOT NULL,
|
||||
`chat_id` bigint(20) NOT NULL,
|
||||
`user_name` varchar(150) DEFAULT NULL,
|
||||
`query_text` varchar(200) DEFAULT NULL,
|
||||
`interface_name` varchar(100) DEFAULT NULL,
|
||||
`cost` int(6) DEFAULT '0',
|
||||
`type` int(11) DEFAULT NULL,
|
||||
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
KEY `commonIndex` (`question_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_chat_model` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL COMMENT '名称',
|
||||
`description` varchar(500) DEFAULT NULL COMMENT '描述',
|
||||
`config` 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 '更新人',
|
||||
`admin` varchar(500) DEFAULT NULL,
|
||||
`viewer` varchar(500) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='对话大模型实例表';
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL COMMENT '名称',
|
||||
`description` varchar(500) DEFAULT NULL COMMENT '描述',
|
||||
`config` 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 '更新人',
|
||||
`admin` varchar(500) DEFAULT NULL,
|
||||
`viewer` varchar(500) DEFAULT NULL,
|
||||
`is_open` tinyint DEFAULT NULL COMMENT '是否公开',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='对话大模型实例表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_database` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL COMMENT '名称',
|
||||
`description` varchar(500) DEFAULT NULL COMMENT '描述',
|
||||
`version` varchar(64) DEFAULT NULL,
|
||||
`type` varchar(20) NOT NULL COMMENT '类型 mysql,clickhouse,tdw',
|
||||
`config` 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 '更新人',
|
||||
`admin` varchar(500) DEFAULT NULL,
|
||||
`viewer` varchar(500) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='数据库实例表';
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL COMMENT '名称',
|
||||
`description` varchar(500) DEFAULT NULL COMMENT '描述',
|
||||
`version` varchar(64) DEFAULT NULL,
|
||||
`type` varchar(20) NOT NULL COMMENT '类型 mysql,clickhouse,tdw',
|
||||
`config` 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 '更新人',
|
||||
`admin` varchar(500) DEFAULT NULL,
|
||||
`viewer` varchar(500) DEFAULT NULL,
|
||||
`is_open` tinyint DEFAULT NULL COMMENT '是否公开',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='数据库实例表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_dictionary_conf` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`description` varchar(255) ,
|
||||
`type` varchar(255) NOT NULL ,
|
||||
`item_id` INT NOT NULL ,
|
||||
`config` mediumtext ,
|
||||
`status` varchar(255) NOT NULL ,
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间' ,
|
||||
`created_by` varchar(100) NOT NULL ,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='字典配置信息表';
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`description` varchar(255) ,
|
||||
`type` varchar(255) NOT NULL ,
|
||||
`item_id` INT NOT NULL ,
|
||||
`config` mediumtext ,
|
||||
`status` varchar(255) NOT NULL ,
|
||||
`created_at` datetime NOT NULL COMMENT '创建时间' ,
|
||||
`created_by` varchar(100) NOT NULL ,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='字典配置信息表';
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_dictionary_task` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL ,
|
||||
`description` varchar(255) ,
|
||||
`type` varchar(255) NOT NULL ,
|
||||
`item_id` INT NOT NULL ,
|
||||
`config` mediumtext ,
|
||||
`status` varchar(255) NOT NULL ,
|
||||
`created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`created_by` varchar(100) NOT NULL ,
|
||||
`elapsed_ms` int(10) DEFAULT NULL ,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='字典运行任务表';
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL ,
|
||||
`description` varchar(255) ,
|
||||
`type` varchar(255) NOT NULL ,
|
||||
`item_id` INT NOT NULL ,
|
||||
`config` mediumtext ,
|
||||
`status` varchar(255) NOT NULL ,
|
||||
`created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`created_by` varchar(100) NOT NULL ,
|
||||
`elapsed_ms` int(10) DEFAULT NULL ,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='字典运行任务表';
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_dimension` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '维度ID',
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '维度ID',
|
||||
`model_id` bigint(20) DEFAULT NULL,
|
||||
`name` varchar(255) NOT NULL COMMENT '维度名称',
|
||||
`biz_name` varchar(255) NOT NULL COMMENT '字段名称',
|
||||
@@ -225,32 +227,32 @@ CREATE TABLE IF NOT EXISTS `s2_dimension` (
|
||||
`updated_at` datetime NOT NULL COMMENT '更新时间',
|
||||
`updated_by` varchar(100) NOT NULL COMMENT '更新人',
|
||||
`semantic_type` varchar(20) NOT NULL COMMENT '语义类型DATE, ID, CATEGORY',
|
||||
`alias` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`alias` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`default_values` varchar(500) DEFAULT NULL,
|
||||
`dim_value_maps` varchar(5000) DEFAULT NULL,
|
||||
`is_tag` tinyint DEFAULT NULL,
|
||||
`ext` varchar(1000) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='维度表';
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='维度表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_domain` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||
`name` varchar(255) DEFAULT NULL COMMENT '主题域名称',
|
||||
`biz_name` varchar(255) DEFAULT NULL COMMENT '内部名称',
|
||||
`parent_id` bigint(20) DEFAULT '0' COMMENT '父主题域ID',
|
||||
`status` tinyint NOT NULL COMMENT '主题域状态',
|
||||
`created_at` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`created_by` varchar(100) DEFAULT NULL COMMENT '创建人',
|
||||
`updated_at` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
`updated_by` varchar(100) DEFAULT NULL COMMENT '更新人',
|
||||
`admin` varchar(3000) DEFAULT NULL COMMENT '主题域管理员',
|
||||
`admin_org` varchar(3000) DEFAULT NULL COMMENT '主题域管理员组织',
|
||||
`is_open` tinyint DEFAULT NULL COMMENT '主题域是否公开',
|
||||
`viewer` varchar(3000) DEFAULT NULL COMMENT '主题域可用用户',
|
||||
`view_org` varchar(3000) DEFAULT NULL COMMENT '主题域可用组织',
|
||||
`entity` varchar(500) DEFAULT NULL COMMENT '主题域实体信息',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='主题域基础信息表';
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
|
||||
`name` varchar(255) DEFAULT NULL COMMENT '主题域名称',
|
||||
`biz_name` varchar(255) DEFAULT NULL COMMENT '内部名称',
|
||||
`parent_id` bigint(20) DEFAULT '0' COMMENT '父主题域ID',
|
||||
`status` tinyint NOT NULL COMMENT '主题域状态',
|
||||
`created_at` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`created_by` varchar(100) DEFAULT NULL COMMENT '创建人',
|
||||
`updated_at` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
`updated_by` varchar(100) DEFAULT NULL COMMENT '更新人',
|
||||
`admin` varchar(3000) DEFAULT NULL COMMENT '主题域管理员',
|
||||
`admin_org` varchar(3000) DEFAULT NULL COMMENT '主题域管理员组织',
|
||||
`is_open` tinyint DEFAULT NULL COMMENT '主题域是否公开',
|
||||
`viewer` varchar(3000) DEFAULT NULL COMMENT '主题域可用用户',
|
||||
`view_org` varchar(3000) DEFAULT NULL COMMENT '主题域可用组织',
|
||||
`entity` varchar(500) DEFAULT NULL COMMENT '主题域实体信息',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主题域基础信息表';
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_metric`
|
||||
@@ -270,35 +272,35 @@ CREATE TABLE IF NOT EXISTS `s2_metric`
|
||||
`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,
|
||||
`classifications` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`alias` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`classifications` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`relate_dimensions` varchar(500) DEFAULT NULL COMMENT '指标相关维度',
|
||||
`ext` text DEFAULT NULL,
|
||||
`define_type` varchar(50) DEFAULT NULL, -- MEASURE, FIELD, METRIC
|
||||
`is_publish` tinyint DEFAULT NULL COMMENT '是否发布',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8 COMMENT ='指标表';
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT ='指标表';
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_model` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`biz_name` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`biz_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`domain_id` bigint(20) DEFAULT NULL,
|
||||
`alias` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`alias` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`status` tinyint DEFAULT NULL,
|
||||
`description` varchar(500) DEFAULT NULL,
|
||||
`viewer` varchar(500) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`view_org` varchar(500) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`admin` varchar(500) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`admin_org` varchar(500) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`viewer` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`view_org` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`admin` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`admin_org` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`is_open` tinyint DEFAULT NULL,
|
||||
`created_by` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`created_by` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`created_at` datetime DEFAULT NULL,
|
||||
`updated_by` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`updated_by` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`updated_at` datetime DEFAULT NULL,
|
||||
`entity` text COLLATE utf8_unicode_ci,
|
||||
`entity` text COLLATE utf8mb4_unicode_ci,
|
||||
`drill_down_dimensions` TEXT DEFAULT NULL,
|
||||
`database_id` INT NOT NULL ,
|
||||
`model_detail` text NOT NULL ,
|
||||
@@ -308,61 +310,61 @@ CREATE TABLE IF NOT EXISTS `s2_model` (
|
||||
`tag_object_id` int(11) DEFAULT '0',
|
||||
`ext` varchar(1000) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_plugin` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`type` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'DASHBOARD,WIDGET,URL',
|
||||
`data_set` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`pattern` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`parse_mode` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`parse_mode_config` text COLLATE utf8mb4_unicode_ci,
|
||||
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`created_at` datetime DEFAULT NULL,
|
||||
`created_by` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`updated_at` datetime DEFAULT NULL,
|
||||
`updated_by` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`config` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
|
||||
`comment` text COLLATE utf8mb4_unicode_ci,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'DASHBOARD,WIDGET,URL',
|
||||
`data_set` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`pattern` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`parse_mode` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`parse_mode_config` text COLLATE utf8mb4_unicode_ci,
|
||||
`name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`created_at` datetime DEFAULT NULL,
|
||||
`created_by` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`updated_at` datetime DEFAULT NULL,
|
||||
`updated_by` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`config` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
|
||||
`comment` text COLLATE utf8mb4_unicode_ci,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_query_stat_info` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`trace_id` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '查询标识',
|
||||
`model_id` bigint(20) DEFAULT NULL,
|
||||
`data_set_id` bigint(20) DEFAULT NULL,
|
||||
`query_user` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '执行sql的用户',
|
||||
`created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`query_type` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '查询对应的场景',
|
||||
`query_type_back` int(10) DEFAULT '0' COMMENT '查询类型, 0-正常查询, 1-预刷类型',
|
||||
`query_sql_cmd` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '对应查询的struct',
|
||||
`sql_cmd_md5` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'sql md5值',
|
||||
`query_struct_cmd` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '对应查询的struct',
|
||||
`struct_cmd_md5` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'sql md5值',
|
||||
`query_sql` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '对应查询的sql',
|
||||
`sql_md5` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'sql md5值',
|
||||
`query_engine` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '查询引擎',
|
||||
`elapsed_ms` bigint(10) DEFAULT NULL COMMENT '查询耗时',
|
||||
`query_state` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '查询最终状态',
|
||||
`native_query` int(10) DEFAULT NULL COMMENT '1-明细查询,0-聚合查询',
|
||||
`start_date` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'sql开始日期',
|
||||
`end_date` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'sql结束日期',
|
||||
`dimensions` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql 涉及的维度',
|
||||
`metrics` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql 涉及的指标',
|
||||
`select_cols` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql select部分涉及的标签',
|
||||
`agg_cols` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql agg部分涉及的标签',
|
||||
`filter_cols` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql where部分涉及的标签',
|
||||
`group_by_cols` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql grouy by部分涉及的标签',
|
||||
`order_by_cols` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql order by部分涉及的标签',
|
||||
`use_result_cache` tinyint(1) DEFAULT '-1' COMMENT '是否命中sql缓存',
|
||||
`use_sql_cache` tinyint(1) DEFAULT '-1' COMMENT '是否命中sql缓存',
|
||||
`sql_cache_key` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '缓存的key',
|
||||
`result_cache_key` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '缓存的key',
|
||||
`query_opt_mode` varchar(20) null comment '优化模式',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `domain_index` (`model_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='查询统计信息表';
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`trace_id` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '查询标识',
|
||||
`model_id` bigint(20) DEFAULT NULL,
|
||||
`data_set_id` bigint(20) DEFAULT NULL,
|
||||
`query_user` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '执行sql的用户',
|
||||
`created_at` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`query_type` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '查询对应的场景',
|
||||
`query_type_back` int(10) DEFAULT '0' COMMENT '查询类型, 0-正常查询, 1-预刷类型',
|
||||
`query_sql_cmd` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '对应查询的struct',
|
||||
`sql_cmd_md5` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'sql md5值',
|
||||
`query_struct_cmd` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '对应查询的struct',
|
||||
`struct_cmd_md5` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'sql md5值',
|
||||
`query_sql` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '对应查询的sql',
|
||||
`sql_md5` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'sql md5值',
|
||||
`query_engine` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '查询引擎',
|
||||
`elapsed_ms` bigint(10) DEFAULT NULL COMMENT '查询耗时',
|
||||
`query_state` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '查询最终状态',
|
||||
`native_query` int(10) DEFAULT NULL COMMENT '1-明细查询,0-聚合查询',
|
||||
`start_date` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'sql开始日期',
|
||||
`end_date` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'sql结束日期',
|
||||
`dimensions` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql 涉及的维度',
|
||||
`metrics` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql 涉及的指标',
|
||||
`select_cols` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql select部分涉及的标签',
|
||||
`agg_cols` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql agg部分涉及的标签',
|
||||
`filter_cols` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql where部分涉及的标签',
|
||||
`group_by_cols` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql grouy by部分涉及的标签',
|
||||
`order_by_cols` mediumtext COLLATE utf8mb4_unicode_ci COMMENT 'sql order by部分涉及的标签',
|
||||
`use_result_cache` tinyint(1) DEFAULT '-1' COMMENT '是否命中sql缓存',
|
||||
`use_sql_cache` tinyint(1) DEFAULT '-1' COMMENT '是否命中sql缓存',
|
||||
`sql_cache_key` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '缓存的key',
|
||||
`result_cache_key` mediumtext COLLATE utf8mb4_unicode_ci COMMENT '缓存的key',
|
||||
`query_opt_mode` varchar(20) null comment '优化模式',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `domain_index` (`model_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='查询统计信息表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_canvas`
|
||||
(
|
||||
@@ -375,7 +377,7 @@ CREATE TABLE IF NOT EXISTS `s2_canvas`
|
||||
`updated_at` datetime DEFAULT NULL,
|
||||
`updated_by` varchar(100) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8;
|
||||
) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS s2_user
|
||||
(
|
||||
@@ -386,16 +388,17 @@ CREATE TABLE IF NOT EXISTS s2_user
|
||||
salt varchar(256) DEFAULT NULL COMMENT 'md5密码盐',
|
||||
email varchar(100) null,
|
||||
is_admin tinyint null,
|
||||
last_login datetime DEFAULT NULL,
|
||||
UNIQUE (`name`),
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS s2_system_config
|
||||
(
|
||||
id int primary key AUTO_INCREMENT COMMENT '主键id',
|
||||
admin varchar(500) COMMENT '系统管理员',
|
||||
parameters text null COMMENT '配置项'
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS s2_model_rela
|
||||
(
|
||||
@@ -404,28 +407,28 @@ CREATE TABLE IF NOT EXISTS s2_model_rela
|
||||
from_model_id bigint,
|
||||
to_model_id bigint,
|
||||
join_type VARCHAR(255),
|
||||
join_condition VARCHAR(255)
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
join_condition text
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_collect` (
|
||||
`id` bigint NOT NULL primary key AUTO_INCREMENT,
|
||||
`type` varchar(20) NOT NULL,
|
||||
`id` bigint NOT NULL primary key AUTO_INCREMENT,
|
||||
`type` varchar(20) NOT NULL,
|
||||
`username` varchar(20) NOT NULL,
|
||||
`collect_id` bigint NOT NULL,
|
||||
`create_time` datetime,
|
||||
`update_time` datetime
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_metric_query_default_config` (
|
||||
`id` bigint NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
`metric_id` bigint,
|
||||
`user_name` varchar(255) NOT NULL,
|
||||
`id` bigint NOT NULL PRIMARY KEY AUTO_INCREMENT,
|
||||
`metric_id` bigint,
|
||||
`user_name` varchar(255) NOT NULL,
|
||||
`default_config` varchar(1000) NOT NULL,
|
||||
`created_at` datetime null,
|
||||
`updated_at` datetime null,
|
||||
`created_by` varchar(100) null,
|
||||
`updated_by` varchar(100) null
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_app`
|
||||
(
|
||||
@@ -442,7 +445,7 @@ CREATE TABLE IF NOT EXISTS `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;
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS s2_data_set
|
||||
(
|
||||
@@ -461,19 +464,19 @@ CREATE TABLE IF NOT EXISTS s2_data_set
|
||||
query_config VARCHAR(3000),
|
||||
`admin` varchar(3000) DEFAULT NULL,
|
||||
`admin_org` varchar(3000) DEFAULT NULL
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS s2_tag(
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`item_id` INT NOT NULL ,
|
||||
`type` varchar(255) NOT NULL ,
|
||||
`created_at` datetime NOT NULL ,
|
||||
`created_by` varchar(100) NOT NULL ,
|
||||
`updated_at` datetime DEFAULT NULL ,
|
||||
`updated_by` varchar(100) DEFAULT NULL ,
|
||||
`ext` text DEFAULT NULL ,
|
||||
PRIMARY KEY (`id`)
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`item_id` INT NOT NULL ,
|
||||
`type` varchar(255) NOT NULL ,
|
||||
`created_at` datetime NOT NULL ,
|
||||
`created_by` varchar(100) NOT NULL ,
|
||||
`updated_at` datetime DEFAULT NULL ,
|
||||
`updated_by` varchar(100) DEFAULT NULL ,
|
||||
`ext` text DEFAULT NULL ,
|
||||
PRIMARY KEY (`id`)
|
||||
)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_tag_object`
|
||||
(
|
||||
@@ -490,11 +493,11 @@ CREATE TABLE IF NOT EXISTS `s2_tag_object`
|
||||
`updated_by` varchar(100) NULL COMMENT '更新人',
|
||||
`ext` text DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8 COMMENT ='标签对象表';
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT ='标签对象表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_query_rule` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`data_set_id` bigint(20) ,
|
||||
`priority` int(10) NOT NULL DEFAULT '1' ,
|
||||
`rule_type` varchar(255) NOT NULL ,
|
||||
@@ -510,10 +513,10 @@ CREATE TABLE IF NOT EXISTS `s2_query_rule` (
|
||||
`updated_by` varchar(100) DEFAULT NULL ,
|
||||
`ext` text DEFAULT NULL ,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT ='查询规则表';
|
||||
) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT ='查询规则表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_term` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`domain_id` bigint(20),
|
||||
`name` varchar(255) NOT NULL ,
|
||||
`description` varchar(500) DEFAULT NULL ,
|
||||
@@ -525,20 +528,20 @@ CREATE TABLE IF NOT EXISTS `s2_term` (
|
||||
`updated_at` datetime DEFAULT NULL ,
|
||||
`updated_by` varchar(100) DEFAULT NULL ,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT ='术语表';
|
||||
) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT ='术语表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `s2_user_token` (
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`user_name` VARCHAR(255) NOT NULL,
|
||||
`expire_time` BIGINT(20) NOT NULL,
|
||||
`token` text NOT NULL,
|
||||
`salt` VARCHAR(255) default NULL,
|
||||
`create_time` DATETIME NOT NULL,
|
||||
`create_by` VARCHAR(255) NOT NULL,
|
||||
`update_time` DATETIME default NULL,
|
||||
`update_by` VARCHAR(255) NOT NULL,
|
||||
`expire_date_time` DATETIME NOT NULL,
|
||||
unique key name_username (`name`, `user_name`),
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin comment='用户令牌信息表';
|
||||
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`user_name` VARCHAR(255) NOT NULL,
|
||||
`expire_time` BIGINT(20) NOT NULL,
|
||||
`token` text NOT NULL,
|
||||
`salt` VARCHAR(255) default NULL,
|
||||
`create_time` DATETIME NOT NULL,
|
||||
`create_by` VARCHAR(255) NOT NULL,
|
||||
`update_time` DATETIME default NULL,
|
||||
`update_by` VARCHAR(255) NOT NULL,
|
||||
`expire_date_time` DATETIME NOT NULL,
|
||||
unique key name_username (`name`, `user_name`),
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci comment='用户令牌信息表';
|
||||
|
||||
@@ -147,7 +147,8 @@ CREATE TABLE IF NOT EXISTS s2_chat_model (
|
||||
updated_at timestamp NOT NULL,
|
||||
updated_by varchar(100) NOT NULL,
|
||||
admin varchar(500) DEFAULT NULL,
|
||||
viewer varchar(500) DEFAULT NULL
|
||||
viewer varchar(500) DEFAULT NULL,
|
||||
is_open smallint DEFAULT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS s2_database (
|
||||
@@ -162,7 +163,8 @@ CREATE TABLE IF NOT EXISTS s2_database (
|
||||
updated_at timestamp NOT NULL,
|
||||
updated_by varchar(100) NOT NULL,
|
||||
admin varchar(500) DEFAULT NULL,
|
||||
viewer varchar(500) DEFAULT NULL
|
||||
viewer varchar(500) DEFAULT NULL,
|
||||
is_open smallint DEFAULT NULL
|
||||
);
|
||||
|
||||
|
||||
@@ -465,7 +467,7 @@ CREATE TABLE IF NOT EXISTS s2_model_rela (
|
||||
from_model_id bigint,
|
||||
to_model_id bigint,
|
||||
join_type VARCHAR(255),
|
||||
join_condition VARCHAR(255)
|
||||
join_condition text
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS s2_collect (
|
||||
@@ -496,5 +498,6 @@ CREATE TABLE IF NOT EXISTS s2_user (
|
||||
salt varchar(256) DEFAULT NULL,
|
||||
email varchar(100) NULL,
|
||||
is_admin smallint NULL,
|
||||
last_login timestamp NULL,
|
||||
UNIQUE(name)
|
||||
);
|
||||
@@ -155,16 +155,6 @@ public class Text2SQLEval extends BaseTest {
|
||||
assert result.getTextResult().contains("3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_detail_query() throws Exception {
|
||||
long start = System.currentTimeMillis();
|
||||
QueryResult result = submitNewChat("特斯拉旗下有哪些品牌", agent.getId());
|
||||
durations.add(System.currentTimeMillis() - start);
|
||||
assert result.getQueryColumns().size() >= 1;
|
||||
assert result.getTextResult().contains("Model Y");
|
||||
assert result.getTextResult().contains("Model 3");
|
||||
}
|
||||
|
||||
public Agent getLLMAgent() {
|
||||
Agent agent = new Agent();
|
||||
agent.setName("Agent for Test");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user