From 311cb8bd9154938f36eecb704f2e1d3f995e136e Mon Sep 17 00:00:00 2001 From: Billy Chan Date: Mon, 6 May 2024 14:10:23 +0800 Subject: [PATCH] Postgres: allow foreign key column without unique constraint (#131) * Postgres: allow foreign key column without unique constraint * rename --- src/postgres/query/constraints/mod.rs | 16 ++++++++-- tests/live/postgres/src/main.rs | 44 +++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/postgres/query/constraints/mod.rs b/src/postgres/query/constraints/mod.rs index fdc53ad..1369762 100644 --- a/src/postgres/query/constraints/mod.rs +++ b/src/postgres/query/constraints/mod.rs @@ -188,9 +188,19 @@ impl SchemaQueryBuilder { .equals((rcsq.clone(), RefC::ConstraintName)), ) .add( - // Only join when the referenced primary key position matches position_in_unique_constraint for the foreign key column - Expr::col((Schema::KeyColumnUsage, Kcuf::PositionInUniqueConstraint)) - .equals((rcsq.clone(), Kcuf::OrdinalPosition)), + Condition::any() + .add( + // Only join when the referenced primary key position matches position_in_unique_constraint for the foreign key column + Expr::col(( + Schema::KeyColumnUsage, + Kcuf::PositionInUniqueConstraint, + )) + .equals((rcsq.clone(), Kcuf::OrdinalPosition)), + ) + .add( + // Allow foreign key column without unique constraint + Expr::col((rcsq.clone(), Kcuf::OrdinalPosition)).is_null(), + ), ), ) .and_where( diff --git a/tests/live/postgres/src/main.rs b/tests/live/postgres/src/main.rs index 60889c6..4782cf7 100644 --- a/tests/live/postgres/src/main.rs +++ b/tests/live/postgres/src/main.rs @@ -55,6 +55,8 @@ async fn main() { create_parent_table(), create_child_table(), create_db_types_table(), + create_fkey_parent_table(), + create_fkey_child_table(), ]; for tbl_create_stmt in tbl_create_stmts.iter() { @@ -62,6 +64,15 @@ async fn main() { println!("{};", sql); println!(); sqlx::query(&sql).execute(&mut *executor).await.unwrap(); + if sql.starts_with(r#"CREATE TABLE "fkey_parent_table""#) { + let sql = Index::create() + .table(Alias::new("fkey_parent_table")) + .name("IDX_fkey_parent_table_unique_u") + .col(Alias::new("u")) + .unique() + .to_string(PostgresQueryBuilder); + sqlx::query(&sql).execute(&mut *executor).await.unwrap(); + } } let schema_discovery = SchemaDiscovery::new(connection, "public"); @@ -456,3 +467,36 @@ fn create_db_types_table() -> TableCreateStatement { ) .to_owned() } + +fn create_fkey_parent_table() -> TableCreateStatement { + Table::create() + .table(Alias::new("fkey_parent_table")) + .col( + ColumnDef::new(Alias::new("id")) + .integer() + .not_null() + .auto_increment(), + ) + .col(ColumnDef::new(Alias::new("u")).integer().not_null()) + .to_owned() +} + +fn create_fkey_child_table() -> TableCreateStatement { + Table::create() + .table(Alias::new("fkey_child_table")) + .col( + ColumnDef::new(Alias::new("fk_u")) + .integer() + .not_null() + .auto_increment(), + ) + .foreign_key( + ForeignKey::create() + .name("FK_tabl2_fkey_parent_table") + .from(Alias::new("fkey_child_table"), Alias::new("fk_u")) + .to(Alias::new("fkey_parent_table"), Alias::new("u")) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), + ) + .to_owned() +}