This is an automated email from the ASF dual-hosted git repository. morningman pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push: new db8d18eb40 [Enhance](auth)row policy support role (#23022) db8d18eb40 is described below commit db8d18eb40d152f342754c9e3da6a0679d7399dc Author: zhangdong <493738...@qq.com> AuthorDate: Sat Aug 26 10:24:59 2023 +0800 [Enhance](auth)row policy support role (#23022) ``` CREATE ROW POLICY test_row_policy_1 ON test.table1 AS {RESTRICTIVE|PERMISSIVE} [TO user] [TO ROLE role] USING (id in (1, 2)); // add `to role` DROP [ROW] POLICY [IF EXISTS] test_row_policy;//delete `for user` and `on table` SHOW ROW POLICY [FOR user][FOR ROLE role] // add `for role` ``` --- .../antlr4/org/apache/doris/nereids/DorisParser.g4 | 2 +- fe/fe-core/src/main/cup/sql_parser.cup | 27 ++- .../apache/doris/analysis/CreatePolicyStmt.java | 26 ++- .../org/apache/doris/analysis/DropPolicyStmt.java | 28 +-- .../org/apache/doris/analysis/ShowPolicyStmt.java | 12 +- .../org/apache/doris/analysis/StmtRewriter.java | 7 +- .../doris/nereids/parser/LogicalPlanBuilder.java | 4 +- .../trees/plans/commands/CreatePolicyCommand.java | 4 +- .../trees/plans/logical/LogicalCheckPolicy.java | 6 +- .../org/apache/doris/policy/DropPolicyLog.java | 30 +-- .../main/java/org/apache/doris/policy/Policy.java | 11 +- .../java/org/apache/doris/policy/PolicyMgr.java | 221 ++++++++++----------- .../java/org/apache/doris/policy/RowPolicy.java | 49 ++--- .../nereids/rules/analysis/CheckRowPolicyTest.java | 5 +- .../java/org/apache/doris/policy/PolicyTest.java | 148 ++++++++++---- .../account_p0/test_nereids_row_policy.groovy | 2 +- 16 files changed, 310 insertions(+), 272 deletions(-) diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 index 2b014d3610..cd178cd220 100644 --- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 +++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 @@ -38,7 +38,7 @@ statement | CREATE ROW POLICY (IF NOT EXISTS)? name=identifier ON table=multipartIdentifier AS type=(RESTRICTIVE | PERMISSIVE) - TO user=userIdentify + TO (user=userIdentify | ROLE roleName=identifier) USING LEFT_PAREN booleanExpression RIGHT_PAREN #createRowPolicy | explain? INSERT INTO tableName=multipartIdentifier (PARTITION partition=identifierList)? // partition define diff --git a/fe/fe-core/src/main/cup/sql_parser.cup b/fe/fe-core/src/main/cup/sql_parser.cup index c4258b2330..19d4c22037 100644 --- a/fe/fe-core/src/main/cup/sql_parser.cup +++ b/fe/fe-core/src/main/cup/sql_parser.cup @@ -1999,7 +1999,12 @@ create_stmt ::= | KW_CREATE KW_ROW KW_POLICY opt_if_not_exists:ifNotExists ident:policyName KW_ON table_name:tbl KW_AS ident:filterType KW_TO user_identity:user KW_USING LPAREN expr:wherePredicate RPAREN {: - RESULT = new CreatePolicyStmt(PolicyTypeEnum.ROW, ifNotExists, policyName, tbl, filterType, user, wherePredicate); + RESULT = new CreatePolicyStmt(PolicyTypeEnum.ROW, ifNotExists, policyName, tbl, filterType, user, null, wherePredicate); + :} + | KW_CREATE KW_ROW KW_POLICY opt_if_not_exists:ifNotExists ident:policyName KW_ON table_name:tbl KW_AS ident:filterType KW_TO KW_ROLE ident:role + KW_USING LPAREN expr:wherePredicate RPAREN + {: + RESULT = new CreatePolicyStmt(PolicyTypeEnum.ROW, ifNotExists, policyName, tbl, filterType, null, role, wherePredicate); :} /* storage policy */ | KW_CREATE KW_STORAGE KW_POLICY opt_if_not_exists:ifNotExists ident:policyName opt_properties:properties @@ -3133,17 +3138,13 @@ drop_stmt ::= {: RESULT = new DropSqlBlockRuleStmt(ifExists, ruleNames); :} - | KW_DROP KW_ROW KW_POLICY opt_if_exists:ifExists ident:policyName KW_ON table_name:tbl + | KW_DROP KW_ROW KW_POLICY opt_if_exists:ifExists ident:policyName {: - RESULT = new DropPolicyStmt(PolicyTypeEnum.ROW, ifExists, policyName, tbl, null); - :} - | KW_DROP KW_ROW KW_POLICY opt_if_exists:ifExists ident:policyName KW_ON table_name:tbl KW_FOR user_identity:user - {: - RESULT = new DropPolicyStmt(PolicyTypeEnum.ROW, ifExists, policyName, tbl, user); + RESULT = new DropPolicyStmt(PolicyTypeEnum.ROW, ifExists, policyName); :} | KW_DROP KW_STORAGE KW_POLICY opt_if_exists:ifExists ident:policyName {: - RESULT = new DropPolicyStmt(PolicyTypeEnum.STORAGE, ifExists, policyName, null, null); + RESULT = new DropPolicyStmt(PolicyTypeEnum.STORAGE, ifExists, policyName); :} /* statistics */ | KW_DROP KW_STATS table_name:tbl opt_col_list:cols @@ -3793,15 +3794,19 @@ show_stmt ::= :} | KW_SHOW KW_ROW KW_POLICY KW_FOR user_identity:user {: - RESULT = new ShowPolicyStmt(PolicyTypeEnum.ROW, user); + RESULT = new ShowPolicyStmt(PolicyTypeEnum.ROW, user, null); + :} + | KW_SHOW KW_ROW KW_POLICY KW_FOR KW_ROLE STRING_LITERAL:role + {: + RESULT = new ShowPolicyStmt(PolicyTypeEnum.ROW, null, role); :} | KW_SHOW KW_ROW KW_POLICY {: - RESULT = new ShowPolicyStmt(PolicyTypeEnum.ROW, null); + RESULT = new ShowPolicyStmt(PolicyTypeEnum.ROW, null, null); :} | KW_SHOW KW_STORAGE KW_POLICY {: - RESULT = new ShowPolicyStmt(PolicyTypeEnum.STORAGE, null); + RESULT = new ShowPolicyStmt(PolicyTypeEnum.STORAGE, null, null); :} ; diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreatePolicyStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreatePolicyStmt.java index 7b38af073c..06430a8bd9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreatePolicyStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreatePolicyStmt.java @@ -57,6 +57,9 @@ public class CreatePolicyStmt extends DdlStmt { @Getter private UserIdentity user = null; + @Getter + private String roleName = null; + @Getter private Expr wherePredicate; @@ -67,13 +70,14 @@ public class CreatePolicyStmt extends DdlStmt { * Use for cup. **/ public CreatePolicyStmt(PolicyTypeEnum type, boolean ifNotExists, String policyName, TableName tableName, - String filterType, UserIdentity user, Expr wherePredicate) { + String filterType, UserIdentity user, String roleName, Expr wherePredicate) { this.type = type; this.ifNotExists = ifNotExists; this.policyName = policyName; this.tableName = tableName; this.filterType = FilterType.of(filterType); this.user = user; + this.roleName = roleName; this.wherePredicate = wherePredicate; } @@ -81,7 +85,7 @@ public class CreatePolicyStmt extends DdlStmt { * Use for cup. */ public CreatePolicyStmt(PolicyTypeEnum type, boolean ifNotExists, String policyName, - Map<String, String> properties) { + Map<String, String> properties) { this.type = type; this.ifNotExists = ifNotExists; this.policyName = policyName; @@ -101,10 +105,12 @@ public class CreatePolicyStmt extends DdlStmt { case ROW: default: tableName.analyze(analyzer); - user.analyze(analyzer.getClusterName()); - if (user.isRootUser() || user.isAdminUser()) { - ErrorReport.reportAnalysisException(ErrorCode.ERR_TABLEACCESS_DENIED_ERROR, "CreatePolicyStmt", - user.getQualifiedUser(), user.getHost(), tableName.getTbl()); + if (user != null) { + user.analyze(analyzer.getClusterName()); + if (user.isRootUser() || user.isAdminUser()) { + ErrorReport.reportAnalysisException(ErrorCode.ERR_TABLEACCESS_DENIED_ERROR, "CreatePolicyStmt", + user.getQualifiedUser(), user.getHost(), tableName.getTbl()); + } } } // check auth @@ -128,7 +134,13 @@ public class CreatePolicyStmt extends DdlStmt { case ROW: default: sb.append(" ON ").append(tableName.toSql()).append(" AS ").append(filterType) - .append(" TO ").append(user.getQualifiedUser()).append(" USING ").append(wherePredicate.toSql()); + .append(" TO "); + if (user == null) { + sb.append("ROLE ").append(roleName); + } else { + sb.append(user.getQualifiedUser()); + } + sb.append(" USING ").append(wherePredicate.toSql()); } return sb.toString(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DropPolicyStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DropPolicyStmt.java index bd3fb0f375..541206bef0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DropPolicyStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DropPolicyStmt.java @@ -31,7 +31,7 @@ import lombok.Getter; /** * Drop policy statement. * syntax: - * DROP [ROW] POLICY [IF EXISTS] test_row_policy ON test_table [FOR user] + * DROP [ROW] POLICY [IF EXISTS] test_row_policy **/ @AllArgsConstructor public class DropPolicyStmt extends DdlStmt { @@ -45,25 +45,9 @@ public class DropPolicyStmt extends DdlStmt { @Getter private final String policyName; - @Getter - private final TableName tableName; - - @Getter - private final UserIdentity user; - @Override public void analyze(Analyzer analyzer) throws UserException { super.analyze(analyzer); - switch (type) { - case STORAGE: - break; - case ROW: - default: - tableName.analyze(analyzer); - if (user != null) { - user.analyze(analyzer.getClusterName()); - } - } // check auth if (!Env.getCurrentEnv().getAccessManager().checkGlobalPriv(ConnectContext.get(), PrivPredicate.ADMIN)) { ErrorReport.reportAnalysisException(ErrorCode.ERR_SPECIFIC_ACCESS_DENIED_ERROR, "ADMIN"); @@ -78,16 +62,6 @@ public class DropPolicyStmt extends DdlStmt { sb.append("IF EXISTS "); } sb.append(policyName); - switch (type) { - case STORAGE: - break; - case ROW: - default: - sb.append(" ON ").append(tableName.toSql()); - if (user != null) { - sb.append(" FOR ").append(user.getQualifiedUser()); - } - } return sb.toString(); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowPolicyStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowPolicyStmt.java index 9cc8ba549f..8da1ea4b43 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowPolicyStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowPolicyStmt.java @@ -29,11 +29,12 @@ import org.apache.doris.qe.ConnectContext; import org.apache.doris.qe.ShowResultSetMetaData; import lombok.Getter; +import org.apache.commons.lang3.StringUtils; /** * Show policy statement * syntax: - * SHOW ROW POLICY [FOR user] + * SHOW ROW POLICY [FOR user|ROLE role] **/ public class ShowPolicyStmt extends ShowStmt { @@ -43,9 +44,13 @@ public class ShowPolicyStmt extends ShowStmt { @Getter private final UserIdentity user; - public ShowPolicyStmt(PolicyTypeEnum type, UserIdentity user) { + @Getter + private final String roleName; + + public ShowPolicyStmt(PolicyTypeEnum type, UserIdentity user, String roleName) { this.type = type; this.user = user; + this.roleName = roleName; } @Override @@ -72,6 +77,9 @@ public class ShowPolicyStmt extends ShowStmt { if (user != null) { sb.append(" FOR ").append(user); } + if (!StringUtils.isEmpty(roleName)) { + sb.append(" FOR ROLE ").append(roleName); + } } return sb.toString(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/StmtRewriter.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/StmtRewriter.java index b15db8703f..89c1113bcc 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/StmtRewriter.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/StmtRewriter.java @@ -1293,13 +1293,10 @@ public class StmtRewriter { public static boolean rewriteByPolicy(StatementBase statementBase, Analyzer analyzer) throws UserException { Env currentEnv = Env.getCurrentEnv(); UserIdentity currentUserIdentity = ConnectContext.get().getCurrentUserIdentity(); - String user = analyzer.getQualifiedUser(); if (currentUserIdentity.isRootUser() || currentUserIdentity.isAdminUser()) { return false; } - if (!currentEnv.getPolicyMgr().existPolicy(user)) { - return false; - } + if (!(statementBase instanceof SelectStmt)) { return false; } @@ -1324,7 +1321,7 @@ public class StmtRewriter { .getDbOrAnalysisException(dbName); long dbId = db.getId(); long tableId = table.getId(); - RowPolicy matchPolicy = currentEnv.getPolicyMgr().getMatchTablePolicy(dbId, tableId, user); + RowPolicy matchPolicy = currentEnv.getPolicyMgr().getMatchTablePolicy(dbId, tableId, currentUserIdentity); if (matchPolicy == null) { continue; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java index 679e3d457e..f0a270bdb6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java @@ -458,7 +458,9 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { FilterType filterType = FilterType.of(ctx.type.getText()); List<String> nameParts = visitMultipartIdentifier(ctx.table); return new CreatePolicyCommand(PolicyTypeEnum.ROW, ctx.name.getText(), - ctx.EXISTS() != null, nameParts, Optional.of(filterType), visitUserIdentify(ctx.user), + ctx.EXISTS() != null, nameParts, Optional.of(filterType), + ctx.user == null ? null : visitUserIdentify(ctx.user), + ctx.roleName == null ? null : ctx.roleName.getText(), Optional.of(getExpression(ctx.booleanExpression())), ImmutableMap.of()); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreatePolicyCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreatePolicyCommand.java index 8509803589..318d1b5e79 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreatePolicyCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreatePolicyCommand.java @@ -39,6 +39,7 @@ public class CreatePolicyCommand extends Command implements ForwardWithSync { private final List<String> nameParts; private final Optional<FilterType> filterType; private final UserIdentity user; + private final String roleName; private final Optional<Expression> wherePredicate; private final Map<String, String> properties; @@ -46,7 +47,7 @@ public class CreatePolicyCommand extends Command implements ForwardWithSync { * ctor of this command. */ public CreatePolicyCommand(PolicyTypeEnum policyType, String policyName, boolean ifNotExists, - List<String> nameParts, Optional<FilterType> filterType, UserIdentity user, + List<String> nameParts, Optional<FilterType> filterType, UserIdentity user, String roleName, Optional<Expression> wherePredicate, Map<String, String> properties) { super(PlanType.CREATE_POLICY_COMMAND); this.policyType = policyType; @@ -55,6 +56,7 @@ public class CreatePolicyCommand extends Command implements ForwardWithSync { this.nameParts = nameParts; this.filterType = filterType; this.user = user; + this.roleName = roleName; this.wherePredicate = wherePredicate; this.properties = properties; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCheckPolicy.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCheckPolicy.java index 78578fa7b5..b9fc7ecfe6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCheckPolicy.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalCheckPolicy.java @@ -125,18 +125,14 @@ public class LogicalCheckPolicy<CHILD_TYPE extends Plan> extends LogicalUnary<CH PolicyMgr policyMgr = connectContext.getEnv().getPolicyMgr(); UserIdentity currentUserIdentity = connectContext.getCurrentUserIdentity(); - String user = connectContext.getQualifiedUser(); if (currentUserIdentity.isRootUser() || currentUserIdentity.isAdminUser()) { return Optional.empty(); } - if (!policyMgr.existPolicy(user)) { - return Optional.empty(); - } CatalogRelation catalogRelation = (CatalogRelation) logicalRelation; long dbId = catalogRelation.getDatabase().getId(); long tableId = catalogRelation.getTable().getId(); - List<RowPolicy> policies = policyMgr.getMatchRowPolicy(dbId, tableId, currentUserIdentity); + List<RowPolicy> policies = policyMgr.getUserPolicies(dbId, tableId, currentUserIdentity); if (policies.isEmpty()) { return Optional.empty(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/policy/DropPolicyLog.java b/fe/fe-core/src/main/java/org/apache/doris/policy/DropPolicyLog.java index 603dee86ed..7ff18ed413 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/policy/DropPolicyLog.java +++ b/fe/fe-core/src/main/java/org/apache/doris/policy/DropPolicyLog.java @@ -18,15 +18,10 @@ package org.apache.doris.policy; import org.apache.doris.analysis.DropPolicyStmt; -import org.apache.doris.analysis.UserIdentity; -import org.apache.doris.catalog.Database; -import org.apache.doris.catalog.Env; -import org.apache.doris.catalog.Table; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.io.Text; import org.apache.doris.common.io.Writable; import org.apache.doris.persist.gson.GsonUtils; -import org.apache.doris.qe.ConnectContext; import com.google.gson.annotations.SerializedName; import lombok.AllArgsConstructor; @@ -42,41 +37,18 @@ import java.io.IOException; @AllArgsConstructor @Getter public class DropPolicyLog implements Writable { - - @SerializedName(value = "dbId") - private long dbId; - - @SerializedName(value = "tableId") - private long tableId; - @SerializedName(value = "type") private PolicyTypeEnum type; @SerializedName(value = "policyName") private String policyName; - @SerializedName(value = "user") - private UserIdentity user; /** * Generate delete logs through stmt. **/ public static DropPolicyLog fromDropStmt(DropPolicyStmt stmt) throws AnalysisException { - switch (stmt.getType()) { - case STORAGE: - return new DropPolicyLog(-1, -1, stmt.getType(), stmt.getPolicyName(), null); - case ROW: - String curDb = stmt.getTableName().getDb(); - if (curDb == null) { - curDb = ConnectContext.get().getDatabase(); - } - Database db = Env.getCurrentInternalCatalog().getDbOrAnalysisException(curDb); - Table table = db.getTableOrAnalysisException(stmt.getTableName().getTbl()); - return new DropPolicyLog(db.getId(), table.getId(), stmt.getType(), - stmt.getPolicyName(), stmt.getUser()); - default: - throw new AnalysisException("Invalid policy type: " + stmt.getType().name()); - } + return new DropPolicyLog(stmt.getType(), stmt.getPolicyName()); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/policy/Policy.java b/fe/fe-core/src/main/java/org/apache/doris/policy/Policy.java index 8c1231f35d..b06cd19d0c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/policy/Policy.java +++ b/fe/fe-core/src/main/java/org/apache/doris/policy/Policy.java @@ -82,7 +82,8 @@ public abstract class Policy implements Writable, GsonPostProcessable { } // just for subclass lombok @Data - public Policy() {} + public Policy() { + } public Policy(PolicyTypeEnum type) { this.type = type; @@ -117,9 +118,11 @@ public abstract class Policy implements Writable, GsonPostProcessable { .getCatalogOrAnalysisException(stmt.getTableName().getCtl()) .getDbOrAnalysisException(stmt.getTableName().getDb()); UserIdentity userIdent = stmt.getUser(); - userIdent.analyze(ConnectContext.get().getClusterName()); + if (userIdent != null) { + userIdent.analyze(ConnectContext.get().getClusterName()); + } TableIf table = db.getTableOrAnalysisException(stmt.getTableName().getTbl()); - return new RowPolicy(policyId, stmt.getPolicyName(), db.getId(), userIdent, + return new RowPolicy(policyId, stmt.getPolicyName(), db.getId(), userIdent, stmt.getRoleName(), stmt.getOrigStmt().originStmt, table.getId(), stmt.getFilterType(), stmt.getWherePredicate()); default: throw new AnalysisException("Unknown policy type: " + stmt.getType()); @@ -149,7 +152,7 @@ public abstract class Policy implements Writable, GsonPostProcessable { protected boolean checkMatched(PolicyTypeEnum type, String policyName) { return (type == null || type.equals(this.type)) - && (policyName == null || StringUtils.equals(policyName, this.policyName)); + && (policyName == null || StringUtils.equals(policyName, this.policyName)); } // it is used to check whether this policy is in PolicyMgr diff --git a/fe/fe-core/src/main/java/org/apache/doris/policy/PolicyMgr.java b/fe/fe-core/src/main/java/org/apache/doris/policy/PolicyMgr.java index ce47793ffe..96004adf66 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/policy/PolicyMgr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/policy/PolicyMgr.java @@ -27,6 +27,7 @@ import org.apache.doris.catalog.Database; import org.apache.doris.catalog.Env; import org.apache.doris.catalog.OlapTable; import org.apache.doris.catalog.Table; +import org.apache.doris.cluster.ClusterNamespace; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.DdlException; import org.apache.doris.common.UserException; @@ -39,13 +40,13 @@ import org.apache.doris.task.AgentBatchTask; import org.apache.doris.task.AgentTaskExecutor; import org.apache.doris.task.PushStoragePolicyTask; -import com.google.common.base.Joiner; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import com.google.gson.annotations.SerializedName; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -54,8 +55,6 @@ import java.io.DataOutput; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -74,13 +73,8 @@ public class PolicyMgr implements Writable { @SerializedName(value = "typeToPolicyMap") private Map<PolicyTypeEnum, List<Policy>> typeToPolicyMap = Maps.newConcurrentMap(); - /** - * Cache merge policy for match. - * key:dbId:tableId-type-user - **/ - private Map<Long, Map<String, RowPolicy>> dbIdToMergeTablePolicyMap = Maps.newConcurrentMap(); - - private Set<String> userPolicySet = Sets.newConcurrentHashSet(); + // dbId -> tableId -> List<RowPolicy> + private Map<Long, Map<Long, List<RowPolicy>>> tablePolicies = Maps.newConcurrentMap(); private void writeLock() { lock.writeLock().lock(); @@ -173,16 +167,6 @@ public class PolicyMgr implements Writable { } } - /** - * Check whether this user has policy. - * - * @param user user who has policy - * @return exist or not - */ - public boolean existPolicy(String user) { - return userPolicySet.contains(user); - } - /** * Check whether the policy exist. * @@ -267,7 +251,10 @@ public class PolicyMgr implements Writable { List<Policy> dbPolicies = getPoliciesByType(policy.getType()); dbPolicies.add(policy); typeToPolicyMap.put(policy.getType(), dbPolicies); - updateMergeTablePolicyMap(); + if (PolicyTypeEnum.ROW == policy.getType()) { + addTablePolicies((RowPolicy) policy); + } + } public void replayDrop(DropPolicyLog log) { @@ -290,51 +277,88 @@ public class PolicyMgr implements Writable { if (policy instanceof StoragePolicy) { ((StoragePolicy) policy).removeResourceReference(); } + if (policy instanceof RowPolicy) { + dropTablePolicies((RowPolicy) policy); + } return true; } return false; }); typeToPolicyMap.put(log.getType(), policies); - updateMergeTablePolicyMap(); } /** * Match row policy and return it. **/ - public RowPolicy getMatchTablePolicy(long dbId, long tableId, String user) { + public RowPolicy getMatchTablePolicy(long dbId, long tableId, UserIdentity user) { + List<RowPolicy> res = getUserPolicies(dbId, tableId, user); + if (CollectionUtils.isEmpty(res)) { + return null; + } + return mergeRowPolicies(res); + } + + public List<RowPolicy> getUserPolicies(long dbId, long tableId, UserIdentity user) { + List<RowPolicy> res = Lists.newArrayList(); + // Make a judgment in advance to reduce the number of times to obtain getRoles + if (!tablePolicies.containsKey(dbId) || !tablePolicies.get(dbId).containsKey(tableId)) { + return res; + } + Set<String> roles = Env.getCurrentEnv().getAccessManager().getAuth().getRolesByUserWithLdap(user).stream() + .map(role -> ClusterNamespace.getNameFromFullName(role.getRoleName())).collect(Collectors.toSet()); readLock(); try { - if (!dbIdToMergeTablePolicyMap.containsKey(dbId)) { - return null; + // double check in lock,avoid NPE + if (!tablePolicies.containsKey(dbId) || !tablePolicies.get(dbId).containsKey(tableId)) { + return res; } - String key = Joiner.on("-").join(tableId, PolicyTypeEnum.ROW.name(), user); - if (!dbIdToMergeTablePolicyMap.get(dbId).containsKey(key)) { - return null; + List<RowPolicy> policys = tablePolicies.get(dbId).get(tableId); + for (RowPolicy rowPolicy : policys) { + // on rowPolicy to user + if ((rowPolicy.getUser() != null && rowPolicy.getUser().getQualifiedUser() + .equals(user.getQualifiedUser())) + || !StringUtils.isEmpty(rowPolicy.getRoleName()) && roles.contains(rowPolicy.getRoleName())) { + res.add(rowPolicy); + } } - return dbIdToMergeTablePolicyMap.get(dbId).get(key); + return res; } finally { readUnlock(); } } - /** - * Match all row policy and return them. - **/ - public List<RowPolicy> getMatchRowPolicy(long dbId, long tableId, UserIdentity user) { - RowPolicy checkedPolicy = new RowPolicy(); - checkedPolicy.setDbId(dbId); - checkedPolicy.setTableId(tableId); - checkedPolicy.setUser(user); - readLock(); - try { - return getPoliciesByType(PolicyTypeEnum.ROW).stream() - .filter(p -> p.matchPolicy(checkedPolicy)) - .filter(p -> !p.isInvalid()) - .map(p -> (RowPolicy) p) - .collect(Collectors.toList()); - } finally { - readUnlock(); + private RowPolicy mergeRowPolicies(List<RowPolicy> policys) { + if (CollectionUtils.isEmpty(policys)) { + return null; + } + RowPolicy andPolicy = null; + RowPolicy orPolicy = null; + for (RowPolicy rowPolicy : policys) { + if (CompoundPredicate.Operator.AND.equals(rowPolicy.getFilterType().getOp())) { + if (andPolicy == null) { + andPolicy = rowPolicy.clone(); + } else { + andPolicy.setWherePredicate(new CompoundPredicate(CompoundPredicate.Operator.AND, + andPolicy.getWherePredicate(), rowPolicy.getWherePredicate())); + } + } else { + if (orPolicy == null) { + orPolicy = rowPolicy; + } else { + orPolicy.setWherePredicate(new CompoundPredicate(CompoundPredicate.Operator.OR, + orPolicy.getWherePredicate(), rowPolicy.getWherePredicate())); + } + } + } + if (andPolicy == null) { + return orPolicy; } + if (orPolicy == null) { + return andPolicy; + } + andPolicy.setWherePredicate(new CompoundPredicate(CompoundPredicate.Operator.AND, andPolicy.getWherePredicate(), + orPolicy.getWherePredicate())); + return andPolicy; } /** @@ -354,6 +378,9 @@ public class PolicyMgr implements Writable { if (showStmt.getUser() != null) { rowPolicy.setUser(showStmt.getUser()); } + if (!StringUtils.isEmpty(showStmt.getRoleName())) { + rowPolicy.setRoleName(showStmt.getRoleName()); + } if (currentDbId != -1) { rowPolicy.setDbId(currentDbId); } @@ -382,84 +409,48 @@ public class PolicyMgr implements Writable { } } + private void addTablePolicies(RowPolicy policy) { + if (policy.getUser() != null) { + policy.getUser().setIsAnalyzed(); + } + List<RowPolicy> policys = getOrCreateTblPolicies(policy.getDbId(), policy.getTableId()); + policys.add(policy); + } + + private void dropTablePolicies(RowPolicy policy) { + List<RowPolicy> policys = getOrCreateTblPolicies(policy.getDbId(), policy.getTableId()); + policys.removeIf(p -> p.matchPolicy(policy)); + } + + private List<RowPolicy> getOrCreateTblPolicies(long dbId, long tableId) { + Map<Long, List<RowPolicy>> dbPolicyMap = getOrCreateDbPolicyMap(dbId); + if (!dbPolicyMap.containsKey(tableId)) { + dbPolicyMap.put(tableId, Lists.newArrayList()); + } + return dbPolicyMap.get(tableId); + } + + private Map<Long, List<RowPolicy>> getOrCreateDbPolicyMap(Long dbId) { + if (!tablePolicies.containsKey(dbId)) { + tablePolicies.put(dbId, Maps.newConcurrentMap()); + } + return tablePolicies.get(dbId); + } + /** * The merge policy cache needs to be regenerated after the update. **/ - private void updateMergeTablePolicyMap() { + private void updateTablePolicies() { readLock(); try { if (!typeToPolicyMap.containsKey(PolicyTypeEnum.ROW)) { return; } List<Policy> allPolicies = typeToPolicyMap.get(PolicyTypeEnum.ROW); - Map<Long, List<RowPolicy>> policyMap = new HashMap<>(); - dbIdToMergeTablePolicyMap.clear(); - userPolicySet.clear(); for (Policy policy : allPolicies) { - if (!(policy instanceof RowPolicy)) { - continue; - } - RowPolicy rowPolicy = (RowPolicy) policy; - if (!policyMap.containsKey(rowPolicy.getDbId())) { - policyMap.put(rowPolicy.getDbId(), new ArrayList<>()); - } - policyMap.get(rowPolicy.getDbId()).add(rowPolicy); - if (rowPolicy.getUser() != null) { - userPolicySet.add(rowPolicy.getUser().getQualifiedUser()); - } - } - for (Map.Entry<Long, List<RowPolicy>> entry : policyMap.entrySet()) { - List<RowPolicy> policies = entry.getValue(); - Map<String, RowPolicy> andMap = new HashMap<>(); - Map<String, RowPolicy> orMap = new HashMap<>(); - for (RowPolicy rowPolicy : policies) { - // read from json, need set isAnalyzed - rowPolicy.getUser().setIsAnalyzed(); - String key = Joiner.on("-") - .join(rowPolicy.getTableId(), rowPolicy.getType(), rowPolicy.getUser().getQualifiedUser()); - // merge wherePredicate - if (CompoundPredicate.Operator.AND.equals(rowPolicy.getFilterType().getOp())) { - RowPolicy frontPolicy = andMap.get(key); - if (frontPolicy == null) { - andMap.put(key, rowPolicy.clone()); - } else { - frontPolicy.setWherePredicate(new CompoundPredicate(CompoundPredicate.Operator.AND, - frontPolicy.getWherePredicate(), rowPolicy.getWherePredicate())); - andMap.put(key, frontPolicy.clone()); - } - } else { - RowPolicy frontPolicy = orMap.get(key); - if (frontPolicy == null) { - orMap.put(key, rowPolicy.clone()); - } else { - frontPolicy.setWherePredicate(new CompoundPredicate(CompoundPredicate.Operator.OR, - frontPolicy.getWherePredicate(), rowPolicy.getWherePredicate())); - orMap.put(key, frontPolicy.clone()); - } - } - } - Map<String, RowPolicy> mergeMap = new HashMap<>(); - Set<String> policyKeys = new HashSet<>(); - policyKeys.addAll(andMap.keySet()); - policyKeys.addAll(orMap.keySet()); - policyKeys.forEach(key -> { - if (andMap.containsKey(key) && orMap.containsKey(key)) { - RowPolicy mergePolicy = andMap.get(key).clone(); - mergePolicy.setWherePredicate( - new CompoundPredicate(CompoundPredicate.Operator.AND, mergePolicy.getWherePredicate(), - orMap.get(key).getWherePredicate())); - mergeMap.put(key, mergePolicy); - } - if (!andMap.containsKey(key)) { - mergeMap.put(key, orMap.get(key)); - } - if (!orMap.containsKey(key)) { - mergeMap.put(key, andMap.get(key)); - } - }); - long dbId = entry.getKey(); - dbIdToMergeTablePolicyMap.put(dbId, mergeMap); + addTablePolicies((RowPolicy) policy); } + } finally { readUnlock(); } @@ -477,7 +468,7 @@ public class PolicyMgr implements Writable { String json = Text.readString(in); PolicyMgr policyMgr = GsonUtils.GSON.fromJson(json, PolicyMgr.class); // update merge policy cache and userPolicySet - policyMgr.updateMergeTablePolicyMap(); + policyMgr.updateTablePolicies(); return policyMgr; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/policy/RowPolicy.java b/fe/fe-core/src/main/java/org/apache/doris/policy/RowPolicy.java index 2708462b42..d1d2cc6636 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/policy/RowPolicy.java +++ b/fe/fe-core/src/main/java/org/apache/doris/policy/RowPolicy.java @@ -41,6 +41,7 @@ import org.apache.logging.log4j.Logger; import java.io.IOException; import java.io.StringReader; import java.util.List; +import java.util.Objects; /** * Save policy for filtering data. @@ -50,15 +51,16 @@ public class RowPolicy extends Policy { public static final ShowResultSetMetaData ROW_META_DATA = ShowResultSetMetaData.builder() - .addColumn(new Column("PolicyName", ScalarType.createVarchar(100))) - .addColumn(new Column("DbName", ScalarType.createVarchar(100))) - .addColumn(new Column("TableName", ScalarType.createVarchar(100))) - .addColumn(new Column("Type", ScalarType.createVarchar(20))) - .addColumn(new Column("FilterType", ScalarType.createVarchar(20))) - .addColumn(new Column("WherePredicate", ScalarType.createVarchar(65535))) - .addColumn(new Column("User", ScalarType.createVarchar(20))) - .addColumn(new Column("OriginStmt", ScalarType.createVarchar(65535))) - .build(); + .addColumn(new Column("PolicyName", ScalarType.createVarchar(100))) + .addColumn(new Column("DbName", ScalarType.createVarchar(100))) + .addColumn(new Column("TableName", ScalarType.createVarchar(100))) + .addColumn(new Column("Type", ScalarType.createVarchar(20))) + .addColumn(new Column("FilterType", ScalarType.createVarchar(20))) + .addColumn(new Column("WherePredicate", ScalarType.createVarchar(65535))) + .addColumn(new Column("User", ScalarType.createVarchar(20))) + .addColumn(new Column("Role", ScalarType.createVarchar(20))) + .addColumn(new Column("OriginStmt", ScalarType.createVarchar(65535))) + .build(); private static final Logger LOG = LogManager.getLogger(RowPolicy.class); @@ -68,6 +70,9 @@ public class RowPolicy extends Policy { @SerializedName(value = "user") private UserIdentity user = null; + @SerializedName(value = "roleName") + private String roleName = null; + @SerializedName(value = "dbId") private long dbId = -1; @@ -99,15 +104,18 @@ public class RowPolicy extends Policy { * @param policyName policy name * @param dbId database i * @param user username + * @param roleName roleName * @param originStmt origin stmt * @param tableId table id * @param filterType filter type * @param wherePredicate where predicate */ - public RowPolicy(long policyId, final String policyName, long dbId, UserIdentity user, String originStmt, + public RowPolicy(long policyId, final String policyName, long dbId, UserIdentity user, String roleName, + String originStmt, final long tableId, final FilterType filterType, final Expr wherePredicate) { super(policyId, PolicyTypeEnum.ROW, policyName); this.user = user; + this.roleName = roleName; this.dbId = dbId; this.tableId = tableId; this.filterType = filterType; @@ -122,7 +130,8 @@ public class RowPolicy extends Policy { Database database = Env.getCurrentInternalCatalog().getDbOrAnalysisException(this.dbId); Table table = database.getTableOrAnalysisException(this.tableId); return Lists.newArrayList(this.policyName, database.getFullName(), table.getName(), this.type.name(), - this.filterType.name(), this.wherePredicate.toSql(), this.user.getQualifiedUser(), this.originStmt); + this.filterType.name(), this.wherePredicate.toSql(), + this.user == null ? null : this.user.getQualifiedUser(), this.roleName, this.originStmt); } @Override @@ -142,17 +151,18 @@ public class RowPolicy extends Policy { @Override public RowPolicy clone() { - return new RowPolicy(this.id, this.policyName, this.dbId, this.user, this.originStmt, this.tableId, + return new RowPolicy(this.id, this.policyName, this.dbId, this.user, this.roleName, this.originStmt, + this.tableId, this.filterType, this.wherePredicate); } private boolean checkMatched(long dbId, long tableId, PolicyTypeEnum type, - String policyName, UserIdentity user) { + String policyName, UserIdentity user, String roleName) { return super.checkMatched(type, policyName) && (dbId == -1 || dbId == this.dbId) && (tableId == -1 || tableId == this.tableId) - && (user == null || this.user == null - || StringUtils.equals(user.getQualifiedUser(), this.user.getQualifiedUser())); + && (StringUtils.isEmpty(roleName) || StringUtils.equals(roleName, this.roleName)) + && (user == null || Objects.equals(user, this.user)); } @Override @@ -162,14 +172,7 @@ public class RowPolicy extends Policy { } RowPolicy rowPolicy = (RowPolicy) checkedPolicyCondition; return checkMatched(rowPolicy.getDbId(), rowPolicy.getTableId(), rowPolicy.getType(), - rowPolicy.getPolicyName(), rowPolicy.getUser()); - } - - @Override - public boolean matchPolicy(DropPolicyLog checkedDropPolicyLogCondition) { - return checkMatched(checkedDropPolicyLogCondition.getDbId(), checkedDropPolicyLogCondition.getTableId(), - checkedDropPolicyLogCondition.getType(), checkedDropPolicyLogCondition.getPolicyName(), - checkedDropPolicyLogCondition.getUser()); + rowPolicy.getPolicyName(), rowPolicy.getUser(), rowPolicy.getRoleName()); } @Override diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/CheckRowPolicyTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/CheckRowPolicyTest.java index 1464de74d8..1e81db8bf9 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/CheckRowPolicyTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/CheckRowPolicyTest.java @@ -144,9 +144,6 @@ public class CheckRowPolicyTest extends TestWithFeService { Assertions.assertTrue(ImmutableList.copyOf(filter.getConjuncts()).get(0) instanceof EqualTo); Assertions.assertTrue(filter.getConjuncts().toString().contains("'k1 = 1")); - dropPolicy("DROP ROW POLICY " - + policyName - + " ON " - + tableName); + dropPolicy("DROP ROW POLICY " + policyName); } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/policy/PolicyTest.java b/fe/fe-core/src/test/java/org/apache/doris/policy/PolicyTest.java index b678f33614..ba912baf79 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/policy/PolicyTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/policy/PolicyTest.java @@ -18,6 +18,7 @@ package org.apache.doris.policy; import org.apache.doris.analysis.Analyzer; +import org.apache.doris.analysis.CreateRoleStmt; import org.apache.doris.analysis.CreateUserStmt; import org.apache.doris.analysis.Expr; import org.apache.doris.analysis.GrantStmt; @@ -77,6 +78,16 @@ public class PolicyTest extends TestWithFeService { Analyzer analyzer = new Analyzer(connectContext.getEnv(), connectContext); grantStmt.analyze(analyzer); Env.getCurrentEnv().getAuth().grant(grantStmt); + //create role + String role = "role1"; + CreateRoleStmt createRoleStmt = new CreateRoleStmt(role); + createRoleStmt.analyze(analyzer); + Env.getCurrentEnv().getAuth().createRole(createRoleStmt); + // grant role to user + grantStmt = new GrantStmt(Lists.newArrayList(role), user); + grantStmt.analyze(analyzer); + Env.getCurrentEnv().getAuth().grant(grantStmt); + useUser("test_policy"); } @@ -90,23 +101,35 @@ public class PolicyTest extends TestWithFeService { } @Test - public void testExistPolicy() throws Exception { - createPolicy("CREATE ROW POLICY test_row_policy ON test.table1 AS PERMISSIVE TO test_policy USING (k1 = 1)"); - Assertions.assertTrue(Env.getCurrentEnv().getPolicyMgr().existPolicy("default_cluster:test_policy")); - dropPolicy("DROP ROW POLICY test_row_policy ON test.table1 FOR test_policy"); - Assertions.assertFalse(Env.getCurrentEnv().getPolicyMgr().existPolicy("default_cluster:test_policy")); + public void testNormalSql() throws Exception { + // test user createPolicy("CREATE ROW POLICY test_row_policy ON test.table1 AS PERMISSIVE TO test_policy USING (k1 = 1)"); - dropPolicy("DROP ROW POLICY test_row_policy ON test.table1"); - Assertions.assertFalse(Env.getCurrentEnv().getPolicyMgr().existPolicy("default_cluster:test_policy")); + String queryStr = "EXPLAIN select /*+ SET_VAR(enable_nereids_planner=false) */ * from test.table1"; + String explainString = getSQLPlanOrErrorMsg(queryStr); + Assertions.assertTrue(explainString.contains("`k1` = 1")); + dropPolicy("DROP ROW POLICY test_row_policy"); + // test role + createPolicy("CREATE ROW POLICY test_row_policy ON test.table1 AS PERMISSIVE TO ROLE role1 USING (k1 = 2)"); + queryStr = "EXPLAIN select /*+ SET_VAR(enable_nereids_planner=false) */ * from test.table1"; + explainString = getSQLPlanOrErrorMsg(queryStr); + Assertions.assertTrue(explainString.contains("`k1` = 2")); + dropPolicy("DROP ROW POLICY test_row_policy"); } @Test - public void testNormalSql() throws Exception { + public void testNormalSqlNereidsPlanners() throws Exception { + // test user createPolicy("CREATE ROW POLICY test_row_policy ON test.table1 AS PERMISSIVE TO test_policy USING (k1 = 1)"); - String queryStr = "EXPLAIN select /*+ SET_VAR(enable_nereids_planner=false) */ * from test.table1"; + String queryStr = "EXPLAIN select * from test.table1"; String explainString = getSQLPlanOrErrorMsg(queryStr); - Assertions.assertTrue(explainString.contains("`k1` = 1")); - dropPolicy("DROP ROW POLICY test_row_policy ON test.table1 FOR test_policy"); + Assertions.assertTrue(explainString.contains("k1[#0] = 1")); + dropPolicy("DROP ROW POLICY test_row_policy"); + //test role + createPolicy("CREATE ROW POLICY test_row_policy ON test.table1 AS PERMISSIVE TO ROLE role1 USING (k1 = 2)"); + queryStr = "EXPLAIN select * from test.table1"; + explainString = getSQLPlanOrErrorMsg(queryStr); + Assertions.assertTrue(explainString.contains("k1[#0] = 2")); + dropPolicy("DROP ROW POLICY test_row_policy"); } @Test @@ -118,7 +141,7 @@ public class PolicyTest extends TestWithFeService { queryStr = "EXPLAIN select /*+ SET_VAR(enable_nereids_planner=false) */ * from test.table1 b"; explainString = getSQLPlanOrErrorMsg(queryStr); Assertions.assertTrue(explainString.contains("`b`.`k1` = 1")); - dropPolicy("DROP ROW POLICY test_row_policy ON test.table1 FOR test_policy"); + dropPolicy("DROP ROW POLICY test_row_policy"); } @Test @@ -132,26 +155,46 @@ public class PolicyTest extends TestWithFeService { queryStr = "EXPLAIN select * from test.table1 b"; explainString = getSQLPlanOrErrorMsg(queryStr); Assertions.assertTrue(explainString.contains("k1[#0] = 1")); - dropPolicy("DROP ROW POLICY test_row_policy ON test.table1 FOR test_policy"); + dropPolicy("DROP ROW POLICY test_row_policy"); connectContext.getSessionVariable().setEnableNereidsPlanner(beforeConfig); } @Test public void testUnionSql() throws Exception { createPolicy("CREATE ROW POLICY test_row_policy ON test.table1 AS PERMISSIVE TO test_policy USING (k1 = 1)"); - String queryStr = "EXPLAIN select /*+ SET_VAR(enable_nereids_planner=false) */ * from test.table1 union all select * from test.table1"; + String queryStr + = "EXPLAIN select /*+ SET_VAR(enable_nereids_planner=false) */ * from test.table1 union all select * from test.table1"; String explainString = getSQLPlanOrErrorMsg(queryStr); Assertions.assertTrue(explainString.contains("`k1` = 1")); - dropPolicy("DROP ROW POLICY test_row_policy ON test.table1 FOR test_policy"); + dropPolicy("DROP ROW POLICY test_row_policy"); + } + + @Test + public void testUnionSqlNereidsPlanner() throws Exception { + createPolicy("CREATE ROW POLICY test_row_policy ON test.table1 AS PERMISSIVE TO test_policy USING (k1 = 1)"); + String queryStr = "EXPLAIN select * from test.table1 union all select * from test.table1"; + String explainString = getSQLPlanOrErrorMsg(queryStr); + Assertions.assertTrue(explainString.contains("k1[#0] = 1")); + dropPolicy("DROP ROW POLICY test_row_policy"); } @Test public void testInsertSelectSql() throws Exception { createPolicy("CREATE ROW POLICY test_row_policy ON test.table1 AS PERMISSIVE TO test_policy USING (k1 = 1)"); - String queryStr = "EXPLAIN insert into test.table1 select /*+ SET_VAR(enable_nereids_planner=false) */ * from test.table1"; + String queryStr + = "EXPLAIN insert into test.table1 select /*+ SET_VAR(enable_nereids_planner=false) */ * from test.table1"; String explainString = getSQLPlanOrErrorMsg(queryStr); Assertions.assertTrue(explainString.contains("`k1` = 1")); - dropPolicy("DROP ROW POLICY test_row_policy ON test.table1 FOR test_policy"); + dropPolicy("DROP ROW POLICY test_row_policy"); + } + + @Test + public void testInsertSelectSqlNereidsPlanner() throws Exception { + createPolicy("CREATE ROW POLICY test_row_policy ON test.table1 AS PERMISSIVE TO test_policy USING (k1 = 1)"); + String queryStr = "EXPLAIN insert into test.table1 select * from test.table1"; + String explainString = getSQLPlanOrErrorMsg(queryStr); + Assertions.assertTrue(explainString.contains("k1[#0] = 1")); + dropPolicy("DROP ROW POLICY test_row_policy"); } @Test @@ -162,7 +205,7 @@ public class PolicyTest extends TestWithFeService { ExceptionChecker.expectThrowsWithMsg(DdlException.class, "the policy test_row_policy1 already create", () -> createPolicy("CREATE ROW POLICY test_row_policy1 ON test.table1 AS PERMISSIVE" + " TO test_policy USING (k1 = 1)")); - dropPolicy("DROP ROW POLICY test_row_policy1 ON test.table1"); + dropPolicy("DROP ROW POLICY test_row_policy1"); } @Test @@ -181,8 +224,8 @@ public class PolicyTest extends TestWithFeService { (ShowPolicyStmt) parseAndAnalyzeStmt("SHOW ROW POLICY"); int firstSize = Env.getCurrentEnv().getPolicyMgr().showPolicy(showPolicyStmt).getResultRows().size(); Assertions.assertTrue(firstSize > 0); - dropPolicy("DROP ROW POLICY test_row_policy1 ON test.table1"); - dropPolicy("DROP ROW POLICY test_row_policy2 ON test.table1"); + dropPolicy("DROP ROW POLICY test_row_policy1"); + dropPolicy("DROP ROW POLICY test_row_policy2"); int secondSize = Env.getCurrentEnv().getPolicyMgr().showPolicy(showPolicyStmt).getResultRows().size(); Assertions.assertEquals(2, firstSize - secondSize); } @@ -190,41 +233,74 @@ public class PolicyTest extends TestWithFeService { @Test public void testDropPolicy() throws Exception { createPolicy("CREATE ROW POLICY test_row_policy1 ON test.table1 AS PERMISSIVE TO test_policy USING (k2 = 1)"); - dropPolicy("DROP ROW POLICY test_row_policy1 ON test.table1"); - dropPolicy("DROP ROW POLICY IF EXISTS test_row_policy5 ON test.table1"); + dropPolicy("DROP ROW POLICY test_row_policy1"); + dropPolicy("DROP ROW POLICY IF EXISTS test_row_policy5"); ExceptionChecker.expectThrowsWithMsg(DdlException.class, "the policy test_row_policy1 not exist", - () -> dropPolicy("DROP ROW POLICY test_row_policy1 ON test.table1")); + () -> dropPolicy("DROP ROW POLICY test_row_policy1")); } @Test public void testMergeFilter() throws Exception { createPolicy("CREATE ROW POLICY test_row_policy1 ON test.table1 AS RESTRICTIVE TO test_policy USING (k1 = 1)"); - createPolicy("CREATE ROW POLICY test_row_policy2 ON test.table1 AS RESTRICTIVE TO test_policy USING (k2 = 1)"); - createPolicy("CREATE ROW POLICY test_row_policy3 ON test.table1 AS PERMISSIVE TO test_policy USING (k2 = 2)"); + createPolicy("CREATE ROW POLICY test_row_policy2 ON test.table1 AS RESTRICTIVE TO ROLE role1 USING (k2 = 1)"); + createPolicy("CREATE ROW POLICY test_row_policy3 ON test.table1 AS PERMISSIVE TO ROLE role1 USING (k2 = 2)"); createPolicy("CREATE ROW POLICY test_row_policy4 ON test.table1 AS PERMISSIVE TO test_policy USING (k2 = 1)"); String queryStr = "EXPLAIN select /*+ SET_VAR(enable_nereids_planner=false) */ * from test.table1"; String explainString = getSQLPlanOrErrorMsg(queryStr); Assertions.assertTrue(explainString.contains("`k1` = 1 AND `k2` = 1 AND `k2` = 2 OR `k2` = 1")); - dropPolicy("DROP ROW POLICY test_row_policy1 ON test.table1"); - dropPolicy("DROP ROW POLICY test_row_policy2 ON test.table1"); - dropPolicy("DROP ROW POLICY test_row_policy3 ON test.table1"); - dropPolicy("DROP ROW POLICY test_row_policy4 ON test.table1"); + dropPolicy("DROP ROW POLICY test_row_policy1"); + dropPolicy("DROP ROW POLICY test_row_policy2"); + dropPolicy("DROP ROW POLICY test_row_policy3"); + dropPolicy("DROP ROW POLICY test_row_policy4"); + } + + @Test + public void testMergeFilterNereidsPlanner() throws Exception { + createPolicy("CREATE ROW POLICY test_row_policy1 ON test.table1 AS RESTRICTIVE TO test_policy USING (k1 = 1)"); + createPolicy("CREATE ROW POLICY test_row_policy3 ON test.table1 AS PERMISSIVE TO ROLE role1 USING (k2 = 2)"); + createPolicy("CREATE ROW POLICY test_row_policy4 ON test.table1 AS PERMISSIVE TO test_policy USING (k2 = 1)"); + String queryStr = "EXPLAIN select * from test.table1"; + String explainString = getSQLPlanOrErrorMsg(queryStr); + Assertions.assertTrue(explainString.contains("k2[#1] IN (1, 2) AND k1[#0] = 1")); + dropPolicy("DROP ROW POLICY test_row_policy1"); + dropPolicy("DROP ROW POLICY test_row_policy3"); + dropPolicy("DROP ROW POLICY test_row_policy4"); } @Test public void testComplexSql() throws Exception { createPolicy("CREATE ROW POLICY test_row_policy1 ON test.table1 AS RESTRICTIVE TO test_policy USING (k1 = 1)"); createPolicy("CREATE ROW POLICY test_row_policy2 ON test.table1 AS RESTRICTIVE TO test_policy USING (k2 = 1)"); - String joinSql = "select /*+ SET_VAR(enable_nereids_planner=false) */ * from table1 join table2 on table1.k1=table2.k1"; + String joinSql + = "select /*+ SET_VAR(enable_nereids_planner=false) */ * from table1 join table2 on table1.k1=table2.k1"; Assertions.assertTrue(getSQLPlanOrErrorMsg(joinSql).contains("PREDICATES: `k1` = 1 AND `k2` = 1")); - String unionSql = "select /*+ SET_VAR(enable_nereids_planner=false) */ * from table1 union select * from table2"; + String unionSql + = "select /*+ SET_VAR(enable_nereids_planner=false) */ * from table1 union select * from table2"; Assertions.assertTrue(getSQLPlanOrErrorMsg(unionSql).contains("PREDICATES: `k1` = 1 AND `k2` = 1")); - String subQuerySql = "select /*+ SET_VAR(enable_nereids_planner=false) */ * from table2 where k1 in (select k1 from table1)"; + String subQuerySql + = "select /*+ SET_VAR(enable_nereids_planner=false) */ * from table2 where k1 in (select k1 from table1)"; Assertions.assertTrue(getSQLPlanOrErrorMsg(subQuerySql).contains("PREDICATES: `k1` = 1 AND `k2` = 1")); - String aliasSql = "select /*+ SET_VAR(enable_nereids_planner=false) */ * from table1 t1 join table2 t2 on t1.k1=t2.k1"; + String aliasSql + = "select /*+ SET_VAR(enable_nereids_planner=false) */ * from table1 t1 join table2 t2 on t1.k1=t2.k1"; Assertions.assertTrue(getSQLPlanOrErrorMsg(aliasSql).contains("PREDICATES: `t1`.`k1` = 1 AND `t1`.`k2` = 1")); - dropPolicy("DROP ROW POLICY test_row_policy1 ON test.table1"); - dropPolicy("DROP ROW POLICY test_row_policy2 ON test.table1"); + dropPolicy("DROP ROW POLICY test_row_policy1"); + dropPolicy("DROP ROW POLICY test_row_policy2"); + } + + @Test + public void testComplexSqlNereidsPlanner() throws Exception { + createPolicy("CREATE ROW POLICY test_row_policy1 ON test.table1 AS RESTRICTIVE TO test_policy USING (k1 = 1)"); + createPolicy("CREATE ROW POLICY test_row_policy2 ON test.table1 AS RESTRICTIVE TO test_policy USING (k2 = 1)"); + String joinSql = "select * from table1 join table2 on table1.k1=table2.k1"; + Assertions.assertTrue(getSQLPlanOrErrorMsg(joinSql).contains("PREDICATES: k1 = 1 AND k2 = 1")); + String unionSql = "select * from table1 union select * from table2"; + Assertions.assertTrue(getSQLPlanOrErrorMsg(unionSql).contains("PREDICATES: k1 = 1 AND k2 = 1")); + String subQuerySql = "select * from table2 where k1 in (select k1 from table1)"; + Assertions.assertTrue(getSQLPlanOrErrorMsg(subQuerySql).contains("PREDICATES: k1 = 1 AND k2 = 1")); + String aliasSql = "select * from table1 t1 join table2 t2 on t1.k1=t2.k1"; + Assertions.assertTrue(getSQLPlanOrErrorMsg(aliasSql).contains("PREDICATES: k1 = 1 AND k2 = 1")); + dropPolicy("DROP ROW POLICY test_row_policy1"); + dropPolicy("DROP ROW POLICY test_row_policy2"); } @Test @@ -240,7 +316,7 @@ public class PolicyTest extends TestWithFeService { FilterType filterType = FilterType.PERMISSIVE; Expr wherePredicate = null; - Policy rowPolicy = new RowPolicy(10000, policyName, dbId, user, originStmt, tableId, filterType, + Policy rowPolicy = new RowPolicy(10000, policyName, dbId, user, null, originStmt, tableId, filterType, wherePredicate); ByteArrayOutputStream emptyOutputStream = new ByteArrayOutputStream(); diff --git a/regression-test/suites/account_p0/test_nereids_row_policy.groovy b/regression-test/suites/account_p0/test_nereids_row_policy.groovy index d12b11261d..bcc1a7b817 100644 --- a/regression-test/suites/account_p0/test_nereids_row_policy.groovy +++ b/regression-test/suites/account_p0/test_nereids_row_policy.groovy @@ -51,7 +51,7 @@ suite("test_nereids_row_policy") { def dropPolciy = { name -> sql """ - DROP ROW POLICY IF EXISTS ${name} ON ${dbName}.${tableName} FOR ${user} + DROP ROW POLICY IF EXISTS ${name} """ } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org