diff --git a/src/backend/index_builder.rs b/src/backend/index_builder.rs index 346b824de..4489096ef 100644 --- a/src/backend/index_builder.rs +++ b/src/backend/index_builder.rs @@ -29,6 +29,8 @@ pub trait IndexBuilder: QuotedBuilder { self.prepare_index_type(&create.index_type, sql); self.prepare_index_columns(&create.index.columns, sql); + + self.prepare_filter(&create.r#where, sql); } /// Translate [`IndexDropStatement`] into SQL statement. @@ -71,6 +73,10 @@ pub trait IndexBuilder: QuotedBuilder { write!(sql, ")").unwrap(); } + #[doc(hidden)] + // Write WHERE clause for partial index. This function is not available in MySQL. + fn prepare_filter(&self, _condition: &ConditionHolder, _sql: &mut SqlWriter) {} + #[doc(hidden)] /// Write index name. fn prepare_index_name(&self, name: &Option, sql: &mut SqlWriter) { diff --git a/src/backend/postgres/index.rs b/src/backend/postgres/index.rs index ff99b8aa3..eddcb796e 100644 --- a/src/backend/postgres/index.rs +++ b/src/backend/postgres/index.rs @@ -32,6 +32,8 @@ impl IndexBuilder for PostgresQueryBuilder { self.prepare_index_type(&create.index_type, sql); self.prepare_index_columns(&create.index.columns, sql); + + self.prepare_filter(&create.r#where, sql); } fn prepare_index_drop_statement(&self, drop: &IndexDropStatement, sql: &mut SqlWriter) { @@ -57,6 +59,12 @@ impl IndexBuilder for PostgresQueryBuilder { } } + fn prepare_filter(&self, condition: &ConditionHolder, sql: &mut SqlWriter) { + let mut _params: Vec = Vec::new(); + let mut _collector = |v| _params.push(v); + self.prepare_condition(condition, "WHERE", sql, &mut _collector); + } + fn prepare_index_prefix(&self, create: &IndexCreateStatement, sql: &mut SqlWriter) { if create.primary { write!(sql, "PRIMARY KEY ").unwrap(); diff --git a/src/backend/sqlite/index.rs b/src/backend/sqlite/index.rs index 04102992b..b2964d27c 100644 --- a/src/backend/sqlite/index.rs +++ b/src/backend/sqlite/index.rs @@ -29,6 +29,8 @@ impl IndexBuilder for SqliteQueryBuilder { } self.prepare_index_columns(&create.index.columns, sql); + + self.prepare_filter(&create.r#where, sql); } fn prepare_index_drop_statement(&self, drop: &IndexDropStatement, sql: &mut SqlWriter) { @@ -46,6 +48,12 @@ impl IndexBuilder for SqliteQueryBuilder { fn write_column_index_prefix(&self, _col_prefix: &Option, _sql: &mut SqlWriter) {} + fn prepare_filter(&self, condition: &ConditionHolder, sql: &mut SqlWriter) { + let mut _params: Vec = Vec::new(); + let mut _collector = |v| _params.push(v); + self.prepare_condition(condition, "WHERE", sql, &mut _collector); + } + fn prepare_index_prefix(&self, create: &IndexCreateStatement, sql: &mut SqlWriter) { if create.primary { write!(sql, "PRIMARY KEY ").unwrap(); diff --git a/src/index/create.rs b/src/index/create.rs index 9716a931c..535cd23a2 100644 --- a/src/index/create.rs +++ b/src/index/create.rs @@ -1,5 +1,7 @@ use super::common::*; +use crate::query::IntoCondition; use crate::{backend::SchemaBuilder, prepare::*, types::*, SchemaStatementBuilder}; +use crate::{ConditionHolder, ConditionalStatement}; /// Create an index for an existing table /// @@ -120,6 +122,28 @@ use crate::{backend::SchemaBuilder, prepare::*, types::*, SchemaStatementBuilder /// r#"CREATE INDEX "idx-glyph-aspect" ON "glyph" ("aspect" ASC)"# /// ); /// ``` +/// +/// Partial Index with prefix and order +/// ``` +/// use sea_query::{tests_cfg::*, *}; +/// +/// let index = Index::create() +/// .name("idx-glyph-aspect") +/// .table(Glyph::Table) +/// .col((Glyph::Aspect, 64, IndexOrder::Asc)) +/// .and_where(Expr::tbl(Glyph::Table, Glyph::Aspect).is_in(vec![3, 4])) +/// .to_owned(); +/// +/// assert_eq!( +/// index.to_string(PostgresQueryBuilder), +/// r#"CREATE INDEX "idx-glyph-aspect" ON "glyph" ("aspect" (64) ASC) WHERE "glyph"."aspect" IN ($1, $2)"# +/// ); +/// assert_eq!( +/// index.to_string(SqliteQueryBuilder), +/// r#"CREATE INDEX "idx-glyph-aspect" ON "glyph" ("aspect" ASC) WHERE "glyph"."aspect" IN (?, ?)"# +/// ); +/// ``` + #[derive(Debug, Clone)] pub struct IndexCreateStatement { pub(crate) table: Option, @@ -128,6 +152,7 @@ pub struct IndexCreateStatement { pub(crate) unique: bool, pub(crate) index_type: Option, pub(crate) if_not_exists: bool, + pub(crate) r#where: ConditionHolder, } /// Specification of a table index @@ -155,6 +180,7 @@ impl IndexCreateStatement { unique: false, index_type: None, if_not_exists: false, + r#where: ConditionHolder::new(), } } @@ -233,6 +259,7 @@ impl IndexCreateStatement { unique: self.unique, index_type: self.index_type.take(), if_not_exists: self.if_not_exists, + r#where: self.r#where.clone(), } } } @@ -250,3 +277,18 @@ impl SchemaStatementBuilder for IndexCreateStatement { sql.result() } } + +impl ConditionalStatement for IndexCreateStatement { + fn and_or_where(&mut self, condition: LogicalChainOper) -> &mut Self { + self.r#where.add_and_or(condition); + self + } + + fn cond_where(&mut self, condition: C) -> &mut Self + where + C: IntoCondition, + { + self.r#where.add_condition(condition.into_condition()); + self + } +} diff --git a/src/query/shim.rs b/src/query/shim.rs index f9d21ead9..c4b0309b6 100644 --- a/src/query/shim.rs +++ b/src/query/shim.rs @@ -12,3 +12,4 @@ impl_ordered_statement!(delete_statement_ordered, DeleteStatement); impl_conditional_statement!(select_statement_conditional, SelectStatement); impl_conditional_statement!(update_statement_conditional, UpdateStatement); impl_conditional_statement!(delete_statement_conditional, DeleteStatement); +impl_conditional_statement!(index_create_conditional, IndexCreateStatement);