Skip to content

Commit 5d63663

Browse files
authored
Use IndexColumn in all index definitions (apache#1900)
1 parent 7865de0 commit 5d63663

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
@@ -6868,9 +6868,7 @@ impl<'a> Parser<'a> {
68686868
None
68696869
};
68706870

6871-
self.expect_token(&Token::LParen)?;
6872-
let columns = self.parse_comma_separated(Parser::parse_create_index_expr)?;
6873-
self.expect_token(&Token::RParen)?;
6871+
let columns = self.parse_parenthesized_index_column_list()?;
68746872

68756873
let include = if self.parse_keyword(Keyword::INCLUDE) {
68766874
self.expect_token(&Token::LParen)?;
@@ -8070,7 +8068,7 @@ impl<'a> Parser<'a> {
80708068
let index_name = self.parse_optional_ident()?;
80718069
let index_type = self.parse_optional_using_then_index_type()?;
80728070

8073-
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
8071+
let columns = self.parse_parenthesized_index_column_list()?;
80748072
let index_options = self.parse_index_options()?;
80758073
let characteristics = self.parse_constraint_characteristics()?;
80768074
Ok(Some(TableConstraint::Unique {
@@ -8092,7 +8090,7 @@ impl<'a> Parser<'a> {
80928090
let index_name = self.parse_optional_ident()?;
80938091
let index_type = self.parse_optional_using_then_index_type()?;
80948092

8095-
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
8093+
let columns = self.parse_parenthesized_index_column_list()?;
80968094
let index_options = self.parse_index_options()?;
80978095
let characteristics = self.parse_constraint_characteristics()?;
80988096
Ok(Some(TableConstraint::PrimaryKey {
@@ -8170,7 +8168,7 @@ impl<'a> Parser<'a> {
81708168
};
81718169

81728170
let index_type = self.parse_optional_using_then_index_type()?;
8173-
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
8171+
let columns = self.parse_parenthesized_index_column_list()?;
81748172

81758173
Ok(Some(TableConstraint::Index {
81768174
display_as_key,
@@ -8199,7 +8197,7 @@ impl<'a> Parser<'a> {
81998197

82008198
let opt_index_name = self.parse_optional_ident()?;
82018199

8202-
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
8200+
let columns = self.parse_parenthesized_index_column_list()?;
82038201

82048202
Ok(Some(TableConstraint::FulltextOrSpatial {
82058203
fulltext,
@@ -10601,6 +10599,14 @@ impl<'a> Parser<'a> {
1060110599
self.parse_parenthesized_column_list_inner(optional, allow_empty, |p| p.parse_identifier())
1060210600
}
1060310601

10602+
/// Parses a parenthesized comma-separated list of index columns, which can be arbitrary
10603+
/// expressions with ordering information (and an opclass in some dialects).
10604+
fn parse_parenthesized_index_column_list(&mut self) -> Result<Vec<IndexColumn>, ParserError> {
10605+
self.parse_parenthesized_column_list_inner(Mandatory, false, |p| {
10606+
p.parse_create_index_expr()
10607+
})
10608+
}
10609+
1060410610
/// Parses a parenthesized comma-separated list of qualified, possibly quoted identifiers.
1060510611
/// For example: `(db1.sc1.tbl1.col1, db1.sc1.tbl1."col 2", ...)`
1060610612
pub fn parse_parenthesized_qualified_column_list(
@@ -16527,6 +16533,20 @@ mod tests {
1652716533
}};
1652816534
}
1652916535

16536+
fn mk_expected_col(name: &str) -> IndexColumn {
16537+
IndexColumn {
16538+
column: OrderByExpr {
16539+
expr: Expr::Identifier(name.into()),
16540+
options: OrderByOptions {
16541+
asc: None,
16542+
nulls_first: None,
16543+
},
16544+
with_fill: None,
16545+
},
16546+
operator_class: None,
16547+
}
16548+
}
16549+
1653016550
let dialect =
1653116551
TestedDialects::new(vec![Box::new(GenericDialect {}), Box::new(MySqlDialect {})]);
1653216552

@@ -16537,7 +16557,7 @@ mod tests {
1653716557
display_as_key: false,
1653816558
name: None,
1653916559
index_type: None,
16540-
columns: vec![Ident::new("c1")],
16560+
columns: vec![mk_expected_col("c1")],
1654116561
}
1654216562
);
1654316563

@@ -16548,7 +16568,7 @@ mod tests {
1654816568
display_as_key: true,
1654916569
name: None,
1655016570
index_type: None,
16551-
columns: vec![Ident::new("c1")],
16571+
columns: vec![mk_expected_col("c1")],
1655216572
}
1655316573
);
1655416574

@@ -16559,7 +16579,7 @@ mod tests {
1655916579
display_as_key: false,
1656016580
name: Some(Ident::with_quote('\'', "index")),
1656116581
index_type: None,
16562-
columns: vec![Ident::new("c1"), Ident::new("c2")],
16582+
columns: vec![mk_expected_col("c1"), mk_expected_col("c2")],
1656316583
}
1656416584
);
1656516585

@@ -16570,7 +16590,7 @@ mod tests {
1657016590
display_as_key: false,
1657116591
name: None,
1657216592
index_type: Some(IndexType::BTree),
16573-
columns: vec![Ident::new("c1")],
16593+
columns: vec![mk_expected_col("c1")],
1657416594
}
1657516595
);
1657616596

@@ -16581,7 +16601,7 @@ mod tests {
1658116601
display_as_key: false,
1658216602
name: None,
1658316603
index_type: Some(IndexType::Hash),
16584-
columns: vec![Ident::new("c1")],
16604+
columns: vec![mk_expected_col("c1")],
1658516605
}
1658616606
);
1658716607

@@ -16592,7 +16612,7 @@ mod tests {
1659216612
display_as_key: false,
1659316613
name: Some(Ident::new("idx_name")),
1659416614
index_type: Some(IndexType::BTree),
16595-
columns: vec![Ident::new("c1")],
16615+
columns: vec![mk_expected_col("c1")],
1659616616
}
1659716617
);
1659816618

@@ -16603,7 +16623,7 @@ mod tests {
1660316623
display_as_key: false,
1660416624
name: Some(Ident::new("idx_name")),
1660516625
index_type: Some(IndexType::Hash),
16606-
columns: vec![Ident::new("c1")],
16626+
columns: vec![mk_expected_col("c1")],
1660716627
}
1660816628
);
1660916629
}

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)