mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-07-07 17:04:59 +00:00
MySQL: Support index_name
in FK constraints (#1871)
This commit is contained in:
parent
5327f0ce13
commit
de2cc7b502
5 changed files with 31 additions and 7 deletions
|
@ -1019,6 +1019,9 @@ pub enum TableConstraint {
|
||||||
/// }`).
|
/// }`).
|
||||||
ForeignKey {
|
ForeignKey {
|
||||||
name: Option<Ident>,
|
name: Option<Ident>,
|
||||||
|
/// MySQL-specific field
|
||||||
|
/// <https://dev.mysql.com/doc/refman/8.4/en/create-table-foreign-keys.html>
|
||||||
|
index_name: Option<Ident>,
|
||||||
columns: Vec<Ident>,
|
columns: Vec<Ident>,
|
||||||
foreign_table: ObjectName,
|
foreign_table: ObjectName,
|
||||||
referred_columns: Vec<Ident>,
|
referred_columns: Vec<Ident>,
|
||||||
|
@ -1129,6 +1132,7 @@ impl fmt::Display for TableConstraint {
|
||||||
}
|
}
|
||||||
TableConstraint::ForeignKey {
|
TableConstraint::ForeignKey {
|
||||||
name,
|
name,
|
||||||
|
index_name,
|
||||||
columns,
|
columns,
|
||||||
foreign_table,
|
foreign_table,
|
||||||
referred_columns,
|
referred_columns,
|
||||||
|
@ -1138,8 +1142,9 @@ impl fmt::Display for TableConstraint {
|
||||||
} => {
|
} => {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{}FOREIGN KEY ({}) REFERENCES {}",
|
"{}FOREIGN KEY{} ({}) REFERENCES {}",
|
||||||
display_constraint_name(name),
|
display_constraint_name(name),
|
||||||
|
display_option_spaced(index_name),
|
||||||
display_comma_separated(columns),
|
display_comma_separated(columns),
|
||||||
foreign_table,
|
foreign_table,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -671,6 +671,7 @@ impl Spanned for TableConstraint {
|
||||||
TableConstraint::ForeignKey {
|
TableConstraint::ForeignKey {
|
||||||
name,
|
name,
|
||||||
columns,
|
columns,
|
||||||
|
index_name,
|
||||||
foreign_table,
|
foreign_table,
|
||||||
referred_columns,
|
referred_columns,
|
||||||
on_delete,
|
on_delete,
|
||||||
|
@ -679,6 +680,7 @@ impl Spanned for TableConstraint {
|
||||||
} => union_spans(
|
} => union_spans(
|
||||||
name.iter()
|
name.iter()
|
||||||
.map(|i| i.span)
|
.map(|i| i.span)
|
||||||
|
.chain(index_name.iter().map(|i| i.span))
|
||||||
.chain(columns.iter().map(|i| i.span))
|
.chain(columns.iter().map(|i| i.span))
|
||||||
.chain(core::iter::once(foreign_table.span()))
|
.chain(core::iter::once(foreign_table.span()))
|
||||||
.chain(referred_columns.iter().map(|i| i.span))
|
.chain(referred_columns.iter().map(|i| i.span))
|
||||||
|
|
|
@ -8061,7 +8061,7 @@ impl<'a> Parser<'a> {
|
||||||
let nulls_distinct = self.parse_optional_nulls_distinct()?;
|
let nulls_distinct = self.parse_optional_nulls_distinct()?;
|
||||||
|
|
||||||
// optional index name
|
// optional index name
|
||||||
let index_name = self.parse_optional_indent()?;
|
let index_name = self.parse_optional_ident()?;
|
||||||
let index_type = self.parse_optional_using_then_index_type()?;
|
let index_type = self.parse_optional_using_then_index_type()?;
|
||||||
|
|
||||||
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
|
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
|
||||||
|
@ -8083,7 +8083,7 @@ impl<'a> Parser<'a> {
|
||||||
self.expect_keyword_is(Keyword::KEY)?;
|
self.expect_keyword_is(Keyword::KEY)?;
|
||||||
|
|
||||||
// optional index name
|
// optional index name
|
||||||
let index_name = self.parse_optional_indent()?;
|
let index_name = self.parse_optional_ident()?;
|
||||||
let index_type = self.parse_optional_using_then_index_type()?;
|
let index_type = self.parse_optional_using_then_index_type()?;
|
||||||
|
|
||||||
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
|
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
|
||||||
|
@ -8100,6 +8100,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
Token::Word(w) if w.keyword == Keyword::FOREIGN => {
|
Token::Word(w) if w.keyword == Keyword::FOREIGN => {
|
||||||
self.expect_keyword_is(Keyword::KEY)?;
|
self.expect_keyword_is(Keyword::KEY)?;
|
||||||
|
let index_name = self.parse_optional_ident()?;
|
||||||
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
|
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
|
||||||
self.expect_keyword_is(Keyword::REFERENCES)?;
|
self.expect_keyword_is(Keyword::REFERENCES)?;
|
||||||
let foreign_table = self.parse_object_name(false)?;
|
let foreign_table = self.parse_object_name(false)?;
|
||||||
|
@ -8122,6 +8123,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
Ok(Some(TableConstraint::ForeignKey {
|
Ok(Some(TableConstraint::ForeignKey {
|
||||||
name,
|
name,
|
||||||
|
index_name,
|
||||||
columns,
|
columns,
|
||||||
foreign_table,
|
foreign_table,
|
||||||
referred_columns,
|
referred_columns,
|
||||||
|
@ -8145,7 +8147,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let name = match self.peek_token().token {
|
let name = match self.peek_token().token {
|
||||||
Token::Word(word) if word.keyword == Keyword::USING => None,
|
Token::Word(word) if word.keyword == Keyword::USING => None,
|
||||||
_ => self.parse_optional_indent()?,
|
_ => self.parse_optional_ident()?,
|
||||||
};
|
};
|
||||||
|
|
||||||
let index_type = self.parse_optional_using_then_index_type()?;
|
let index_type = self.parse_optional_using_then_index_type()?;
|
||||||
|
@ -8176,7 +8178,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
let index_type_display = self.parse_index_type_display();
|
let index_type_display = self.parse_index_type_display();
|
||||||
|
|
||||||
let opt_index_name = self.parse_optional_indent()?;
|
let opt_index_name = self.parse_optional_ident()?;
|
||||||
|
|
||||||
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
|
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
|
||||||
|
|
||||||
|
@ -8286,7 +8288,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
/// Parse `[ident]`, mostly `ident` is name, like:
|
/// Parse `[ident]`, mostly `ident` is name, like:
|
||||||
/// `window_name`, `index_name`, ...
|
/// `window_name`, `index_name`, ...
|
||||||
pub fn parse_optional_indent(&mut self) -> Result<Option<Ident>, ParserError> {
|
pub fn parse_optional_ident(&mut self) -> Result<Option<Ident>, ParserError> {
|
||||||
self.maybe_parse(|parser| parser.parse_identifier())
|
self.maybe_parse(|parser| parser.parse_identifier())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15698,7 +15700,7 @@ impl<'a> Parser<'a> {
|
||||||
pub fn parse_window_spec(&mut self) -> Result<WindowSpec, ParserError> {
|
pub fn parse_window_spec(&mut self) -> Result<WindowSpec, ParserError> {
|
||||||
let window_name = match self.peek_token().token {
|
let window_name = match self.peek_token().token {
|
||||||
Token::Word(word) if word.keyword == Keyword::NoKeyword => {
|
Token::Word(word) if word.keyword == Keyword::NoKeyword => {
|
||||||
self.parse_optional_indent()?
|
self.parse_optional_ident()?
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3791,6 +3791,7 @@ fn parse_create_table() {
|
||||||
vec![
|
vec![
|
||||||
TableConstraint::ForeignKey {
|
TableConstraint::ForeignKey {
|
||||||
name: Some("fkey".into()),
|
name: Some("fkey".into()),
|
||||||
|
index_name: None,
|
||||||
columns: vec!["lat".into()],
|
columns: vec!["lat".into()],
|
||||||
foreign_table: ObjectName::from(vec!["othertable3".into()]),
|
foreign_table: ObjectName::from(vec!["othertable3".into()]),
|
||||||
referred_columns: vec!["lat".into()],
|
referred_columns: vec!["lat".into()],
|
||||||
|
@ -3800,6 +3801,7 @@ fn parse_create_table() {
|
||||||
},
|
},
|
||||||
TableConstraint::ForeignKey {
|
TableConstraint::ForeignKey {
|
||||||
name: Some("fkey2".into()),
|
name: Some("fkey2".into()),
|
||||||
|
index_name: None,
|
||||||
columns: vec!["lat".into()],
|
columns: vec!["lat".into()],
|
||||||
foreign_table: ObjectName::from(vec!["othertable4".into()]),
|
foreign_table: ObjectName::from(vec!["othertable4".into()]),
|
||||||
referred_columns: vec!["lat".into()],
|
referred_columns: vec!["lat".into()],
|
||||||
|
@ -3809,6 +3811,7 @@ fn parse_create_table() {
|
||||||
},
|
},
|
||||||
TableConstraint::ForeignKey {
|
TableConstraint::ForeignKey {
|
||||||
name: None,
|
name: None,
|
||||||
|
index_name: None,
|
||||||
columns: vec!["lat".into()],
|
columns: vec!["lat".into()],
|
||||||
foreign_table: ObjectName::from(vec!["othertable4".into()]),
|
foreign_table: ObjectName::from(vec!["othertable4".into()]),
|
||||||
referred_columns: vec!["lat".into()],
|
referred_columns: vec!["lat".into()],
|
||||||
|
@ -3818,6 +3821,7 @@ fn parse_create_table() {
|
||||||
},
|
},
|
||||||
TableConstraint::ForeignKey {
|
TableConstraint::ForeignKey {
|
||||||
name: None,
|
name: None,
|
||||||
|
index_name: None,
|
||||||
columns: vec!["lng".into()],
|
columns: vec!["lng".into()],
|
||||||
foreign_table: ObjectName::from(vec!["othertable4".into()]),
|
foreign_table: ObjectName::from(vec!["othertable4".into()]),
|
||||||
referred_columns: vec!["longitude".into()],
|
referred_columns: vec!["longitude".into()],
|
||||||
|
@ -3914,6 +3918,7 @@ fn parse_create_table_with_constraint_characteristics() {
|
||||||
vec![
|
vec![
|
||||||
TableConstraint::ForeignKey {
|
TableConstraint::ForeignKey {
|
||||||
name: Some("fkey".into()),
|
name: Some("fkey".into()),
|
||||||
|
index_name: None,
|
||||||
columns: vec!["lat".into()],
|
columns: vec!["lat".into()],
|
||||||
foreign_table: ObjectName::from(vec!["othertable3".into()]),
|
foreign_table: ObjectName::from(vec!["othertable3".into()]),
|
||||||
referred_columns: vec!["lat".into()],
|
referred_columns: vec!["lat".into()],
|
||||||
|
@ -3927,6 +3932,7 @@ fn parse_create_table_with_constraint_characteristics() {
|
||||||
},
|
},
|
||||||
TableConstraint::ForeignKey {
|
TableConstraint::ForeignKey {
|
||||||
name: Some("fkey2".into()),
|
name: Some("fkey2".into()),
|
||||||
|
index_name: None,
|
||||||
columns: vec!["lat".into()],
|
columns: vec!["lat".into()],
|
||||||
foreign_table: ObjectName::from(vec!["othertable4".into()]),
|
foreign_table: ObjectName::from(vec!["othertable4".into()]),
|
||||||
referred_columns: vec!["lat".into()],
|
referred_columns: vec!["lat".into()],
|
||||||
|
@ -3940,6 +3946,7 @@ fn parse_create_table_with_constraint_characteristics() {
|
||||||
},
|
},
|
||||||
TableConstraint::ForeignKey {
|
TableConstraint::ForeignKey {
|
||||||
name: None,
|
name: None,
|
||||||
|
index_name: None,
|
||||||
columns: vec!["lat".into()],
|
columns: vec!["lat".into()],
|
||||||
foreign_table: ObjectName::from(vec!["othertable4".into()]),
|
foreign_table: ObjectName::from(vec!["othertable4".into()]),
|
||||||
referred_columns: vec!["lat".into()],
|
referred_columns: vec!["lat".into()],
|
||||||
|
@ -3953,6 +3960,7 @@ fn parse_create_table_with_constraint_characteristics() {
|
||||||
},
|
},
|
||||||
TableConstraint::ForeignKey {
|
TableConstraint::ForeignKey {
|
||||||
name: None,
|
name: None,
|
||||||
|
index_name: None,
|
||||||
columns: vec!["lng".into()],
|
columns: vec!["lng".into()],
|
||||||
foreign_table: ObjectName::from(vec!["othertable4".into()]),
|
foreign_table: ObjectName::from(vec!["othertable4".into()]),
|
||||||
referred_columns: vec!["longitude".into()],
|
referred_columns: vec!["longitude".into()],
|
||||||
|
|
|
@ -3988,6 +3988,13 @@ fn parse_straight_join() {
|
||||||
.verified_stmt("SELECT a.*, b.* FROM table_a STRAIGHT_JOIN table_b AS b ON a.b_id = b.id");
|
.verified_stmt("SELECT a.*, b.* FROM table_a STRAIGHT_JOIN table_b AS b ON a.b_id = b.id");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mysql_foreign_key_with_index_name() {
|
||||||
|
mysql().verified_stmt(
|
||||||
|
"CREATE TABLE orders (customer_id INT, INDEX idx_customer (customer_id), CONSTRAINT fk_customer FOREIGN KEY idx_customer (customer_id) REFERENCES customers(id))",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_drop_index() {
|
fn parse_drop_index() {
|
||||||
let sql = "DROP INDEX idx_name ON table_name";
|
let sql = "DROP INDEX idx_name ON table_name";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue