Skip to content

Commit 982c3af

Browse files
author
Alex.Mo
committed
Add support column prefix index for MySQL
1 parent 72312ba commit 982c3af

File tree

5 files changed

+267
-56
lines changed

5 files changed

+267
-56
lines changed

src/ast/ddl.rs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ use crate::ast::value::escape_single_quote_string;
3232
use crate::ast::{
3333
display_comma_separated, display_separated, CommentDef, CreateFunctionBody,
3434
CreateFunctionUsing, DataType, Expr, FunctionBehavior, FunctionCalledOnNull,
35-
FunctionDeterminismSpecifier, FunctionParallel, Ident, MySQLColumnPosition, ObjectName,
36-
OperateFunctionArg, OrderByExpr, ProjectionSelect, SequenceOptions, SqlOption, Tag, Value,
35+
FunctionDeterminismSpecifier, FunctionParallel, Ident, IndexField, MySQLColumnPosition,
36+
ObjectName, OperateFunctionArg, OrderByExpr, ProjectionSelect, SequenceOptions, SqlOption, Tag,
37+
Value,
3738
};
3839
use crate::keywords::Keyword;
3940
use crate::tokenizer::Token;
@@ -832,8 +833,8 @@ pub enum TableConstraint {
832833
///
833834
/// [1]: IndexType
834835
index_type: Option<IndexType>,
835-
/// Identifiers of the columns that are unique.
836-
columns: Vec<Ident>,
836+
/// Index field list.
837+
index_fields: Vec<IndexField>,
837838
index_options: Vec<IndexOption>,
838839
characteristics: Option<ConstraintCharacteristics>,
839840
/// Optional Postgres nulls handling: `[ NULLS [ NOT ] DISTINCT ]`
@@ -868,8 +869,8 @@ pub enum TableConstraint {
868869
///
869870
/// [1]: IndexType
870871
index_type: Option<IndexType>,
871-
/// Identifiers of the columns that form the primary key.
872-
columns: Vec<Ident>,
872+
/// Index field list that form the primary key.
873+
index_fields: Vec<IndexField>,
873874
index_options: Vec<IndexOption>,
874875
characteristics: Option<ConstraintCharacteristics>,
875876
},
@@ -907,8 +908,10 @@ pub enum TableConstraint {
907908
///
908909
/// [1]: IndexType
909910
index_type: Option<IndexType>,
910-
/// Referred column identifier list.
911-
columns: Vec<Ident>,
911+
/// [Index field list][1].
912+
///
913+
/// [1]: IndexField
914+
index_fields: Vec<IndexField>,
912915
},
913916
/// MySQLs [fulltext][1] definition. Since the [`SPATIAL`][2] definition is exactly the same,
914917
/// and MySQL displays both the same way, it is part of this definition as well.
@@ -930,8 +933,8 @@ pub enum TableConstraint {
930933
index_type_display: KeyOrIndexDisplay,
931934
/// Optional index name.
932935
opt_index_name: Option<Ident>,
933-
/// Referred column identifier list.
934-
columns: Vec<Ident>,
936+
/// Index field list.
937+
index_fields: Vec<IndexField>,
935938
},
936939
}
937940

@@ -943,7 +946,7 @@ impl fmt::Display for TableConstraint {
943946
index_name,
944947
index_type_display,
945948
index_type,
946-
columns,
949+
index_fields,
947950
index_options,
948951
characteristics,
949952
nulls_distinct,
@@ -954,7 +957,7 @@ impl fmt::Display for TableConstraint {
954957
display_constraint_name(name),
955958
display_option_spaced(index_name),
956959
display_option(" USING ", "", index_type),
957-
display_comma_separated(columns),
960+
display_comma_separated(index_fields),
958961
)?;
959962

960963
if !index_options.is_empty() {
@@ -968,7 +971,7 @@ impl fmt::Display for TableConstraint {
968971
name,
969972
index_name,
970973
index_type,
971-
columns,
974+
index_fields,
972975
index_options,
973976
characteristics,
974977
} => {
@@ -978,7 +981,7 @@ impl fmt::Display for TableConstraint {
978981
display_constraint_name(name),
979982
display_option_spaced(index_name),
980983
display_option(" USING ", "", index_type),
981-
display_comma_separated(columns),
984+
display_comma_separated(index_fields),
982985
)?;
983986

984987
if !index_options.is_empty() {
@@ -1025,7 +1028,7 @@ impl fmt::Display for TableConstraint {
10251028
display_as_key,
10261029
name,
10271030
index_type,
1028-
columns,
1031+
index_fields,
10291032
} => {
10301033
write!(f, "{}", if *display_as_key { "KEY" } else { "INDEX" })?;
10311034
if let Some(name) = name {
@@ -1034,15 +1037,16 @@ impl fmt::Display for TableConstraint {
10341037
if let Some(index_type) = index_type {
10351038
write!(f, " USING {index_type}")?;
10361039
}
1037-
write!(f, " ({})", display_comma_separated(columns))?;
1040+
1041+
write!(f, " ({})", display_comma_separated(index_fields))?;
10381042

10391043
Ok(())
10401044
}
10411045
Self::FulltextOrSpatial {
10421046
fulltext,
10431047
index_type_display,
10441048
opt_index_name,
1045-
columns,
1049+
index_fields,
10461050
} => {
10471051
if *fulltext {
10481052
write!(f, "FULLTEXT")?;
@@ -1056,7 +1060,7 @@ impl fmt::Display for TableConstraint {
10561060
write!(f, " {name}")?;
10571061
}
10581062

1059-
write!(f, " ({})", display_comma_separated(columns))?;
1063+
write!(f, " ({})", display_comma_separated(index_fields))?;
10601064

10611065
Ok(())
10621066
}

src/ast/mod.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8647,6 +8647,61 @@ pub enum CopyIntoSnowflakeKind {
86478647
Location,
86488648
}
86498649

8650+
/// Index Field
8651+
///
8652+
/// This structure used here [`MySQL` CREATE INDEX][1], [`PostgreSQL` CREATE INDEX][2], [`MySQL` CREATE TABLE][3].
8653+
///
8654+
/// [1]: https://dev.mysql.com/doc/refman/8.3/en/create-index.html
8655+
/// [2]: https://www.postgresql.org/docs/17/sql-createindex.html
8656+
/// [3]: https://dev.mysql.com/doc/refman/8.3/en/create-table.html
8657+
8658+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8659+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8660+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8661+
pub struct IndexField {
8662+
pub expr: IndexExpr,
8663+
/// Optional `ASC` or `DESC`
8664+
pub asc: Option<bool>,
8665+
}
8666+
8667+
impl fmt::Display for IndexField {
8668+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8669+
write!(f, "{}", self.expr)?;
8670+
match self.asc {
8671+
Some(true) => write!(f, " ASC")?,
8672+
Some(false) => write!(f, " DESC")?,
8673+
None => (),
8674+
}
8675+
Ok(())
8676+
}
8677+
}
8678+
8679+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8680+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8681+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8682+
pub enum IndexExpr {
8683+
Column(Ident),
8684+
/// Mysql specific syntax
8685+
///
8686+
/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.3/en/create-index.html)
8687+
/// for more details.
8688+
ColumnPrefix {
8689+
column: Ident,
8690+
length: u64,
8691+
},
8692+
Functional(Box<Expr>),
8693+
}
8694+
8695+
impl fmt::Display for IndexExpr {
8696+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8697+
match self {
8698+
IndexExpr::Column(column) => write!(f, "{}", column),
8699+
IndexExpr::ColumnPrefix { column, length } => write!(f, "{column}({length})"),
8700+
IndexExpr::Functional(expr) => write!(f, "({expr})"),
8701+
}
8702+
}
8703+
}
8704+
86508705
#[cfg(test)]
86518706
mod tests {
86528707
use super::*;

src/ast/spans.rs

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -628,29 +628,27 @@ impl Spanned for TableConstraint {
628628
index_name,
629629
index_type_display: _,
630630
index_type: _,
631-
columns,
631+
index_fields: _,
632632
index_options: _,
633633
characteristics,
634634
nulls_distinct: _,
635635
} => union_spans(
636636
name.iter()
637637
.map(|i| i.span)
638638
.chain(index_name.iter().map(|i| i.span))
639-
.chain(columns.iter().map(|i| i.span))
640639
.chain(characteristics.iter().map(|i| i.span())),
641640
),
642641
TableConstraint::PrimaryKey {
643642
name,
644643
index_name,
645644
index_type: _,
646-
columns,
645+
index_fields: _,
647646
index_options: _,
648647
characteristics,
649648
} => union_spans(
650649
name.iter()
651650
.map(|i| i.span)
652651
.chain(index_name.iter().map(|i| i.span))
653-
.chain(columns.iter().map(|i| i.span))
654652
.chain(characteristics.iter().map(|i| i.span())),
655653
),
656654
TableConstraint::ForeignKey {
@@ -678,23 +676,14 @@ impl Spanned for TableConstraint {
678676
display_as_key: _,
679677
name,
680678
index_type: _,
681-
columns,
682-
} => union_spans(
683-
name.iter()
684-
.map(|i| i.span)
685-
.chain(columns.iter().map(|i| i.span)),
686-
),
679+
index_fields: _,
680+
} => union_spans(name.iter().map(|i| i.span)),
687681
TableConstraint::FulltextOrSpatial {
688682
fulltext: _,
689683
index_type_display: _,
690684
opt_index_name,
691-
columns,
692-
} => union_spans(
693-
opt_index_name
694-
.iter()
695-
.map(|i| i.span)
696-
.chain(columns.iter().map(|i| i.span)),
697-
),
685+
index_fields: _,
686+
} => union_spans(opt_index_name.iter().map(|i| i.span)),
698687
}
699688
}
700689
}

0 commit comments

Comments
 (0)