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(handler): support [I]LIKE in show commands #11791

Merged
merged 4 commits into from
Aug 21, 2023
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
11 changes: 10 additions & 1 deletion e2e_test/ddl/show.slt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ show tables from public;
----
t3

query T
show tables from public like "t_";
----
t3

query T
show tables from public like "_t";
----

query T
show views;
----
Expand Down Expand Up @@ -150,4 +159,4 @@ drop table t3;
#definition varchar
#matviewid integer
#matviewtimezone varchar
#matviewgraph varchar
#matviewgraph varchar
5 changes: 4 additions & 1 deletion src/frontend/src/handler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,10 @@ pub async fn handle(
handle_privilege::handle_revoke_privilege(handler_args, stmt).await
}
Statement::Describe { name } => describe::handle_describe(handler_args, name),
Statement::ShowObjects(show_object) => show::handle_show_object(handler_args, show_object),
Statement::ShowObjects {
object: show_object,
filter,
} => show::handle_show_object(handler_args, show_object, filter),
Statement::ShowCreateObject { create_type, name } => {
show::handle_show_create_object(handler_args, create_type, name)
}
Expand Down
25 changes: 23 additions & 2 deletions src/frontend/src/handler/show.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ use risingwave_common::error::{ErrorCode, Result};
use risingwave_common::types::DataType;
use risingwave_common::util::addr::HostAddr;
use risingwave_connector::source::kafka::PRIVATELINK_CONNECTION;
use risingwave_expr::vector_op::like::{i_like_default, like_default};
use risingwave_pb::catalog::connection;
use risingwave_sqlparser::ast::{Ident, ObjectName, ShowCreateType, ShowObject};
use risingwave_sqlparser::ast::{
Ident, ObjectName, ShowCreateType, ShowObject, ShowStatementFilter,
};
use serde_json;

use super::RwPgResponse;
Expand Down Expand Up @@ -78,10 +81,22 @@ fn schema_or_default(schema: &Option<Ident>) -> String {
.map_or_else(|| DEFAULT_SCHEMA_NAME.to_string(), |s| s.real_value())
}

pub fn handle_show_object(handler_args: HandlerArgs, command: ShowObject) -> Result<RwPgResponse> {
pub fn handle_show_object(
handler_args: HandlerArgs,
command: ShowObject,
filter: Option<ShowStatementFilter>,
) -> Result<RwPgResponse> {
let session = handler_args.session;
let catalog_reader = session.env().catalog_reader().read_guard();

if let Some(ShowStatementFilter::Where(..)) = filter {
return Err(ErrorCode::NotImplemented(
"WHERE clause in SHOW statement".to_string(),
None.into(),
)
.into());
}

let names = match command {
// If not include schema name, use default schema name
ShowObject::Table { schema } => catalog_reader
Expand Down Expand Up @@ -356,6 +371,12 @@ pub fn handle_show_object(handler_args: HandlerArgs, command: ShowObject) -> Res

let rows = names
.into_iter()
.filter(|arg| match &filter {
Some(ShowStatementFilter::Like(pattern)) => like_default(arg, pattern),
Some(ShowStatementFilter::ILike(pattern)) => i_like_default(arg, pattern),
Some(ShowStatementFilter::Where(..)) => unreachable!(),
None => true,
})
.map(|n| Row::new(vec![Some(n.into())]))
.collect_vec();

Expand Down
5 changes: 4 additions & 1 deletion src/frontend/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,10 @@ fn infer(bound: Option<BoundStatement>, stmt: Statement) -> Result<Vec<PgFieldDe
.iter()
.map(to_pg_field)
.collect()),
Statement::ShowObjects(show_object) => match show_object {
Statement::ShowObjects {
object: show_object,
..
} => match show_object {
ShowObject::Columns { table: _ } => Ok(vec![
PgFieldDescriptor::new(
"Name".to_owned(),
Expand Down
10 changes: 8 additions & 2 deletions src/sqlparser/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1103,7 +1103,10 @@ pub enum Statement {
name: ObjectName,
},
/// SHOW OBJECT COMMAND
ShowObjects(ShowObject),
ShowObjects {
object: ShowObject,
filter: Option<ShowStatementFilter>,
},
/// SHOW CREATE COMMAND
ShowCreateObject {
/// Show create object type
Expand Down Expand Up @@ -1264,8 +1267,11 @@ impl fmt::Display for Statement {
write!(f, "DESCRIBE {}", name)?;
Ok(())
}
Statement::ShowObjects(show_object) => {
Statement::ShowObjects{ object: show_object, filter} => {
write!(f, "SHOW {}", show_object)?;
if let Some(filter) = filter {
write!(f, " {}", filter)?;
}
Ok(())
}
Statement::ShowCreateObject{ create_type: show_type, name } => {
Expand Down
123 changes: 90 additions & 33 deletions src/sqlparser/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3814,76 +3814,115 @@ impl Parser {
if let Token::Word(w) = self.next_token().token {
match w.keyword {
Keyword::TABLES => {
return Ok(Statement::ShowObjects(ShowObject::Table {
schema: self.parse_from_and_identifier()?,
}));
return Ok(Statement::ShowObjects {
object: ShowObject::Table {
schema: self.parse_from_and_identifier()?,
},
filter: self.parse_show_statement_filter()?,
});
}
Keyword::INTERNAL => {
self.expect_keyword(Keyword::TABLES)?;
return Ok(Statement::ShowObjects(ShowObject::InternalTable {
schema: self.parse_from_and_identifier()?,
}));
return Ok(Statement::ShowObjects {
object: ShowObject::InternalTable {
schema: self.parse_from_and_identifier()?,
},
filter: self.parse_show_statement_filter()?,
});
}
Keyword::SOURCES => {
return Ok(Statement::ShowObjects(ShowObject::Source {
schema: self.parse_from_and_identifier()?,
}));
return Ok(Statement::ShowObjects {
object: ShowObject::Source {
schema: self.parse_from_and_identifier()?,
},
filter: self.parse_show_statement_filter()?,
});
}
Keyword::SINKS => {
return Ok(Statement::ShowObjects(ShowObject::Sink {
schema: self.parse_from_and_identifier()?,
}))
return Ok(Statement::ShowObjects {
object: ShowObject::Sink {
schema: self.parse_from_and_identifier()?,
},
filter: self.parse_show_statement_filter()?,
});
}
Keyword::DATABASES => {
return Ok(Statement::ShowObjects(ShowObject::Database));
return Ok(Statement::ShowObjects {
object: ShowObject::Database,
filter: self.parse_show_statement_filter()?,
});
}
Keyword::SCHEMAS => {
return Ok(Statement::ShowObjects(ShowObject::Schema));
return Ok(Statement::ShowObjects {
object: ShowObject::Schema,
filter: self.parse_show_statement_filter()?,
});
}
Keyword::VIEWS => {
return Ok(Statement::ShowObjects(ShowObject::View {
schema: self.parse_from_and_identifier()?,
}));
return Ok(Statement::ShowObjects {
object: ShowObject::View {
schema: self.parse_from_and_identifier()?,
},
filter: self.parse_show_statement_filter()?,
});
}
Keyword::MATERIALIZED => {
if self.parse_keyword(Keyword::VIEWS) {
return Ok(Statement::ShowObjects(ShowObject::MaterializedView {
schema: self.parse_from_and_identifier()?,
}));
return Ok(Statement::ShowObjects {
object: ShowObject::MaterializedView {
schema: self.parse_from_and_identifier()?,
},
filter: self.parse_show_statement_filter()?,
});
} else {
return self.expected("VIEWS after MATERIALIZED", self.peek_token());
}
}
Keyword::COLUMNS => {
if self.parse_keyword(Keyword::FROM) {
return Ok(Statement::ShowObjects(ShowObject::Columns {
table: self.parse_object_name()?,
}));
return Ok(Statement::ShowObjects {
object: ShowObject::Columns {
table: self.parse_object_name()?,
},
filter: self.parse_show_statement_filter()?,
});
} else {
return self.expected("from after columns", self.peek_token());
}
}
Keyword::CONNECTIONS => {
return Ok(Statement::ShowObjects(ShowObject::Connection {
schema: self.parse_from_and_identifier()?,
}));
return Ok(Statement::ShowObjects {
object: ShowObject::Connection {
schema: self.parse_from_and_identifier()?,
},
filter: self.parse_show_statement_filter()?,
});
}
Keyword::FUNCTIONS => {
return Ok(Statement::ShowObjects(ShowObject::Function {
schema: self.parse_from_and_identifier()?,
}));
return Ok(Statement::ShowObjects {
object: ShowObject::Function {
schema: self.parse_from_and_identifier()?,
},
filter: self.parse_show_statement_filter()?,
});
}
Keyword::INDEXES => {
if self.parse_keyword(Keyword::FROM) {
return Ok(Statement::ShowObjects(ShowObject::Indexes {
table: self.parse_object_name()?,
}));
return Ok(Statement::ShowObjects {
object: ShowObject::Indexes {
table: self.parse_object_name()?,
},
filter: self.parse_show_statement_filter()?,
});
} else {
return self.expected("from after indexes", self.peek_token());
}
}
Keyword::CLUSTER => {
return Ok(Statement::ShowObjects(ShowObject::Cluster));
return Ok(Statement::ShowObjects {
object: ShowObject::Cluster,
filter: self.parse_show_statement_filter()?,
});
}
_ => {}
}
Expand Down Expand Up @@ -3939,6 +3978,24 @@ impl Parser {
)
}

pub fn parse_show_statement_filter(
&mut self,
) -> Result<Option<ShowStatementFilter>, ParserError> {
if self.parse_keyword(Keyword::LIKE) {
Ok(Some(ShowStatementFilter::Like(
self.parse_literal_string()?,
)))
} else if self.parse_keyword(Keyword::ILIKE) {
Ok(Some(ShowStatementFilter::ILike(
self.parse_literal_string()?,
)))
} else if self.parse_keyword(Keyword::WHERE) {
Ok(Some(ShowStatementFilter::Where(self.parse_expr()?)))
} else {
Ok(None)
}
}

pub fn parse_table_and_joins(&mut self) -> Result<TableWithJoins, ParserError> {
let relation = self.parse_table_factor()?;

Expand Down
32 changes: 19 additions & 13 deletions src/sqlparser/tests/testdata/show.yaml
Original file line number Diff line number Diff line change
@@ -1,43 +1,49 @@
# This file is automatically generated. See `src/sqlparser/test_runner/src/bin/apply.rs` for more information.
- input: SHOW DATABASES
formatted_sql: SHOW DATABASES
formatted_ast: ShowObjects(Database)
formatted_ast: 'ShowObjects { object: Database, filter: None }'
- input: SHOW SCHEMAS
formatted_sql: SHOW SCHEMAS
formatted_ast: ShowObjects(Schema)
formatted_ast: 'ShowObjects { object: Schema, filter: None }'
- input: SHOW TABLES
formatted_sql: SHOW TABLES
formatted_ast: 'ShowObjects(Table { schema: None })'
formatted_ast: 'ShowObjects { object: Table { schema: None }, filter: None }'
- input: SHOW TABLES FROM t
formatted_sql: SHOW TABLES FROM t
formatted_ast: 'ShowObjects(Table { schema: Some(Ident { value: "t", quote_style: None }) })'
formatted_ast: 'ShowObjects { object: Table { schema: Some(Ident { value: "t", quote_style: None }) }, filter: None }'
- input: SHOW TABLES FROM t LIKE "t%"
formatted_sql: SHOW TABLES FROM t LIKE 't%'
formatted_ast: 'ShowObjects { object: Table { schema: Some(Ident { value: "t", quote_style: None }) }, filter: Some(Like("t%")) }'
- input: SHOW VIEWS
formatted_sql: SHOW VIEWS
formatted_ast: 'ShowObjects(View { schema: None })'
formatted_ast: 'ShowObjects { object: View { schema: None }, filter: None }'
- input: SHOW VIEWS FROM t
formatted_sql: SHOW VIEWS FROM t
formatted_ast: 'ShowObjects(View { schema: Some(Ident { value: "t", quote_style: None }) })'
formatted_ast: 'ShowObjects { object: View { schema: Some(Ident { value: "t", quote_style: None }) }, filter: None }'
- input: SHOW MATERIALIZED VIEWS
formatted_sql: SHOW MATERIALIZED VIEWS
formatted_ast: 'ShowObjects(MaterializedView { schema: None })'
formatted_ast: 'ShowObjects { object: MaterializedView { schema: None }, filter: None }'
- input: SHOW INTERNAL TABLES
formatted_sql: SHOW INTERNAL TABLES
formatted_ast: 'ShowObjects(InternalTable { schema: None })'
formatted_ast: 'ShowObjects { object: InternalTable { schema: None }, filter: None }'
- input: SHOW INTERNAL TABLES FROM t
formatted_sql: SHOW INTERNAL TABLES FROM t
formatted_ast: 'ShowObjects(InternalTable { schema: Some(Ident { value: "t", quote_style: None }) })'
formatted_ast: 'ShowObjects { object: InternalTable { schema: Some(Ident { value: "t", quote_style: None }) }, filter: None }'
- input: SHOW INTERNAL TABLES LIKE "%mv1%"
formatted_sql: SHOW INTERNAL TABLES LIKE '%mv1%'
formatted_ast: 'ShowObjects { object: InternalTable { schema: None }, filter: Some(Like("%mv1%")) }'
- input: SHOW MATERIALIZED VIEWS FROM t
formatted_sql: SHOW MATERIALIZED VIEWS FROM t
formatted_ast: 'ShowObjects(MaterializedView { schema: Some(Ident { value: "t", quote_style: None }) })'
formatted_ast: 'ShowObjects { object: MaterializedView { schema: Some(Ident { value: "t", quote_style: None }) }, filter: None }'
- input: SHOW SOURCES FROM t
formatted_sql: SHOW SOURCES FROM t
formatted_ast: 'ShowObjects(Source { schema: Some(Ident { value: "t", quote_style: None }) })'
formatted_ast: 'ShowObjects { object: Source { schema: Some(Ident { value: "t", quote_style: None }) }, filter: None }'
- input: DESCRIBE schema.t
formatted_sql: DESCRIBE schema.t
formatted_ast: 'Describe { name: ObjectName([Ident { value: "schema", quote_style: None }, Ident { value: "t", quote_style: None }]) }'
- input: SHOW COLUMNS FROM schema.t
formatted_sql: SHOW COLUMNS FROM schema.t
formatted_ast: 'ShowObjects(Columns { table: ObjectName([Ident { value: "schema", quote_style: None }, Ident { value: "t", quote_style: None }]) })'
formatted_ast: 'ShowObjects { object: Columns { table: ObjectName([Ident { value: "schema", quote_style: None }, Ident { value: "t", quote_style: None }]) }, filter: None }'
- input: SHOW CREATE MATERIALIZED VIEW schema.mv
formatted_sql: SHOW CREATE MATERIALIZED VIEW schema.mv
formatted_ast: 'ShowCreateObject { create_type: MaterializedView, name: ObjectName([Ident { value: "schema", quote_style: None }, Ident { value: "mv", quote_style: None }]) }'
Expand All @@ -46,4 +52,4 @@
formatted_ast: 'ShowCreateObject { create_type: View, name: ObjectName([Ident { value: "schema", quote_style: None }, Ident { value: "v", quote_style: None }]) }'
- input: SHOW INDEXES FROM t
formatted_sql: SHOW INDEXES FROM t
formatted_ast: 'ShowObjects(Indexes { table: ObjectName([Ident { value: "t", quote_style: None }]) })'
formatted_ast: 'ShowObjects { object: Indexes { table: ObjectName([Ident { value: "t", quote_style: None }]) }, filter: None }'
1 change: 0 additions & 1 deletion src/stream/src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
pub use builder::*;
pub use column_mapping::*;

// t
mod builder;
pub mod cache;
mod column_mapping;
Expand Down
2 changes: 1 addition & 1 deletion src/utils/pgwire/src/pg_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ impl StatementType {
Statement::Grant { .. } => Ok(StatementType::GRANT_PRIVILEGE),
Statement::Revoke { .. } => Ok(StatementType::REVOKE_PRIVILEGE),
Statement::Describe { .. } => Ok(StatementType::DESCRIBE),
Statement::ShowCreateObject { .. } | Statement::ShowObjects(_) => {
Statement::ShowCreateObject { .. } | Statement::ShowObjects { .. } => {
Ok(StatementType::SHOW_COMMAND)
}
Statement::Drop(stmt) => match stmt.object_type {
Expand Down
Loading