Skip to content

Commit 9913d5f

Browse files
[BugFix] fix the privilege issue DROP STATS command (backport #55695) (#55776)
Co-authored-by: Murphy <[email protected]>
1 parent e8d5c46 commit 9913d5f

File tree

5 files changed

+62
-34
lines changed

5 files changed

+62
-34
lines changed

fe/fe-core/src/main/java/com/starrocks/load/DeleteMgr.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,11 @@ private List<String> partitionPruneForDelete(DeleteStmt stmt, OlapTable table) {
303303
String predicate = stmt.getWherePredicate().toSql();
304304
String fakeSql = String.format("SELECT * FROM %s WHERE %s", tableName, predicate);
305305
PhysicalOlapScanOperator physicalOlapScanOperator;
306+
ConnectContext currentSession = ConnectContext.get();
306307
try {
307-
List<StatementBase> parse = SqlParser.parse(fakeSql, ConnectContext.get().getSessionVariable());
308+
// Bypass the privilege check, as current user may have only the DELETE privilege but not SELECT
309+
currentSession.setBypassAuthorizerCheck(true);
310+
List<StatementBase> parse = SqlParser.parse(fakeSql, currentSession.getSessionVariable());
308311
StatementBase selectStmt = parse.get(0);
309312
Analyzer.analyze(selectStmt, ConnectContext.get());
310313
ExecPlan plan = StatementPlanner.plan(selectStmt, ConnectContext.get());
@@ -318,6 +321,8 @@ private List<String> partitionPruneForDelete(DeleteStmt stmt, OlapTable table) {
318321
} catch (Exception e) {
319322
LOG.warn("failed to do partition pruning for delete {}", stmt.toString(), e);
320323
return Lists.newArrayList(table.getVisiblePartitionNames());
324+
} finally {
325+
currentSession.setBypassAuthorizerCheck(false);
321326
}
322327
List<Long> selectedPartitionId = physicalOlapScanOperator.getSelectedPartitionId();
323328
return ListUtils.emptyIfNull(selectedPartitionId)

fe/fe-core/src/main/java/com/starrocks/qe/ConnectContext.java

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ public class ConnectContext {
200200
protected boolean isStatisticsContext = false;
201201
protected boolean needQueued = true;
202202

203+
// Bypass the authorizer check for certain cases
204+
protected boolean bypassAuthorizerCheck = false;
205+
203206
protected DumpInfo dumpInfo;
204207

205208
// The related db ids for current sql
@@ -341,17 +344,10 @@ public void setThreadLocalInfo() {
341344
threadLocalInfo.set(this);
342345
}
343346

344-
/**
345-
* Set this connect to thread-local if not exists
346-
*
347-
* @return set or not
348-
*/
349-
public boolean setThreadLocalInfoIfNotExists() {
350-
if (threadLocalInfo.get() == null) {
351-
threadLocalInfo.set(this);
352-
return true;
353-
}
354-
return false;
347+
public static ConnectContext exchangeThreadLocalInfo(ConnectContext ctx) {
348+
ConnectContext prev = threadLocalInfo.get();
349+
threadLocalInfo.set(ctx);
350+
return prev;
355351
}
356352

357353
public void setGlobalStateMgr(GlobalStateMgr globalStateMgr) {
@@ -759,6 +755,14 @@ public void setNeedQueued(boolean needQueued) {
759755
this.needQueued = needQueued;
760756
}
761757

758+
public boolean isBypassAuthorizerCheck() {
759+
return bypassAuthorizerCheck;
760+
}
761+
762+
public void setBypassAuthorizerCheck(boolean value) {
763+
this.bypassAuthorizerCheck = value;
764+
}
765+
762766
public ConnectContext getParent() {
763767
return parent;
764768
}
@@ -934,8 +938,15 @@ public StmtExecutor executeSql(String sql) throws Exception {
934938
return executor;
935939
}
936940

941+
/**
942+
* Bind the context to current scope, exchange the context if it's already existed
943+
* Sample usage:
944+
* try (var guard = context.bindScope()) {
945+
* ......
946+
* }
947+
*/
937948
public ScopeGuard bindScope() {
938-
return ScopeGuard.setIfNotExists(this);
949+
return ScopeGuard.bind(this);
939950
}
940951

941952
/**
@@ -944,21 +955,30 @@ public ScopeGuard bindScope() {
944955
public static class ScopeGuard implements AutoCloseable {
945956

946957
private boolean set = false;
958+
private ConnectContext prev;
947959

948960
private ScopeGuard() {
949961
}
950962

951-
public static ScopeGuard setIfNotExists(ConnectContext session) {
963+
private static ScopeGuard bind(ConnectContext session) {
952964
ScopeGuard res = new ScopeGuard();
953-
res.set = session.setThreadLocalInfoIfNotExists();
965+
res.prev = exchangeThreadLocalInfo(session);
966+
res.set = true;
954967
return res;
955968
}
956969

970+
public ConnectContext prev() {
971+
return prev;
972+
}
973+
957974
@Override
958975
public void close() {
959976
if (set) {
960977
ConnectContext.remove();
961978
}
979+
if (prev != null) {
980+
prev.setThreadLocalInfo();
981+
}
962982
}
963983
}
964984

fe/fe-core/src/main/java/com/starrocks/qe/StmtExecutor.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,11 +1287,9 @@ private void executeAnalyze(AnalyzeStmt analyzeStmt, AnalyzeStatus analyzeStatus
12871287
// from current session, may execute analyze stmt
12881288
statsConnectCtx.getSessionVariable().setStatisticCollectParallelism(
12891289
context.getSessionVariable().getStatisticCollectParallelism());
1290-
statsConnectCtx.setThreadLocalInfo();
1291-
try {
1290+
statsConnectCtx.setStatisticsConnection(true);
1291+
try (ConnectContext.ScopeGuard guard = statsConnectCtx.bindScope()) {
12921292
executeAnalyze(statsConnectCtx, analyzeStmt, analyzeStatus, db, table);
1293-
} finally {
1294-
ConnectContext.remove();
12951293
}
12961294

12971295
}

fe/fe-core/src/main/java/com/starrocks/sql/StatementPlanner.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@ public static ExecPlan plan(StatementBase stmt, ConnectContext session,
115115
analyzeStatement(stmt, session, dbs);
116116

117117
// Authorization check
118-
Authorizer.check(stmt, session);
118+
if (!session.isBypassAuthorizerCheck()) {
119+
Authorizer.check(stmt, session);
120+
}
119121
if (stmt instanceof QueryStatement) {
120122
OptimizerTraceUtil.logQueryStatement("after analyze:\n%s", (QueryStatement) stmt);
121123
}

fe/fe-core/src/main/java/com/starrocks/statistic/AnalyzeMgr.java

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -422,11 +422,12 @@ public void clearStatisticFromDroppedTable() {
422422
tableIdHasDeleted.removeAll(tables);
423423

424424
ConnectContext statsConnectCtx = StatisticUtils.buildConnectContext();
425-
statsConnectCtx.setThreadLocalInfo();
426-
statsConnectCtx.setStatisticsConnection(true);
425+
try (ConnectContext.ScopeGuard guard = statsConnectCtx.bindScope()) {
426+
statsConnectCtx.setStatisticsConnection(true);
427427

428-
dropBasicStatsMetaAndData(statsConnectCtx, tableIdHasDeleted);
429-
dropHistogramStatsMetaAndData(statsConnectCtx, tableIdHasDeleted);
428+
dropBasicStatsMetaAndData(statsConnectCtx, tableIdHasDeleted);
429+
dropHistogramStatsMetaAndData(statsConnectCtx, tableIdHasDeleted);
430+
}
430431
}
431432
public void recordDropPartition(long partitionId) {
432433
dropPartitionIds.add(partitionId);
@@ -596,17 +597,19 @@ private void clearStaleStatsWhenStarted() {
596597

597598
public void dropBasicStatsMetaAndData(ConnectContext statsConnectCtx, Set<Long> tableIdHasDeleted) {
598599
StatisticExecutor statisticExecutor = new StatisticExecutor();
599-
for (Long tableId : tableIdHasDeleted) {
600-
BasicStatsMeta basicStatsMeta = basicStatsMetaMap.get(tableId);
601-
if (basicStatsMeta == null) {
602-
continue;
600+
try (ConnectContext.ScopeGuard guard = statsConnectCtx.bindScope()) {
601+
for (Long tableId : tableIdHasDeleted) {
602+
BasicStatsMeta basicStatsMeta = basicStatsMetaMap.get(tableId);
603+
if (basicStatsMeta == null) {
604+
continue;
605+
}
606+
// Both types of tables need to be deleted, because there may have been a switch of
607+
// collecting statistics types, leaving some discarded statistics data.
608+
statisticExecutor.dropTableStatistics(statsConnectCtx, tableId, StatsConstants.AnalyzeType.SAMPLE);
609+
statisticExecutor.dropTableStatistics(statsConnectCtx, tableId, StatsConstants.AnalyzeType.FULL);
610+
GlobalStateMgr.getCurrentState().getEditLog().logRemoveBasicStatsMeta(basicStatsMetaMap.get(tableId));
611+
basicStatsMetaMap.remove(tableId);
603612
}
604-
// Both types of tables need to be deleted, because there may have been a switch of
605-
// collecting statistics types, leaving some discarded statistics data.
606-
statisticExecutor.dropTableStatistics(statsConnectCtx, tableId, StatsConstants.AnalyzeType.SAMPLE);
607-
statisticExecutor.dropTableStatistics(statsConnectCtx, tableId, StatsConstants.AnalyzeType.FULL);
608-
GlobalStateMgr.getCurrentState().getEditLog().logRemoveBasicStatsMeta(basicStatsMetaMap.get(tableId));
609-
basicStatsMetaMap.remove(tableId);
610613
}
611614
}
612615

0 commit comments

Comments
 (0)