Skip to content

Commit 3ea8ed2

Browse files
author
Alex.Mo
committed
Add support column prefix index for MySQL
1 parent b482562 commit 3ea8ed2

File tree

5 files changed

+267
-56
lines changed

5 files changed

+267
-56
lines changed

src/ast/ddl.rs

+22-18
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

+55
Original file line numberDiff line numberDiff line change
@@ -8591,6 +8591,61 @@ pub enum CopyIntoSnowflakeKind {
85918591
Location,
85928592
}
85938593

8594+
/// Index Field
8595+
///
8596+
/// This structure used here [`MySQL` CREATE INDEX][1], [`PostgreSQL` CREATE INDEX][2], [`MySQL` CREATE TABLE][3].
8597+
///
8598+
/// [1]: https://dev.mysql.com/doc/refman/8.3/en/create-index.html
8599+
/// [2]: https://www.postgresql.org/docs/17/sql-createindex.html
8600+
/// [3]: https://dev.mysql.com/doc/refman/8.3/en/create-table.html
8601+
8602+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8603+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8604+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8605+
pub struct IndexField {
8606+
pub expr: IndexExpr,
8607+
/// Optional `ASC` or `DESC`
8608+
pub asc: Option<bool>,
8609+
}
8610+
8611+
impl fmt::Display for IndexField {
8612+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8613+
write!(f, "{}", self.expr)?;
8614+
match self.asc {
8615+
Some(true) => write!(f, " ASC")?,
8616+
Some(false) => write!(f, " DESC")?,
8617+
None => (),
8618+
}
8619+
Ok(())
8620+
}
8621+
}
8622+
8623+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8624+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8625+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8626+
pub enum IndexExpr {
8627+
Column(Ident),
8628+
/// Mysql specific syntax
8629+
///
8630+
/// See [Mysql documentation](https://dev.mysql.com/doc/refman/8.3/en/create-index.html)
8631+
/// for more details.
8632+
ColumnPrefix {
8633+
column: Ident,
8634+
length: u64,
8635+
},
8636+
Functional(Box<Expr>),
8637+
}
8638+
8639+
impl fmt::Display for IndexExpr {
8640+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
8641+
match self {
8642+
IndexExpr::Column(column) => write!(f, "{}", column),
8643+
IndexExpr::ColumnPrefix { column, length } => write!(f, "{column}({length})"),
8644+
IndexExpr::Functional(expr) => write!(f, "({expr})"),
8645+
}
8646+
}
8647+
}
8648+
85948649
#[cfg(test)]
85958650
mod tests {
85968651
use super::*;

src/ast/spans.rs

+6-17
Original file line numberDiff line numberDiff line change
@@ -632,29 +632,27 @@ impl Spanned for TableConstraint {
632632
index_name,
633633
index_type_display: _,
634634
index_type: _,
635-
columns,
635+
index_fields: _,
636636
index_options: _,
637637
characteristics,
638638
nulls_distinct: _,
639639
} => union_spans(
640640
name.iter()
641641
.map(|i| i.span)
642642
.chain(index_name.iter().map(|i| i.span))
643-
.chain(columns.iter().map(|i| i.span))
644643
.chain(characteristics.iter().map(|i| i.span())),
645644
),
646645
TableConstraint::PrimaryKey {
647646
name,
648647
index_name,
649648
index_type: _,
650-
columns,
649+
index_fields: _,
651650
index_options: _,
652651
characteristics,
653652
} => union_spans(
654653
name.iter()
655654
.map(|i| i.span)
656655
.chain(index_name.iter().map(|i| i.span))
657-
.chain(columns.iter().map(|i| i.span))
658656
.chain(characteristics.iter().map(|i| i.span())),
659657
),
660658
TableConstraint::ForeignKey {
@@ -682,23 +680,14 @@ impl Spanned for TableConstraint {
682680
display_as_key: _,
683681
name,
684682
index_type: _,
685-
columns,
686-
} => union_spans(
687-
name.iter()
688-
.map(|i| i.span)
689-
.chain(columns.iter().map(|i| i.span)),
690-
),
683+
index_fields: _,
684+
} => union_spans(name.iter().map(|i| i.span)),
691685
TableConstraint::FulltextOrSpatial {
692686
fulltext: _,
693687
index_type_display: _,
694688
opt_index_name,
695-
columns,
696-
} => union_spans(
697-
opt_index_name
698-
.iter()
699-
.map(|i| i.span)
700-
.chain(columns.iter().map(|i| i.span)),
701-
),
689+
index_fields: _,
690+
} => union_spans(opt_index_name.iter().map(|i| i.span)),
702691
}
703692
}
704693
}

0 commit comments

Comments
 (0)