Skip to content

Commit 27df88f

Browse files
mvzinkayman-sigma
authored andcommitted
Use IndexColumn in all index definitions (apache#1900)
1 parent 9ce1d88 commit 27df88f

File tree

5 files changed

+181
-35
lines changed

5 files changed

+181
-35
lines changed

src/ast/ddl.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +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,
37-
ValueWithSpan,
35+
FunctionDeterminismSpecifier, FunctionParallel, Ident, IndexColumn, MySQLColumnPosition,
36+
ObjectName, OperateFunctionArg, OrderByExpr, ProjectionSelect, SequenceOptions, SqlOption, Tag,
37+
Value, ValueWithSpan,
3838
};
3939
use crate::keywords::Keyword;
4040
use crate::tokenizer::Token;
@@ -979,7 +979,7 @@ pub enum TableConstraint {
979979
/// [1]: IndexType
980980
index_type: Option<IndexType>,
981981
/// Identifiers of the columns that are unique.
982-
columns: Vec<Ident>,
982+
columns: Vec<IndexColumn>,
983983
index_options: Vec<IndexOption>,
984984
characteristics: Option<ConstraintCharacteristics>,
985985
/// Optional Postgres nulls handling: `[ NULLS [ NOT ] DISTINCT ]`
@@ -1015,7 +1015,7 @@ pub enum TableConstraint {
10151015
/// [1]: IndexType
10161016
index_type: Option<IndexType>,
10171017
/// Identifiers of the columns that form the primary key.
1018-
columns: Vec<Ident>,
1018+
columns: Vec<IndexColumn>,
10191019
index_options: Vec<IndexOption>,
10201020
characteristics: Option<ConstraintCharacteristics>,
10211021
},
@@ -1060,7 +1060,7 @@ pub enum TableConstraint {
10601060
/// [1]: IndexType
10611061
index_type: Option<IndexType>,
10621062
/// Referred column identifier list.
1063-
columns: Vec<Ident>,
1063+
columns: Vec<IndexColumn>,
10641064
},
10651065
/// MySQLs [fulltext][1] definition. Since the [`SPATIAL`][2] definition is exactly the same,
10661066
/// and MySQL displays both the same way, it is part of this definition as well.
@@ -1083,7 +1083,7 @@ pub enum TableConstraint {
10831083
/// Optional index name.
10841084
opt_index_name: Option<Ident>,
10851085
/// Referred column identifier list.
1086-
columns: Vec<Ident>,
1086+
columns: Vec<IndexColumn>,
10871087
},
10881088
}
10891089

src/ast/spans.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,17 @@ use super::{
2828
ConstraintCharacteristics, CopySource, CreateIndex, CreateTable, CreateTableOptions, Cte,
2929
Delete, DoUpdate, ExceptSelectItem, ExcludeSelectItem, Expr, ExprWithAlias, Fetch, FromTable,
3030
Function, FunctionArg, FunctionArgExpr, FunctionArgumentClause, FunctionArgumentList,
31-
FunctionArguments, GroupByExpr, HavingBound, IfStatement, IlikeSelectItem, Insert, Interpolate,
32-
InterpolateExpr, Join, JoinConstraint, JoinOperator, JsonPath, JsonPathElem, LateralView,
33-
LimitClause, MatchRecognizePattern, Measure, NamedParenthesizedList, NamedWindowDefinition,
34-
ObjectName, ObjectNamePart, Offset, OnConflict, OnConflictAction, OnInsert, OpenStatement,
35-
OrderBy, OrderByExpr, OrderByKind, Partition, PivotValueSource, ProjectionSelect, Query,
36-
RaiseStatement, RaiseStatementValue, ReferentialAction, RenameSelectItem, ReplaceSelectElement,
37-
ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SqlOption, Statement, Subscript,
38-
SymbolDefinition, TableAlias, TableAliasColumnDef, TableConstraint, TableFactor, TableObject,
39-
TableOptionsClustered, TableWithJoins, UpdateTableFromKind, Use, Value, Values, ViewColumnDef,
40-
WhileStatement, WildcardAdditionalOptions, With, WithFill,
31+
FunctionArguments, GroupByExpr, HavingBound, IfStatement, IlikeSelectItem, IndexColumn, Insert,
32+
Interpolate, InterpolateExpr, Join, JoinConstraint, JoinOperator, JsonPath, JsonPathElem,
33+
LateralView, LimitClause, MatchRecognizePattern, Measure, NamedParenthesizedList,
34+
NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, OnConflict, OnConflictAction,
35+
OnInsert, OpenStatement, OrderBy, OrderByExpr, OrderByKind, Partition, PivotValueSource,
36+
ProjectionSelect, Query, RaiseStatement, RaiseStatementValue, ReferentialAction,
37+
RenameSelectItem, ReplaceSelectElement, ReplaceSelectItem, Select, SelectInto, SelectItem,
38+
SetExpr, SqlOption, Statement, Subscript, SymbolDefinition, TableAlias, TableAliasColumnDef,
39+
TableConstraint, TableFactor, TableObject, TableOptionsClustered, TableWithJoins,
40+
UpdateTableFromKind, Use, Value, Values, ViewColumnDef, WhileStatement,
41+
WildcardAdditionalOptions, With, WithFill,
4142
};
4243

4344
/// Given an iterator of spans, return the [Span::union] of all spans.
@@ -650,7 +651,7 @@ impl Spanned for TableConstraint {
650651
name.iter()
651652
.map(|i| i.span)
652653
.chain(index_name.iter().map(|i| i.span))
653-
.chain(columns.iter().map(|i| i.span))
654+
.chain(columns.iter().map(|i| i.span()))
654655
.chain(characteristics.iter().map(|i| i.span())),
655656
),
656657
TableConstraint::PrimaryKey {
@@ -664,7 +665,7 @@ impl Spanned for TableConstraint {
664665
name.iter()
665666
.map(|i| i.span)
666667
.chain(index_name.iter().map(|i| i.span))
667-
.chain(columns.iter().map(|i| i.span))
668+
.chain(columns.iter().map(|i| i.span()))
668669
.chain(characteristics.iter().map(|i| i.span())),
669670
),
670671
TableConstraint::ForeignKey {
@@ -700,7 +701,7 @@ impl Spanned for TableConstraint {
700701
} => union_spans(
701702
name.iter()
702703
.map(|i| i.span)
703-
.chain(columns.iter().map(|i| i.span)),
704+
.chain(columns.iter().map(|i| i.span())),
704705
),
705706
TableConstraint::FulltextOrSpatial {
706707
fulltext: _,
@@ -711,7 +712,7 @@ impl Spanned for TableConstraint {
711712
opt_index_name
712713
.iter()
713714
.map(|i| i.span)
714-
.chain(columns.iter().map(|i| i.span)),
715+
.chain(columns.iter().map(|i| i.span())),
715716
),
716717
}
717718
}
@@ -745,6 +746,12 @@ impl Spanned for CreateIndex {
745746
}
746747
}
747748

749+
impl Spanned for IndexColumn {
750+
fn span(&self) -> Span {
751+
self.column.span()
752+
}
753+
}
754+
748755
impl Spanned for CaseStatement {
749756
fn span(&self) -> Span {
750757
let CaseStatement {

src/parser/mod.rs

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6899,9 +6899,7 @@ impl<'a> Parser<'a> {
68996899
None
69006900
};
69016901

6902-
self.expect_token(&Token::LParen)?;
6903-
let columns = self.parse_comma_separated(Parser::parse_create_index_expr)?;
6904-
self.expect_token(&Token::RParen)?;
6902+
let columns = self.parse_parenthesized_index_column_list()?;
69056903

69066904
let include = if self.parse_keyword(Keyword::INCLUDE) {
69076905
self.expect_token(&Token::LParen)?;
@@ -8101,7 +8099,7 @@ impl<'a> Parser<'a> {
81018099
let index_name = self.parse_optional_ident()?;
81028100
let index_type = self.parse_optional_using_then_index_type()?;
81038101

8104-
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
8102+
let columns = self.parse_parenthesized_index_column_list()?;
81058103
let index_options = self.parse_index_options()?;
81068104
let characteristics = self.parse_constraint_characteristics()?;
81078105
Ok(Some(TableConstraint::Unique {
@@ -8123,7 +8121,7 @@ impl<'a> Parser<'a> {
81238121
let index_name = self.parse_optional_ident()?;
81248122
let index_type = self.parse_optional_using_then_index_type()?;
81258123

8126-
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
8124+
let columns = self.parse_parenthesized_index_column_list()?;
81278125
let index_options = self.parse_index_options()?;
81288126
let characteristics = self.parse_constraint_characteristics()?;
81298127
Ok(Some(TableConstraint::PrimaryKey {
@@ -8201,7 +8199,7 @@ impl<'a> Parser<'a> {
82018199
};
82028200

82038201
let index_type = self.parse_optional_using_then_index_type()?;
8204-
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
8202+
let columns = self.parse_parenthesized_index_column_list()?;
82058203

82068204
Ok(Some(TableConstraint::Index {
82078205
display_as_key,
@@ -8230,7 +8228,7 @@ impl<'a> Parser<'a> {
82308228

82318229
let opt_index_name = self.parse_optional_ident()?;
82328230

8233-
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
8231+
let columns = self.parse_parenthesized_index_column_list()?;
82348232

82358233
Ok(Some(TableConstraint::FulltextOrSpatial {
82368234
fulltext,
@@ -10632,6 +10630,14 @@ impl<'a> Parser<'a> {
1063210630
self.parse_parenthesized_column_list_inner(optional, allow_empty, |p| p.parse_identifier())
1063310631
}
1063410632

10633+
/// Parses a parenthesized comma-separated list of index columns, which can be arbitrary
10634+
/// expressions with ordering information (and an opclass in some dialects).
10635+
fn parse_parenthesized_index_column_list(&mut self) -> Result<Vec<IndexColumn>, ParserError> {
10636+
self.parse_parenthesized_column_list_inner(Mandatory, false, |p| {
10637+
p.parse_create_index_expr()
10638+
})
10639+
}
10640+
1063510641
/// Parses a parenthesized comma-separated list of qualified, possibly quoted identifiers.
1063610642
/// For example: `(db1.sc1.tbl1.col1, db1.sc1.tbl1."col 2", ...)`
1063710643
pub fn parse_parenthesized_qualified_column_list(
@@ -16559,6 +16565,20 @@ mod tests {
1655916565
}};
1656016566
}
1656116567

16568+
fn mk_expected_col(name: &str) -> IndexColumn {
16569+
IndexColumn {
16570+
column: OrderByExpr {
16571+
expr: Expr::Identifier(name.into()),
16572+
options: OrderByOptions {
16573+
asc: None,
16574+
nulls_first: None,
16575+
},
16576+
with_fill: None,
16577+
},
16578+
operator_class: None,
16579+
}
16580+
}
16581+
1656216582
let dialect =
1656316583
TestedDialects::new(vec![Box::new(GenericDialect {}), Box::new(MySqlDialect {})]);
1656416584

@@ -16569,7 +16589,7 @@ mod tests {
1656916589
display_as_key: false,
1657016590
name: None,
1657116591
index_type: None,
16572-
columns: vec![Ident::new("c1")],
16592+
columns: vec![mk_expected_col("c1")],
1657316593
}
1657416594
);
1657516595

@@ -16580,7 +16600,7 @@ mod tests {
1658016600
display_as_key: true,
1658116601
name: None,
1658216602
index_type: None,
16583-
columns: vec![Ident::new("c1")],
16603+
columns: vec![mk_expected_col("c1")],
1658416604
}
1658516605
);
1658616606

@@ -16591,7 +16611,7 @@ mod tests {
1659116611
display_as_key: false,
1659216612
name: Some(Ident::with_quote('\'', "index")),
1659316613
index_type: None,
16594-
columns: vec![Ident::new("c1"), Ident::new("c2")],
16614+
columns: vec![mk_expected_col("c1"), mk_expected_col("c2")],
1659516615
}
1659616616
);
1659716617

@@ -16602,7 +16622,7 @@ mod tests {
1660216622
display_as_key: false,
1660316623
name: None,
1660416624
index_type: Some(IndexType::BTree),
16605-
columns: vec![Ident::new("c1")],
16625+
columns: vec![mk_expected_col("c1")],
1660616626
}
1660716627
);
1660816628

@@ -16613,7 +16633,7 @@ mod tests {
1661316633
display_as_key: false,
1661416634
name: None,
1661516635
index_type: Some(IndexType::Hash),
16616-
columns: vec![Ident::new("c1")],
16636+
columns: vec![mk_expected_col("c1")],
1661716637
}
1661816638
);
1661916639

@@ -16624,7 +16644,7 @@ mod tests {
1662416644
display_as_key: false,
1662516645
name: Some(Ident::new("idx_name")),
1662616646
index_type: Some(IndexType::BTree),
16627-
columns: vec![Ident::new("c1")],
16647+
columns: vec![mk_expected_col("c1")],
1662816648
}
1662916649
);
1663016650

@@ -16635,7 +16655,7 @@ mod tests {
1663516655
display_as_key: false,
1663616656
name: Some(Ident::new("idx_name")),
1663716657
index_type: Some(IndexType::Hash),
16638-
columns: vec![Ident::new("c1")],
16658+
columns: vec![mk_expected_col("c1")],
1663916659
}
1664016660
);
1664116661
}

src/test_utils.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,3 +448,47 @@ pub fn call(function: &str, args: impl IntoIterator<Item = Expr>) -> Expr {
448448
within_group: vec![],
449449
})
450450
}
451+
452+
/// Gets the first index column (mysql calls it a key part) of the first index found in a
453+
/// [`Statement::CreateIndex`], [`Statement::CreateTable`], or [`Statement::AlterTable`].
454+
pub fn index_column(stmt: Statement) -> Expr {
455+
match stmt {
456+
Statement::CreateIndex(CreateIndex { columns, .. }) => {
457+
columns.first().unwrap().column.expr.clone()
458+
}
459+
Statement::CreateTable(CreateTable { constraints, .. }) => {
460+
match constraints.first().unwrap() {
461+
TableConstraint::Index { columns, .. } => {
462+
columns.first().unwrap().column.expr.clone()
463+
}
464+
TableConstraint::Unique { columns, .. } => {
465+
columns.first().unwrap().column.expr.clone()
466+
}
467+
TableConstraint::PrimaryKey { columns, .. } => {
468+
columns.first().unwrap().column.expr.clone()
469+
}
470+
TableConstraint::FulltextOrSpatial { columns, .. } => {
471+
columns.first().unwrap().column.expr.clone()
472+
}
473+
_ => panic!("Expected an index, unique, primary, full text, or spatial constraint (foreign key does not support general key part expressions)"),
474+
}
475+
}
476+
Statement::AlterTable { operations, .. } => match operations.first().unwrap() {
477+
AlterTableOperation::AddConstraint(TableConstraint::Index { columns, .. }) => {
478+
columns.first().unwrap().column.expr.clone()
479+
}
480+
AlterTableOperation::AddConstraint(TableConstraint::Unique { columns, .. }) => {
481+
columns.first().unwrap().column.expr.clone()
482+
}
483+
AlterTableOperation::AddConstraint(TableConstraint::PrimaryKey { columns, .. }) => {
484+
columns.first().unwrap().column.expr.clone()
485+
}
486+
AlterTableOperation::AddConstraint(TableConstraint::FulltextOrSpatial {
487+
columns,
488+
..
489+
}) => columns.first().unwrap().column.expr.clone(),
490+
_ => panic!("Expected an index, unique, primary, full text, or spatial constraint (foreign key does not support general key part expressions)"),
491+
},
492+
_ => panic!("Expected CREATE INDEX, ALTER TABLE, or CREATE TABLE, got: {stmt:?}"),
493+
}
494+
}

0 commit comments

Comments
 (0)