mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-22 15:04:04 +00:00
feat: Add ALTER SCHEMA
support (#1980)
Some checks are pending
license / Release Audit Tool (RAT) (push) Waiting to run
Rust / codestyle (push) Waiting to run
Rust / lint (push) Waiting to run
Rust / benchmark-lint (push) Waiting to run
Rust / compile (push) Waiting to run
Rust / docs (push) Waiting to run
Rust / compile-no-std (push) Waiting to run
Rust / test (beta) (push) Waiting to run
Rust / test (nightly) (push) Waiting to run
Rust / test (stable) (push) Waiting to run
Some checks are pending
license / Release Audit Tool (RAT) (push) Waiting to run
Rust / codestyle (push) Waiting to run
Rust / lint (push) Waiting to run
Rust / benchmark-lint (push) Waiting to run
Rust / compile (push) Waiting to run
Rust / docs (push) Waiting to run
Rust / compile-no-std (push) Waiting to run
Rust / test (beta) (push) Waiting to run
Rust / test (nightly) (push) Waiting to run
Rust / test (stable) (push) Waiting to run
This commit is contained in:
parent
56848b03dd
commit
cb7a51e85f
5 changed files with 164 additions and 11 deletions
|
@ -3080,6 +3080,48 @@ impl fmt::Display for CreateConnector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An `ALTER SCHEMA` (`Statement::AlterSchema`) operation.
|
||||||
|
///
|
||||||
|
/// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
|
pub enum AlterSchemaOperation {
|
||||||
|
SetDefaultCollate {
|
||||||
|
collate: Expr,
|
||||||
|
},
|
||||||
|
AddReplica {
|
||||||
|
replica: Ident,
|
||||||
|
options: Option<Vec<SqlOption>>,
|
||||||
|
},
|
||||||
|
DropReplica {
|
||||||
|
replica: Ident,
|
||||||
|
},
|
||||||
|
SetOptionsParens {
|
||||||
|
options: Vec<SqlOption>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for AlterSchemaOperation {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
AlterSchemaOperation::SetDefaultCollate { collate } => {
|
||||||
|
write!(f, "SET DEFAULT COLLATE {collate}")
|
||||||
|
}
|
||||||
|
AlterSchemaOperation::AddReplica { replica, options } => {
|
||||||
|
write!(f, "ADD REPLICA {replica}")?;
|
||||||
|
if let Some(options) = options {
|
||||||
|
write!(f, " OPTIONS ({})", display_comma_separated(options))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
AlterSchemaOperation::DropReplica { replica } => write!(f, "DROP REPLICA {replica}"),
|
||||||
|
AlterSchemaOperation::SetOptionsParens { options } => {
|
||||||
|
write!(f, "SET OPTIONS ({})", display_comma_separated(options))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/// `RenameTableNameKind` is the kind used in an `ALTER TABLE _ RENAME` statement.
|
/// `RenameTableNameKind` is the kind used in an `ALTER TABLE _ RENAME` statement.
|
||||||
///
|
///
|
||||||
/// Note: [MySQL] is the only database that supports the AS keyword for this operation.
|
/// Note: [MySQL] is the only database that supports the AS keyword for this operation.
|
||||||
|
@ -3102,6 +3144,30 @@ impl fmt::Display for RenameTableNameKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
|
pub struct AlterSchema {
|
||||||
|
pub name: ObjectName,
|
||||||
|
pub if_exists: bool,
|
||||||
|
pub operations: Vec<AlterSchemaOperation>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for AlterSchema {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "ALTER SCHEMA ")?;
|
||||||
|
if self.if_exists {
|
||||||
|
write!(f, "IF EXISTS ")?;
|
||||||
|
}
|
||||||
|
write!(f, "{}", self.name)?;
|
||||||
|
for operation in &self.operations {
|
||||||
|
write!(f, " {operation}")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Spanned for RenameTableNameKind {
|
impl Spanned for RenameTableNameKind {
|
||||||
fn span(&self) -> Span {
|
fn span(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -59,16 +59,17 @@ pub use self::dcl::{
|
||||||
};
|
};
|
||||||
pub use self::ddl::{
|
pub use self::ddl::{
|
||||||
AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterPolicyOperation,
|
AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterPolicyOperation,
|
||||||
AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterType, AlterTypeAddValue,
|
AlterSchema, AlterSchemaOperation, AlterTableAlgorithm, AlterTableLock, AlterTableOperation,
|
||||||
AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
|
AlterType, AlterTypeAddValue, AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename,
|
||||||
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
|
AlterTypeRenameValue, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions,
|
||||||
ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain, CreateFunction,
|
ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain,
|
||||||
CreateIndex, CreateTable, Deduplicate, DeferrableInitial, DropBehavior, GeneratedAs,
|
CreateFunction, CreateIndex, CreateTable, Deduplicate, DeferrableInitial, DropBehavior,
|
||||||
GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
|
GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty,
|
||||||
IdentityPropertyKind, IdentityPropertyOrder, IndexColumn, IndexOption, IndexType,
|
IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexColumn,
|
||||||
KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition, ProcedureParam, ReferentialAction,
|
IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition,
|
||||||
RenameTableNameKind, ReplicaIdentity, TableConstraint, TagsColumnOption,
|
ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity, TableConstraint,
|
||||||
UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation, ViewColumnDef,
|
TagsColumnOption, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation,
|
||||||
|
ViewColumnDef,
|
||||||
};
|
};
|
||||||
pub use self::dml::{Delete, Insert};
|
pub use self::dml::{Delete, Insert};
|
||||||
pub use self::operator::{BinaryOperator, UnaryOperator};
|
pub use self::operator::{BinaryOperator, UnaryOperator};
|
||||||
|
@ -3388,6 +3389,11 @@ pub enum Statement {
|
||||||
end_token: AttachedToken,
|
end_token: AttachedToken,
|
||||||
},
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
|
/// ALTER SCHEMA
|
||||||
|
/// ```
|
||||||
|
/// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
|
||||||
|
AlterSchema(AlterSchema),
|
||||||
|
/// ```sql
|
||||||
/// ALTER INDEX
|
/// ALTER INDEX
|
||||||
/// ```
|
/// ```
|
||||||
AlterIndex {
|
AlterIndex {
|
||||||
|
@ -6336,6 +6342,7 @@ impl fmt::Display for Statement {
|
||||||
Statement::Remove(command) => write!(f, "REMOVE {command}"),
|
Statement::Remove(command) => write!(f, "REMOVE {command}"),
|
||||||
Statement::ExportData(e) => write!(f, "{e}"),
|
Statement::ExportData(e) => write!(f, "{e}"),
|
||||||
Statement::CreateUser(s) => write!(f, "{s}"),
|
Statement::CreateUser(s) => write!(f, "{s}"),
|
||||||
|
Statement::AlterSchema(s) => write!(f, "{s}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,10 @@
|
||||||
// specific language governing permissions and limitations
|
// specific language governing permissions and limitations
|
||||||
// under the License.
|
// under the License.
|
||||||
|
|
||||||
use crate::ast::{query::SelectItemQualifiedWildcardKind, ColumnOptions, ExportData, TypedString};
|
use crate::ast::{
|
||||||
|
ddl::AlterSchema, query::SelectItemQualifiedWildcardKind, AlterSchemaOperation, ColumnOptions,
|
||||||
|
ExportData, TypedString,
|
||||||
|
};
|
||||||
use core::iter;
|
use core::iter;
|
||||||
|
|
||||||
use crate::tokenizer::Span;
|
use crate::tokenizer::Span;
|
||||||
|
@ -548,6 +551,7 @@ impl Spanned for Statement {
|
||||||
.chain(connection.iter().map(|i| i.span())),
|
.chain(connection.iter().map(|i| i.span())),
|
||||||
),
|
),
|
||||||
Statement::CreateUser(..) => Span::empty(),
|
Statement::CreateUser(..) => Span::empty(),
|
||||||
|
Statement::AlterSchema(s) => s.span(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2387,6 +2391,30 @@ impl Spanned for OpenStatement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Spanned for AlterSchemaOperation {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
AlterSchemaOperation::SetDefaultCollate { collate } => collate.span(),
|
||||||
|
AlterSchemaOperation::AddReplica { replica, options } => union_spans(
|
||||||
|
core::iter::once(replica.span)
|
||||||
|
.chain(options.iter().flat_map(|i| i.iter().map(|i| i.span()))),
|
||||||
|
),
|
||||||
|
AlterSchemaOperation::DropReplica { replica } => replica.span,
|
||||||
|
AlterSchemaOperation::SetOptionsParens { options } => {
|
||||||
|
union_spans(options.iter().map(|i| i.span()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Spanned for AlterSchema {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
union_spans(
|
||||||
|
core::iter::once(self.name.span()).chain(self.operations.iter().map(|i| i.span())),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod tests {
|
pub mod tests {
|
||||||
use crate::dialect::{Dialect, GenericDialect, SnowflakeDialect};
|
use crate::dialect::{Dialect, GenericDialect, SnowflakeDialect};
|
||||||
|
|
|
@ -9247,8 +9247,14 @@ impl<'a> Parser<'a> {
|
||||||
Keyword::POLICY,
|
Keyword::POLICY,
|
||||||
Keyword::CONNECTOR,
|
Keyword::CONNECTOR,
|
||||||
Keyword::ICEBERG,
|
Keyword::ICEBERG,
|
||||||
|
Keyword::SCHEMA,
|
||||||
])?;
|
])?;
|
||||||
match object_type {
|
match object_type {
|
||||||
|
Keyword::SCHEMA => {
|
||||||
|
self.prev_token();
|
||||||
|
self.prev_token();
|
||||||
|
self.parse_alter_schema()
|
||||||
|
}
|
||||||
Keyword::VIEW => self.parse_alter_view(),
|
Keyword::VIEW => self.parse_alter_view(),
|
||||||
Keyword::TYPE => self.parse_alter_type(),
|
Keyword::TYPE => self.parse_alter_type(),
|
||||||
Keyword::TABLE => self.parse_alter_table(false),
|
Keyword::TABLE => self.parse_alter_table(false),
|
||||||
|
@ -9387,6 +9393,40 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse a [Statement::AlterSchema]
|
||||||
|
// ALTER SCHEMA [ IF EXISTS ] schema_name
|
||||||
|
pub fn parse_alter_schema(&mut self) -> Result<Statement, ParserError> {
|
||||||
|
self.expect_keywords(&[Keyword::ALTER, Keyword::SCHEMA])?;
|
||||||
|
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||||
|
let name = self.parse_object_name(false)?;
|
||||||
|
let operation = if self.parse_keywords(&[Keyword::SET, Keyword::OPTIONS]) {
|
||||||
|
self.prev_token();
|
||||||
|
let options = self.parse_options(Keyword::OPTIONS)?;
|
||||||
|
AlterSchemaOperation::SetOptionsParens { options }
|
||||||
|
} else if self.parse_keywords(&[Keyword::SET, Keyword::DEFAULT, Keyword::COLLATE]) {
|
||||||
|
let collate = self.parse_expr()?;
|
||||||
|
AlterSchemaOperation::SetDefaultCollate { collate }
|
||||||
|
} else if self.parse_keywords(&[Keyword::ADD, Keyword::REPLICA]) {
|
||||||
|
let replica = self.parse_identifier()?;
|
||||||
|
let options = if self.peek_keyword(Keyword::OPTIONS) {
|
||||||
|
Some(self.parse_options(Keyword::OPTIONS)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
AlterSchemaOperation::AddReplica { replica, options }
|
||||||
|
} else if self.parse_keywords(&[Keyword::DROP, Keyword::REPLICA]) {
|
||||||
|
let replica = self.parse_identifier()?;
|
||||||
|
AlterSchemaOperation::DropReplica { replica }
|
||||||
|
} else {
|
||||||
|
return self.expected_ref("ALTER SCHEMA operation", self.peek_token_ref());
|
||||||
|
};
|
||||||
|
Ok(Statement::AlterSchema(AlterSchema {
|
||||||
|
name,
|
||||||
|
if_exists,
|
||||||
|
operations: vec![operation],
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse a `CALL procedure_name(arg1, arg2, ...)`
|
/// Parse a `CALL procedure_name(arg1, arg2, ...)`
|
||||||
/// or `CALL procedure_name` statement
|
/// or `CALL procedure_name` statement
|
||||||
pub fn parse_call(&mut self) -> Result<Statement, ParserError> {
|
pub fn parse_call(&mut self) -> Result<Statement, ParserError> {
|
||||||
|
|
|
@ -2825,3 +2825,15 @@ fn test_begin_transaction() {
|
||||||
fn test_begin_statement() {
|
fn test_begin_statement() {
|
||||||
bigquery().verified_stmt("BEGIN");
|
bigquery().verified_stmt("BEGIN");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_alter_schema() {
|
||||||
|
bigquery_and_generic().verified_stmt("ALTER SCHEMA mydataset SET DEFAULT COLLATE 'und:ci'");
|
||||||
|
bigquery_and_generic().verified_stmt("ALTER SCHEMA mydataset ADD REPLICA 'us'");
|
||||||
|
bigquery_and_generic()
|
||||||
|
.verified_stmt("ALTER SCHEMA mydataset ADD REPLICA 'us' OPTIONS (location = 'us')");
|
||||||
|
bigquery_and_generic().verified_stmt("ALTER SCHEMA mydataset DROP REPLICA 'us'");
|
||||||
|
bigquery_and_generic().verified_stmt("ALTER SCHEMA mydataset SET OPTIONS (location = 'us')");
|
||||||
|
bigquery_and_generic()
|
||||||
|
.verified_stmt("ALTER SCHEMA IF EXISTS mydataset SET OPTIONS (location = 'us')");
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue