Skip to content
Open
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
47 changes: 47 additions & 0 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4772,6 +4772,14 @@ pub enum Statement {
table_name: ObjectName,
},
/// ```sql
/// DESC | DESCRIBE { VIEW | DATABASE | SCHEMA | EXTERNAL VOLUME } <name>
/// ```
/// See [DESCRIBE VIEW](https://docs.snowflake.com/en/sql-reference/sql/desc-view),
/// [DESCRIBE DATABASE](https://docs.snowflake.com/en/sql-reference/sql/desc-database),
/// [DESCRIBE SCHEMA](https://docs.snowflake.com/en/sql-reference/sql/desc-schema)
/// and [DESCRIBE EXTERNAL VOLUME](https://docs.snowflake.com/en/sql-reference/sql/desc-external-volume)
DescribeObject(DescribeObject),
/// ```sql
/// [EXPLAIN | DESC | DESCRIBE] <statement>
/// ```
Explain {
Expand Down Expand Up @@ -5259,6 +5267,7 @@ impl fmt::Display for Statement {

write!(f, "{id}")
}
Statement::DescribeObject(s) => write!(f, "{s}"),
Statement::ExplainTable {
describe_alias,
hive_format,
Expand Down Expand Up @@ -8788,6 +8797,8 @@ pub enum ObjectType {
User,
/// A stream.
Stream,
/// A Snowflake external volume.
ExternalVolume,
/// A warehouse.
Warehouse,
}
Expand All @@ -8809,6 +8820,7 @@ impl fmt::Display for ObjectType {
ObjectType::Type => "TYPE",
ObjectType::User => "USER",
ObjectType::Stream => "STREAM",
ObjectType::ExternalVolume => "EXTERNAL VOLUME",
ObjectType::Warehouse => "WAREHOUSE",
})
}
Expand Down Expand Up @@ -8986,6 +8998,35 @@ impl fmt::Display for DescribeAlias {
}
}

/// ```sql
/// DESC | DESCRIBE { VIEW | DATABASE | SCHEMA | EXTERNAL VOLUME } <name>
/// ```
/// See [DESCRIBE VIEW](https://docs.snowflake.com/en/sql-reference/sql/desc-view),
/// [DESCRIBE DATABASE](https://docs.snowflake.com/en/sql-reference/sql/desc-database),
/// [DESCRIBE SCHEMA](https://docs.snowflake.com/en/sql-reference/sql/desc-schema)
/// and [DESCRIBE EXTERNAL VOLUME](https://docs.snowflake.com/en/sql-reference/sql/desc-external-volume)
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct DescribeObject {
/// The keyword used, `DESC` or `DESCRIBE`.
pub describe_alias: DescribeAlias,
/// The kind of object described: `VIEW`, `DATABASE`, `SCHEMA` or `EXTERNAL VOLUME`.
pub object_type: ObjectType,
/// Name of the object.
pub name: ObjectName,
}

impl fmt::Display for DescribeObject {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{} {} {}",
self.describe_alias, self.object_type, self.name
)
}
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
Expand Down Expand Up @@ -12751,6 +12792,12 @@ impl From<CreateWarehouse> for Statement {
}
}

impl From<DescribeObject> for Statement {
fn from(d: DescribeObject) -> Self {
Self::DescribeObject(d)
}
}

impl From<VacuumStatement> for Statement {
fn from(v: VacuumStatement) -> Self {
Self::Vacuum(v)
Expand Down
1 change: 1 addition & 0 deletions src/ast/spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ impl Spanned for Statement {
Statement::Prepare { .. } => Span::empty(),
Statement::Kill { .. } => Span::empty(),
Statement::ExplainTable { .. } => Span::empty(),
Statement::DescribeObject(..) => Span::empty(),
Statement::Explain { .. } => Span::empty(),
Statement::Savepoint { .. } => Span::empty(),
Statement::ReleaseSavepoint { .. } => Span::empty(),
Expand Down
4 changes: 4 additions & 0 deletions src/dialect/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,4 +372,8 @@ impl Dialect for GenericDialect {
fn supports_add_column_if_not_exists(&self) -> bool {
true
}

fn supports_describe_object(&self) -> bool {
true
}
}
9 changes: 9 additions & 0 deletions src/dialect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1192,6 +1192,15 @@ pub trait Dialect: Debug + Any {
false
}

/// Returns true if this dialect supports `DESC | DESCRIBE <object_type> <name>`
/// for object types other than `TABLE`, e.g. `DESCRIBE VIEW my_view`,
/// `DESCRIBE DATABASE my_db` or `DESCRIBE SCHEMA my_schema`.
///
/// See <https://docs.snowflake.com/en/sql-reference/sql/desc>
fn supports_describe_object(&self) -> bool {
false
}

/// Returns true if this dialect allows the `EXTRACT` function to words other than [`Keyword`].
fn allow_extract_custom(&self) -> bool {
false
Expand Down
4 changes: 4 additions & 0 deletions src/dialect/snowflake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,10 @@ impl Dialect for SnowflakeDialect {
true
}

fn supports_describe_object(&self) -> bool {
true
}

fn allow_extract_custom(&self) -> bool {
true
}
Expand Down
35 changes: 35 additions & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15190,6 +15190,14 @@ impl<'a> Parser<'a> {
options,
}),
_ => {
if describe_alias != DescribeAlias::Explain
&& self.dialect.supports_describe_object()
{
if let Some(statement) = self.parse_describe_object(describe_alias)? {
return Ok(statement);
}
}

let hive_format =
match self.parse_one_of_keywords(&[Keyword::EXTENDED, Keyword::FORMATTED]) {
Some(Keyword::EXTENDED) => Some(HiveDescribeFormat::Extended),
Expand All @@ -15215,6 +15223,33 @@ impl<'a> Parser<'a> {
}
}

/// Parse `{ VIEW | DATABASE | SCHEMA | EXTERNAL VOLUME } <name>` following `DESC | DESCRIBE`.
/// Returns `None` if none of the object type keywords is present.
fn parse_describe_object(
&mut self,
describe_alias: DescribeAlias,
) -> Result<Option<Statement>, ParserError> {
let object_type = if self.parse_keywords(&[Keyword::EXTERNAL, Keyword::VOLUME]) {
ObjectType::ExternalVolume
} else {
match self.parse_one_of_keywords(&[Keyword::VIEW, Keyword::DATABASE, Keyword::SCHEMA]) {
Some(Keyword::VIEW) => ObjectType::View,
Some(Keyword::DATABASE) => ObjectType::Database,
Some(Keyword::SCHEMA) => ObjectType::Schema,
_ => return Ok(None),
}
};
let name = self.parse_object_name(false)?;
Ok(Some(
DescribeObject {
describe_alias,
object_type,
name,
}
.into(),
))
}

/// Parse a query expression, i.e. a `SELECT` statement optionally
/// preceded with some `WITH` CTE declarations and optionally followed
/// by `ORDER BY`. Unlike some other parse_... methods, this one doesn't
Expand Down
15 changes: 15 additions & 0 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22744,3 +22744,18 @@ fn display_create_procedure_parameter_list_propagates_write_errors() {
let mut writer = RejectingWriter(" (");
assert_eq!(write!(writer, "{statement}"), Err(fmt::Error));
}

#[test]
fn parse_describe_object() {
let dialects = all_dialects_where(|d| d.supports_describe_object());
dialects.verified_stmt("DESCRIBE VIEW v");
dialects.verified_stmt("DESC VIEW db.s.v");
dialects.verified_stmt("DESCRIBE DATABASE d");
dialects.verified_stmt("DESC SCHEMA db.s");

let dialects = all_dialects_where(|d| !d.supports_describe_object());
assert!(matches!(
dialects.verified_stmt("DESC schema"),
Statement::ExplainTable { .. }
));
}
6 changes: 6 additions & 0 deletions tests/sqlparser_snowflake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5042,3 +5042,9 @@ fn test_stage_name_delimiters() {
ParserError::ParserError("Expected: stage name identifier, found: .".to_string()),
);
}

#[test]
fn parse_describe_external_volume() {
snowflake().verified_stmt("DESCRIBE EXTERNAL VOLUME my_vol");
snowflake().verified_stmt("DESC EXTERNAL VOLUME my_vol");
}
Loading