[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:
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
27
regression-test/data/query_p0/show/test_show_where.out
Normal file
27
regression-test/data/query_p0/show/test_show_where.out
Normal 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
|
||||
81
regression-test/suites/query_p0/show/test_show_where.groovy
Normal file
81
regression-test/suites/query_p0/show/test_show_where.groovy
Normal 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}`")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user