This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.1 by this push:
new 9c486189c94 [enhancement](mysql compatible) add user and procs_priv
tables to mysql db in all catalogs (#33058)
9c486189c94 is described below
commit 9c486189c947756f49a2044fd24011273df76b42
Author: zy-kkk <[email protected]>
AuthorDate: Tue Apr 2 22:56:14 2024 +0800
[enhancement](mysql compatible) add user and procs_priv tables to mysql db
in all catalogs (#33058)
Issue Number: close #xxx
This PR aims to enhance the compatibility of BI tools (such as Dbeaver,
DataGrip) when using the mysql connector to connect to Doris, because some BI
tools query some tables in the mysql database. In our tests, the user and
procs_priv tables were mainly queried. This PR adds these two tables and adds
actual data to the user table. However, please note that most of the fields in
the user table are in Doris' own format rather than mysql format, so it can
only ensure that the BI tool is [...]
Thanks to @liujiwen-up for assisting in testing
---
be/src/exec/schema_scanner.cpp | 5 +
be/src/exec/schema_scanner/schema_helper.cpp | 10 ++
be/src/exec/schema_scanner/schema_helper.h | 4 +
be/src/exec/schema_scanner/schema_user_scanner.cpp | 134 +++++++++++++++++++++
be/src/exec/schema_scanner/schema_user_scanner.h | 53 ++++++++
.../org/apache/doris/analysis/RefreshDbStmt.java | 6 +
.../org/apache/doris/analysis/SchemaTableType.java | 4 +-
.../org/apache/doris/catalog/MysqlDBTable.java | 98 +++++++++++++++
.../java/org/apache/doris/catalog/MysqlDb.java | 6 +-
.../apache/doris/datasource/ExternalCatalog.java | 12 +-
.../apache/doris/datasource/ExternalDatabase.java | 28 ++++-
.../infoschema/ExternalMysqlDatabase.java | 55 +++++++++
.../datasource/infoschema/ExternalMysqlTable.java | 51 ++++++++
.../doris/datasource/jdbc/client/JdbcClient.java | 2 +
.../datasource/jdbc/client/JdbcMySQLClient.java | 2 +
.../org/apache/doris/mysql/privilege/Auth.java | 94 +++++++++++++++
.../org/apache/doris/persist/gson/GsonUtils.java | 4 +
.../apache/doris/service/FrontendServiceImpl.java | 9 ++
.../org/apache/doris/catalog/RefreshTableTest.java | 11 ++
.../doris/datasource/RefreshCatalogTest.java | 14 ++-
.../doris/service/FrontendServiceImplTest.java | 10 ++
gensrc/thrift/Descriptors.thrift | 4 +-
gensrc/thrift/FrontendService.thrift | 8 ++
.../jdbc/test_clickhouse_jdbc_catalog.out | Bin 5487 -> 5493 bytes
.../jdbc/test_db2_jdbc_catalog.out | 1 +
.../jdbc/test_mariadb_jdbc_catalog.out | 2 +-
.../jdbc/test_mysql_jdbc_catalog.out | 7 +-
.../jdbc/test_mysql_jdbc_driver5_catalog.out | 9 +-
.../jdbc/test_oracle_jdbc_catalog.out | 3 +
.../jdbc/test_pg_jdbc_catalog.out | 5 +
.../jdbc/test_sqlserver_jdbc_catalog.out | 2 +
31 files changed, 634 insertions(+), 19 deletions(-)
diff --git a/be/src/exec/schema_scanner.cpp b/be/src/exec/schema_scanner.cpp
index 32197e37e1e..87995a3f0ef 100644
--- a/be/src/exec/schema_scanner.cpp
+++ b/be/src/exec/schema_scanner.cpp
@@ -43,6 +43,7 @@
#include "exec/schema_scanner/schema_table_privileges_scanner.h"
#include "exec/schema_scanner/schema_tables_scanner.h"
#include "exec/schema_scanner/schema_user_privileges_scanner.h"
+#include "exec/schema_scanner/schema_user_scanner.h"
#include "exec/schema_scanner/schema_variables_scanner.h"
#include "exec/schema_scanner/schema_views_scanner.h"
#include "exec/schema_scanner/schema_workload_groups_scanner.h"
@@ -161,6 +162,10 @@ std::unique_ptr<SchemaScanner>
SchemaScanner::create(TSchemaTableType::type type
return SchemaWorkloadGroupsScanner::create_unique();
case TSchemaTableType::SCH_PROCESSLIST:
return SchemaProcessListScanner::create_unique();
+ case TSchemaTableType::SCH_PROCEDURES:
+ return SchemaRoutinesScanner::create_unique();
+ case TSchemaTableType::SCH_USER:
+ return SchemaUserScanner::create_unique();
default:
return SchemaDummyScanner::create_unique();
break;
diff --git a/be/src/exec/schema_scanner/schema_helper.cpp
b/be/src/exec/schema_scanner/schema_helper.cpp
index 965dc7a6eb4..2819dc603f7 100644
--- a/be/src/exec/schema_scanner/schema_helper.cpp
+++ b/be/src/exec/schema_scanner/schema_helper.cpp
@@ -37,6 +37,8 @@ class TShowVariableRequest;
class TShowVariableResult;
class TShowProcessListRequest;
class TShowProcessListResult;
+class TShowUserRequest;
+class TShowUserResult;
Status SchemaHelper::get_db_names(const std::string& ip, const int32_t port,
const TGetDbsParams& request, TGetDbsResult*
result) {
@@ -134,4 +136,12 @@ Status SchemaHelper::show_process_list(const std::string&
ip, const int32_t port
});
}
+Status SchemaHelper::show_user(const std::string& ip, const int32_t port,
+ const TShowUserRequest& request,
TShowUserResult* result) {
+ return ThriftRpcHelper::rpc<FrontendServiceClient>(
+ ip, port, [&request, &result](FrontendServiceConnection& client) {
+ client->showUser(*result, request);
+ });
+}
+
} // namespace doris
diff --git a/be/src/exec/schema_scanner/schema_helper.h
b/be/src/exec/schema_scanner/schema_helper.h
index 5602e3c005f..752e282bb52 100644
--- a/be/src/exec/schema_scanner/schema_helper.h
+++ b/be/src/exec/schema_scanner/schema_helper.h
@@ -39,6 +39,8 @@ class TShowVariableRequest;
class TShowVariableResult;
class TShowProcessListRequest;
class TShowProcessListResult;
+class TShowUserRequest;
+class TShowUserResult;
// this class is a helper for getting schema info from FE
class SchemaHelper {
@@ -82,6 +84,8 @@ public:
static Status show_process_list(const std::string& ip, const int32_t port,
const TShowProcessListRequest& request,
TShowProcessListResult* result);
+ static Status show_user(const std::string& ip, const int32_t port,
+ const TShowUserRequest& request, TShowUserResult*
result);
};
} // namespace doris
diff --git a/be/src/exec/schema_scanner/schema_user_scanner.cpp
b/be/src/exec/schema_scanner/schema_user_scanner.cpp
new file mode 100644
index 00000000000..9b153414380
--- /dev/null
+++ b/be/src/exec/schema_scanner/schema_user_scanner.cpp
@@ -0,0 +1,134 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "exec/schema_scanner/schema_user_scanner.h"
+
+#include <gen_cpp/FrontendService_types.h>
+
+#include <vector>
+
+#include "exec/schema_scanner/schema_helper.h"
+#include "runtime/runtime_state.h"
+#include "vec/common/string_ref.h"
+#include "vec/core/block.h"
+#include "vec/data_types/data_type_factory.hpp"
+
+namespace doris {
+
+std::vector<SchemaScanner::ColumnDesc> SchemaUserScanner::_s_user_columns = {
+ {"Host", TYPE_CHAR, sizeof(StringRef), false},
+ {"User", TYPE_CHAR, sizeof(StringRef), false},
+ {"Node_priv", TYPE_CHAR, sizeof(StringRef), false},
+ {"Admin_priv", TYPE_CHAR, sizeof(StringRef), false},
+ {"Grant_priv", TYPE_CHAR, sizeof(StringRef), false},
+ {"Select_priv", TYPE_CHAR, sizeof(StringRef), false},
+ {"Load_priv", TYPE_CHAR, sizeof(StringRef), false},
+ {"Alter_priv", TYPE_CHAR, sizeof(StringRef), false},
+ {"Create_priv", TYPE_CHAR, sizeof(StringRef), false},
+ {"Drop_priv", TYPE_CHAR, sizeof(StringRef), false},
+ {"Usage_priv", TYPE_CHAR, sizeof(StringRef), false},
+ {"Show_view_priv", TYPE_CHAR, sizeof(StringRef), false},
+ {"Cluster_usage_priv", TYPE_CHAR, sizeof(StringRef), false},
+ {"Stage_usage_priv", TYPE_CHAR, sizeof(StringRef), false},
+ {"ssl_type", TYPE_CHAR, sizeof(StringRef), false},
+ {"ssl_cipher", TYPE_VARCHAR, sizeof(StringRef), false},
+ {"x509_issuer", TYPE_VARCHAR, sizeof(StringRef), false},
+ {"x509_subject", TYPE_VARCHAR, sizeof(StringRef), false},
+ {"max_questions", TYPE_BIGINT, sizeof(int64_t), false},
+ {"max_updates", TYPE_BIGINT, sizeof(int64_t), false},
+ {"max_connections", TYPE_BIGINT, sizeof(int64_t), false},
+ {"max_user_connections", TYPE_BIGINT, sizeof(int64_t), false},
+ {"plugin", TYPE_CHAR, sizeof(StringRef), false},
+ {"authentication_string", TYPE_VARCHAR, sizeof(StringRef), false},
+ {"password_policy.expiration_seconds", TYPE_VARCHAR,
sizeof(StringRef), false},
+ {"password_policy.password_creation_time", TYPE_VARCHAR,
sizeof(StringRef), false},
+ {"password_policy.history_num", TYPE_VARCHAR, sizeof(StringRef),
false},
+ {"password_policy.history_passwords", TYPE_VARCHAR, sizeof(StringRef),
false},
+ {"password_policy.num_failed_login", TYPE_VARCHAR, sizeof(StringRef),
false},
+ {"password_policy.password_lock_seconds", TYPE_VARCHAR,
sizeof(StringRef), false},
+ {"password_policy.failed_login_counter", TYPE_VARCHAR,
sizeof(StringRef), false},
+ {"password_policy.lock_time", TYPE_VARCHAR, sizeof(StringRef), false}};
+
+SchemaUserScanner::SchemaUserScanner()
+ : SchemaScanner(_s_user_columns, TSchemaTableType::SCH_USER) {}
+
+SchemaUserScanner::~SchemaUserScanner() = default;
+
+Status SchemaUserScanner::start(RuntimeState* state) {
+ TShowUserRequest request;
+ RETURN_IF_ERROR(SchemaHelper::show_user(*(_param->common_param->ip),
_param->common_param->port,
+ request, &_user_result));
+
+ return Status::OK();
+}
+
+Status SchemaUserScanner::get_next_block(vectorized::Block* block, bool* eos) {
+ if (!_is_init) {
+ return Status::InternalError("call this before initial.");
+ }
+ if (block == nullptr || eos == nullptr) {
+ return Status::InternalError("invalid parameter.");
+ }
+
+ *eos = true;
+ if (_user_result.userinfo_list.empty()) {
+ return Status::OK();
+ }
+
+ return _fill_block_impl(block);
+}
+
+Status SchemaUserScanner::_fill_block_impl(vectorized::Block* block) {
+ SCOPED_TIMER(_fill_block_timer);
+
+ const auto& userinfo_list = _user_result.userinfo_list;
+ size_t row_num = userinfo_list.size();
+ if (row_num == 0) {
+ return Status::OK();
+ }
+
+ for (size_t col_idx = 0; col_idx < _s_user_columns.size(); ++col_idx) {
+ std::vector<StringRef> str_refs(row_num);
+ std::vector<int64_t> int_vals(row_num);
+ std::vector<void*> datas(row_num);
+ std::vector<std::string> column_values(
+ row_num); // Store the strings to ensure their lifetime
+
+ for (size_t row_idx = 0; row_idx < row_num; ++row_idx) {
+ const auto& row = userinfo_list[row_idx];
+ std::string column_value = row.size() > col_idx ? row[col_idx] :
"";
+
+ // Ensure column value assignment and type casting
+ column_values[row_idx] = column_value;
+ if (_s_user_columns[col_idx].type == TYPE_BIGINT) {
+ int64_t val = !column_value.empty() ? std::stoll(column_value)
: 0;
+ int_vals[row_idx] = val;
+ datas[row_idx] = &int_vals[row_idx];
+ } else {
+ str_refs[row_idx] =
+ StringRef(column_values[row_idx].data(),
column_values[row_idx].size());
+ datas[row_idx] = &str_refs[row_idx];
+ }
+ }
+
+ RETURN_IF_ERROR(fill_dest_column_for_range(block, col_idx, datas));
+ }
+
+ return Status::OK();
+}
+
+} // namespace doris
diff --git a/be/src/exec/schema_scanner/schema_user_scanner.h
b/be/src/exec/schema_scanner/schema_user_scanner.h
new file mode 100644
index 00000000000..c55f216804d
--- /dev/null
+++ b/be/src/exec/schema_scanner/schema_user_scanner.h
@@ -0,0 +1,53 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include "common/status.h"
+#include "exec/schema_scanner.h"
+#include "gen_cpp/FrontendService_types.h"
+
+namespace doris {
+
+class RuntimeState;
+
+namespace vectorized {
+class Block;
+}
+
+class SchemaUserScanner : public SchemaScanner {
+ ENABLE_FACTORY_CREATOR(SchemaUserScanner);
+
+public:
+ SchemaUserScanner();
+ ~SchemaUserScanner() override;
+
+ Status start(RuntimeState* state) override;
+ Status get_next_block(vectorized::Block* block, bool* eos) override;
+
+ static std::vector<SchemaScanner::ColumnDesc> _s_user_columns;
+
+private:
+ Status _fill_block_impl(vectorized::Block* block);
+
+ TShowUserResult _user_result;
+};
+
+} // namespace doris
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/RefreshDbStmt.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/RefreshDbStmt.java
index 5251a18b3d6..e8bdc168ddc 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/RefreshDbStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/RefreshDbStmt.java
@@ -19,6 +19,7 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.InfoSchemaDb;
+import org.apache.doris.catalog.MysqlDb;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
@@ -79,6 +80,11 @@ public class RefreshDbStmt extends DdlStmt {
ErrorReport.reportAnalysisException(
ErrorCode.ERR_DBACCESS_DENIED_ERROR,
analyzer.getQualifiedUser(), dbName);
}
+ // Don't allow dropping 'mysql' database
+ if (dbName.equalsIgnoreCase(MysqlDb.DATABASE_NAME)) {
+ ErrorReport.reportAnalysisException(
+ ErrorCode.ERR_DBACCESS_DENIED_ERROR,
analyzer.getQualifiedUser(), dbName);
+ }
// check access
if
(!Env.getCurrentEnv().getAccessManager().checkDbPriv(ConnectContext.get(),
catalogName,
dbName, PrivPredicate.DROP)) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java
index bb1aa5e7952..2c0901c1e50 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SchemaTableType.java
@@ -72,7 +72,9 @@ public enum SchemaTableType {
SCH_PROFILING("PROFILING", "PROFILING", TSchemaTableType.SCH_PROFILING),
SCH_BACKEND_ACTIVE_TASKS("BACKEND_ACTIVE_TASKS", "BACKEND_ACTIVE_TASKS",
TSchemaTableType.SCH_BACKEND_ACTIVE_TASKS),
SCH_ACTIVE_QUERIES("ACTIVE_QUERIES", "ACTIVE_QUERIES",
TSchemaTableType.SCH_ACTIVE_QUERIES),
- SCH_WORKLOAD_GROUPS("WORKLOAD_GROUPS", "WORKLOAD_GROUPS",
TSchemaTableType.SCH_WORKLOAD_GROUPS);
+ SCH_WORKLOAD_GROUPS("WORKLOAD_GROUPS", "WORKLOAD_GROUPS",
TSchemaTableType.SCH_WORKLOAD_GROUPS),
+ SCHE_USER("user", "user", TSchemaTableType.SCH_USER),
+ SCH_PROCS_PRIV("procs_priv", "procs_priv",
TSchemaTableType.SCH_PROCS_PRIV);
private static final String dbName = "INFORMATION_SCHEMA";
private static SelectList fullSelectLists;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/MysqlDBTable.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/MysqlDBTable.java
new file mode 100644
index 00000000000..4f3c6cdf57b
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/MysqlDBTable.java
@@ -0,0 +1,98 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.catalog;
+
+import org.apache.doris.analysis.SchemaTableType;
+import org.apache.doris.common.SystemIdGenerator;
+import org.apache.doris.thrift.TSchemaTable;
+import org.apache.doris.thrift.TTableDescriptor;
+import org.apache.doris.thrift.TTableType;
+
+import com.google.common.collect.ImmutableMap;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Doris's representation of MySQL mysql table metadata.
+ */
+public class MysqlDBTable extends SchemaTable {
+
+ public static Map<String, Table> TABLE_MAP = ImmutableMap.<String,
Table>builder().put("user",
+ new MysqlDBTable(SystemIdGenerator.getNextId(), "user",
TableType.SCHEMA,
+ builder().column("Host",
ScalarType.createCharType(255))
+ .column("User",
ScalarType.createCharType(32))
+ .column("Node_priv",
ScalarType.createCharType(1))
+ .column("Admin_priv",
ScalarType.createCharType(1))
+ .column("Grant_priv",
ScalarType.createCharType(1))
+ .column("Select_priv",
ScalarType.createCharType(1))
+ .column("Load_priv",
ScalarType.createCharType(1))
+ .column("Alter_priv",
ScalarType.createCharType(1))
+ .column("Create_priv",
ScalarType.createCharType(1))
+ .column("Drop_priv",
ScalarType.createCharType(1))
+ .column("Usage_priv",
ScalarType.createCharType(1))
+ .column("Show_view_priv",
ScalarType.createCharType(1))
+ .column("Cluster_usage_priv",
ScalarType.createCharType(1))
+ .column("Stage_usage_priv",
ScalarType.createCharType(1))
+ .column("ssl_type",
ScalarType.createCharType(9))
+ .column("ssl_cipher",
ScalarType.createVarcharType(ScalarType.MAX_VARCHAR_LENGTH))
+ .column("x509_issuer",
ScalarType.createVarcharType(ScalarType.MAX_VARCHAR_LENGTH))
+ .column("x509_subject",
ScalarType.createVarcharType(ScalarType.MAX_VARCHAR_LENGTH))
+ .column("max_questions", Type.BIGINT)
+ .column("max_updates", Type.BIGINT)
+ .column("max_connections", Type.BIGINT)
+ .column("max_user_connections",
Type.BIGINT)
+ .column("plugin",
ScalarType.createCharType(64))
+ .column("authentication_string",
+
ScalarType.createVarcharType(ScalarType.MAX_VARCHAR_LENGTH))
+
.column("password_policy.expiration_seconds", ScalarType.createVarcharType(32))
+
.column("password_policy.password_creation_time",
ScalarType.createVarcharType(32))
+ .column("password_policy.history_num",
ScalarType.createVarcharType(32))
+
.column("password_policy.history_passwords",
+
ScalarType.createVarcharType(ScalarType.MAX_VARCHAR_LENGTH))
+
.column("password_policy.num_failed_login", ScalarType.createVarcharType(32))
+
.column("password_policy.password_lock_seconds",
ScalarType.createVarcharType(32))
+
.column("password_policy.failed_login_counter",
ScalarType.createVarcharType(32))
+ .column("password_policy.lock_time",
ScalarType.createVarcharType(32))
+ .build()))
+ .put("procs_priv",
+ new MysqlDBTable(SystemIdGenerator.getNextId(),
"procs_priv", TableType.SCHEMA,
+ builder().column("Host",
ScalarType.createCharType(60))
+ .column("Db",
ScalarType.createCharType(64))
+ .column("User",
ScalarType.createCharType(32))
+ .column("Routine_name",
ScalarType.createCharType(64))
+ .column("Routine_type",
ScalarType.createCharType(9))
+ .column("Grantor",
ScalarType.createCharType(93))
+ .column("Proc_priv",
ScalarType.createCharType(16))
+ .column("Timestamp",
ScalarType.createCharType(1))
+ .build()))
+ .build();
+
+ public MysqlDBTable(long id, String tableName, TableType type,
List<Column> fullSchema) {
+ super(id, tableName, type, fullSchema);
+ }
+
+ @Override
+ public TTableDescriptor toThrift() {
+ TSchemaTable tSchemaTable = new
TSchemaTable(SchemaTableType.getThriftType(this.name));
+ TTableDescriptor tTableDescriptor = new TTableDescriptor(getId(),
TTableType.SCHEMA_TABLE,
+ TABLE_MAP.get(this.name).getBaseSchema().size(), 0, this.name,
"");
+ tTableDescriptor.setSchemaTable(tSchemaTable);
+ return tTableDescriptor;
+ }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/MysqlDb.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/MysqlDb.java
index 67d7fc8ecca..cec2461b9e4 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/MysqlDb.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/MysqlDb.java
@@ -49,7 +49,11 @@ public class MysqlDb extends MysqlCompatibleDatabase {
* If we need tables of mysql database in the future, create a MysqlTable
class like {@link SchemaTable}
*/
@Override
- public void initTables() {}
+ public void initTables() {
+ for (Table table : MysqlDBTable.TABLE_MAP.values()) {
+ super.registerTable(table);
+ }
+ }
@Override
public boolean registerTable(TableIf table) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java
index a3525321edf..45d99e02223 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalCatalog.java
@@ -26,6 +26,7 @@ import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.DatabaseIf;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.InfoSchemaDb;
+import org.apache.doris.catalog.MysqlDb;
import org.apache.doris.catalog.Resource;
import org.apache.doris.catalog.TableIf;
import org.apache.doris.cluster.ClusterNamespace;
@@ -40,6 +41,7 @@ import org.apache.doris.datasource.hive.HMSExternalCatalog;
import org.apache.doris.datasource.hive.HMSExternalDatabase;
import org.apache.doris.datasource.iceberg.IcebergExternalDatabase;
import org.apache.doris.datasource.infoschema.ExternalInfoSchemaDatabase;
+import org.apache.doris.datasource.infoschema.ExternalMysqlDatabase;
import org.apache.doris.datasource.jdbc.JdbcExternalDatabase;
import org.apache.doris.datasource.maxcompute.MaxComputeExternalDatabase;
import org.apache.doris.datasource.operations.ExternalMetadataOps;
@@ -291,10 +293,12 @@ public abstract class ExternalCatalog
allDatabases.remove(InfoSchemaDb.DATABASE_NAME);
allDatabases.add(InfoSchemaDb.DATABASE_NAME);
+ allDatabases.remove(MysqlDb.DATABASE_NAME);
+ allDatabases.add(MysqlDb.DATABASE_NAME);
Map<String, Boolean> includeDatabaseMap = getIncludeDatabaseMap();
Map<String, Boolean> excludeDatabaseMap = getExcludeDatabaseMap();
for (String dbName : allDatabases) {
- if (!dbName.equals(InfoSchemaDb.DATABASE_NAME)) {
+ if (!dbName.equals(InfoSchemaDb.DATABASE_NAME) &&
!dbName.equals(MysqlDb.DATABASE_NAME)) {
// Exclude database map take effect with higher priority over
include database map
if (!excludeDatabaseMap.isEmpty() &&
excludeDatabaseMap.containsKey(dbName)) {
continue;
@@ -438,6 +442,9 @@ public abstract class ExternalCatalog
if (realDbName.equalsIgnoreCase(InfoSchemaDb.DATABASE_NAME)) {
return idToDb.get(dbNameToId.get(InfoSchemaDb.DATABASE_NAME));
}
+ if (realDbName.equalsIgnoreCase(MysqlDb.DATABASE_NAME)) {
+ return idToDb.get(dbNameToId.get(MysqlDb.DATABASE_NAME));
+ }
}
return null;
}
@@ -549,6 +556,9 @@ public abstract class ExternalCatalog
if (dbName.equals(InfoSchemaDb.DATABASE_NAME)) {
return new ExternalInfoSchemaDatabase(this, dbId);
}
+ if (dbName.equals(MysqlDb.DATABASE_NAME)) {
+ return new ExternalMysqlDatabase(this, dbId);
+ }
switch (logType) {
case HMS:
return new HMSExternalDatabase(this, dbId, dbName);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java
index 2d0d47f633c..3308b04968f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalDatabase.java
@@ -21,6 +21,7 @@ import org.apache.doris.catalog.DatabaseIf;
import org.apache.doris.catalog.DatabaseProperty;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.InfoSchemaDb;
+import org.apache.doris.catalog.MysqlDb;
import org.apache.doris.catalog.TableIf;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.MetaNotFoundException;
@@ -29,6 +30,8 @@ import org.apache.doris.common.io.Writable;
import org.apache.doris.common.util.Util;
import org.apache.doris.datasource.infoschema.ExternalInfoSchemaDatabase;
import org.apache.doris.datasource.infoschema.ExternalInfoSchemaTable;
+import org.apache.doris.datasource.infoschema.ExternalMysqlDatabase;
+import org.apache.doris.datasource.infoschema.ExternalMysqlTable;
import org.apache.doris.persist.gson.GsonPostProcessable;
import org.apache.doris.persist.gson.GsonUtils;
import org.apache.doris.qe.ConnectContext;
@@ -60,7 +63,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
* @param <T> External table type is ExternalTable or its subclass.
*/
public abstract class ExternalDatabase<T extends ExternalTable>
- implements DatabaseIf<T>, Writable, GsonPostProcessable {
+ implements DatabaseIf<T>, Writable, GsonPostProcessable {
private static final Logger LOG =
LogManager.getLogger(ExternalDatabase.class);
protected ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true);
@@ -173,6 +176,8 @@ public abstract class ExternalDatabase<T extends
ExternalTable>
List<String> tableNames;
if (name.equals(InfoSchemaDb.DATABASE_NAME)) {
tableNames = ExternalInfoSchemaDatabase.listTableNames();
+ } else if (name.equals(MysqlDb.DATABASE_NAME)) {
+ tableNames = ExternalMysqlDatabase.listTableNames();
} else {
tableNames = extCatalog.listTableNames(null, name);
}
@@ -350,10 +355,23 @@ public abstract class ExternalDatabase<T extends
ExternalTable>
Map<Long, T> tmpIdToTbl = Maps.newConcurrentMap();
for (Object obj : idToTbl.values()) {
if (obj instanceof LinkedTreeMap) {
- ExternalInfoSchemaTable table =
GsonUtils.GSON.fromJson(GsonUtils.GSON.toJson(obj),
- ExternalInfoSchemaTable.class);
- tmpIdToTbl.put(table.getId(), (T) table);
- tableNameToId.put(table.getName(), table.getId());
+ String clazzType = ((LinkedTreeMap<?, ?>)
obj).get("clazz").toString();
+ switch (clazzType) {
+ case "ExternalInfoSchemaTable":
+ ExternalInfoSchemaTable infoSchemaTable =
GsonUtils.GSON.fromJson(GsonUtils.GSON.toJson(obj),
+ ExternalInfoSchemaTable.class);
+ tmpIdToTbl.put(infoSchemaTable.getId(), (T)
infoSchemaTable);
+ tableNameToId.put(infoSchemaTable.getName(),
infoSchemaTable.getId());
+ break;
+ case "ExternalMysqlTable":
+ ExternalMysqlTable mysqlTable =
GsonUtils.GSON.fromJson(GsonUtils.GSON.toJson(obj),
+ ExternalMysqlTable.class);
+ tmpIdToTbl.put(mysqlTable.getId(), (T) mysqlTable);
+ tableNameToId.put(mysqlTable.getName(),
mysqlTable.getId());
+ break;
+ default:
+ break;
+ }
} else {
Preconditions.checkState(obj instanceof ExternalTable);
tmpIdToTbl.put(((ExternalTable) obj).getId(), (T) obj);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlDatabase.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlDatabase.java
new file mode 100644
index 00000000000..8e9ba26ab2b
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlDatabase.java
@@ -0,0 +1,55 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.datasource.infoschema;
+
+import org.apache.doris.catalog.MysqlDBTable;
+import org.apache.doris.catalog.MysqlDb;
+import org.apache.doris.datasource.ExternalCatalog;
+import org.apache.doris.datasource.ExternalDatabase;
+import org.apache.doris.datasource.ExternalTable;
+import org.apache.doris.datasource.InitDatabaseLog.Type;
+
+import com.google.common.collect.Lists;
+
+import java.util.List;
+
+public class ExternalMysqlDatabase extends ExternalDatabase {
+ /**
+ * Create external database.
+ *
+ * @param extCatalog The catalog this database belongs to.
+ * @param dbId The id of this database.
+ */
+ public ExternalMysqlDatabase(ExternalCatalog extCatalog, long dbId) {
+ super(extCatalog, dbId, MysqlDb.DATABASE_NAME, Type.INFO_SCHEMA_DB);
+ }
+
+ public static List<String> listTableNames() {
+ return Lists.newArrayList(MysqlDBTable.TABLE_MAP.keySet());
+ }
+
+ @Override
+ protected ExternalTable newExternalTable(String tableName, long tblId,
ExternalCatalog catalog) {
+ return new ExternalMysqlTable(tblId, tableName, catalog);
+ }
+
+ @Override
+ public ExternalTable getTableNullable(String name) {
+ return super.getTableNullable(name.toLowerCase());
+ }
+}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlTable.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlTable.java
new file mode 100644
index 00000000000..fc64bc053a4
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/infoschema/ExternalMysqlTable.java
@@ -0,0 +1,51 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.datasource.infoschema;
+
+import org.apache.doris.analysis.SchemaTableType;
+import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.MysqlDBTable;
+import org.apache.doris.catalog.MysqlDb;
+import org.apache.doris.datasource.ExternalCatalog;
+import org.apache.doris.datasource.ExternalTable;
+import org.apache.doris.thrift.TSchemaTable;
+import org.apache.doris.thrift.TTableDescriptor;
+import org.apache.doris.thrift.TTableType;
+
+import java.util.List;
+
+public class ExternalMysqlTable extends ExternalTable {
+ public ExternalMysqlTable(long id, String name, ExternalCatalog catalog) {
+ super(id, name, catalog, MysqlDb.DATABASE_NAME, TableType.SCHEMA);
+ }
+
+ @Override
+ public List<Column> initSchema() {
+ makeSureInitialized();
+ return MysqlDBTable.TABLE_MAP.get(name).getFullSchema();
+ }
+
+ @Override
+ public TTableDescriptor toThrift() {
+ TSchemaTable tSchemaTable = new
TSchemaTable(SchemaTableType.getThriftType(this.name));
+ TTableDescriptor tTableDescriptor = new TTableDescriptor(getId(),
TTableType.SCHEMA_TABLE,
+ getFullSchema().size(), 0, this.name, "");
+ tTableDescriptor.setSchemaTable(tSchemaTable);
+ return tTableDescriptor;
+ }
+}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcClient.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcClient.java
index a95c6c74f2b..7e093f1008c 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcClient.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcClient.java
@@ -409,6 +409,8 @@ public abstract class JdbcClient {
protected Set<String> getFilterInternalDatabases() {
return ImmutableSet.<String>builder()
.add("information_schema")
+ .add("performance_schema")
+ .add("mysql")
.build();
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClient.java
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClient.java
index 20047b29be2..6ea5ea127d5 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClient.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClient.java
@@ -173,6 +173,8 @@ public class JdbcMySQLClient extends JdbcClient {
protected Set<String> getFilterInternalDatabases() {
return ImmutableSet.<String>builder()
+ .add("information_schema")
+ .add("performance_schema")
.add("mysql")
.add("sys")
.build();
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java
b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java
index 182863e7ac9..3bad8c318cc 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java
@@ -77,6 +77,7 @@ import org.apache.logging.log4j.Logger;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -1812,4 +1813,97 @@ public class Auth implements Writable {
sb.append(ldapInfo).append("\n");
return sb.toString();
}
+
+ // for mysql.user table
+ public List<List<String>> getAllUserInfo() {
+ List<List<String>> userInfos = Lists.newArrayList();
+ readLock();
+ try {
+ Map<String, List<User>> nameToUsers = userManager.getNameToUsers();
+ for (List<User> users : nameToUsers.values()) {
+ for (User user : users) {
+ if (!user.isSetByDomainResolver()) {
+ List<String> userInfo =
Lists.newArrayList(Collections.nCopies(32, ""));
+ UserIdentity userIdent = user.getUserIdentity();
+ userInfo.set(0, userIdent.getHost());
+ userInfo.set(1, userIdent.getQualifiedUser());
+ for (int i = 2; i <= 13; i++) {
+ userInfo.set(i, "N");
+ }
+
+ PrivTable privTable =
getUserGlobalPrivTable(userIdent);
+ if (!privTable.entries.isEmpty()) {
+ PrivEntry privEntry = privTable.entries.get(0);
+ if (!privEntry.getPrivSet().isEmpty()) {
+ boolean isAdmin = false;
+ for (Privilege globalPriv :
privEntry.getPrivSet().toPrivilegeList()) {
+ switch (globalPriv) {
+ case NODE_PRIV:
+ userInfo.set(2, "Y");
+ break;
+ case ADMIN_PRIV:
+ isAdmin = true;
+ userInfo.set(3, "Y");
+ break;
+ case GRANT_PRIV:
+ userInfo.set(4, "Y");
+ break;
+ case SELECT_PRIV:
+ userInfo.set(5, "Y");
+ break;
+ case LOAD_PRIV:
+ userInfo.set(6, "Y");
+ break;
+ case ALTER_PRIV:
+ userInfo.set(7, "Y");
+ break;
+ case CREATE_PRIV:
+ userInfo.set(8, "Y");
+ break;
+ case DROP_PRIV:
+ userInfo.set(9, "Y");
+ break;
+ case USAGE_PRIV:
+ userInfo.set(10, "Y");
+ break;
+ case SHOW_VIEW_PRIV:
+ userInfo.set(11, "Y");
+ break;
+ case CLUSTER_USAGE_PRIV:
+ userInfo.set(12, "Y");
+ break;
+ case STAGE_USAGE_PRIV:
+ userInfo.set(13, "Y");
+ break;
+ default:
+ break;
+ }
+ }
+
+ // If the user is admin, set all permissions
to 'Y' except Node_priv
+ if (isAdmin) {
+ for (int i = 4; i <= 13; i++) {
+ userInfo.set(i, "Y");
+ }
+ }
+ }
+ }
+
+ // Set password policy info
+ userInfo.set(21,
String.valueOf(getMaxConn(userIdent.getQualifiedUser())));
+ List<List<String>> passWordPolicyInfo =
getPasswdPolicyInfo(userIdent);
+ if (passWordPolicyInfo.size() == 8) {
+ for (int i = 0; i < passWordPolicyInfo.size();
i++) {
+ userInfo.set(24 + i,
passWordPolicyInfo.get(i).get(1));
+ }
+ }
+ userInfos.add(userInfo);
+ }
+ }
+ }
+ } finally {
+ readUnlock();
+ }
+ return userInfos;
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java
b/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java
index 6d71cd58826..d380d6824fa 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java
@@ -69,6 +69,8 @@ import
org.apache.doris.datasource.iceberg.IcebergHadoopExternalCatalog;
import org.apache.doris.datasource.iceberg.IcebergRestExternalCatalog;
import org.apache.doris.datasource.infoschema.ExternalInfoSchemaDatabase;
import org.apache.doris.datasource.infoschema.ExternalInfoSchemaTable;
+import org.apache.doris.datasource.infoschema.ExternalMysqlDatabase;
+import org.apache.doris.datasource.infoschema.ExternalMysqlTable;
import org.apache.doris.datasource.jdbc.JdbcExternalCatalog;
import org.apache.doris.datasource.jdbc.JdbcExternalDatabase;
import org.apache.doris.datasource.jdbc.JdbcExternalTable;
@@ -261,6 +263,7 @@ public class GsonUtils {
.registerSubtype(PaimonExternalDatabase.class,
PaimonExternalDatabase.class.getSimpleName())
.registerSubtype(MaxComputeExternalDatabase.class,
MaxComputeExternalDatabase.class.getSimpleName())
.registerSubtype(ExternalInfoSchemaDatabase.class,
ExternalInfoSchemaDatabase.class.getSimpleName())
+ .registerSubtype(ExternalMysqlDatabase.class,
ExternalMysqlDatabase.class.getSimpleName())
.registerSubtype(TestExternalDatabase.class,
TestExternalDatabase.class.getSimpleName());
private static RuntimeTypeAdapterFactory<TableIf> tblTypeAdapterFactory =
RuntimeTypeAdapterFactory.of(
@@ -273,6 +276,7 @@ public class GsonUtils {
.registerSubtype(PaimonExternalTable.class,
PaimonExternalTable.class.getSimpleName())
.registerSubtype(MaxComputeExternalTable.class,
MaxComputeExternalTable.class.getSimpleName())
.registerSubtype(ExternalInfoSchemaTable.class,
ExternalInfoSchemaTable.class.getSimpleName())
+ .registerSubtype(ExternalMysqlTable.class,
ExternalMysqlTable.class.getSimpleName())
.registerSubtype(TestExternalTable.class,
TestExternalTable.class.getSimpleName());
// runtime adapter for class "PartitionInfo"
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
index 87adc37722c..5269a43898c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
@@ -212,6 +212,8 @@ import org.apache.doris.thrift.TRollbackTxnResult;
import org.apache.doris.thrift.TSchemaTableName;
import org.apache.doris.thrift.TShowProcessListRequest;
import org.apache.doris.thrift.TShowProcessListResult;
+import org.apache.doris.thrift.TShowUserRequest;
+import org.apache.doris.thrift.TShowUserResult;
import org.apache.doris.thrift.TShowVariableRequest;
import org.apache.doris.thrift.TShowVariableResult;
import org.apache.doris.thrift.TSnapshotLoaderReportRequest;
@@ -3843,4 +3845,11 @@ public class FrontendServiceImpl implements
FrontendService.Iface {
return result;
}
+ @Override
+ public TShowUserResult showUser(TShowUserRequest request) {
+ List<List<String>> userInfo =
Env.getCurrentEnv().getAuth().getAllUserInfo();
+ TShowUserResult result = new TShowUserResult();
+ result.setUserinfoList(userInfo);
+ return result;
+ }
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/catalog/RefreshTableTest.java
b/fe/fe-core/src/test/java/org/apache/doris/catalog/RefreshTableTest.java
index c979926335e..d37058c20cd 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/RefreshTableTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/RefreshTableTest.java
@@ -30,6 +30,8 @@ import org.apache.doris.common.FeConstants;
import org.apache.doris.datasource.CatalogIf;
import org.apache.doris.datasource.infoschema.ExternalInfoSchemaDatabase;
import org.apache.doris.datasource.infoschema.ExternalInfoSchemaTable;
+import org.apache.doris.datasource.infoschema.ExternalMysqlDatabase;
+import org.apache.doris.datasource.infoschema.ExternalMysqlTable;
import org.apache.doris.datasource.test.TestExternalCatalog;
import org.apache.doris.datasource.test.TestExternalTable;
import org.apache.doris.mysql.privilege.Auth;
@@ -109,6 +111,15 @@ public class RefreshTableTest extends TestWithFeService {
List<Column> schema = infoTbl.getFullSchema();
Assertions.assertEquals(SchemaTable.TABLE_MAP.get(tblName).getColumns().size(),
schema.size());
}
+ // external mysql db
+ ExternalMysqlDatabase mysqlDb = (ExternalMysqlDatabase)
test1.getDbNullable(MysqlDb.DATABASE_NAME);
+ Assertions.assertNotNull(mysqlDb);
+ for (String tblName : MysqlDBTable.TABLE_MAP.keySet()) {
+ ExternalMysqlTable mysqlTbl = (ExternalMysqlTable)
mysqlDb.getTableNullable(tblName);
+ Assertions.assertNotNull(mysqlTbl);
+ List<Column> schema = mysqlTbl.getFullSchema();
+
Assertions.assertEquals(MysqlDBTable.TABLE_MAP.get(tblName).getColumns().size(),
schema.size());
+ }
}
@Test
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/datasource/RefreshCatalogTest.java
b/fe/fe-core/src/test/java/org/apache/doris/datasource/RefreshCatalogTest.java
index 8480154f243..0cdd0db8ae3 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/datasource/RefreshCatalogTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/datasource/RefreshCatalogTest.java
@@ -22,9 +22,11 @@ import org.apache.doris.analysis.DropCatalogStmt;
import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.InfoSchemaDb;
+import org.apache.doris.catalog.MysqlDb;
import org.apache.doris.catalog.PrimitiveType;
import org.apache.doris.common.FeConstants;
import org.apache.doris.datasource.infoschema.ExternalInfoSchemaDatabase;
+import org.apache.doris.datasource.infoschema.ExternalMysqlDatabase;
import org.apache.doris.datasource.test.TestExternalCatalog;
import org.apache.doris.datasource.test.TestExternalDatabase;
import org.apache.doris.mysql.privilege.Auth;
@@ -77,19 +79,21 @@ public class RefreshCatalogTest extends TestWithFeService {
public void testRefreshCatalog() throws Exception {
CatalogIf test1 = env.getCatalogMgr().getCatalog("test1");
List<String> dbNames1 = test1.getDbNames();
- // there are test1.db1 , test1.db2, information_schema
- Assertions.assertEquals(3, dbNames1.size());
+ // there are test1.db1 , test1.db2, information_schema, mysql
+ Assertions.assertEquals(4, dbNames1.size());
// 1.simulate ExternalCatalog adds a new table
RefreshCatalogProvider.addData();
// 2.wait for the refresh time of the catalog
Thread.sleep(5000);
- // there are test1.db1 , test1.db2 , test1.db3, information_schema
+ // there are test1.db1 , test1.db2 , test1.db3, information_schema,
mysql
List<String> dbNames2 = test1.getDbNames();
- Assertions.assertEquals(4, dbNames2.size());
+ Assertions.assertEquals(5, dbNames2.size());
ExternalInfoSchemaDatabase infoDb = (ExternalInfoSchemaDatabase)
test1.getDb(InfoSchemaDb.DATABASE_NAME).get();
Assertions.assertEquals(31, infoDb.getTables().size());
TestExternalDatabase testDb = (TestExternalDatabase)
test1.getDb("db1").get();
Assertions.assertEquals(2, testDb.getTables().size());
+ ExternalMysqlDatabase mysqlDb = (ExternalMysqlDatabase)
test1.getDb(MysqlDb.DATABASE_NAME).get();
+ Assertions.assertEquals(2, mysqlDb.getTables().size());
String json = GsonUtils.GSON.toJson(env.getCatalogMgr());
System.out.println(json);
@@ -99,6 +103,8 @@ public class RefreshCatalogTest extends TestWithFeService {
Assertions.assertEquals(31, infoDb.getTables().size());
testDb = (TestExternalDatabase) test1.getDb("db1").get();
Assertions.assertEquals(2, testDb.getTables().size());
+ mysqlDb = (ExternalMysqlDatabase)
test1.getDb(MysqlDb.DATABASE_NAME).get();
+ Assertions.assertEquals(2, mysqlDb.getTables().size());
}
public static class RefreshCatalogProvider implements
TestExternalCatalog.TestCatalogProvider {
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
b/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
index ed7cc927273..2e5a4e07456 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/service/FrontendServiceImplTest.java
@@ -39,6 +39,8 @@ import org.apache.doris.thrift.TMetadataTableRequestParams;
import org.apache.doris.thrift.TMetadataType;
import org.apache.doris.thrift.TNullableStringLiteral;
import org.apache.doris.thrift.TSchemaTableName;
+import org.apache.doris.thrift.TShowUserRequest;
+import org.apache.doris.thrift.TShowUserResult;
import org.apache.doris.thrift.TStatusCode;
import org.apache.doris.utframe.UtFrameUtils;
@@ -220,4 +222,12 @@ public class FrontendServiceImplTest {
Assert.assertEquals(result.getStatus().getStatusCode(),
TStatusCode.OK);
Assert.assertEquals(result.getDataBatchSize(), 1);
}
+
+ @Test
+ public void testShowUser() {
+ FrontendServiceImpl impl = new FrontendServiceImpl(exeEnv);
+ TShowUserRequest request = new TShowUserRequest();
+ TShowUserResult result = impl.showUser(request);
+ System.out.println(result);
+ }
}
diff --git a/gensrc/thrift/Descriptors.thrift b/gensrc/thrift/Descriptors.thrift
index d8bbe0e244a..d99ea0bea86 100644
--- a/gensrc/thrift/Descriptors.thrift
+++ b/gensrc/thrift/Descriptors.thrift
@@ -128,7 +128,9 @@ enum TSchemaTableType {
SCH_PROFILING,
SCH_BACKEND_ACTIVE_TASKS,
SCH_ACTIVE_QUERIES,
- SCH_WORKLOAD_GROUPS;
+ SCH_WORKLOAD_GROUPS,
+ SCH_USER,
+ SCH_PROCS_PRIV;
}
enum THdfsCompression {
diff --git a/gensrc/thrift/FrontendService.thrift
b/gensrc/thrift/FrontendService.thrift
index 150783dcae3..1bd12c364bb 100644
--- a/gensrc/thrift/FrontendService.thrift
+++ b/gensrc/thrift/FrontendService.thrift
@@ -1411,6 +1411,13 @@ struct TShowProcessListResult {
1: optional list<list<string>> process_list
}
+struct TShowUserRequest {
+}
+
+struct TShowUserResult {
+ 1: optional list<list<string>> userinfo_list
+}
+
service FrontendService {
TGetDbsResult getDbNames(1: TGetDbsParams params)
TGetTablesResult getTableNames(1: TGetTablesParams params)
@@ -1499,4 +1506,5 @@ service FrontendService {
Status.TStatus invalidateStatsCache(1:
TInvalidateFollowerStatsCacheRequest request)
TShowProcessListResult showProcessList(1: TShowProcessListRequest request)
+ TShowUserResult showUser(1: TShowUserRequest request)
}
diff --git
a/regression-test/data/external_table_p0/jdbc/test_clickhouse_jdbc_catalog.out
b/regression-test/data/external_table_p0/jdbc/test_clickhouse_jdbc_catalog.out
index 38aea106c14..f5123a6ee86 100644
Binary files
a/regression-test/data/external_table_p0/jdbc/test_clickhouse_jdbc_catalog.out
and
b/regression-test/data/external_table_p0/jdbc/test_clickhouse_jdbc_catalog.out
differ
diff --git
a/regression-test/data/external_table_p0/jdbc/test_db2_jdbc_catalog.out
b/regression-test/data/external_table_p0/jdbc/test_db2_jdbc_catalog.out
index 50cfbe42102..d7225bb16b3 100644
--- a/regression-test/data/external_table_p0/jdbc/test_db2_jdbc_catalog.out
+++ b/regression-test/data/external_table_p0/jdbc/test_db2_jdbc_catalog.out
@@ -57,6 +57,7 @@ SYSSTAT
SYSTOOLS
TEST
information_schema
+mysql
-- !select_xml --
1000 <catalog><book><author> Gambardella Matthew</author><title>XML
Developers
Guide</title><genre>Computer</genre><price>44.95</price><publish_date>2000-10-01</publish_date><description>An
in-depth look at creating application\n with
XML</description></book></catalog>
diff --git
a/regression-test/data/external_table_p0/jdbc/test_mariadb_jdbc_catalog.out
b/regression-test/data/external_table_p0/jdbc/test_mariadb_jdbc_catalog.out
index cea4cfe4aef..01ba13f742a 100644
--- a/regression-test/data/external_table_p0/jdbc/test_mariadb_jdbc_catalog.out
+++ b/regression-test/data/external_table_p0/jdbc/test_mariadb_jdbc_catalog.out
@@ -5,7 +5,7 @@ internal
-- !show_db --
doris_test
information_schema
-performance_schema
+mysql
-- !sql --
internal
diff --git
a/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog.out
b/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog.out
index f3a9f5f937c..4586d38228a 100644
--- a/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog.out
+++ b/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog.out
@@ -274,10 +274,12 @@ doris3 20
-- !specified_database_1 --
doris_test
information_schema
+mysql
-- !specified_database_2 --
doris_test
information_schema
+mysql
-- !specified_database_3 --
DORIS
@@ -285,11 +287,12 @@ Doris
doris
information_schema
init_db
-performance_schema
+mysql
show_test_do_not_modify
-- !specified_database_4 --
information_schema
+mysql
-- !ex_tb1 --
{"k1":"v1", "k2":"v2"}
@@ -427,7 +430,7 @@ doris_3
doris_test
information_schema
init_db
-performance_schema
+mysql
show_test_do_not_modify
-- !sql --
diff --git
a/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_driver5_catalog.out
b/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_driver5_catalog.out
index b3c63311cc3..35c805ab896 100644
---
a/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_driver5_catalog.out
+++
b/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_driver5_catalog.out
@@ -9,7 +9,7 @@ doris
doris_test
information_schema
init_db
-performance_schema
+mysql
show_test_do_not_modify
-- !sql --
@@ -284,10 +284,12 @@ doris3 20
-- !specified_database_1 --
doris_test
information_schema
+mysql
-- !specified_database_2 --
doris_test
information_schema
+mysql
-- !specified_database_3 --
DORIS
@@ -295,11 +297,12 @@ Doris
doris
information_schema
init_db
-performance_schema
+mysql
show_test_do_not_modify
-- !specified_database_4 --
information_schema
+mysql
-- !ex_tb1 --
{"k1":"v1", "k2":"v2"}
@@ -437,7 +440,7 @@ doris_3
doris_test
information_schema
init_db
-performance_schema
+mysql
show_test_do_not_modify
-- !sql --
diff --git
a/regression-test/data/external_table_p0/jdbc/test_oracle_jdbc_catalog.out
b/regression-test/data/external_table_p0/jdbc/test_oracle_jdbc_catalog.out
index 21613b426ab..c5473a451e8 100644
--- a/regression-test/data/external_table_p0/jdbc/test_oracle_jdbc_catalog.out
+++ b/regression-test/data/external_table_p0/jdbc/test_oracle_jdbc_catalog.out
@@ -6,6 +6,7 @@ APEX_PUBLIC_USER
DORIS_TEST
HR
information_schema
+mysql
-- !test0 --
1 alice 20 99.5
@@ -223,10 +224,12 @@ TINYINT_VALUE2 SMALLINT Yes false \N
NONE
-- !specified_database --
DORIS_TEST
information_schema
+mysql
-- !specified_database --
DORIS_TEST
information_schema
+mysql
-- !lower_case_table_names1 --
1 111 123 7456123.89 573 34 673.43 34.1264 60.0
23.231
diff --git
a/regression-test/data/external_table_p0/jdbc/test_pg_jdbc_catalog.out
b/regression-test/data/external_table_p0/jdbc/test_pg_jdbc_catalog.out
index 728f48a2999..0c0598f4661 100644
--- a/regression-test/data/external_table_p0/jdbc/test_pg_jdbc_catalog.out
+++ b/regression-test/data/external_table_p0/jdbc/test_pg_jdbc_catalog.out
@@ -3,6 +3,7 @@
catalog_pg_test
doris_test
information_schema
+mysql
pg_catalog
public
@@ -2274,19 +2275,23 @@ varchar_value TEXT Yes false \N NONE
-- !specified_database_1 --
doris_test
information_schema
+mysql
-- !specified_database_2 --
doris_test
information_schema
+mysql
-- !specified_database_3 --
catalog_pg_test
information_schema
+mysql
pg_catalog
public
-- !specified_database_4 --
information_schema
+mysql
-- !test_old --
123 abc
diff --git
a/regression-test/data/external_table_p0/jdbc/test_sqlserver_jdbc_catalog.out
b/regression-test/data/external_table_p0/jdbc/test_sqlserver_jdbc_catalog.out
index d0d394cdee2..f646561b0c9 100644
---
a/regression-test/data/external_table_p0/jdbc/test_sqlserver_jdbc_catalog.out
+++
b/regression-test/data/external_table_p0/jdbc/test_sqlserver_jdbc_catalog.out
@@ -12,6 +12,7 @@ db_securityadmin
dbo
guest
information_schema
+mysql
sys
-- !test0 --
@@ -142,5 +143,6 @@ db_securityadmin
dbo
guest
information_schema
+mysql
sys
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]