Skip to content

Commit fd31b4e

Browse files
lewiszlwiffyioalamb
authored andcommitted
Support create index with clause (apache#1389)
Co-authored-by: Ifeanyi Ubah <[email protected]> Co-authored-by: Andrew Lamb <[email protected]>
1 parent 10d0f10 commit fd31b4e

File tree

7 files changed

+92
-0
lines changed

7 files changed

+92
-0
lines changed

src/ast/dml.rs

+5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ pub struct CreateIndex {
4545
pub if_not_exists: bool,
4646
pub include: Vec<Ident>,
4747
pub nulls_distinct: Option<bool>,
48+
/// WITH clause: <https://www.postgresql.org/docs/current/sql-createindex.html>
49+
pub with: Vec<Expr>,
4850
pub predicate: Option<Expr>,
4951
}
5052

@@ -83,6 +85,9 @@ impl Display for CreateIndex {
8385
write!(f, " NULLS NOT DISTINCT")?;
8486
}
8587
}
88+
if !self.with.is_empty() {
89+
write!(f, " WITH ({})", display_comma_separated(&self.with))?;
90+
}
8691
if let Some(predicate) = &self.predicate {
8792
write!(f, " WHERE {predicate}")?;
8893
}

src/dialect/generic.rs

+4
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,8 @@ impl Dialect for GenericDialect {
8686
fn allow_extract_single_quotes(&self) -> bool {
8787
true
8888
}
89+
90+
fn supports_create_index_with_clause(&self) -> bool {
91+
true
92+
}
8993
}

src/dialect/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,12 @@ pub trait Dialect: Debug + Any {
509509
fn allow_extract_single_quotes(&self) -> bool {
510510
false
511511
}
512+
513+
/// Does the dialect support with clause in create index statement?
514+
/// e.g. `CREATE INDEX idx ON t WITH (key = value, key2)`
515+
fn supports_create_index_with_clause(&self) -> bool {
516+
false
517+
}
512518
}
513519

514520
/// This represents the operators for which precedence must be defined

src/dialect/postgresql.rs

+4
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ impl Dialect for PostgreSqlDialect {
162162
fn allow_extract_single_quotes(&self) -> bool {
163163
true
164164
}
165+
166+
fn supports_create_index_with_clause(&self) -> bool {
167+
true
168+
}
165169
}
166170

167171
pub fn parse_comment(parser: &mut Parser) -> Result<Statement, ParserError> {

src/parser/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -5338,6 +5338,17 @@ impl<'a> Parser<'a> {
53385338
None
53395339
};
53405340

5341+
let with = if self.dialect.supports_create_index_with_clause()
5342+
&& self.parse_keyword(Keyword::WITH)
5343+
{
5344+
self.expect_token(&Token::LParen)?;
5345+
let with_params = self.parse_comma_separated(Parser::parse_expr)?;
5346+
self.expect_token(&Token::RParen)?;
5347+
with_params
5348+
} else {
5349+
Vec::new()
5350+
};
5351+
53415352
let predicate = if self.parse_keyword(Keyword::WHERE) {
53425353
Some(self.parse_expr()?)
53435354
} else {
@@ -5354,6 +5365,7 @@ impl<'a> Parser<'a> {
53545365
if_not_exists,
53555366
include,
53565367
nulls_distinct,
5368+
with,
53575369
predicate,
53585370
}))
53595371
}

tests/sqlparser_common.rs

+47
Original file line numberDiff line numberDiff line change
@@ -7555,6 +7555,7 @@ fn test_create_index_with_using_function() {
75557555
if_not_exists,
75567556
include,
75577557
nulls_distinct: None,
7558+
with,
75587559
predicate: None,
75597560
}) => {
75607561
assert_eq!("idx_name", name.to_string());
@@ -7565,6 +7566,52 @@ fn test_create_index_with_using_function() {
75657566
assert!(!concurrently);
75667567
assert!(if_not_exists);
75677568
assert!(include.is_empty());
7569+
assert!(with.is_empty());
7570+
}
7571+
_ => unreachable!(),
7572+
}
7573+
}
7574+
7575+
#[test]
7576+
fn test_create_index_with_with_clause() {
7577+
let sql = "CREATE UNIQUE INDEX title_idx ON films(title) WITH (fillfactor = 70, single_param)";
7578+
let indexed_columns = vec![OrderByExpr {
7579+
expr: Expr::Identifier(Ident::new("title")),
7580+
asc: None,
7581+
nulls_first: None,
7582+
with_fill: None,
7583+
}];
7584+
let with_parameters = vec![
7585+
Expr::BinaryOp {
7586+
left: Box::new(Expr::Identifier(Ident::new("fillfactor"))),
7587+
op: BinaryOperator::Eq,
7588+
right: Box::new(Expr::Value(number("70"))),
7589+
},
7590+
Expr::Identifier(Ident::new("single_param")),
7591+
];
7592+
let dialects = all_dialects_where(|d| d.supports_create_index_with_clause());
7593+
match dialects.verified_stmt(sql) {
7594+
Statement::CreateIndex(CreateIndex {
7595+
name: Some(name),
7596+
table_name,
7597+
using: None,
7598+
columns,
7599+
unique,
7600+
concurrently,
7601+
if_not_exists,
7602+
include,
7603+
nulls_distinct: None,
7604+
with,
7605+
predicate: None,
7606+
}) => {
7607+
pretty_assertions::assert_eq!("title_idx", name.to_string());
7608+
pretty_assertions::assert_eq!("films", table_name.to_string());
7609+
pretty_assertions::assert_eq!(indexed_columns, columns);
7610+
assert!(unique);
7611+
assert!(!concurrently);
7612+
assert!(!if_not_exists);
7613+
assert!(include.is_empty());
7614+
pretty_assertions::assert_eq!(with_parameters, with);
75687615
}
75697616
_ => unreachable!(),
75707617
}

tests/sqlparser_postgres.rs

+14
Original file line numberDiff line numberDiff line change
@@ -2251,6 +2251,7 @@ fn parse_create_index() {
22512251
if_not_exists,
22522252
nulls_distinct: None,
22532253
include,
2254+
with,
22542255
predicate: None,
22552256
}) => {
22562257
assert_eq_vec(&["my_index"], &name);
@@ -2261,6 +2262,7 @@ fn parse_create_index() {
22612262
assert!(if_not_exists);
22622263
assert_eq_vec(&["col1", "col2"], &columns);
22632264
assert!(include.is_empty());
2265+
assert!(with.is_empty());
22642266
}
22652267
_ => unreachable!(),
22662268
}
@@ -2280,6 +2282,7 @@ fn parse_create_anonymous_index() {
22802282
if_not_exists,
22812283
include,
22822284
nulls_distinct: None,
2285+
with,
22832286
predicate: None,
22842287
}) => {
22852288
assert_eq!(None, name);
@@ -2290,6 +2293,7 @@ fn parse_create_anonymous_index() {
22902293
assert!(!if_not_exists);
22912294
assert_eq_vec(&["col1", "col2"], &columns);
22922295
assert!(include.is_empty());
2296+
assert!(with.is_empty());
22932297
}
22942298
_ => unreachable!(),
22952299
}
@@ -2309,6 +2313,7 @@ fn parse_create_index_concurrently() {
23092313
if_not_exists,
23102314
include,
23112315
nulls_distinct: None,
2316+
with,
23122317
predicate: None,
23132318
}) => {
23142319
assert_eq_vec(&["my_index"], &name);
@@ -2319,6 +2324,7 @@ fn parse_create_index_concurrently() {
23192324
assert!(if_not_exists);
23202325
assert_eq_vec(&["col1", "col2"], &columns);
23212326
assert!(include.is_empty());
2327+
assert!(with.is_empty());
23222328
}
23232329
_ => unreachable!(),
23242330
}
@@ -2338,6 +2344,7 @@ fn parse_create_index_with_predicate() {
23382344
if_not_exists,
23392345
include,
23402346
nulls_distinct: None,
2347+
with,
23412348
predicate: Some(_),
23422349
}) => {
23432350
assert_eq_vec(&["my_index"], &name);
@@ -2348,6 +2355,7 @@ fn parse_create_index_with_predicate() {
23482355
assert!(if_not_exists);
23492356
assert_eq_vec(&["col1", "col2"], &columns);
23502357
assert!(include.is_empty());
2358+
assert!(with.is_empty());
23512359
}
23522360
_ => unreachable!(),
23532361
}
@@ -2367,6 +2375,7 @@ fn parse_create_index_with_include() {
23672375
if_not_exists,
23682376
include,
23692377
nulls_distinct: None,
2378+
with,
23702379
predicate: None,
23712380
}) => {
23722381
assert_eq_vec(&["my_index"], &name);
@@ -2377,6 +2386,7 @@ fn parse_create_index_with_include() {
23772386
assert!(if_not_exists);
23782387
assert_eq_vec(&["col1", "col2"], &columns);
23792388
assert_eq_vec(&["col3"], &include);
2389+
assert!(with.is_empty());
23802390
}
23812391
_ => unreachable!(),
23822392
}
@@ -2396,6 +2406,7 @@ fn parse_create_index_with_nulls_distinct() {
23962406
if_not_exists,
23972407
include,
23982408
nulls_distinct: Some(nulls_distinct),
2409+
with,
23992410
predicate: None,
24002411
}) => {
24012412
assert_eq_vec(&["my_index"], &name);
@@ -2407,6 +2418,7 @@ fn parse_create_index_with_nulls_distinct() {
24072418
assert_eq_vec(&["col1", "col2"], &columns);
24082419
assert!(include.is_empty());
24092420
assert!(!nulls_distinct);
2421+
assert!(with.is_empty());
24102422
}
24112423
_ => unreachable!(),
24122424
}
@@ -2423,6 +2435,7 @@ fn parse_create_index_with_nulls_distinct() {
24232435
if_not_exists,
24242436
include,
24252437
nulls_distinct: Some(nulls_distinct),
2438+
with,
24262439
predicate: None,
24272440
}) => {
24282441
assert_eq_vec(&["my_index"], &name);
@@ -2434,6 +2447,7 @@ fn parse_create_index_with_nulls_distinct() {
24342447
assert_eq_vec(&["col1", "col2"], &columns);
24352448
assert!(include.is_empty());
24362449
assert!(nulls_distinct);
2450+
assert!(with.is_empty());
24372451
}
24382452
_ => unreachable!(),
24392453
}

0 commit comments

Comments
 (0)