From 732222ab98efc5c50d106f24958fece6347ea94e Mon Sep 17 00:00:00 2001 From: jerryjzhang Date: Wed, 5 Mar 2025 14:29:40 +0800 Subject: [PATCH 1/3] (fix)(headless)Fix database permission check. (fix)(headless)Fix database permission check. --- .../service/impl/DatabaseServiceImpl.java | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/impl/DatabaseServiceImpl.java b/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/impl/DatabaseServiceImpl.java index b26aac388..89b84f30c 100644 --- a/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/impl/DatabaseServiceImpl.java +++ b/headless/server/src/main/java/com/tencent/supersonic/headless/server/service/impl/DatabaseServiceImpl.java @@ -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 getDatabaseList(User user) { - List databaseResps = - list().stream().map(DatabaseConverter::convert).collect(Collectors.toList()); + List databaseResps = list().stream().map(DatabaseConverter::convert) + .filter(database -> filterByAuth(database, user, AuthType.VIEWER)) + .collect(Collectors.toList()); fillPermission(databaseResps, user); return databaseResps; } @@ -100,6 +102,43 @@ public class DatabaseServiceImpl extends ServiceImpl 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 viewers = database.getViewers(); + + if (viewers.contains(user.getName())) { + return true; + } + return false; + } + @Override public void deleteDatabase(Long databaseId) { ModelFilter modelFilter = new ModelFilter(); From efddf4cacf61f62bef3f672c95eabd03925a453a Mon Sep 17 00:00:00 2001 From: zyclove Date: Wed, 5 Mar 2025 14:54:16 +0800 Subject: [PATCH 2/3] fix: https://github.com/tencentmusic/supersonic/issues/2132 (#2137) --- .../common/calcite/SqlDialectFactory.java | 14 ++++++++++++++ .../translator/parser/calcite/SemanticNode.java | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/com/tencent/supersonic/common/calcite/SqlDialectFactory.java b/common/src/main/java/com/tencent/supersonic/common/calcite/SqlDialectFactory.java index ab7aea92f..c82db0f4e 100644 --- a/common/src/main/java/com/tencent/supersonic/common/calcite/SqlDialectFactory.java +++ b/common/src/main/java/com/tencent/supersonic/common/calcite/SqlDialectFactory.java @@ -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 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) { diff --git a/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/parser/calcite/SemanticNode.java b/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/parser/calcite/SemanticNode.java index b4096e555..9f85d4abb 100644 --- a/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/parser/calcite/SemanticNode.java +++ b/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/parser/calcite/SemanticNode.java @@ -78,7 +78,7 @@ 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); From e0dc3fbf1a3a6f84f106c5e296c5f8cd4f60b67b Mon Sep 17 00:00:00 2001 From: jerryjzhang Date: Wed, 5 Mar 2025 16:48:40 +0800 Subject: [PATCH 3/3] (improvement)(headless)Optimize compatibility and robustness in ontology query translation. (improvement)(headless)Optimize compatibility and robustness in ontology query translation. --- .../common/jsqlparser/FiledFilterReplaceVisitor.java | 3 ++- .../core/translator/parser/calcite/SemanticNode.java | 9 +++++---- .../core/translator/parser/calcite/SqlBuilder.java | 8 +++++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/com/tencent/supersonic/common/jsqlparser/FiledFilterReplaceVisitor.java b/common/src/main/java/com/tencent/supersonic/common/jsqlparser/FiledFilterReplaceVisitor.java index 448ac06a4..8758cf9c1 100644 --- a/common/src/main/java/com/tencent/supersonic/common/jsqlparser/FiledFilterReplaceVisitor.java +++ b/common/src/main/java/com/tencent/supersonic/common/jsqlparser/FiledFilterReplaceVisitor.java @@ -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; } diff --git a/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/parser/calcite/SemanticNode.java b/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/parser/calcite/SemanticNode.java index 9f85d4abb..8757d3e6d 100644 --- a/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/parser/calcite/SemanticNode.java +++ b/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/parser/calcite/SemanticNode.java @@ -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 || engineType == EngineType.PRESTO || engineType == EngineType.TRINO) { + 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; } } } diff --git a/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/parser/calcite/SqlBuilder.java b/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/parser/calcite/SqlBuilder.java index 3617d6df4..b9db3dc5d 100644 --- a/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/parser/calcite/SqlBuilder.java +++ b/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/parser/calcite/SqlBuilder.java @@ -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); }