Allow for creation of indexes for PostgeSQL and SQLite (#593)
* Allow for creation of indexes for PostgeSQL and SQLite PostgreSQL and SQLite do not allow creation of general indexes within a `CREATE TABLE` statement, so a method is required to generate `CREATE INDEX` statements for these. `create_table_from_entity` avoids creating invalid statements for non-MySQL backends, forcing uses to explicitly run `create_index_from_entity`. Ideally creating indexes would be removed from `create_table_from_entity` entirely, but this would introduce a breaking change for MySQL use. * Remove index creation from create_table_from_entity Use `create_index_from_entity` for all index creation for consistency across all backends. This is a backwards incompatible change, affecting those using MySQL backend when creating the schema only. * Revert change to join_8 test after migration to new indexes entity
This commit is contained in:
parent
fe1f763feb
commit
a09790ef81
@ -5,6 +5,7 @@ use crate::{
|
||||
use sea_query::{
|
||||
extension::postgres::{Type, TypeCreateStatement},
|
||||
Alias, ColumnDef, ForeignKeyCreateStatement, Iden, Index, TableCreateStatement,
|
||||
IndexCreateStatement,
|
||||
};
|
||||
|
||||
impl Schema {
|
||||
@ -24,13 +25,22 @@ impl Schema {
|
||||
create_enum_from_entity(entity, self.backend)
|
||||
}
|
||||
|
||||
/// Creates a table from an Entity. See [TableCreateStatement] for more details
|
||||
/// Creates a table from an Entity. See [TableCreateStatement] for more details.
|
||||
pub fn create_table_from_entity<E>(&self, entity: E) -> TableCreateStatement
|
||||
where
|
||||
E: EntityTrait,
|
||||
{
|
||||
create_table_from_entity(entity, self.backend)
|
||||
}
|
||||
|
||||
/// Creates the indexes from an Entity, returning an empty Vec if there are none
|
||||
/// to create. See [IndexCreateStatement] for more details
|
||||
pub fn create_index_from_entity<E>(&self, entity: E) -> Vec<IndexCreateStatement>
|
||||
where
|
||||
E: EntityTrait,
|
||||
{
|
||||
create_index_from_entity(entity, self.backend)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn create_enum_from_active_enum<A>(backend: DbBackend) -> TypeCreateStatement
|
||||
@ -77,6 +87,31 @@ where
|
||||
vec
|
||||
}
|
||||
|
||||
pub(crate) fn create_index_from_entity<E>(entity: E, _backend: DbBackend) -> Vec<IndexCreateStatement>
|
||||
where
|
||||
E: EntityTrait,
|
||||
{
|
||||
let mut vec = Vec::new();
|
||||
for column in E::Column::iter() {
|
||||
let column_def = column.def();
|
||||
if !column_def.indexed {
|
||||
continue;
|
||||
}
|
||||
let stmt = Index::create()
|
||||
.name(&format!(
|
||||
"idx-{}-{}",
|
||||
entity.to_string(),
|
||||
column.to_string()
|
||||
))
|
||||
.table(entity)
|
||||
.col(column)
|
||||
.to_owned();
|
||||
vec.push(stmt)
|
||||
}
|
||||
vec
|
||||
}
|
||||
|
||||
|
||||
pub(crate) fn create_table_from_entity<E>(entity: E, backend: DbBackend) -> TableCreateStatement
|
||||
where
|
||||
E: EntityTrait,
|
||||
@ -116,18 +151,6 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
if orm_column_def.indexed {
|
||||
stmt.index(
|
||||
Index::create()
|
||||
.name(&format!(
|
||||
"idx-{}-{}",
|
||||
entity.to_string(),
|
||||
column.to_string()
|
||||
))
|
||||
.table(entity)
|
||||
.col(column),
|
||||
);
|
||||
}
|
||||
stmt.col(&mut column_def);
|
||||
}
|
||||
|
||||
@ -206,12 +229,12 @@ mod tests {
|
||||
let schema = Schema::new(builder);
|
||||
assert_eq!(
|
||||
builder.build(&schema.create_table_from_entity(CakeFillingPrice)),
|
||||
builder.build(&get_stmt().table(CakeFillingPrice.table_ref()).to_owned())
|
||||
builder.build(&get_cake_filling_price_stmt().table(CakeFillingPrice.table_ref()).to_owned())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_stmt() -> TableCreateStatement {
|
||||
fn get_cake_filling_price_stmt() -> TableCreateStatement {
|
||||
Table::create()
|
||||
.col(
|
||||
ColumnDef::new(cake_filling_price::Column::CakeId)
|
||||
@ -247,4 +270,73 @@ mod tests {
|
||||
)
|
||||
.to_owned()
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_create_index_from_entity_table_ref() {
|
||||
for builder in [DbBackend::MySql, DbBackend::Postgres, DbBackend::Sqlite] {
|
||||
let schema = Schema::new(builder);
|
||||
|
||||
assert_eq!(
|
||||
builder.build(&schema.create_table_from_entity(indexes::Entity)),
|
||||
builder.build(&get_indexes_stmt().table(indexes::Entity.table_ref()).to_owned())
|
||||
);
|
||||
|
||||
|
||||
let stmts = schema.create_index_from_entity(indexes::Entity);
|
||||
assert_eq!(stmts.len(), 2);
|
||||
|
||||
|
||||
let idx: IndexCreateStatement = Index::create()
|
||||
.name("idx-indexes-index1_attr")
|
||||
.table(indexes::Entity)
|
||||
.col(indexes::Column::Index1Attr)
|
||||
.to_owned();
|
||||
assert_eq!(
|
||||
builder.build(&stmts[0]),
|
||||
builder.build(&idx)
|
||||
);
|
||||
|
||||
let idx: IndexCreateStatement = Index::create()
|
||||
.name("idx-indexes-index2_attr")
|
||||
.table(indexes::Entity)
|
||||
.col(indexes::Column::Index2Attr)
|
||||
.to_owned();
|
||||
assert_eq!(
|
||||
builder.build(&stmts[1]),
|
||||
builder.build(&idx)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn get_indexes_stmt() -> TableCreateStatement {
|
||||
Table::create()
|
||||
.col(
|
||||
ColumnDef::new(indexes::Column::IndexesId)
|
||||
.integer()
|
||||
.not_null()
|
||||
.auto_increment()
|
||||
.primary_key(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(indexes::Column::UniqueAttr)
|
||||
.integer()
|
||||
.not_null()
|
||||
.unique_key(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(indexes::Column::Index1Attr)
|
||||
.integer()
|
||||
.not_null(),
|
||||
)
|
||||
.col(
|
||||
ColumnDef::new(indexes::Column::Index2Attr)
|
||||
.integer()
|
||||
.not_null()
|
||||
.unique_key(),
|
||||
)
|
||||
.to_owned()
|
||||
}
|
||||
|
||||
}
|
||||
|
67
src/tests_cfg/indexes.rs
Normal file
67
src/tests_cfg/indexes.rs
Normal file
@ -0,0 +1,67 @@
|
||||
//! An entity definition for testing table index creation.
|
||||
use crate as sea_orm;
|
||||
use crate::entity::prelude::*;
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug, DeriveEntity)]
|
||||
pub struct Entity;
|
||||
|
||||
impl EntityName for Entity {
|
||||
fn schema_name(&self) -> Option<&str> {
|
||||
Some("public")
|
||||
}
|
||||
|
||||
fn table_name(&self) -> &str {
|
||||
"indexes"
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
|
||||
pub struct Model {
|
||||
pub indexes_id: i32,
|
||||
pub unique_attr: i32,
|
||||
pub index1_attr: i32,
|
||||
pub index2_attr: i32,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
|
||||
pub enum Column {
|
||||
IndexesId,
|
||||
UniqueAttr,
|
||||
Index1Attr,
|
||||
Index2Attr,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)]
|
||||
pub enum PrimaryKey {
|
||||
IndexesId,
|
||||
}
|
||||
|
||||
impl PrimaryKeyTrait for PrimaryKey {
|
||||
type ValueType = i32;
|
||||
|
||||
fn auto_increment() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||
pub enum Relation { }
|
||||
|
||||
impl ColumnTrait for Column {
|
||||
type EntityName = Entity;
|
||||
|
||||
fn def(&self) -> ColumnDef {
|
||||
match self {
|
||||
Self::IndexesId => ColumnType::Integer.def(),
|
||||
Self::UniqueAttr => ColumnType::Integer.def().unique(),
|
||||
Self::Index1Attr => ColumnType::Integer.def().indexed(),
|
||||
Self::Index2Attr => ColumnType::Integer.def().indexed().unique(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RelationTrait for Relation {
|
||||
fn def(&self) -> RelationDef { panic!() }
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
@ -9,6 +9,7 @@ pub mod filling;
|
||||
pub mod fruit;
|
||||
pub mod rust_keyword;
|
||||
pub mod vendor;
|
||||
pub mod indexes;
|
||||
|
||||
pub use cake::Entity as Cake;
|
||||
pub use cake_expanded::Entity as CakeExpanded;
|
||||
|
Loading…
x
Reference in New Issue
Block a user