Skip to content

Commit e36f743

Browse files
chenkovskyayman-sigma
authored andcommitted
feat: Add ALTER SCHEMA support (apache#1980)
1 parent e682430 commit e36f743

5 files changed

Lines changed: 164 additions & 11 deletions

File tree

src/ast/ddl.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3080,6 +3080,48 @@ impl fmt::Display for CreateConnector {
30803080
}
30813081
}
30823082

3083+
/// An `ALTER SCHEMA` (`Statement::AlterSchema`) operation.
3084+
///
3085+
/// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3086+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3087+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3088+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3089+
pub enum AlterSchemaOperation {
3090+
SetDefaultCollate {
3091+
collate: Expr,
3092+
},
3093+
AddReplica {
3094+
replica: Ident,
3095+
options: Option<Vec<SqlOption>>,
3096+
},
3097+
DropReplica {
3098+
replica: Ident,
3099+
},
3100+
SetOptionsParens {
3101+
options: Vec<SqlOption>,
3102+
},
3103+
}
3104+
3105+
impl fmt::Display for AlterSchemaOperation {
3106+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3107+
match self {
3108+
AlterSchemaOperation::SetDefaultCollate { collate } => {
3109+
write!(f, "SET DEFAULT COLLATE {collate}")
3110+
}
3111+
AlterSchemaOperation::AddReplica { replica, options } => {
3112+
write!(f, "ADD REPLICA {replica}")?;
3113+
if let Some(options) = options {
3114+
write!(f, " OPTIONS ({})", display_comma_separated(options))?;
3115+
}
3116+
Ok(())
3117+
}
3118+
AlterSchemaOperation::DropReplica { replica } => write!(f, "DROP REPLICA {replica}"),
3119+
AlterSchemaOperation::SetOptionsParens { options } => {
3120+
write!(f, "SET OPTIONS ({})", display_comma_separated(options))
3121+
}
3122+
}
3123+
}
3124+
}
30833125
/// `RenameTableNameKind` is the kind used in an `ALTER TABLE _ RENAME` statement.
30843126
///
30853127
/// Note: [MySQL] is the only database that supports the AS keyword for this operation.
@@ -3102,6 +3144,30 @@ impl fmt::Display for RenameTableNameKind {
31023144
}
31033145
}
31043146

3147+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3148+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3149+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3150+
pub struct AlterSchema {
3151+
pub name: ObjectName,
3152+
pub if_exists: bool,
3153+
pub operations: Vec<AlterSchemaOperation>,
3154+
}
3155+
3156+
impl fmt::Display for AlterSchema {
3157+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3158+
write!(f, "ALTER SCHEMA ")?;
3159+
if self.if_exists {
3160+
write!(f, "IF EXISTS ")?;
3161+
}
3162+
write!(f, "{}", self.name)?;
3163+
for operation in &self.operations {
3164+
write!(f, " {operation}")?;
3165+
}
3166+
3167+
Ok(())
3168+
}
3169+
}
3170+
31053171
impl Spanned for RenameTableNameKind {
31063172
fn span(&self) -> Span {
31073173
match self {

src/ast/mod.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,17 @@ pub use self::dcl::{
5959
};
6060
pub use self::ddl::{
6161
AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterPolicyOperation,
62-
AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterType, AlterTypeAddValue,
63-
AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
64-
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
65-
ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain, CreateFunction,
66-
CreateIndex, CreateTable, Deduplicate, DeferrableInitial, DropBehavior, GeneratedAs,
67-
GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
68-
IdentityPropertyKind, IdentityPropertyOrder, IndexColumn, IndexOption, IndexType,
69-
KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition, ProcedureParam, ReferentialAction,
70-
RenameTableNameKind, ReplicaIdentity, TableConstraint, TagsColumnOption,
71-
UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation, ViewColumnDef,
62+
AlterSchema, AlterSchemaOperation, AlterTableAlgorithm, AlterTableLock, AlterTableOperation,
63+
AlterType, AlterTypeAddValue, AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename,
64+
AlterTypeRenameValue, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions,
65+
ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain,
66+
CreateFunction, CreateIndex, CreateTable, Deduplicate, DeferrableInitial, DropBehavior,
67+
GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty,
68+
IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexColumn,
69+
IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition,
70+
ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity, TableConstraint,
71+
TagsColumnOption, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation,
72+
ViewColumnDef,
7273
};
7374
pub use self::dml::{Delete, Insert};
7475
pub use self::operator::{BinaryOperator, UnaryOperator};
@@ -3417,6 +3418,11 @@ pub enum Statement {
34173418
end_token: AttachedToken,
34183419
},
34193420
/// ```sql
3421+
/// ALTER SCHEMA
3422+
/// ```
3423+
/// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#alter_schema_collate_statement)
3424+
AlterSchema(AlterSchema),
3425+
/// ```sql
34203426
/// ALTER INDEX
34213427
/// ```
34223428
AlterIndex {
@@ -6365,6 +6371,7 @@ impl fmt::Display for Statement {
63656371
Statement::Remove(command) => write!(f, "REMOVE {command}"),
63666372
Statement::ExportData(e) => write!(f, "{e}"),
63676373
Statement::CreateUser(s) => write!(f, "{s}"),
6374+
Statement::AlterSchema(s) => write!(f, "{s}"),
63686375
}
63696376
}
63706377
}

src/ast/spans.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
use crate::ast::{query::SelectItemQualifiedWildcardKind, ColumnOptions, ExportData, TypedString};
18+
use crate::ast::{
19+
ddl::AlterSchema, query::SelectItemQualifiedWildcardKind, AlterSchemaOperation, ColumnOptions,
20+
ExportData, TypedString,
21+
};
1922
use core::iter;
2023

2124
use crate::tokenizer::Span;
@@ -548,6 +551,7 @@ impl Spanned for Statement {
548551
.chain(connection.iter().map(|i| i.span())),
549552
),
550553
Statement::CreateUser(..) => Span::empty(),
554+
Statement::AlterSchema(s) => s.span(),
551555
}
552556
}
553557
}
@@ -2396,6 +2400,30 @@ impl Spanned for OpenStatement {
23962400
}
23972401
}
23982402

2403+
impl Spanned for AlterSchemaOperation {
2404+
fn span(&self) -> Span {
2405+
match self {
2406+
AlterSchemaOperation::SetDefaultCollate { collate } => collate.span(),
2407+
AlterSchemaOperation::AddReplica { replica, options } => union_spans(
2408+
core::iter::once(replica.span)
2409+
.chain(options.iter().flat_map(|i| i.iter().map(|i| i.span()))),
2410+
),
2411+
AlterSchemaOperation::DropReplica { replica } => replica.span,
2412+
AlterSchemaOperation::SetOptionsParens { options } => {
2413+
union_spans(options.iter().map(|i| i.span()))
2414+
}
2415+
}
2416+
}
2417+
}
2418+
2419+
impl Spanned for AlterSchema {
2420+
fn span(&self) -> Span {
2421+
union_spans(
2422+
core::iter::once(self.name.span()).chain(self.operations.iter().map(|i| i.span())),
2423+
)
2424+
}
2425+
}
2426+
23992427
#[cfg(test)]
24002428
pub mod tests {
24012429
use crate::dialect::{Dialect, GenericDialect, SnowflakeDialect};

src/parser/mod.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9278,8 +9278,14 @@ impl<'a> Parser<'a> {
92789278
Keyword::POLICY,
92799279
Keyword::CONNECTOR,
92809280
Keyword::ICEBERG,
9281+
Keyword::SCHEMA,
92819282
])?;
92829283
match object_type {
9284+
Keyword::SCHEMA => {
9285+
self.prev_token();
9286+
self.prev_token();
9287+
self.parse_alter_schema()
9288+
}
92839289
Keyword::VIEW => self.parse_alter_view(),
92849290
Keyword::TYPE => self.parse_alter_type(),
92859291
Keyword::TABLE => self.parse_alter_table(false),
@@ -9418,6 +9424,40 @@ impl<'a> Parser<'a> {
94189424
}
94199425
}
94209426

9427+
// Parse a [Statement::AlterSchema]
9428+
// ALTER SCHEMA [ IF EXISTS ] schema_name
9429+
pub fn parse_alter_schema(&mut self) -> Result<Statement, ParserError> {
9430+
self.expect_keywords(&[Keyword::ALTER, Keyword::SCHEMA])?;
9431+
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
9432+
let name = self.parse_object_name(false)?;
9433+
let operation = if self.parse_keywords(&[Keyword::SET, Keyword::OPTIONS]) {
9434+
self.prev_token();
9435+
let options = self.parse_options(Keyword::OPTIONS)?;
9436+
AlterSchemaOperation::SetOptionsParens { options }
9437+
} else if self.parse_keywords(&[Keyword::SET, Keyword::DEFAULT, Keyword::COLLATE]) {
9438+
let collate = self.parse_expr()?;
9439+
AlterSchemaOperation::SetDefaultCollate { collate }
9440+
} else if self.parse_keywords(&[Keyword::ADD, Keyword::REPLICA]) {
9441+
let replica = self.parse_identifier()?;
9442+
let options = if self.peek_keyword(Keyword::OPTIONS) {
9443+
Some(self.parse_options(Keyword::OPTIONS)?)
9444+
} else {
9445+
None
9446+
};
9447+
AlterSchemaOperation::AddReplica { replica, options }
9448+
} else if self.parse_keywords(&[Keyword::DROP, Keyword::REPLICA]) {
9449+
let replica = self.parse_identifier()?;
9450+
AlterSchemaOperation::DropReplica { replica }
9451+
} else {
9452+
return self.expected_ref("ALTER SCHEMA operation", self.peek_token_ref());
9453+
};
9454+
Ok(Statement::AlterSchema(AlterSchema {
9455+
name,
9456+
if_exists,
9457+
operations: vec![operation],
9458+
}))
9459+
}
9460+
94219461
/// Parse a `CALL procedure_name(arg1, arg2, ...)`
94229462
/// or `CALL procedure_name` statement
94239463
pub fn parse_call(&mut self) -> Result<Statement, ParserError> {

tests/sqlparser_bigquery.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2825,3 +2825,15 @@ fn test_begin_transaction() {
28252825
fn test_begin_statement() {
28262826
bigquery().verified_stmt("BEGIN");
28272827
}
2828+
2829+
#[test]
2830+
fn test_alter_schema() {
2831+
bigquery_and_generic().verified_stmt("ALTER SCHEMA mydataset SET DEFAULT COLLATE 'und:ci'");
2832+
bigquery_and_generic().verified_stmt("ALTER SCHEMA mydataset ADD REPLICA 'us'");
2833+
bigquery_and_generic()
2834+
.verified_stmt("ALTER SCHEMA mydataset ADD REPLICA 'us' OPTIONS (location = 'us')");
2835+
bigquery_and_generic().verified_stmt("ALTER SCHEMA mydataset DROP REPLICA 'us'");
2836+
bigquery_and_generic().verified_stmt("ALTER SCHEMA mydataset SET OPTIONS (location = 'us')");
2837+
bigquery_and_generic()
2838+
.verified_stmt("ALTER SCHEMA IF EXISTS mydataset SET OPTIONS (location = 'us')");
2839+
}

0 commit comments

Comments
 (0)