mirror of
https://github.com/tencentmusic/supersonic.git
synced 2026-04-21 06:04:19 +08:00
Compare commits
12 Commits
v0.9.10
...
eaca4dddfa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eaca4dddfa | ||
|
|
4bb0aae8fc | ||
|
|
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
|
mvn -version
|
||||||
|
|
||||||
- name: Cache Maven packages
|
- name: Cache Maven packages
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.m2
|
path: ~/.m2
|
||||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
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'
|
distribution: 'adopt'
|
||||||
|
|
||||||
- name: Cache Maven packages
|
- name: Cache Maven packages
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/Library/Caches/Maven # macOS Maven cache path
|
path: ~/Library/Caches/Maven # macOS Maven cache path
|
||||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
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'
|
distribution: 'adopt'
|
||||||
|
|
||||||
- name: Cache Maven packages
|
- name: Cache Maven packages
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.m2
|
path: ~/.m2
|
||||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
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
|
distribution: 'adopt' # You might need to change this if 'adopt' doesn't support JDK 21
|
||||||
|
|
||||||
- name: Cache Maven packages
|
- name: Cache Maven packages
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~\.m2 # Windows uses a backslash for paths
|
path: ~\.m2 # Windows uses a backslash for paths
|
||||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
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
|
b. a commercial license must be obtained from the author if you want to develop and distribute a derivative work based
|
||||||
on SuperSonic.
|
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:
|
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
|
## 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
|
## 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連絡先
|
## WeChat連絡先
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.tencent.supersonic.auth.authentication.interceptor;
|
package com.tencent.supersonic.auth.authentication.interceptor;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
||||||
import com.tencent.supersonic.auth.authentication.service.UserServiceImpl;
|
import com.tencent.supersonic.auth.api.authentication.service.UserService;
|
||||||
import com.tencent.supersonic.auth.authentication.utils.TokenService;
|
import com.tencent.supersonic.auth.authentication.utils.TokenService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -16,7 +16,7 @@ public abstract class AuthenticationInterceptor implements HandlerInterceptor {
|
|||||||
|
|
||||||
protected AuthenticationConfig authenticationConfig;
|
protected AuthenticationConfig authenticationConfig;
|
||||||
|
|
||||||
protected UserServiceImpl userServiceImpl;
|
protected UserService userService;
|
||||||
|
|
||||||
protected TokenService tokenService;
|
protected TokenService tokenService;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package com.tencent.supersonic.auth.authentication.interceptor;
|
|||||||
import com.tencent.supersonic.auth.api.authentication.annotation.AuthenticationIgnore;
|
import com.tencent.supersonic.auth.api.authentication.annotation.AuthenticationIgnore;
|
||||||
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
||||||
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
|
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
|
||||||
import com.tencent.supersonic.auth.authentication.service.UserServiceImpl;
|
import com.tencent.supersonic.auth.api.authentication.service.UserService;
|
||||||
import com.tencent.supersonic.auth.authentication.utils.TokenService;
|
import com.tencent.supersonic.auth.authentication.utils.TokenService;
|
||||||
import com.tencent.supersonic.common.pojo.exception.AccessException;
|
import com.tencent.supersonic.common.pojo.exception.AccessException;
|
||||||
import com.tencent.supersonic.common.util.ContextUtils;
|
import com.tencent.supersonic.common.util.ContextUtils;
|
||||||
@@ -16,12 +16,7 @@ import org.springframework.web.method.HandlerMethod;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_IS_ADMIN;
|
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.*;
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_DISPLAY_NAME;
|
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_EMAIL;
|
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_ID;
|
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_NAME;
|
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_PASSWORD;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor {
|
public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor {
|
||||||
@@ -30,7 +25,7 @@ public class DefaultAuthenticationInterceptor extends AuthenticationInterceptor
|
|||||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
||||||
Object handler) throws AccessException {
|
Object handler) throws AccessException {
|
||||||
authenticationConfig = ContextUtils.getBean(AuthenticationConfig.class);
|
authenticationConfig = ContextUtils.getBean(AuthenticationConfig.class);
|
||||||
userServiceImpl = ContextUtils.getBean(UserServiceImpl.class);
|
userService = ContextUtils.getBean(UserService.class);
|
||||||
tokenService = ContextUtils.getBean(TokenService.class);
|
tokenService = ContextUtils.getBean(TokenService.class);
|
||||||
if (!authenticationConfig.isEnabled()) {
|
if (!authenticationConfig.isEnabled()) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -26,6 +26,16 @@ public class SqlDialectFactory {
|
|||||||
.withLiteralQuoteString("'").withIdentifierQuoteString("\"")
|
.withLiteralQuoteString("'").withIdentifierQuoteString("\"")
|
||||||
.withLiteralEscapedQuoteString("''").withUnquotedCasing(Casing.UNCHANGED)
|
.withLiteralEscapedQuoteString("''").withUnquotedCasing(Casing.UNCHANGED)
|
||||||
.withQuotedCasing(Casing.UNCHANGED).withCaseSensitive(true);
|
.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;
|
private static Map<EngineType, SemanticSqlDialect> sqlDialectMap;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -35,6 +45,10 @@ public class SqlDialectFactory {
|
|||||||
sqlDialectMap.put(EngineType.H2, new SemanticSqlDialect(DEFAULT_CONTEXT));
|
sqlDialectMap.put(EngineType.H2, new SemanticSqlDialect(DEFAULT_CONTEXT));
|
||||||
sqlDialectMap.put(EngineType.POSTGRESQL, new SemanticSqlDialect(POSTGRESQL_CONTEXT));
|
sqlDialectMap.put(EngineType.POSTGRESQL, new SemanticSqlDialect(POSTGRESQL_CONTEXT));
|
||||||
sqlDialectMap.put(EngineType.HANADB, new SemanticSqlDialect(HANADB_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) {
|
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 com.tencent.supersonic.common.pojo.enums.EngineType;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.calcite.sql.SqlIdentifier;
|
import net.sf.jsqlparser.expression.Alias;
|
||||||
import org.apache.calcite.sql.SqlLiteral;
|
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||||
import org.apache.calcite.sql.SqlNode;
|
import net.sf.jsqlparser.statement.select.ParenthesedSelect;
|
||||||
import org.apache.calcite.sql.SqlNodeList;
|
import net.sf.jsqlparser.statement.select.Select;
|
||||||
import org.apache.calcite.sql.SqlOrderBy;
|
import net.sf.jsqlparser.statement.select.WithItem;
|
||||||
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 java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -22,85 +14,37 @@ import java.util.List;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class SqlMergeWithUtils {
|
public class SqlMergeWithUtils {
|
||||||
public static String mergeWith(EngineType engineType, String sql, List<String> parentSqlList,
|
public static String mergeWith(EngineType engineType, String sql, List<String> parentSqlList,
|
||||||
List<String> parentWithNameList) throws SqlParseException {
|
List<String> parentWithNameList) throws Exception {
|
||||||
SqlParser.Config parserConfig = Configuration.getParserConfig(engineType);
|
|
||||||
|
|
||||||
// Parse the main SQL statement
|
Select selectStatement = (Select) CCJSqlParserUtil.parse(sql);
|
||||||
SqlParser parser = SqlParser.create(sql, parserConfig);
|
List<WithItem> withItemList = new ArrayList<>();
|
||||||
SqlNode sqlNode1 = parser.parseQuery();
|
|
||||||
|
|
||||||
// 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++) {
|
for (int i = 0; i < parentSqlList.size(); i++) {
|
||||||
String parentSql = parentSqlList.get(i);
|
String parentSql = parentSqlList.get(i);
|
||||||
String parentWithName = parentWithNameList.get(i);
|
String parentWithName = parentWithNameList.get(i);
|
||||||
|
|
||||||
// Parse the parent SQL statement
|
Select parentSelect = (Select) CCJSqlParserUtil.parse(parentSql);
|
||||||
parser = SqlParser.create(parentSql, parserConfig);
|
ParenthesedSelect select = new ParenthesedSelect();
|
||||||
SqlNode sqlNode2 = parser.parseQuery();
|
select.setSelect(parentSelect);
|
||||||
|
|
||||||
// Create a new WITH item for parentWithName without quotes
|
// Create a new WITH item for parentWithName without quotes
|
||||||
SqlWithItem withItem = new SqlWithItem(SqlParserPos.ZERO,
|
WithItem withItem = new WithItem();
|
||||||
new SqlIdentifier(parentWithName, SqlParserPos.ZERO), null, sqlNode2,
|
withItem.setAlias(new Alias(parentWithName));
|
||||||
SqlLiteral.createBoolean(false, SqlParserPos.ZERO));
|
withItem.setSelect(select);
|
||||||
|
|
||||||
// Add the new WITH item to the list
|
// Add the new WITH item to the list
|
||||||
withItemList.add(withItem);
|
withItemList.add(withItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the main SQL node contains an ORDER BY or LIMIT clause
|
// Extract existing WITH items from mainSelectBody if it has any
|
||||||
SqlNode limitNode = null;
|
if (selectStatement.getWithItemsList() != null) {
|
||||||
SqlNodeList orderByList = null;
|
withItemList.addAll(selectStatement.getWithItemsList());
|
||||||
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 sqlNode1 if it is a SqlWith
|
// Set the new WITH items list to the main select body
|
||||||
if (sqlNode1 instanceof SqlWith) {
|
selectStatement.setWithItemsList(withItemList);
|
||||||
SqlWith sqlWith = (SqlWith) sqlNode1;
|
|
||||||
withItemList.addAll(sqlWith.withList.getList());
|
|
||||||
sqlNode1 = sqlWith.body;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
// Pretty print the final SQL
|
||||||
SqlPrettyWriter writer = new SqlPrettyWriter(config);
|
return selectStatement.toString();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,8 @@ public class FiledFilterReplaceVisitor extends ExpressionVisitorAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExpressionList<?> leftFunctionParams = leftFunction.getParameters();
|
ExpressionList<?> leftFunctionParams = leftFunction.getParameters();
|
||||||
if (CollectionUtils.isEmpty(leftFunctionParams)) {
|
if (CollectionUtils.isEmpty(leftFunctionParams)
|
||||||
|
|| !(leftFunctionParams.get(0) instanceof Column)) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -989,6 +989,15 @@ public class SqlSelectHelper {
|
|||||||
for (SelectItem selectItem : selectItems) {
|
for (SelectItem selectItem : selectItems) {
|
||||||
selectItem.accept(visitor);
|
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();
|
return !visitor.getFunctionNames().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.tencent.supersonic.common.pojo;
|
|||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import static com.tencent.supersonic.common.pojo.Constants.ASC_UPPER;
|
import static com.tencent.supersonic.common.pojo.Constants.ASC_UPPER;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.tencent.supersonic.common.calcite;
|
|||||||
|
|
||||||
import com.tencent.supersonic.common.pojo.enums.EngineType;
|
import com.tencent.supersonic.common.pojo.enums.EngineType;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.calcite.sql.parser.SqlParseException;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@@ -12,7 +11,7 @@ import java.util.Collections;
|
|||||||
class SqlWithMergerTest {
|
class SqlWithMergerTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void test1() throws SqlParseException {
|
void test1() throws Exception {
|
||||||
String sql1 = "WITH DepartmentVisits AS (\n" + " SELECT department, SUM(pv) AS 总访问次数\n"
|
String sql1 = "WITH DepartmentVisits AS (\n" + " SELECT department, SUM(pv) AS 总访问次数\n"
|
||||||
+ " FROM t_1\n"
|
+ " FROM t_1\n"
|
||||||
+ " WHERE sys_imp_date >= '2024-09-01' AND sys_imp_date <= '2024-09-29'\n"
|
+ " WHERE sys_imp_date >= '2024-09-01' AND sys_imp_date <= '2024-09-29'\n"
|
||||||
@@ -38,7 +37,7 @@ class SqlWithMergerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void test2() throws SqlParseException {
|
void test2() throws Exception {
|
||||||
|
|
||||||
String sql1 =
|
String sql1 =
|
||||||
"WITH DepartmentVisits AS (SELECT department, SUM(pv) AS 总访问次数 FROM t_1 WHERE sys_imp_date >= '2024-08-28' "
|
"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
|
@Test
|
||||||
void test3() throws SqlParseException {
|
void test3() throws Exception {
|
||||||
|
|
||||||
String sql1 = "SELECT COUNT(*) FROM DepartmentVisits WHERE 总访问次数 > 100 LIMIT 1000";
|
String sql1 = "SELECT COUNT(*) FROM DepartmentVisits WHERE 总访问次数 > 100 LIMIT 1000";
|
||||||
|
|
||||||
@@ -89,7 +88,7 @@ class SqlWithMergerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void test4() throws SqlParseException {
|
void test4() throws Exception {
|
||||||
String sql1 = "SELECT COUNT(*) FROM DepartmentVisits WHERE 总访问次数 > 100";
|
String sql1 = "SELECT COUNT(*) FROM DepartmentVisits WHERE 总访问次数 > 100";
|
||||||
|
|
||||||
String sql2 =
|
String sql2 =
|
||||||
@@ -112,7 +111,7 @@ class SqlWithMergerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void test5() throws SqlParseException {
|
void test5() throws Exception {
|
||||||
|
|
||||||
String sql1 = "SELECT COUNT(*) FROM Department join Visits WHERE 总访问次数 > 100";
|
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` "
|
"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 "
|
+ "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`) "
|
+ "(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");
|
+ "WHERE 总访问次数 > 100");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void test6() throws SqlParseException {
|
void test6() throws Exception {
|
||||||
|
|
||||||
String sql1 =
|
String sql1 =
|
||||||
"SELECT COUNT(*) FROM Department join Visits WHERE 总访问次数 > 100 ORDER BY 总访问次数 LIMIT 10";
|
"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 "
|
"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`,"
|
+ "(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`) "
|
+ " `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) {
|
private static String format(String mergeSql) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "15432:5432"
|
- "15432:5432"
|
||||||
# volumes:
|
# volumes:
|
||||||
# - postgres_data:/var/lib/postgresql
|
# - postgres_data:/var/lib/postgresql/data
|
||||||
networks:
|
networks:
|
||||||
- supersonic_network
|
- supersonic_network
|
||||||
dns:
|
dns:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.tencent.supersonic.headless.core.translator;
|
package com.tencent.supersonic.headless.core.translator;
|
||||||
|
|
||||||
import com.tencent.supersonic.common.calcite.SqlMergeWithUtils;
|
import com.tencent.supersonic.common.calcite.SqlMergeWithUtils;
|
||||||
|
import com.tencent.supersonic.common.jsqlparser.SqlSelectHelper;
|
||||||
import com.tencent.supersonic.common.pojo.enums.EngineType;
|
import com.tencent.supersonic.common.pojo.enums.EngineType;
|
||||||
import com.tencent.supersonic.headless.api.pojo.response.QueryState;
|
import com.tencent.supersonic.headless.api.pojo.response.QueryState;
|
||||||
import com.tencent.supersonic.headless.core.pojo.OntologyQuery;
|
import com.tencent.supersonic.headless.core.pojo.OntologyQuery;
|
||||||
@@ -73,7 +74,7 @@ public class DefaultSemanticTranslator implements SemanticTranslator {
|
|||||||
String finalSql = null;
|
String finalSql = null;
|
||||||
if (sqlQuery.isSupportWith()) {
|
if (sqlQuery.isSupportWith()) {
|
||||||
EngineType engineType = queryStatement.getOntology().getDatabaseType();
|
EngineType engineType = queryStatement.getOntology().getDatabaseType();
|
||||||
if (!SqlMergeWithUtils.hasWith(engineType, ontologyOuterSql)) {
|
if (!SqlSelectHelper.hasWith(ontologyOuterSql)) {
|
||||||
finalSql = "with " + tables.stream()
|
finalSql = "with " + tables.stream()
|
||||||
.map(t -> String.format("%s as (%s)", t.getLeft(), t.getRight()))
|
.map(t -> String.format("%s as (%s)", t.getLeft(), t.getRight()))
|
||||||
.collect(Collectors.joining(",")) + "\n" + ontologyOuterSql;
|
.collect(Collectors.joining(",")) + "\n" + ontologyOuterSql;
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ public abstract class SemanticNode {
|
|||||||
scope.getValidator().getCatalogReader().getRootSchema(), engineType);
|
scope.getValidator().getCatalogReader().getRootSchema(), engineType);
|
||||||
if (Configuration.getSqlAdvisor(sqlValidatorWithHints, engineType).getReservedAndKeyWords()
|
if (Configuration.getSqlAdvisor(sqlValidatorWithHints, engineType).getReservedAndKeyWords()
|
||||||
.contains(expression.toUpperCase())) {
|
.contains(expression.toUpperCase())) {
|
||||||
if (engineType == EngineType.HANADB) {
|
if (engineType == EngineType.HANADB || engineType == EngineType.PRESTO
|
||||||
|
|| engineType == EngineType.TRINO) {
|
||||||
expression = String.format("\"%s\"", expression);
|
expression = String.format("\"%s\"", expression);
|
||||||
} else {
|
} else {
|
||||||
expression = String.format("`%s`", expression);
|
expression = String.format("`%s`", expression);
|
||||||
@@ -166,9 +167,9 @@ public abstract class SemanticNode {
|
|||||||
if (sqlNode instanceof SqlBasicCall) {
|
if (sqlNode instanceof SqlBasicCall) {
|
||||||
SqlBasicCall sqlBasicCall = (SqlBasicCall) sqlNode;
|
SqlBasicCall sqlBasicCall = (SqlBasicCall) sqlNode;
|
||||||
if (sqlBasicCall.getOperator().getKind().equals(SqlKind.AS)) {
|
if (sqlBasicCall.getOperator().getKind().equals(SqlKind.AS)) {
|
||||||
if (sqlBasicCall.getOperandList().get(0) instanceof SqlSelect) {
|
SqlNode innerQuery = sqlBasicCall.getOperandList().get(0);
|
||||||
SqlSelect table = (SqlSelect) sqlBasicCall.getOperandList().get(0);
|
if (innerQuery instanceof SqlCall) {
|
||||||
return table;
|
return innerQuery;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,13 @@ public class SqlBuilder {
|
|||||||
SqlNode parserNode = tableView.build();
|
SqlNode parserNode = tableView.build();
|
||||||
DatabaseResp database = queryStatement.getOntology().getDatabase();
|
DatabaseResp database = queryStatement.getOntology().getDatabase();
|
||||||
EngineType engineType = EngineType.fromString(database.getType());
|
EngineType engineType = EngineType.fromString(database.getType());
|
||||||
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);
|
return SemanticNode.getSql(parserNode, engineType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.tencent.supersonic.headless.server.rest;
|
|||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
|
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
|
||||||
import com.tencent.supersonic.common.pojo.User;
|
import com.tencent.supersonic.common.pojo.User;
|
||||||
|
import com.tencent.supersonic.common.pojo.enums.StatusEnum;
|
||||||
import com.tencent.supersonic.headless.api.pojo.MetaFilter;
|
import com.tencent.supersonic.headless.api.pojo.MetaFilter;
|
||||||
import com.tencent.supersonic.headless.api.pojo.request.DataSetReq;
|
import com.tencent.supersonic.headless.api.pojo.request.DataSetReq;
|
||||||
import com.tencent.supersonic.headless.api.pojo.response.DataSetResp;
|
import com.tencent.supersonic.headless.api.pojo.response.DataSetResp;
|
||||||
@@ -51,6 +52,7 @@ public class DataSetController {
|
|||||||
public List<DataSetResp> getDataSetList(@RequestParam("domainId") Long domainId) {
|
public List<DataSetResp> getDataSetList(@RequestParam("domainId") Long domainId) {
|
||||||
MetaFilter metaFilter = new MetaFilter();
|
MetaFilter metaFilter = new MetaFilter();
|
||||||
metaFilter.setDomainId(domainId);
|
metaFilter.setDomainId(domainId);
|
||||||
|
metaFilter.setStatus(StatusEnum.ONLINE.getCode());
|
||||||
return dataSetService.getDataSetList(metaFilter);
|
return dataSetService.getDataSetList(metaFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,9 +56,9 @@ public class DataSetServiceImpl extends ServiceImpl<DataSetDOMapper, DataSetDO>
|
|||||||
public DataSetResp save(DataSetReq dataSetReq, User user) {
|
public DataSetResp save(DataSetReq dataSetReq, User user) {
|
||||||
dataSetReq.createdBy(user.getName());
|
dataSetReq.createdBy(user.getName());
|
||||||
DataSetDO dataSetDO = convert(dataSetReq);
|
DataSetDO dataSetDO = convert(dataSetReq);
|
||||||
dataSetDO.setStatus(StatusEnum.ONLINE.getCode());
|
dataSetDO.setStatus(dataSetReq.getStatus() != null ? dataSetReq.getStatus()
|
||||||
|
: StatusEnum.ONLINE.getCode());
|
||||||
DataSetResp dataSetResp = convert(dataSetDO);
|
DataSetResp dataSetResp = convert(dataSetDO);
|
||||||
// conflictCheck(dataSetResp);
|
|
||||||
save(dataSetDO);
|
save(dataSetDO);
|
||||||
dataSetResp.setId(dataSetDO.getId());
|
dataSetResp.setId(dataSetDO.getId());
|
||||||
return dataSetResp;
|
return dataSetResp;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.tencent.supersonic.common.pojo.QueryColumn;
|
import com.tencent.supersonic.common.pojo.QueryColumn;
|
||||||
import com.tencent.supersonic.common.pojo.User;
|
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.common.pojo.enums.EngineType;
|
||||||
import com.tencent.supersonic.headless.api.pojo.DBColumn;
|
import com.tencent.supersonic.headless.api.pojo.DBColumn;
|
||||||
import com.tencent.supersonic.headless.api.pojo.enums.DataType;
|
import com.tencent.supersonic.headless.api.pojo.enums.DataType;
|
||||||
@@ -79,8 +80,9 @@ public class DatabaseServiceImpl extends ServiceImpl<DatabaseDOMapper, DatabaseD
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DatabaseResp> getDatabaseList(User user) {
|
public List<DatabaseResp> getDatabaseList(User user) {
|
||||||
List<DatabaseResp> databaseResps =
|
List<DatabaseResp> databaseResps = list().stream().map(DatabaseConverter::convert)
|
||||||
list().stream().map(DatabaseConverter::convert).collect(Collectors.toList());
|
.filter(database -> filterByAuth(database, user, AuthType.VIEWER))
|
||||||
|
.collect(Collectors.toList());
|
||||||
fillPermission(databaseResps, user);
|
fillPermission(databaseResps, user);
|
||||||
return databaseResps;
|
return databaseResps;
|
||||||
}
|
}
|
||||||
@@ -100,6 +102,43 @@ public class DatabaseServiceImpl extends ServiceImpl<DatabaseDOMapper, DatabaseD
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean filterByAuth(DatabaseResp database, User user, AuthType authType) {
|
||||||
|
if (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
|
@Override
|
||||||
public void deleteDatabase(Long databaseId) {
|
public void deleteDatabase(Long databaseId) {
|
||||||
ModelFilter modelFilter = new ModelFilter();
|
ModelFilter modelFilter = new ModelFilter();
|
||||||
|
|||||||
@@ -425,8 +425,12 @@ public class DictUtils {
|
|||||||
.format(DateTimeFormatter.ofPattern(format));
|
.format(DateTimeFormatter.ofPattern(format));
|
||||||
String end = LocalDate.now().minusDays(itemValueDateEnd)
|
String end = LocalDate.now().minusDays(itemValueDateEnd)
|
||||||
.format(DateTimeFormatter.ofPattern(format));
|
.format(DateTimeFormatter.ofPattern(format));
|
||||||
return String.format("( %s >= '%s' and %s <= '%s' )", dateConf.getDateField(), start,
|
if (Objects.nonNull(dateConf)) {
|
||||||
dateConf.getDateField(), end);
|
return String.format("( %s >= '%s' and %s <= '%s' )", dateConf.getDateField(), start,
|
||||||
|
dateConf.getDateField(), end);
|
||||||
|
} else {
|
||||||
|
return String.format("( %s >= '%s' and %s <= '%s' )", "dt", start, "dt", end);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String generateDictDateFilter(DictItemResp dictItemResp) {
|
private String generateDictDateFilter(DictItemResp dictItemResp) {
|
||||||
@@ -440,7 +444,7 @@ public class DictUtils {
|
|||||||
}
|
}
|
||||||
// 未进行设置
|
// 未进行设置
|
||||||
if (Objects.isNull(config) || Objects.isNull(config.getDateConf())) {
|
if (Objects.isNull(config) || Objects.isNull(config.getDateConf())) {
|
||||||
return defaultDateFilter(config.getDateConf());
|
return defaultDateFilter(null);
|
||||||
}
|
}
|
||||||
// 全表扫描
|
// 全表扫描
|
||||||
if (DateConf.DateMode.ALL.equals(config.getDateConf().getDateMode())) {
|
if (DateConf.DateMode.ALL.equals(config.getDateConf().getDateMode())) {
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@@ -26,7 +26,7 @@
|
|||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>0.9.10</revision>
|
<revision>1.0.0-SNAPSHOT</revision>
|
||||||
<java.source.version>21</java.source.version>
|
<java.source.version>21</java.source.version>
|
||||||
<java.target.version>21</java.target.version>
|
<java.target.version>21</java.target.version>
|
||||||
<maven.compiler.source>21</maven.compiler.source>
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
|||||||
Reference in New Issue
Block a user