[fix](mutil-catalog) fix get many same name db/table when show where (#15076)

when show databases/tables/table status where xxx, it will change a selectStmt to select result from 
information_schema, it need catalog info to scan schema table, otherwise may get many
database or table info from multi catalog.

for example
mysql> show databases where schema_name='test';
+----------+
| Database |
+----------+
| test |
| test |
+----------+

MySQL [internal.test]> show tables from test where table_name='test_dc';
+----------------+
| Tables_in_test |
+----------------+
| test_dc |
| test_dc |
+----------------+
This commit is contained in:
xueweizhang
2022-12-19 14:27:48 +08:00
committed by GitHub
parent 000972ae17
commit 1597afcd67
21 changed files with 169 additions and 8 deletions

View File

@ -87,6 +87,10 @@ Status SchemaScanNode::init(const TPlanNode& tnode, RuntimeState* state) {
_scanner_param.table_structure = _pool->add(
new std::vector<TSchemaTableStructure>(tnode.schema_scan_node.table_structure));
}
if (tnode.schema_scan_node.__isset.catalog) {
_scanner_param.catalog = _pool->add(new std::string(tnode.schema_scan_node.catalog));
}
return Status::OK();
}

View File

@ -44,6 +44,7 @@ struct SchemaScannerParam {
int32_t port; // frontend thrift port
int64_t thread_id;
const std::vector<TSchemaTableStructure>* table_structure;
const std::string* catalog;
SchemaScannerParam()
: db(nullptr),
@ -53,7 +54,8 @@ struct SchemaScannerParam {
user_ip(nullptr),
current_user_ident(nullptr),
ip(nullptr),
port(0) {}
port(0),
catalog(nullptr) {}
};
// virtual scanner for all schema table

View File

@ -70,6 +70,9 @@ Status SchemaColumnsScanner::start(RuntimeState* state) {
if (nullptr != _param->db) {
db_params.__set_pattern(*(_param->db));
}
if (nullptr != _param->catalog) {
db_params.__set_catalog(*(_param->catalog));
}
if (nullptr != _param->current_user_ident) {
db_params.__set_current_user_ident(*_param->current_user_ident);
} else {

View File

@ -81,6 +81,9 @@ Status SchemaFilesScanner::start(RuntimeState* state) {
if (NULL != _param->db) {
db_params.__set_pattern(*(_param->db));
}
if (nullptr != _param->catalog) {
db_params.__set_catalog(*(_param->catalog));
}
if (NULL != _param->current_user_ident) {
db_params.__set_current_user_ident(*(_param->current_user_ident));
} else {

View File

@ -69,6 +69,9 @@ Status SchemaPartitionsScanner::start(RuntimeState* state) {
if (NULL != _param->db) {
db_params.__set_pattern(*(_param->db));
}
if (nullptr != _param->catalog) {
db_params.__set_catalog(*(_param->catalog));
}
if (NULL != _param->current_user_ident) {
db_params.__set_current_user_ident(*(_param->current_user_ident));
} else {

View File

@ -46,6 +46,9 @@ Status SchemaSchemataScanner::start(RuntimeState* state) {
if (nullptr != _param->wild) {
db_params.__set_pattern(*(_param->wild));
}
if (nullptr != _param->catalog) {
db_params.__set_catalog(*(_param->catalog));
}
if (nullptr != _param->current_user_ident) {
db_params.__set_current_user_ident(*(_param->current_user_ident));
} else {

View File

@ -64,6 +64,9 @@ Status SchemaTablesScanner::start(RuntimeState* state) {
if (nullptr != _param->db) {
db_params.__set_pattern(*(_param->db));
}
if (nullptr != _param->catalog) {
db_params.__set_catalog(*(_param->catalog));
}
if (nullptr != _param->current_user_ident) {
db_params.__set_current_user_ident(*(_param->current_user_ident));
} else {

View File

@ -53,6 +53,9 @@ Status SchemaViewsScanner::start(RuntimeState* state) {
if (nullptr != _param->db) {
db_params.__set_pattern(*(_param->db));
}
if (nullptr != _param->catalog) {
db_params.__set_catalog(*(_param->catalog));
}
if (nullptr != _param->current_user_ident) {
db_params.__set_current_user_ident(*(_param->current_user_ident));
} else {

View File

@ -97,6 +97,10 @@ Status VSchemaScanNode::init(const TPlanNode& tnode, RuntimeState* state) {
_scanner_param.table_structure = _pool->add(
new std::vector<TSchemaTableStructure>(tnode.schema_scan_node.table_structure));
}
if (tnode.schema_scan_node.__isset.catalog) {
_scanner_param.catalog = _pool->add(new std::string(tnode.schema_scan_node.catalog));
}
return Status::OK();
}

View File

@ -139,6 +139,7 @@ public class Analyzer {
private final Map<TupleId, Integer> currentOutputColumn = Maps.newHashMap();
// used for Information Schema Table Scan
private String schemaDb;
private String schemaCatalog;
private String schemaWild;
private String schemaTable; // table used in DESCRIBE Table
@ -2025,6 +2026,10 @@ public class Analyzer {
return schemaDb;
}
public String getSchemaCatalog() {
return schemaCatalog;
}
public String getSchemaTable() {
return schemaTable;
}
@ -2044,10 +2049,11 @@ public class Analyzer {
}
// for Schema Table Schema like SHOW TABLES LIKE "abc%"
public void setSchemaInfo(String db, String table, String wild) {
public void setSchemaInfo(String db, String table, String wild, String catalog) {
schemaDb = db;
schemaTable = table;
schemaWild = wild;
schemaCatalog = catalog;
}
public String getTargetDbName(FunctionName fnName) {

View File

@ -164,7 +164,7 @@ public class ShowColumnStmt extends ShowStmt {
selectStmt = new SelectStmt(selectList,
new FromClause(Lists.newArrayList(new TableRef(TABLE_NAME, null))),
where, null, null, null, LimitElement.NO_LIMIT);
analyzer.setSchemaInfo(tableName.getDb(), tableName.getTbl(), null);
analyzer.setSchemaInfo(tableName.getDb(), tableName.getTbl(), null, tableName.getCtl());
return selectStmt;
}

View File

@ -88,7 +88,11 @@ public class ShowDbStmt extends ShowStmt {
selectStmt = new SelectStmt(selectList,
new FromClause(Lists.newArrayList(new TableRef(TABLE_NAME, null))),
where, null, null, null, LimitElement.NO_LIMIT);
if (catalogName != null) {
analyzer.setSchemaInfo(null, null, null, catalogName);
} else {
analyzer.setSchemaInfo(null, null, null, analyzer.getDefaultCatalog());
}
return selectStmt;
}

View File

@ -183,7 +183,8 @@ public class ShowTableStatusStmt extends ShowStmt {
selectStmt = new SelectStmt(selectList,
new FromClause(Lists.newArrayList(new TableRef(TABLE_NAME, null))),
where, null, null, null, LimitElement.NO_LIMIT);
analyzer.setSchemaInfo(db, null, null);
analyzer.setSchemaInfo(ClusterNamespace.getNameFromFullName(db), null, null,
analyzer.getDefaultCatalog());
return selectStmt;
}

View File

@ -114,7 +114,8 @@ public class ShowTableStmt extends ShowStmt {
new FromClause(Lists.newArrayList(new TableRef(TABLE_NAME, null))),
where, null, null, null, LimitElement.NO_LIMIT);
analyzer.setSchemaInfo(ClusterNamespace.getNameFromFullName(db), null, null);
analyzer.setSchemaInfo(ClusterNamespace.getNameFromFullName(db), null, null,
analyzer.getDefaultCatalog());
return selectStmt;
}

View File

@ -106,7 +106,7 @@ public class ShowVariablesStmt extends ShowStmt {
// DB: type
// table: thread id
analyzer.setSchemaInfo(type.toSql(), null, null);
analyzer.setSchemaInfo(type.toSql(), null, null, null);
return selectStmt;
}

View File

@ -52,6 +52,7 @@ public class SchemaScanNode extends ScanNode {
private String userIp;
private String frontendIP;
private int frontendPort;
private String schemaCatalog;
/**
* Constructs node to scan given data files of table 'tbl'.
@ -77,6 +78,7 @@ public class SchemaScanNode extends ScanNode {
userIp = analyzer.getContext().getRemoteIP();
frontendIP = FrontendOptions.getLocalHostAddress();
frontendPort = Config.rpc_port;
schemaCatalog = analyzer.getSchemaCatalog();
}
@Override
@ -92,6 +94,9 @@ public class SchemaScanNode extends ScanNode {
msg.schema_scan_node.setDb("SESSION");
}
}
if (schemaCatalog != null) {
msg.schema_scan_node.setCatalog(schemaCatalog);
}
msg.schema_scan_node.show_hidden_cloumns = Util.showHiddenColumns();
if (schemaTable != null) {

View File

@ -172,7 +172,13 @@ public class FrontendServiceImpl implements FrontendService.Iface {
}
Env env = Env.getCurrentEnv();
List<CatalogIf> catalogIfs = env.getCatalogMgr().listCatalogs();
List<CatalogIf> catalogIfs = Lists.newArrayList();
if (Strings.isNullOrEmpty(params.catalog)) {
catalogIfs = env.getCatalogMgr().listCatalogs();
} else {
catalogIfs.add(env.getCatalogMgr()
.getCatalogOrException(params.catalog, catalog -> new TException("Unknown catalog " + catalog)));
}
for (CatalogIf catalog : catalogIfs) {
List<String> dbNames = catalog.getDbNames();
LOG.debug("get db names: {}, in catalog: {}", dbNames, catalog.getName());

View File

@ -287,6 +287,7 @@ struct TGetDbsParams {
2: optional string user // deprecated
3: optional string user_ip // deprecated
4: optional Types.TUserIdentity current_user_ident // to replace the user and user ip
5: optional string catalog
}
// getDbNames returns a list of database names and catalog names

View File

@ -501,6 +501,7 @@ struct TSchemaScanNode {
11: optional Types.TUserIdentity current_user_ident // to replace the user and user_ip
12: optional bool show_hidden_cloumns = false
13: optional list<TSchemaTableStructure> table_structure
14: optional string catalog
}
struct TMetaScanNode {

View File

@ -0,0 +1,27 @@
-- This file is automatically generated. You should know what you did if you want to edit this
-- !select --
doris_test
-- !select --
ex_tb0
-- !select --
ex_tb0
-- !select --
doris_test
-- !select --
ex_tb0
-- !select --
ex_tb0
-- !select --
doris_test
-- !select --
ex_tb0
-- !select --
ex_tb0

View File

@ -0,0 +1,81 @@
// 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.
suite("test_show_where", "query") {
String ex_db_name = "doris_test";
String ex_tb0 = "ex_tb0";
String catalog_name = "test_show_where_mysql_jdbc_catalog";
try {
sql """ drop database if exists ${ex_db_name} """
sql """ create database ${ex_db_name} """
sql """ drop table if exists `${ex_db_name}`.`${ex_tb0}` """
sql """
CREATE TABLE `${ex_db_name}`.`${ex_tb0}` (
`id` INT NULL COMMENT "主键id",
`name` string NULL COMMENT "名字"
) DISTRIBUTED BY HASH(id) BUCKETS 10
PROPERTIES("replication_num" = "1");
"""
sql """ use ${ex_db_name}"""
qt_select "show databases where schema_name= '${ex_db_name}'"
qt_select "show tables"
qt_select "show tables where table_name= '${ex_tb0}'"
String enabled = context.config.otherConfigs.get("enableJdbcTest")
String mysql_port = context.config.otherConfigs.get("mysql_57_port");
if (enabled != null && enabled.equalsIgnoreCase("true")) {
sql """admin set frontend config ("enable_multi_catalog" = "true")"""
sql """drop catalog if exists ${catalog_name} """
// if use 'com.mysql.cj.jdbc.Driver' here, it will report: ClassNotFound
sql """ CREATE CATALOG ${catalog_name} PROPERTIES (
"type"="jdbc",
"jdbc.user"="root",
"jdbc.password"="123456",
"jdbc.jdbc_url" = "jdbc:mysql://127.0.0.1:${mysql_port}/doris_test?useSSL=false",
"jdbc.driver_url" = "https://doris-community-test-1308700295.cos.ap-hongkong.myqcloud.com/jdbc_driver/mysql-connector-java-8.0.25.jar",
"jdbc.driver_class" = "com.mysql.cj.jdbc.Driver");
"""
sql """switch ${catalog_name}"""
sql """ use ${ex_db_name}"""
qt_select "show databases where schema_name= '${ex_db_name}'"
qt_select "show tables"
qt_select "show tables where table_name= '${ex_tb0}'"
sql """switch internal"""
sql """ use ${ex_db_name}"""
qt_select "show databases where schema_name= '${ex_db_name}'"
qt_select "show tables"
qt_select "show tables where table_name= '${ex_tb0}'"
}
} finally {
try_sql("DROP DATABASE IF EXISTS `internal`.`${ex_db_name}` FORCE")
try_sql("DROP CATALOG IF EXISTS `${catalog_name}`")
}
}