Skip to content

Commit 34913c7

Browse files
committed
Implement alter table constraint operation
1 parent 639f01d commit 34913c7

File tree

3 files changed

+116
-0
lines changed

3 files changed

+116
-0
lines changed

src/dialect.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,8 @@ pub struct PostgreSqlDialect {}
454454
impl Dialect for PostgreSqlDialect {
455455
fn keywords(&self) -> Vec<&'static str> {
456456
return vec![
457+
"ALTER",
458+
"ONLY",
457459
"SELECT",
458460
"FROM",
459461
"WHERE",
@@ -529,6 +531,10 @@ impl Dialect for PostgreSqlDialect {
529531
"KEY",
530532
"UNIQUE",
531533
"UUID",
534+
"ADD",
535+
"CONSTRAINT",
536+
"FOREIGN",
537+
"REFERENCES",
532538
];
533539
}
534540

src/sqlast.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ pub enum ASTNode {
123123
/// Optional schema
124124
columns: Vec<SQLColumnDef>,
125125
},
126+
/// ALTER TABLE
127+
SQLAlterTable {
128+
/// Table name
129+
name: String,
130+
operation: AlterOperation,
131+
}
126132
}
127133

128134
/// SQL values such as int, double, string timestamp
@@ -252,3 +258,30 @@ pub enum SQLOperator {
252258
And,
253259
Or,
254260
}
261+
262+
#[derive(Debug, PartialEq, Clone)]
263+
pub enum AlterOperation{
264+
AddConstraint(TableKey),
265+
RemoveConstraint{
266+
name: String,
267+
}
268+
}
269+
270+
271+
#[derive(Debug, PartialEq, Clone)]
272+
pub struct Key{
273+
pub name: Option<String>,
274+
pub columns: Vec<String>,
275+
}
276+
277+
#[derive(Debug, PartialEq, Clone)]
278+
pub enum TableKey{
279+
PrimaryKey(Key),
280+
UniqueKey(Key),
281+
Key(Key),
282+
ForeignKey {
283+
key: Key,
284+
foreign_table: String,
285+
referred_columns: Vec<String>,
286+
}
287+
}

src/sqlparser.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ impl Parser {
102102
"CREATE" => Ok(self.parse_create()?),
103103
"DELETE" => Ok(self.parse_delete()?),
104104
"INSERT" => Ok(self.parse_insert()?),
105+
"ALTER" => Ok(self.parse_alter()?),
105106
"COPY" => Ok(self.parse_copy()?),
106107
"TRUE" => {
107108
self.prev_token();
@@ -544,6 +545,68 @@ impl Parser {
544545
}
545546
}
546547

548+
pub fn parse_table_key(&mut self, constraint_name: &str) -> Result<TableKey, ParserError> {
549+
let is_primary_key = self.parse_keywords(vec!["PRIMARY", "KEY"]);
550+
let is_unique_key = self.parse_keywords(vec!["UNIQUE", "KEY"]);
551+
let is_foreign_key = self.parse_keywords(vec!["FOREIGN", "KEY"]);
552+
self.consume_token(&Token::LParen)?;
553+
let column_names= self.parse_column_names()?;
554+
self.consume_token(&Token::RParen)?;
555+
let key = Key{
556+
name: Some(constraint_name.to_string()),
557+
columns: column_names
558+
};
559+
if is_primary_key{
560+
Ok(TableKey::PrimaryKey(key))
561+
}
562+
else if is_unique_key{
563+
Ok(TableKey::UniqueKey(key))
564+
}
565+
else if is_foreign_key{
566+
if self.parse_keyword("REFERENCES"){
567+
let foreign_table = self.parse_tablename()?;
568+
self.consume_token(&Token::LParen)?;
569+
let referred_columns = self.parse_column_names()?;
570+
self.consume_token(&Token::RParen)?;
571+
Ok(TableKey::ForeignKey{
572+
key,
573+
foreign_table,
574+
referred_columns,
575+
})
576+
}else{
577+
parser_err!("Expecting references")
578+
}
579+
}else{
580+
parser_err!(format!("Expecting primary key, unique key, or foreign key, found: {:?}", self.peek_token()))
581+
}
582+
}
583+
584+
pub fn parse_alter(&mut self) -> Result<ASTNode, ParserError> {
585+
if self.parse_keyword("TABLE") {
586+
let is_only = self.parse_keyword("ONLY");
587+
let table_name = self.parse_tablename()?;
588+
let operation:Result<AlterOperation,ParserError> = if self.parse_keywords(vec!["ADD", "CONSTRAINT"]){
589+
match self.next_token(){
590+
Some(Token::Identifier(ref id)) => {
591+
let table_key = self.parse_table_key(id)?;
592+
Ok(AlterOperation::AddConstraint(table_key))
593+
}
594+
_ => {
595+
return parser_err!(format!("Expecting identifier, found : {:?}", self.peek_token()));
596+
}
597+
}
598+
}else{
599+
return parser_err!(format!("Expecting ADD CONSTRAINT, found :{:?}", self.peek_token()));
600+
};
601+
Ok(ASTNode::SQLAlterTable{
602+
name: table_name,
603+
operation: operation?,
604+
})
605+
} else {
606+
parser_err!(format!("Expecting TABLE after ALTER, found {:?}", self.peek_token()))
607+
}
608+
}
609+
547610

548611
/// Parse a copy statement
549612
pub fn parse_copy(&mut self) -> Result<ASTNode, ParserError> {
@@ -1585,6 +1648,13 @@ mod tests {
15851648
ALTER TABLE ONLY bazaar.address
15861649
ADD CONSTRAINT address_pkey PRIMARY KEY (address_id)");
15871650
let ast = parse_sql(&sql);
1651+
println!("ast: {:?}", ast);
1652+
match ast {
1653+
ASTNode::SQLAlterTable{ name, operation } => {
1654+
assert_eq!(name, "bazaar.address");
1655+
}
1656+
_ => assert!(false),
1657+
}
15881658
}
15891659

15901660
#[test]
@@ -1594,6 +1664,13 @@ mod tests {
15941664
ADD CONSTRAINT customer_address_id_fkey FOREIGN KEY (address_id) REFERENCES public.address(address_id) ON UPDATE CASCADE ON DELETE RESTRICT;
15951665
");
15961666
let ast = parse_sql(&sql);
1667+
println!("ast: {:?}", ast);
1668+
match ast {
1669+
ASTNode::SQLAlterTable{ name, operation } => {
1670+
assert_eq!(name, "public.customer");
1671+
}
1672+
_ => assert!(false),
1673+
}
15971674
}
15981675

15991676
#[test]

0 commit comments

Comments
 (0)