Skip to content

Commit 8072be9

Browse files
authored
Merge pull request #9152 from ClSlaid/multiple-catalogs/show-databases
feat: Multiple catalogs/show databases
2 parents e0cdaff + a9d6dd3 commit 8072be9

File tree

12 files changed

+132
-43
lines changed

12 files changed

+132
-43
lines changed

src/query/ast/src/ast/statements/database.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,21 @@ use crate::ast::Identifier;
2323

2424
#[derive(Debug, Clone, PartialEq)] // Databases
2525
pub struct ShowDatabasesStmt<'a> {
26+
pub catalog: Option<Identifier<'a>>,
27+
pub full: bool,
2628
pub limit: Option<ShowLimit<'a>>,
2729
}
2830

2931
impl Display for ShowDatabasesStmt<'_> {
3032
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
31-
write!(f, "SHOW DATABASES")?;
33+
write!(f, "SHOW ")?;
34+
if self.full {
35+
write!(f, "FULL ")?;
36+
}
37+
write!(f, "DATABASES")?;
38+
if let Some(catalog) = &self.catalog {
39+
write!(f, " FROM {catalog}")?;
40+
}
3241
if let Some(limit) = &self.limit {
3342
write!(f, " {limit}")?;
3443
}

src/query/ast/src/parser/statement.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,9 +234,15 @@ pub fn statement(i: Input) -> IResult<StatementMsg> {
234234

235235
let show_databases = map(
236236
rule! {
237-
SHOW ~ ( DATABASES | SCHEMAS ) ~ #show_limit?
237+
SHOW ~ FULL? ~ ( DATABASES | SCHEMAS ) ~ ( ( FROM | IN) ~ ^#ident )? ~ #show_limit?
238+
},
239+
|(_, opt_full, _, opt_catalog, limit)| {
240+
Statement::ShowDatabases(ShowDatabasesStmt {
241+
catalog: opt_catalog.map(|(_, catalog)| catalog),
242+
full: opt_full.is_some(),
243+
limit,
244+
})
238245
},
239-
|(_, _, limit)| Statement::ShowDatabases(ShowDatabasesStmt { limit }),
240246
);
241247
let show_create_database = map(
242248
rule! {
@@ -978,7 +984,7 @@ pub fn statement(i: Input) -> IResult<StatementMsg> {
978984
| #show_functions : "`SHOW FUNCTIONS [<show_limit>]`"
979985
| #kill_stmt : "`KILL (QUERY | CONNECTION) <object_id>`"
980986
| #set_role: "`SET [DEFAULT] ROLE <role>`"
981-
| #show_databases : "`SHOW DATABASES [<show_limit>]`"
987+
| #show_databases : "`SHOW [FULL] DATABASES [(FROM | IN) <catalog>] [<show_limit>]`"
982988
| #undrop_database : "`UNDROP DATABASE <database>`"
983989
| #show_create_database : "`SHOW CREATE DATABASE <database>`"
984990
| #create_database : "`CREATE DATABASE [IF NOT EXIST] <database> [ENGINE = <engine>]`"

src/query/ast/tests/it/testdata/statement.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ SHOW DATABASES
55
---------- AST ------------
66
ShowDatabases(
77
ShowDatabasesStmt {
8+
catalog: None,
9+
full: false,
810
limit: None,
911
},
1012
)
@@ -17,6 +19,8 @@ SHOW DATABASES
1719
---------- AST ------------
1820
ShowDatabases(
1921
ShowDatabasesStmt {
22+
catalog: None,
23+
full: false,
2024
limit: None,
2125
},
2226
)

src/query/service/tests/it/servers/http/http_query_handlers.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ async fn test_simple_sql() -> Result<()> {
184184
assert_eq!(status, StatusCode::OK, "{:?}", result);
185185
assert!(result.error.is_none(), "{:?}", result);
186186
assert!(result.schema.is_some(), "{:?}", result);
187+
// has only one column
187188
assert_eq!(
188189
result.schema.as_ref().unwrap().fields().len(),
189190
1,
@@ -202,12 +203,26 @@ async fn test_show_databases() -> Result<()> {
202203
assert_eq!(status, StatusCode::OK, "{:?}", result);
203204
assert!(result.error.is_none(), "{:?}", result);
204205
assert!(result.schema.is_some(), "{:?}", result);
206+
// has only one field: name
205207
assert_eq!(
206208
result.schema.as_ref().unwrap().fields().len(),
207209
1,
208210
"{:?}",
209211
result
210212
);
213+
214+
let sql = "show full databases";
215+
let (status, result) = post_sql(sql, 1).await?;
216+
assert_eq!(status, StatusCode::OK, "{:?}", result);
217+
assert!(result.error.is_none(), "{:?}", result);
218+
assert!(result.schema.is_some(), "{:?}", result);
219+
// has two fields: catalog, name
220+
assert_eq!(
221+
result.schema.as_ref().unwrap().fields().len(),
222+
2,
223+
"{:?}",
224+
result
225+
);
211226
Ok(())
212227
}
213228

src/query/service/tests/it/storages/testdata/system-tables.txt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
88
| Engine | system | engines | VARCHAR | | | NO | |
99
| auth_string | system | users | VARCHAR | | | NO | |
1010
| auth_type | system | users | VARCHAR | | | NO | |
11+
| catalog | system | databases | VARCHAR | | | NO | |
1112
| category | system | functions | VARCHAR | | | NO | |
1213
| client_address | system | query_log | VARCHAR | | | NO | |
1314
| client_info | system | query_log | VARCHAR | | | NO | |
@@ -290,13 +291,13 @@ DB.Table: 'system'.'catalogs', Table: catalogs-table_id:1, ver:0, Engine: System
290291
---------- TABLE INFO ------------
291292
DB.Table: 'system'.'databases', Table: databases-table_id:1, ver:0, Engine: SystemDatabases
292293
-------- TABLE CONTENTS ----------
293-
+--------------------+
294-
| name |
295-
+--------------------+
296-
| default |
297-
| information_schema |
298-
| system |
299-
+--------------------+
294+
+---------+--------------------+
295+
| catalog | name |
296+
+---------+--------------------+
297+
| default | default |
298+
| default | information_schema |
299+
| default | system |
300+
+---------+--------------------+
300301

301302

302303
---------- TABLE INFO ------------

src/query/sql/src/planner/binder/ddl/database.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use core::fmt::Write;
1615
use std::collections::BTreeMap;
1716

1817
use common_ast::ast::AlterDatabaseAction;
@@ -32,6 +31,7 @@ use common_datavalues::Vu8;
3231
use common_exception::Result;
3332
use common_meta_app::schema::DatabaseMeta;
3433
use common_meta_app::share::ShareNameIdent;
34+
use tracing::debug;
3535

3636
use crate::binder::Binder;
3737
use crate::planner::semantic::normalize_identifier;
@@ -44,26 +44,48 @@ use crate::plans::RewriteKind;
4444
use crate::plans::ShowCreateDatabasePlan;
4545
use crate::plans::UndropDatabasePlan;
4646
use crate::BindContext;
47+
use crate::SelectBuilder;
4748

4849
impl<'a> Binder {
4950
pub(in crate::planner::binder) async fn bind_show_databases(
5051
&mut self,
5152
bind_context: &BindContext,
5253
stmt: &ShowDatabasesStmt<'a>,
5354
) -> Result<Plan> {
54-
let ShowDatabasesStmt { limit } = stmt;
55-
let mut query = String::new();
56-
write!(query, "SELECT name AS Database FROM system.databases").unwrap();
55+
let ShowDatabasesStmt {
56+
catalog,
57+
full,
58+
limit,
59+
} = stmt;
60+
61+
let mut select_builder = SelectBuilder::from("system.databases");
62+
63+
let ctl = if let Some(ctl) = catalog {
64+
normalize_identifier(ctl, &self.name_resolution_ctx).name
65+
} else {
66+
self.ctx.get_current_catalog().to_string()
67+
};
68+
69+
select_builder.with_filter(format!("catalog = '{ctl}'"));
70+
71+
if *full {
72+
select_builder.with_column("catalog AS Catalog");
73+
}
74+
select_builder.with_column(format!("name AS databases_in_{ctl}"));
75+
select_builder.with_order_by("catalog");
76+
select_builder.with_order_by("name");
5777
match limit {
5878
Some(ShowLimit::Like { pattern }) => {
59-
write!(query, " WHERE name LIKE '{pattern}'").unwrap();
79+
select_builder.with_filter(format!("name LIKE '{pattern}'"));
6080
}
6181
Some(ShowLimit::Where { selection }) => {
62-
write!(query, " WHERE {selection}").unwrap();
82+
select_builder.with_filter(format!("({selection})"));
6383
}
6484
None => (),
6585
}
66-
write!(query, " ORDER BY name").unwrap();
86+
87+
let query = select_builder.build();
88+
debug!("show databases rewrite to: {:?}", query);
6789

6890
self.bind_rewrite_to_query(bind_context, query.as_str(), RewriteKind::ShowDatabases)
6991
.await

src/query/storages/system/src/databases_table.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
use std::sync::Arc;
1616

17+
use common_catalog::catalog::Catalog;
18+
use common_catalog::catalog::CatalogManager;
1719
use common_catalog::table::Table;
1820
use common_catalog::table_context::TableContext;
1921
use common_datablocks::DataBlock;
@@ -40,23 +42,37 @@ impl AsyncSystemTable for DatabasesTable {
4042

4143
async fn get_full_data(&self, ctx: Arc<dyn TableContext>) -> Result<DataBlock> {
4244
let tenant = ctx.get_tenant();
43-
let catalog = ctx.get_catalog(ctx.get_current_catalog().as_str())?;
44-
let databases = catalog.list_databases(tenant.as_str()).await?;
45-
46-
let db_names: Vec<&[u8]> = databases
45+
let catalogs = CatalogManager::instance();
46+
let catalogs: Vec<(String, Arc<dyn Catalog>)> = catalogs
47+
.catalogs
4748
.iter()
48-
.map(|database| database.name().as_bytes())
49+
.map(|e| (e.key().clone(), e.value().clone()))
4950
.collect();
51+
let mut catalog_names = vec![];
52+
let mut database_names = vec![];
53+
for (ctl_name, catalog) in catalogs.into_iter() {
54+
let databases = catalog.list_databases(tenant.as_str()).await?;
55+
56+
for db in databases {
57+
catalog_names.push(ctl_name.clone().into_bytes());
58+
let db_name = db.name().to_string().into_bytes();
59+
database_names.push(db_name);
60+
}
61+
}
5062

5163
Ok(DataBlock::create(self.table_info.schema(), vec![
52-
Series::from_data(db_names),
64+
Series::from_data(catalog_names),
65+
Series::from_data(database_names),
5366
]))
5467
}
5568
}
5669

5770
impl DatabasesTable {
5871
pub fn create(table_id: u64) -> Arc<dyn Table> {
59-
let schema = DataSchemaRefExt::create(vec![DataField::new("name", Vu8::to_data_type())]);
72+
let schema = DataSchemaRefExt::create(vec![
73+
DataField::new("catalog", Vu8::to_data_type()),
74+
DataField::new("name", Vu8::to_data_type()),
75+
]);
6076

6177
let table_info = TableInfo {
6278
desc: "'system'.'databases'".to_string(),

tests/logictest/suites/base/05_ddl/05_0003_ddl_alter_database

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ statement ok
3838
ALTER DATABASE IF EXISTS c RENAME TO a;
3939

4040
statement query T
41-
SELECT * FROM system.databases;
41+
SELECT name FROM system.databases;
4242

4343
----
4444
system
@@ -54,7 +54,7 @@ statement error 1003
5454
ALTER DATABASE c RENAME TO C;
5555

5656
statement query T
57-
SELECT * FROM system.databases;
57+
SELECT name FROM system.databases;
5858

5959
----
6060
system
@@ -70,7 +70,7 @@ statement error 1002
7070
ALTER DATABASE system RENAME TO C;
7171

7272
statement query T
73-
SELECT * FROM system.databases;
73+
SELECT name FROM system.databases;
7474

7575
----
7676
system
@@ -86,7 +86,7 @@ statement error 2301
8686
ALTER DATABASE IF EXISTS a RENAME TO b;
8787

8888
statement query T
89-
SELECT * FROM system.databases;
89+
SELECT name FROM system.databases;
9090

9191
----
9292
system
@@ -99,7 +99,7 @@ statement ok
9999
ALTER DATABASE a RENAME TO a2;
100100

101101
statement query T
102-
SELECT * FROM system.databases;
102+
SELECT name FROM system.databases;
103103

104104
----
105105
system
@@ -127,7 +127,7 @@ SELECT * FROM b.t2;
127127
10
128128

129129
statement query T
130-
SELECT * FROM system.databases;
130+
SELECT name FROM system.databases;
131131

132132
----
133133
system
@@ -146,7 +146,7 @@ SELECT * FROM b2.t2;
146146
10
147147

148148
statement query T
149-
SELECT * FROM system.databases;
149+
SELECT name FROM system.databases;
150150

151151
----
152152
system

tests/logictest/suites/base/06_show/06_0000_show_databases

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ ss
2424
ss1
2525
ss2
2626

27+
statement query TT
28+
SHOW FULL DATABASES like 'ss%';
29+
30+
----
31+
default ss
32+
default ss1
33+
default ss2
34+
35+
statement query TT
36+
SHOW FULL DATABASES FROM default like 'ss%';
37+
38+
----
39+
default ss
40+
default ss1
41+
default ss2
42+
2743
statement query T
2844
SHOW SCHEMAS like 'ss%';
2945

0 commit comments

Comments
 (0)