Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(query): Support show dictionaries DQL. #16602

Merged
merged 18 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/query/ast/src/ast/statements/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use std::fmt::Formatter;
use derive_visitor::Drive;
use derive_visitor::DriveMut;

use super::ShowLimit;
use crate::ast::write_comma_separated_list;
use crate::ast::write_dot_separated_list;
use crate::ast::write_space_separated_string_map;
Expand Down Expand Up @@ -123,3 +124,22 @@ impl Display for ShowCreateDictionaryStmt {
)
}
}

#[derive(Debug, Clone, PartialEq, Drive, DriveMut)]
pub struct ShowDictionariesStmt {
pub database: Option<Identifier>,
pub limit: Option<ShowLimit>,
}

impl Display for ShowDictionariesStmt {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(f, "SHOW DICTIONARIES")?;
if let Some(database) = &self.database {
write!(f, " FROM {database}")?;
}
if let Some(limit) = &self.limit {
write!(f, " {limit}")?;
}
Ok(())
}
}
11 changes: 2 additions & 9 deletions src/query/ast/src/ast/statements/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,7 @@ pub enum Statement {
CreateDictionary(CreateDictionaryStmt),
DropDictionary(DropDictionaryStmt),
ShowCreateDictionary(ShowCreateDictionaryStmt),
ShowDictionaries {
show_options: Option<ShowOptions>,
},
ShowDictionaries(ShowDictionariesStmt),

// Columns
ShowColumns(ShowColumnsStmt),
Expand Down Expand Up @@ -613,12 +611,7 @@ impl Display for Statement {
Statement::CreateDictionary(stmt) => write!(f, "{stmt}")?,
Statement::DropDictionary(stmt) => write!(f, "{stmt}")?,
Statement::ShowCreateDictionary(stmt) => write!(f, "{stmt}")?,
Statement::ShowDictionaries { show_options } => {
write!(f, "SHOW DICTIONARIES")?;
if let Some(show_options) = show_options {
write!(f, " {show_options}")?;
}
}
Statement::ShowDictionaries(stmt) => write!(f, "{stmt}")?,
Statement::CreateView(stmt) => write!(f, "{stmt}")?,
Statement::AlterView(stmt) => write!(f, "{stmt}")?,
Statement::DropView(stmt) => write!(f, "{stmt}")?,
Expand Down
10 changes: 8 additions & 2 deletions src/query/ast/src/parser/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -957,9 +957,15 @@ pub fn statement_body(i: Input) -> IResult<Statement> {
);
let show_dictionaries = map(
rule! {
SHOW ~ DICTIONARIES ~ #show_options?
SHOW ~ DICTIONARIES ~ ((FROM|IN) ~ #ident)? ~ #show_limit?
},
|(_, _, db, limit)| {
let database = match db {
Some((_, d)) => Some(d),
_ => None,
};
Statement::ShowDictionaries(ShowDictionariesStmt { database, limit })
},
|(_, _, show_options)| Statement::ShowDictionaries { show_options },
);
let show_create_dictionary = map(
rule! {
Expand Down
2 changes: 2 additions & 0 deletions src/query/service/src/databases/system/system_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use databend_common_storages_system::ConfigsTable;
use databend_common_storages_system::ContributorsTable;
use databend_common_storages_system::CreditsTable;
use databend_common_storages_system::DatabasesTable;
use databend_common_storages_system::DictionariesTable;
use databend_common_storages_system::EnginesTable;
use databend_common_storages_system::FullStreamsTable;
use databend_common_storages_system::FunctionsTable;
Expand Down Expand Up @@ -144,6 +145,7 @@ impl SystemDatabase {
ViewsTableWithoutHistory::create(sys_db_meta.next_table_id()),
TemporaryTablesTable::create(sys_db_meta.next_table_id()),
ProceduresTable::create(sys_db_meta.next_table_id()),
DictionariesTable::create(sys_db_meta.next_table_id()),
];

let disable_tables = Self::disable_system_tables();
Expand Down
6 changes: 4 additions & 2 deletions src/query/service/src/interpreters/access/privilege_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,11 @@ enum ObjectId {
// some statements like `SELECT 1`, `SHOW USERS`, `SHOW ROLES`, `SHOW TABLES` will be
// rewritten to the queries on the system tables, we need to skip the privilege check on
// these tables.
const SYSTEM_TABLES_ALLOW_LIST: [&str; 19] = [
const SYSTEM_TABLES_ALLOW_LIST: [&str; 20] = [
"catalogs",
"columns",
"databases",
"dictionaries",
"tables",
"views",
"tables_with_history",
Expand Down Expand Up @@ -709,7 +710,8 @@ impl AccessChecker for PrivilegeAccess {
Some(RewriteKind::ShowDatabases)
| Some(RewriteKind::ShowEngines)
| Some(RewriteKind::ShowFunctions)
| Some(RewriteKind::ShowUserFunctions) => {
| Some(RewriteKind::ShowUserFunctions)
| Some(RewriteKind::ShowDictionaries(_)) => {
return Ok(());
}
| Some(RewriteKind::ShowTableFunctions) => {
Expand Down
10 changes: 10 additions & 0 deletions src/query/service/tests/it/storages/testdata/columns_table.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'arguments' | 'system' | 'procedures' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'arguments' | 'system' | 'user_functions' | 'Variant' | 'VARIANT' | '' | '' | 'NO' | '' |
| 'attempt_number' | 'system' | 'task_history' | 'Int32' | 'INT' | '' | '' | 'NO' | '' |
| 'attribute_names' | 'system' | 'dictionaries' | 'Array(String)' | 'ARRAY(STRING)' | '' | '' | 'NO' | '' |
| 'attribute_types' | 'system' | 'dictionaries' | 'Array(String)' | 'ARRAY(STRING)' | '' | '' | 'NO' | '' |
| 'auth_type' | 'system' | 'users' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'auto_increment' | 'information_schema' | 'tables' | 'NULL' | 'NULL' | '' | '' | 'NO' | '' |
| 'byte_size' | 'system' | 'clustering_history' | 'UInt64' | 'BIGINT UNSIGNED' | '' | '' | 'NO' | '' |
Expand Down Expand Up @@ -59,6 +61,7 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'command' | 'system' | 'processes' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'comment' | 'information_schema' | 'statistics' | 'NULL' | 'NULL' | '' | '' | 'NO' | '' |
| 'comment' | 'system' | 'columns' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'comment' | 'system' | 'dictionaries' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'comment' | 'system' | 'notifications' | 'Nullable(String)' | 'VARCHAR' | '' | '' | 'YES' | '' |
| 'comment' | 'system' | 'password_policies' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'comment' | 'system' | 'procedures' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
Expand All @@ -82,6 +85,7 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'create_time' | 'information_schema' | 'tables' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'created_on' | 'system' | 'background_jobs' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'created_on' | 'system' | 'background_tasks' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'created_on' | 'system' | 'dictionaries' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'created_on' | 'system' | 'indexes' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'created_on' | 'system' | 'locks' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'created_on' | 'system' | 'notification_history' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
Expand Down Expand Up @@ -116,6 +120,7 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'data_write_bytes' | 'system' | 'processes' | 'UInt64' | 'BIGINT UNSIGNED' | '' | '' | 'NO' | '' |
| 'database' | 'system' | 'clustering_history' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'database' | 'system' | 'columns' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'database' | 'system' | 'dictionaries' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'database' | 'system' | 'processes' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'database' | 'system' | 'streams' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'database' | 'system' | 'streams_terse' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
Expand Down Expand Up @@ -231,6 +236,8 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'job_type' | 'system' | 'background_jobs' | 'Nullable(String)' | 'VARCHAR' | '' | '' | 'YES' | '' |
| 'join_spilled_bytes' | 'system' | 'query_log' | 'UInt64' | 'BIGINT UNSIGNED' | '' | '' | 'NO' | '' |
| 'join_spilled_rows' | 'system' | 'query_log' | 'UInt64' | 'BIGINT UNSIGNED' | '' | '' | 'NO' | '' |
| 'key_names' | 'system' | 'dictionaries' | 'Array(String)' | 'ARRAY(STRING)' | '' | '' | 'NO' | '' |
| 'key_types' | 'system' | 'dictionaries' | 'Array(String)' | 'ARRAY(STRING)' | '' | '' | 'NO' | '' |
| 'keywords' | 'information_schema' | 'keywords' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'kind' | 'system' | 'metrics' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'labels' | 'system' | 'metrics' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
Expand Down Expand Up @@ -266,6 +273,7 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'name' | 'system' | 'contributors' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'name' | 'system' | 'credits' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'name' | 'system' | 'databases' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'name' | 'system' | 'dictionaries' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'name' | 'system' | 'functions' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'name' | 'system' | 'indexes' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'name' | 'system' | 'malloc_stats_totals' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
Expand Down Expand Up @@ -386,6 +394,7 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'session_settings' | 'system' | 'query_log' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'size' | 'system' | 'caches' | 'UInt64' | 'BIGINT UNSIGNED' | '' | '' | 'NO' | '' |
| 'snapshot_location' | 'system' | 'streams' | 'Nullable(String)' | 'VARCHAR' | '' | '' | 'YES' | '' |
| 'source' | 'system' | 'dictionaries' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'sql' | 'system' | 'query_cache' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
| 'sql_path' | 'information_schema' | 'schemata' | 'NULL' | 'NULL' | '' | '' | 'NO' | '' |
| 'sql_user' | 'system' | 'query_log' | 'String' | 'VARCHAR' | '' | '' | 'NO' | '' |
Expand Down Expand Up @@ -465,6 +474,7 @@ DB.Table: 'system'.'columns', Table: columns-table_id:1, ver:0, Engine: SystemCo
| 'update_on' | 'system' | 'roles' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'update_on' | 'system' | 'users' | 'Nullable(Timestamp)' | 'TIMESTAMP' | '' | '' | 'YES' | '' |
| 'updated_on' | 'system' | 'background_tasks' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'updated_on' | 'system' | 'dictionaries' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
| 'updated_on' | 'system' | 'indexes' | 'Nullable(Timestamp)' | 'TIMESTAMP' | '' | '' | 'YES' | '' |
| 'updated_on' | 'system' | 'password_policies' | 'Nullable(Timestamp)' | 'TIMESTAMP' | '' | '' | 'YES' | '' |
| 'updated_on' | 'system' | 'streams' | 'Timestamp' | 'TIMESTAMP' | '' | '' | 'NO' | '' |
Expand Down
2 changes: 1 addition & 1 deletion src/query/sql/src/planner/binder/binder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ impl<'a> Binder {
Statement::CreateDictionary(stmt) => self.bind_create_dictionary(stmt).await?,
Statement::DropDictionary(stmt) => self.bind_drop_dictionary(stmt).await?,
Statement::ShowCreateDictionary(stmt) => self.bind_show_create_dictionary(stmt).await?,
Statement::ShowDictionaries { show_options: _ } => todo!(),
Statement::ShowDictionaries(stmt) => self.bind_show_dictionaries(bind_context, stmt).await?,
// Views
Statement::CreateView(stmt) => self.bind_create_view(stmt).await?,
Statement::AlterView(stmt) => self.bind_alter_view(stmt).await?,
Expand Down
52 changes: 52 additions & 0 deletions src/query/sql/src/planner/binder/ddl/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use std::sync::LazyLock;
use databend_common_ast::ast::CreateDictionaryStmt;
use databend_common_ast::ast::DropDictionaryStmt;
use databend_common_ast::ast::ShowCreateDictionaryStmt;
use databend_common_ast::ast::ShowDictionariesStmt;
use databend_common_ast::ast::ShowLimit;
use databend_common_exception::ErrorCode;
use databend_common_exception::Result;
use databend_common_expression::types::DataType;
Expand All @@ -28,12 +30,16 @@ use databend_common_expression::TableDataType;
use databend_common_expression::TableSchema;
use databend_common_meta_app::schema::DictionaryMeta;
use itertools::Itertools;
use log::debug;

use crate::plans::CreateDictionaryPlan;
use crate::plans::DropDictionaryPlan;
use crate::plans::Plan;
use crate::plans::RewriteKind;
use crate::plans::ShowCreateDictionaryPlan;
use crate::BindContext;
use crate::Binder;
use crate::SelectBuilder;

pub const DICT_OPT_KEY_SQL_HOST: &str = "host";
pub const DICT_OPT_KEY_SQL_PORT: &str = "port";
Expand Down Expand Up @@ -383,4 +389,50 @@ impl Binder {
},
)))
}

#[async_backtrace::framed]
pub(in crate::planner::binder) async fn bind_show_dictionaries(
&mut self,
bind_context: &mut BindContext,
stmt: &ShowDictionariesStmt,
) -> Result<Plan> {
let ShowDictionariesStmt { database, limit } = stmt;

let mut select_builder = SelectBuilder::from("system.dictionaries");

select_builder
.with_column("database AS Database")
.with_column("name AS Dictionary")
.with_column("key_names AS Key_Names")
.with_column("key_types AS key_Types")
.with_column("attribute_names AS Attribute_Names")
.with_column("attribute_types AS Attribute_Types")
.with_column("source AS Source")
.with_column("comment AS Comment");

select_builder
.with_order_by("database")
.with_order_by("name");

let database = self.check_database_exist(&None, database).await?;
select_builder.with_filter(format!("database = '{}'", database.clone()));

match limit {
None => (),
Some(ShowLimit::Like { pattern }) => {
select_builder.with_filter(format!("name LIKE '{pattern}'"));
}
Some(ShowLimit::Where { selection }) => {
select_builder.with_filter(format!("({selection})"));
}
};
let query = select_builder.build();
debug!("show dictionaries rewrite to: {:?}", query);
self.bind_rewrite_to_query(
bind_context,
query.as_str(),
RewriteKind::ShowDictionaries(database.clone()),
)
.await
}
}
1 change: 1 addition & 0 deletions src/query/sql/src/planner/plans/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ pub enum RewriteKind {
ShowColumns(String, String, String),
ShowTablesStatus,
ShowVirtualColumns,
ShowDictionaries(String),

ShowStreams(String),

Expand Down
Loading
Loading