Skip to content

Commit 8a8fcf5

Browse files
author
mashuai
committed
implement alter table for sqlite grammer: https://www.sqlite.org/lang_altertable.html
1 parent fab6e28 commit 8a8fcf5

File tree

4 files changed

+146
-3
lines changed

4 files changed

+146
-3
lines changed

src/ast/ddl.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,60 @@ use std::fmt;
2323
pub enum AlterTableOperation {
2424
/// `ADD <table_constraint>`
2525
AddConstraint(TableConstraint),
26+
AddColumn {
27+
has_column_identifier: bool,
28+
column_def: ColumnDef,
29+
},
2630
/// TODO: implement `DROP CONSTRAINT <name>`
27-
DropConstraint { name: Ident },
31+
DropConstraint {
32+
name: Ident,
33+
},
34+
RenameColumn {
35+
has_column_identifier: bool,
36+
old_column_name: Ident,
37+
new_column_name: Ident,
38+
},
39+
RenameTable {
40+
table_name: Ident,
41+
},
2842
}
2943

3044
impl fmt::Display for AlterTableOperation {
3145
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3246
match self {
3347
AlterTableOperation::AddConstraint(c) => write!(f, "ADD {}", c),
48+
AlterTableOperation::AddColumn {
49+
has_column_identifier,
50+
column_def,
51+
} => write!(
52+
f,
53+
"ADD {}{}",
54+
if *has_column_identifier {
55+
"COLUMN "
56+
} else {
57+
""
58+
},
59+
column_def.to_string()
60+
),
3461
AlterTableOperation::DropConstraint { name } => write!(f, "DROP CONSTRAINT {}", name),
62+
AlterTableOperation::RenameColumn {
63+
has_column_identifier,
64+
old_column_name,
65+
new_column_name,
66+
} => write!(
67+
f,
68+
"RENAME {}{} TO {}",
69+
if *has_column_identifier {
70+
"COLUMN "
71+
} else {
72+
""
73+
},
74+
old_column_name,
75+
new_column_name
76+
),
77+
AlterTableOperation::RenameTable { table_name } => {
78+
write!(f, "RENAME TO {}", table_name)
79+
}
3580
}
3681
}
3782
}

src/dialect/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ define_keywords!(
340340
REGR_SXY,
341341
REGR_SYY,
342342
RELEASE,
343+
RENAME,
343344
REPEATABLE,
344345
RESTRICT,
345346
RESULT,

src/parser.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,29 @@ impl Parser {
11221122
})
11231123
}
11241124

1125+
fn parse_column(&mut self) -> Result<ColumnDef, ParserError> {
1126+
let name = self.parse_identifier()?;
1127+
let data_type = self.parse_data_type()?;
1128+
let collation = if self.parse_keyword(Keyword::COLLATE) {
1129+
Some(self.parse_object_name()?)
1130+
} else {
1131+
None
1132+
};
1133+
let mut options = vec![];
1134+
loop {
1135+
match self.peek_token() {
1136+
Token::EOF => break,
1137+
_ => options.push(self.parse_column_option_def()?),
1138+
}
1139+
}
1140+
Ok(ColumnDef {
1141+
name,
1142+
data_type,
1143+
collation,
1144+
options,
1145+
})
1146+
}
1147+
11251148
fn parse_columns(&mut self) -> Result<(Vec<ColumnDef>, Vec<TableConstraint>), ParserError> {
11261149
let mut columns = vec![];
11271150
let mut constraints = vec![];
@@ -1318,10 +1341,33 @@ impl Parser {
13181341
if let Some(constraint) = self.parse_optional_table_constraint()? {
13191342
AlterTableOperation::AddConstraint(constraint)
13201343
} else {
1321-
return self.expected("a constraint in ALTER TABLE .. ADD", self.peek_token());
1344+
let has_column_identifier = self.parse_keyword(Keyword::COLUMN);
1345+
let column_def = self.parse_column()?;
1346+
AlterTableOperation::AddColumn {
1347+
has_column_identifier,
1348+
column_def,
1349+
}
1350+
}
1351+
} else if self.parse_keyword(Keyword::RENAME) {
1352+
if self.parse_keyword(Keyword::TO) {
1353+
let table_name = self.parse_identifier()?;
1354+
AlterTableOperation::RenameTable { table_name }
1355+
} else {
1356+
let has_column_identifier = self.parse_keyword(Keyword::COLUMN);
1357+
let old_column_name = self.parse_identifier()?;
1358+
self.expect_keyword(Keyword::TO)?;
1359+
let new_column_name = self.parse_identifier()?;
1360+
AlterTableOperation::RenameColumn {
1361+
has_column_identifier,
1362+
old_column_name,
1363+
new_column_name,
1364+
}
13221365
}
13231366
} else {
1324-
return self.expected("ADD after ALTER TABLE", self.peek_token());
1367+
return self.expected(
1368+
"ADD,RENAME TO or RENAME after ALTER TABLE",
1369+
self.peek_token(),
1370+
);
13251371
};
13261372
Ok(Statement::AlterTable {
13271373
name: table_name,

tests/sqlparser_common.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,57 @@ fn parse_create_table_empty() {
13131313
let _ = verified_stmt("CREATE TABLE t ()");
13141314
}
13151315

1316+
#[test]
1317+
fn parse_alter_table() {
1318+
let add_column = "ALTER TABLE tab ADD column foo TEXT";
1319+
match verified_stmt(add_column) {
1320+
Statement::AlterTable {
1321+
name,
1322+
operation:
1323+
AlterTableOperation::AddColumn {
1324+
has_column_identifier,
1325+
column_def,
1326+
},
1327+
} => {
1328+
assert_eq!("tab", name.to_string());
1329+
assert_eq!(has_column_identifier, false);
1330+
assert_eq!("foo", column_def.name.to_string());
1331+
}
1332+
_ => unreachable!(),
1333+
};
1334+
1335+
let rename_table = "ALTER TABLE tab RENAME TO new_tab";
1336+
match verified_stmt(rename_table) {
1337+
Statement::AlterTable {
1338+
name,
1339+
operation: AlterTableOperation::RenameTable { table_name },
1340+
} => {
1341+
assert_eq!("tab", name.to_string());
1342+
assert_eq!("new_tab", table_name)
1343+
}
1344+
_ => unreachable!(),
1345+
};
1346+
1347+
let rename_column = "ALTER TABLE tab RENAME COLUMN foo TO new_foo";
1348+
match verified_stmt(rename_table) {
1349+
Statement::AlterTable {
1350+
name,
1351+
operation:
1352+
AlterTableOperation::RenameColumn {
1353+
has_column_identifier,
1354+
old_column_name,
1355+
new_column_name,
1356+
},
1357+
} => {
1358+
assert_eq!("tab", name.to_string());
1359+
assert_eq!(has_column_identifier, true);
1360+
assert_eq!(old_column_name, "foo");
1361+
assert_eq!(new_column_name, "new_foo");
1362+
}
1363+
_ => unreachable!(),
1364+
}
1365+
}
1366+
13161367
#[test]
13171368
fn parse_alter_table_constraints() {
13181369
check_one("CONSTRAINT address_pkey PRIMARY KEY (address_id)");

0 commit comments

Comments
 (0)