From b25ba0e80dbd8c25c1e0d446703f913067eac53a Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Wed, 17 Jan 2024 21:50:43 +0800 Subject: [PATCH 1/2] sqlite: support discovery of composite foreign key --- src/sqlite/def/column.rs | 8 ++++---- src/sqlite/def/table.rs | 32 +++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/sqlite/def/column.rs b/src/sqlite/def/column.rs index adf45e20..da6ae80c 100644 --- a/src/sqlite/def/column.rs +++ b/src/sqlite/def/column.rs @@ -189,8 +189,8 @@ pub struct ForeignKeysInfo { pub(crate) id: i32, pub(crate) seq: i32, pub(crate) table: String, - pub(crate) from: String, - pub(crate) to: String, + pub(crate) from: Vec, + pub(crate) to: Vec, pub(crate) on_update: ForeignKeyAction, pub(crate) on_delete: ForeignKeyAction, pub(crate) r#match: MatchAction, @@ -203,8 +203,8 @@ impl From<&SqliteRow> for ForeignKeysInfo { id: row.get(0), seq: row.get(1), table: row.get(2), - from: row.get(3), - to: row.get(4), + from: vec![row.get(3)], + to: vec![row.get(4)], on_update: { let op: &str = row.get(5); op.into() diff --git a/src/sqlite/def/table.rs b/src/sqlite/def/table.rs index a6b6050e..1837f7a9 100644 --- a/src/sqlite/def/table.rs +++ b/src/sqlite/def/table.rs @@ -159,10 +159,18 @@ impl TableDef { let index_info_rows = executor.fetch_all_raw(index_query).await?; + let mut last_fk_id = None; index_info_rows.iter().for_each(|info| { - let index_info: ForeignKeysInfo = info.into(); - - self.foreign_keys.push(index_info); + let mut index_info: ForeignKeysInfo = info.into(); + let fk_id = index_info.id; + if last_fk_id == Some(fk_id) { + let last_fk = self.foreign_keys.last_mut().unwrap(); + last_fk.from.push(index_info.from.pop().unwrap()); + last_fk.to.push(index_info.to.pop().unwrap()); + } else { + self.foreign_keys.push(index_info); + } + last_fk_id = Some(fk_id); }); Ok(self) @@ -250,14 +258,16 @@ impl TableDef { }); self.foreign_keys.iter().for_each(|foreign_key| { - new_table.foreign_key( - &mut ForeignKey::create() - .from(Alias::new(&self.name), Alias::new(&foreign_key.from)) - .to(Alias::new(&foreign_key.table), Alias::new(&foreign_key.to)) - .on_delete(foreign_key.on_delete.to_seaquery_foreign_key_action()) - .on_update(foreign_key.on_update.to_seaquery_foreign_key_action()) - .to_owned(), - ); + let mut fk = ForeignKey::create(); + for from in foreign_key.from.iter() { + fk.from(Alias::new(&self.name), Alias::new(from)); + } + for to in foreign_key.to.iter() { + fk.to(Alias::new(&foreign_key.table), Alias::new(to)); + } + fk.on_delete(foreign_key.on_delete.to_seaquery_foreign_key_action()) + .on_update(foreign_key.on_update.to_seaquery_foreign_key_action()); + new_table.foreign_key(&mut fk); }); self.constraints.iter().for_each(|index| { From 82e23d87e59f4035ebff7acafb093c4e12175066 Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Wed, 17 Jan 2024 21:50:55 +0800 Subject: [PATCH 2/2] sqlite: add test cases --- tests/live/sqlite/src/main.rs | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/live/sqlite/src/main.rs b/tests/live/sqlite/src/main.rs index 22f927e8..1743b731 100644 --- a/tests/live/sqlite/src/main.rs +++ b/tests/live/sqlite/src/main.rs @@ -271,6 +271,8 @@ async fn test_002() -> DiscoveryResult<()> { create_cake_table(), create_cakes_bakers_table(), create_lineitem_table(), + create_parent_table(), + create_child_table(), ]; for tbl_create_stmt in tbl_create_stmts.iter() { @@ -516,3 +518,51 @@ fn create_cake_table() -> TableCreateStatement { ) .to_owned() } + +fn create_parent_table() -> TableCreateStatement { + Table::create() + .table(Alias::new("parent")) + .col(ColumnDef::new(Alias::new("id1")).integer().not_null()) + .col(ColumnDef::new(Alias::new("id2")).integer().not_null()) + .primary_key( + Index::create() + .primary() + .col(Alias::new("id1")) + .col(Alias::new("id2")), + ) + .to_owned() +} + +fn create_child_table() -> TableCreateStatement { + Table::create() + .table(Alias::new("child")) + .col( + ColumnDef::new(Alias::new("id")) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col( + ColumnDef::new(Alias::new("parent_id1")) + .integer() + .not_null(), + ) + .col( + ColumnDef::new(Alias::new("parent_id2")) + .integer() + .not_null(), + ) + .foreign_key( + ForeignKey::create() + .name("FK_child_parent") + .from( + Alias::new("child"), + (Alias::new("parent_id1"), Alias::new("parent_id2")), + ) + .to(Alias::new("parent"), (Alias::new("id1"), Alias::new("id2"))) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), + ) + .to_owned() +}