Skip to content

Commit bda1fae

Browse files
mvzinkayman-sigma
authored andcommitted
Parse MySQL ALTER TABLE ALGORITHM option (apache#1745)
1 parent f11551a commit bda1fae

File tree

6 files changed

+119
-13
lines changed

6 files changed

+119
-13
lines changed

src/ast/ddl.rs

+41-4
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ pub enum AlterTableOperation {
6565
name: Ident,
6666
select: ProjectionSelect,
6767
},
68-
6968
/// `DROP PROJECTION [IF EXISTS] name`
7069
///
7170
/// Note: this is a ClickHouse-specific operation.
@@ -74,7 +73,6 @@ pub enum AlterTableOperation {
7473
if_exists: bool,
7574
name: Ident,
7675
},
77-
7876
/// `MATERIALIZE PROJECTION [IF EXISTS] name [IN PARTITION partition_name]`
7977
///
8078
/// Note: this is a ClickHouse-specific operation.
@@ -84,7 +82,6 @@ pub enum AlterTableOperation {
8482
name: Ident,
8583
partition: Option<Ident>,
8684
},
87-
8885
/// `CLEAR PROJECTION [IF EXISTS] name [IN PARTITION partition_name]`
8986
///
9087
/// Note: this is a ClickHouse-specific operation.
@@ -94,7 +91,6 @@ pub enum AlterTableOperation {
9491
name: Ident,
9592
partition: Option<Ident>,
9693
},
97-
9894
/// `DISABLE ROW LEVEL SECURITY`
9995
///
10096
/// Note: this is a PostgreSQL-specific operation.
@@ -272,6 +268,15 @@ pub enum AlterTableOperation {
272268
DropClusteringKey,
273269
SuspendRecluster,
274270
ResumeRecluster,
271+
/// `ALGORITHM [=] { DEFAULT | INSTANT | INPLACE | COPY }`
272+
///
273+
/// [MySQL]-specific table alter algorithm.
274+
///
275+
/// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html
276+
Algorithm {
277+
equals: bool,
278+
algorithm: AlterTableAlgorithm,
279+
},
275280
}
276281

277282
/// An `ALTER Policy` (`Statement::AlterPolicy`) operation
@@ -317,6 +322,30 @@ impl fmt::Display for AlterPolicyOperation {
317322
}
318323
}
319324

325+
/// [MySQL] `ALTER TABLE` algorithm.
326+
///
327+
/// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html
328+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
329+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
330+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
331+
pub enum AlterTableAlgorithm {
332+
Default,
333+
Instant,
334+
Inplace,
335+
Copy,
336+
}
337+
338+
impl fmt::Display for AlterTableAlgorithm {
339+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
340+
f.write_str(match self {
341+
Self::Default => "DEFAULT",
342+
Self::Instant => "INSTANT",
343+
Self::Inplace => "INPLACE",
344+
Self::Copy => "COPY",
345+
})
346+
}
347+
}
348+
320349
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
321350
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
322351
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
@@ -407,6 +436,14 @@ impl fmt::Display for AlterTableOperation {
407436
}
408437
write!(f, " {} ({})", name, query)
409438
}
439+
AlterTableOperation::Algorithm { equals, algorithm } => {
440+
write!(
441+
f,
442+
"ALGORITHM {}{}",
443+
if *equals { "= " } else { "" },
444+
algorithm
445+
)
446+
}
410447
AlterTableOperation::DropProjection { if_exists, name } => {
411448
write!(f, "DROP PROJECTION")?;
412449
if *if_exists {

src/ast/mod.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,15 @@ pub use self::dcl::{
4848
};
4949
pub use self::ddl::{
5050
AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterPolicyOperation,
51-
AlterTableOperation, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
52-
AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, ClusteredBy, ColumnDef,
53-
ColumnOption, ColumnOptionDef, ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics,
54-
CreateConnector, CreateFunction, Deduplicate, DeferrableInitial, DropBehavior, GeneratedAs,
55-
GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
56-
IdentityPropertyKind, IdentityPropertyOrder, IndexOption, IndexType, KeyOrIndexDisplay,
57-
NullsDistinctOption, Owner, Partition, ProcedureParam, ReferentialAction, TableConstraint,
58-
TagsColumnOption, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation,
59-
ViewColumnDef,
51+
AlterTableAlgorithm, AlterTableOperation, AlterType, AlterTypeAddValue,
52+
AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
53+
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnPolicy, ColumnPolicyProperty,
54+
ConstraintCharacteristics, CreateConnector, CreateFunction, Deduplicate, DeferrableInitial,
55+
DropBehavior, GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty,
56+
IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexOption,
57+
IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition, ProcedureParam,
58+
ReferentialAction, TableConstraint, TagsColumnOption, UserDefinedTypeCompositeAttributeDef,
59+
UserDefinedTypeRepresentation, ViewColumnDef,
6060
};
6161
pub use self::dml::{CreateIndex, CreateTable, Delete, Insert};
6262
pub use self::operator::{BinaryOperator, UnaryOperator};

src/ast/spans.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,7 @@ impl Spanned for AlterTableOperation {
10621062
AlterTableOperation::DropClusteringKey => Span::empty(),
10631063
AlterTableOperation::SuspendRecluster => Span::empty(),
10641064
AlterTableOperation::ResumeRecluster => Span::empty(),
1065+
AlterTableOperation::Algorithm { .. } => Span::empty(),
10651066
}
10661067
}
10671068
}

src/keywords.rs

+2
Original file line numberDiff line numberDiff line change
@@ -427,11 +427,13 @@ define_keywords!(
427427
INNER,
428428
INOUT,
429429
INPATH,
430+
INPLACE,
430431
INPUT,
431432
INPUTFORMAT,
432433
INSENSITIVE,
433434
INSERT,
434435
INSTALL,
436+
INSTANT,
435437
INSTEAD,
436438
INT,
437439
INT128,

src/parser/mod.rs

+18
Original file line numberDiff line numberDiff line change
@@ -8173,6 +8173,24 @@ impl<'a> Parser<'a> {
81738173
AlterTableOperation::SuspendRecluster
81748174
} else if self.parse_keywords(&[Keyword::RESUME, Keyword::RECLUSTER]) {
81758175
AlterTableOperation::ResumeRecluster
8176+
} else if self.parse_keyword(Keyword::ALGORITHM) {
8177+
let equals = self.consume_token(&Token::Eq);
8178+
let algorithm = match self.parse_one_of_keywords(&[
8179+
Keyword::DEFAULT,
8180+
Keyword::INSTANT,
8181+
Keyword::INPLACE,
8182+
Keyword::COPY,
8183+
]) {
8184+
Some(Keyword::DEFAULT) => AlterTableAlgorithm::Default,
8185+
Some(Keyword::INSTANT) => AlterTableAlgorithm::Instant,
8186+
Some(Keyword::INPLACE) => AlterTableAlgorithm::Inplace,
8187+
Some(Keyword::COPY) => AlterTableAlgorithm::Copy,
8188+
_ => self.expected(
8189+
"DEFAULT, INSTANT, INPLACE, or COPY after ALGORITHM [=]",
8190+
self.peek_token(),
8191+
)?,
8192+
};
8193+
AlterTableOperation::Algorithm { equals, algorithm }
81768194
} else {
81778195
let options: Vec<SqlOption> =
81788196
self.parse_options_with_keywords(&[Keyword::SET, Keyword::TBLPROPERTIES])?;

tests/sqlparser_mysql.rs

+48
Original file line numberDiff line numberDiff line change
@@ -2422,6 +2422,54 @@ fn parse_alter_table_modify_column() {
24222422
assert_eq!(expected_operation, operation);
24232423
}
24242424

2425+
#[test]
2426+
fn parse_alter_table_with_algorithm() {
2427+
let sql = "ALTER TABLE tab ALGORITHM = COPY";
2428+
let expected_operation = AlterTableOperation::Algorithm {
2429+
equals: true,
2430+
algorithm: AlterTableAlgorithm::Copy,
2431+
};
2432+
let operation = alter_table_op(mysql_and_generic().verified_stmt(sql));
2433+
assert_eq!(expected_operation, operation);
2434+
2435+
// Check order doesn't matter
2436+
let sql =
2437+
"ALTER TABLE users DROP COLUMN password_digest, ALGORITHM = COPY, RENAME COLUMN name TO username";
2438+
let stmt = mysql_and_generic().verified_stmt(sql);
2439+
match stmt {
2440+
Statement::AlterTable { operations, .. } => {
2441+
assert_eq!(
2442+
operations,
2443+
vec![
2444+
AlterTableOperation::DropColumn {
2445+
column_name: Ident::new("password_digest"),
2446+
if_exists: false,
2447+
drop_behavior: None,
2448+
},
2449+
AlterTableOperation::Algorithm {
2450+
equals: true,
2451+
algorithm: AlterTableAlgorithm::Copy,
2452+
},
2453+
AlterTableOperation::RenameColumn {
2454+
old_column_name: Ident::new("name"),
2455+
new_column_name: Ident::new("username")
2456+
},
2457+
]
2458+
)
2459+
}
2460+
_ => panic!("Unexpected statement {stmt}"),
2461+
}
2462+
2463+
mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM DEFAULT");
2464+
mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM INSTANT");
2465+
mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM INPLACE");
2466+
mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM COPY");
2467+
mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM = DEFAULT");
2468+
mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM = INSTANT");
2469+
mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM = INPLACE");
2470+
mysql_and_generic().verified_stmt("ALTER TABLE `users` ALGORITHM = COPY");
2471+
}
2472+
24252473
#[test]
24262474
fn parse_alter_table_modify_column_with_column_position() {
24272475
let expected_name = ObjectName::from(vec![Ident::new("orders")]);

0 commit comments

Comments
 (0)