diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/proc/FrontendsProcNode.java b/fe/fe-core/src/main/java/org/apache/doris/common/proc/FrontendsProcNode.java index 0d4dccb196ad9a..a4c26b57af6a96 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/common/proc/FrontendsProcNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/common/proc/FrontendsProcNode.java @@ -26,9 +26,9 @@ import org.apache.doris.service.FeDiskInfo; import org.apache.doris.system.Frontend; import org.apache.doris.system.SystemInfoService.HostInfo; +import org.apache.doris.tablefunction.FrontendsTableValuedFunction; import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -45,18 +45,6 @@ public class FrontendsProcNode implements ProcNodeInterface { private static final Logger LOG = LogManager.getLogger(FrontendsProcNode.class); - public static final ImmutableList TITLE_NAMES = new ImmutableList.Builder() - .add("Name").add("Host").add("EditLogPort").add("HttpPort").add("QueryPort").add("RpcPort") - .add("ArrowFlightSqlPort").add("Role").add("IsMaster").add("ClusterId").add("Join").add("Alive") - .add("ReplayedJournalId").add("LastStartTime").add("LastHeartbeat").add("IsHelper").add("ErrMsg") - .add("Version").add("CurrentConnected").add("LiveSince") - .build(); - - public static final ImmutableList DISK_TITLE_NAMES = new ImmutableList.Builder() - .add("Name").add("Host").add("DirType").add("Dir").add("Filesystem") - .add("Capacity").add("Used").add("Available").add("UseRate").add("MountOn") - .build(); - private Env env; public FrontendsProcNode(Env env) { @@ -66,7 +54,7 @@ public FrontendsProcNode(Env env) { @Override public ProcResult fetchResult() { BaseProcResult result = new BaseProcResult(); - result.setNames(TITLE_NAMES); + result.setNames(FrontendsTableValuedFunction.getFrontendsTitleNames()); List> infos = Lists.newArrayList(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowFrontendsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowFrontendsCommand.java index d461a3efbb3ba2..e119f3f3e695bf 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowFrontendsCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowFrontendsCommand.java @@ -34,6 +34,8 @@ import org.apache.doris.qe.ShowResultSet; import org.apache.doris.qe.ShowResultSetMetaData; import org.apache.doris.qe.StmtExecutor; +import org.apache.doris.tablefunction.FrontendsDisksTableValuedFunction; +import org.apache.doris.tablefunction.FrontendsTableValuedFunction; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; @@ -60,9 +62,9 @@ public ShowFrontendsCommand(String detail) { public ShowResultSetMetaData getMetaData() { ShowResultSetMetaData.Builder builder = ShowResultSetMetaData.builder(); - ImmutableList titles = FrontendsProcNode.TITLE_NAMES; + ImmutableList titles = FrontendsTableValuedFunction.getFrontendsTitleNames(); if (detail != null && detail.equalsIgnoreCase("disks")) { - titles = FrontendsProcNode.DISK_TITLE_NAMES; + titles = FrontendsDisksTableValuedFunction.getFrontendsDisksTitleNames(); } for (String title : titles) { builder.addColumn(new Column(title, ScalarType.createVarchar(30))); diff --git a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsDisksTableValuedFunction.java b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsDisksTableValuedFunction.java index 31ddf55313a809..7380585fdae586 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsDisksTableValuedFunction.java +++ b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsDisksTableValuedFunction.java @@ -56,13 +56,17 @@ public class FrontendsDisksTableValuedFunction extends MetadataTableValuedFuncti new Column("MountOn", ScalarType.createStringType())); private static final ImmutableMap COLUMN_TO_INDEX; + private static final ImmutableList TITLE_NAMES; static { ImmutableMap.Builder builder = new ImmutableMap.Builder(); + ImmutableList.Builder immutableListBuilder = ImmutableList.builder(); for (int i = 0; i < SCHEMA.size(); i++) { builder.put(SCHEMA.get(i).getName().toLowerCase(), i); + immutableListBuilder.add(SCHEMA.get(i).getName()); } COLUMN_TO_INDEX = builder.build(); + TITLE_NAMES = immutableListBuilder.build(); } public static Integer getColumnIndexFromColumnName(String columnName) { @@ -105,4 +109,11 @@ public String getTableName() { public List getTableColumns() throws AnalysisException { return SCHEMA; } + + /** + * unify title names for frontends_disks function and show frontends disks command + */ + public static ImmutableList getFrontendsDisksTitleNames() { + return TITLE_NAMES; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsTableValuedFunction.java b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsTableValuedFunction.java index efb90070e65fe3..79b61d33b28555 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsTableValuedFunction.java +++ b/fe/fe-core/src/main/java/org/apache/doris/tablefunction/FrontendsTableValuedFunction.java @@ -62,16 +62,21 @@ public class FrontendsTableValuedFunction extends MetadataTableValuedFunction { new Column("IsHelper", ScalarType.createStringType()), new Column("ErrMsg", ScalarType.createStringType()), new Column("Version", ScalarType.createStringType()), - new Column("CurrentConnected", ScalarType.createStringType())); - + new Column("CurrentConnected", ScalarType.createStringType()), + new Column("LiveSince", ScalarType.createStringType()) + ); private static final ImmutableMap COLUMN_TO_INDEX; + private static final ImmutableList TITLE_NAMES; static { ImmutableMap.Builder builder = new ImmutableMap.Builder(); + ImmutableList.Builder immutableListBuilder = ImmutableList.builder(); for (int i = 0; i < SCHEMA.size(); i++) { builder.put(SCHEMA.get(i).getName().toLowerCase(), i); + immutableListBuilder.add(SCHEMA.get(i).getName()); } COLUMN_TO_INDEX = builder.build(); + TITLE_NAMES = immutableListBuilder.build(); } public static Integer getColumnIndexFromColumnName(String columnName) { @@ -114,4 +119,11 @@ public String getTableName() { public List getTableColumns() throws AnalysisException { return SCHEMA; } + + /** + * unify title names for frontends function and show frontends command + */ + public static ImmutableList getFrontendsTitleNames() { + return TITLE_NAMES; + } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowFrontendsCommandTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowFrontendsCommandTest.java index 294b43d3960a46..8205ecf9863144 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowFrontendsCommandTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowFrontendsCommandTest.java @@ -17,6 +17,8 @@ package org.apache.doris.nereids.trees.plans.commands; +import com.google.common.collect.ImmutableList; +import org.apache.doris.catalog.Column; import org.apache.doris.catalog.Env; import org.apache.doris.catalog.InfoSchemaDb; import org.apache.doris.common.AnalysisException; @@ -25,12 +27,17 @@ import org.apache.doris.mysql.privilege.AccessControllerManager; import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.ShowResultSet; +import org.apache.doris.tablefunction.FrontendsDisksTableValuedFunction; +import org.apache.doris.tablefunction.FrontendsTableValuedFunction; import mockit.Expectations; import mockit.Mocked; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.List; + public class ShowFrontendsCommandTest { private static final String internalCtl = InternalCatalog.INTERNAL_CATALOG_NAME; private static final String infoDB = InfoSchemaDb.DATABASE_NAME; @@ -80,7 +87,13 @@ private void runBefore() throws Exception { public void testNormal() throws Exception { runBefore(); ShowFrontendsCommand command = new ShowFrontendsCommand(null); - Assertions.assertDoesNotThrow(() -> command.doRun(ctx, null)); + ShowResultSet showResultSet = command.doRun(ctx, null); + List columnList = showResultSet.getMetaData().getColumns(); + ImmutableList frontendsTitleNames = FrontendsTableValuedFunction.getFrontendsTitleNames(); + Assertions.assertTrue(!columnList.isEmpty() && columnList.size() == frontendsTitleNames.size()); + for (int i = 0; i < frontendsTitleNames.size(); i++) { + Assertions.assertTrue(columnList.get(i).getName().equalsIgnoreCase(frontendsTitleNames.get(i))); + } } @Test @@ -115,4 +128,50 @@ public void testNoPrivilege() throws Exception { ShowFrontendsCommand command = new ShowFrontendsCommand(null); Assertions.assertThrows(AnalysisException.class, () -> command.doRun(ctx, null)); } + + @Test + public void testNormalShowFrontendsDisks() throws Exception { + runBefore(); + ShowFrontendsCommand command = new ShowFrontendsCommand("disks"); + ShowResultSet showResultSet = command.doRun(ctx, null); + List columnList = showResultSet.getMetaData().getColumns(); + ImmutableList frontendsDisksTitleNames = FrontendsDisksTableValuedFunction.getFrontendsDisksTitleNames(); + Assertions.assertTrue(!columnList.isEmpty() && columnList.size() == frontendsDisksTitleNames.size()); + for (int i = 0; i < frontendsDisksTitleNames.size(); i++) { + Assertions.assertTrue(columnList.get(i).getName().equalsIgnoreCase(frontendsDisksTitleNames.get(i))); + } + } + + @Test + public void testNoPrivilegeShowFrontendsDisks() throws Exception { + new Expectations() { + { + Env.getCurrentEnv(); + minTimes = 0; + result = env; + + env.getAccessManager(); + minTimes = 0; + result = accessControllerManager; + + env.getCatalogMgr(); + minTimes = 0; + result = catalogMgr; + + catalogMgr.getCatalog(anyString); + minTimes = 0; + result = catalog; + + ConnectContext.get(); + minTimes = 0; + result = ctx; + + accessControllerManager.checkDbPriv(ctx, internalCtl, infoDB, PrivPredicate.SELECT); + minTimes = 0; + result = false; + } + }; + ShowFrontendsCommand command = new ShowFrontendsCommand("disks"); + Assertions.assertThrows(AnalysisException.class, () -> command.doRun(ctx, null)); + } } diff --git a/regression-test/suites/external_table_p0/tvf/test_frontends_disks_tvf.groovy b/regression-test/suites/external_table_p0/tvf/test_frontends_disks_tvf.groovy index 509fa5a75dc3a3..07a7ca0639e7c8 100644 --- a/regression-test/suites/external_table_p0/tvf/test_frontends_disks_tvf.groovy +++ b/regression-test/suites/external_table_p0/tvf/test_frontends_disks_tvf.groovy @@ -21,6 +21,19 @@ suite("test_frontends_disks_tvf", "p0,external,external_docker") { assertTrue(table.size() > 0) assertTrue(table[0].size() == 10) + List> titleNames = sql """ describe function frontends_disks(); """ + + assertTrue(titleNames[0][0] == "Name") + assertTrue(titleNames[1][0] == "Host") + assertTrue(titleNames[2][0] == "DirType") + assertTrue(titleNames[3][0] == "Dir") + assertTrue(titleNames[4][0] == "Filesystem") + assertTrue(titleNames[5][0] == "Capacity") + assertTrue(titleNames[6][0] == "Used") + assertTrue(titleNames[7][0] == "Available") + assertTrue(titleNames[8][0] == "UseRate") + assertTrue(titleNames[9][0] == "MountOn") + // filter columns table = sql """ select Name from `frontends_disks`();""" assertTrue(table.size() > 0) diff --git a/regression-test/suites/external_table_p0/tvf/test_frontends_tvf.groovy b/regression-test/suites/external_table_p0/tvf/test_frontends_tvf.groovy index 0fa743d03cd427..623c54ae3c6af6 100644 --- a/regression-test/suites/external_table_p0/tvf/test_frontends_tvf.groovy +++ b/regression-test/suites/external_table_p0/tvf/test_frontends_tvf.groovy @@ -20,7 +20,29 @@ suite("test_frontends_tvf","p0,external,tvf,external_docker") { List> table = sql """ select * from `frontends`(); """ logger.info("${table}") assertTrue(table.size() > 0) - assertTrue(table[0].size() == 19) + assertTrue(table[0].size() == 20) + + List> titleNames = sql """ describe function frontends(); """ + assertTrue(titleNames[0][0] == "Name") + assertTrue(titleNames[1][0] == "Host") + assertTrue(titleNames[2][0] == "EditLogPort") + assertTrue(titleNames[3][0] == "HttpPort") + assertTrue(titleNames[4][0] == "QueryPort") + assertTrue(titleNames[5][0] == "RpcPort") + assertTrue(titleNames[6][0] == "ArrowFlightSqlPort") + assertTrue(titleNames[7][0] == "Role") + assertTrue(titleNames[8][0] == "IsMaster") + assertTrue(titleNames[9][0] == "ClusterId") + assertTrue(titleNames[10][0] == "Join") + assertTrue(titleNames[11][0] == "Alive") + assertTrue(titleNames[12][0] == "ReplayedJournalId") + assertTrue(titleNames[13][0] == "LastStartTime") + assertTrue(titleNames[14][0] == "LastHeartbeat") + assertTrue(titleNames[15][0] == "IsHelper") + assertTrue(titleNames[16][0] == "ErrMsg") + assertTrue(titleNames[17][0] == "Version") + assertTrue(titleNames[18][0] == "CurrentConnected") + assertTrue(titleNames[19][0] == "LiveSince") // filter columns table = sql """ select Name from `frontends`();""" @@ -46,7 +68,7 @@ suite("test_frontends_tvf","p0,external,tvf,external_docker") { sql """ select Name, Host, EditLogPort HttpPort, QueryPort, RpcPort, ArrowFlightSqlPort, `Role`, IsMaster, ClusterId `Join`, Alive, ReplayedJournalId, LastHeartbeat - IsHelper, ErrMsg, Version, CurrentConnected from frontends(); + IsHelper, ErrMsg, Version, CurrentConnected, LiveSince from frontends(); """ // test exception