From f1bfffcb1949ca391bc39444950e3514dc848b7d Mon Sep 17 00:00:00 2001 From: Jeremy Woertink Date: Sat, 10 Feb 2024 14:07:35 -0800 Subject: [PATCH] Wrapping update queries with joins in a subquery. Fixes #827 (#998) --- spec/avram/queryable_spec.cr | 9 +++++++++ src/avram/query_builder.cr | 10 +++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/spec/avram/queryable_spec.cr b/spec/avram/queryable_spec.cr index a4eabb2be..3c690042c 100644 --- a/spec/avram/queryable_spec.cr +++ b/spec/avram/queryable_spec.cr @@ -1320,6 +1320,15 @@ describe Avram::Queryable do bucket = bucket.reload bucket.names.should eq(["Rey"]) end + + it "updates with joins" do + manager1 = ManagerFactory.create(&.name("Mr. Krabs")) + manager2 = ManagerFactory.create(&.name("Mr. Robot")) + EmployeeFactory.create(&.name("Spongebob Alderson").manager_id(manager1.id)) + Employee::BaseQuery.new.where_manager(Manager::BaseQuery.new.id(manager1.id)).update(manager_id: manager2.id) + manager1.employees!.first?.should be_nil + manager2.employees!.first.name.should eq("Spongebob Alderson") + end end describe "#delete" do diff --git a/src/avram/query_builder.cr b/src/avram/query_builder.cr index 39e746eb6..1d67e8703 100644 --- a/src/avram/query_builder.cr +++ b/src/avram/query_builder.cr @@ -66,9 +66,17 @@ class Avram::QueryBuilder clone.statement_for_update!(params, returning?) end + # Creates the SQL for updating. If any joins are present, it + # moves the WHERE clause to a subquery allowing for joins def statement_for_update!(params, return_columns returning? : Bool = true) sql = ["UPDATE #{table}", set_sql_clause(params)] - sql += sql_condition_clauses + if joins_sql.presence + sql += ["WHERE EXISTS", "(", select_sql] + sql += sql_condition_clauses + sql += [")"] + else + sql += sql_condition_clauses + end sql += ["RETURNING #{@selections}"] if returning? join_sql sql