@@ -244,7 +244,7 @@ class ::TestComment < ActiveRecord::Base
244244 class ::TestPost < ActiveRecord ::Base
245245 has_many :test_comments
246246 end
247- @ids = ( 1 ..1010 ) . to_a
247+ @ids = ( 1 ..2010 ) . to_a
248248 TestPost . transaction do
249249 @ids . each do |id |
250250 TestPost . create! ( id : id , title : "Title #{ id } " )
@@ -272,6 +272,38 @@ class ::TestPost < ActiveRecord::Base
272272 posts = TestPost . where ( id : [ *@ids , nil ] ) . to_a
273273 expect ( posts . size ) . to eq ( @ids . size )
274274 end
275+
276+ # some frameworks like baby_squeel construct Arel objects directly
277+ it "should allow more than 1000 items using Arel::Nodes::In" do
278+ table = TestPost . arel_table
279+ in_node = Arel ::Nodes ::In . new ( table [ :id ] , @ids )
280+ query = table . where ( in_node ) . project ( Arel . star )
281+
282+ sql = query . to_sql
283+ posts = TestPost . connection . select_all ( sql ) . to_a
284+ expect ( posts . size ) . to eq ( @ids . size )
285+
286+ # SQL contains multiple IN clauses (split due to 1000 limit)
287+ expect ( sql . scan ( /IN \( / ) . size ) . to be > 1
288+ end
289+
290+ it "should allow more than 1000 items using Arel::Nodes::NotIn" do
291+ ids = @ids . dup
292+ non_not_in = ids . pop
293+
294+ table = TestPost . arel_table
295+ not_in_node = Arel ::Nodes ::NotIn . new ( table [ :id ] , ids )
296+ query = table . where ( not_in_node ) . project ( Arel . star )
297+
298+ sql = query . to_sql
299+ posts = TestPost . connection . select_all ( sql ) . to_a
300+
301+ expect ( posts . size ) . to eq ( 1 )
302+ expect ( posts . first [ "id" ] ) . to eq ( non_not_in )
303+
304+ # SQL contains multiple NOT IN clauses (split due to 1000 limit)
305+ expect ( sql . scan ( /NOT IN \( / ) . size ) . to be > 1
306+ end
275307 end
276308
277309 describe "with statement pool" do
@@ -806,10 +838,54 @@ class ::TestComment < ActiveRecord::Base
806838 ActiveRecord ::Base . clear_cache!
807839 end
808840
841+ before ( :each ) do
842+ TestPost . delete_all
843+ TestComment . delete_all
844+ end
845+
809846 it "should not raise undefined method length" do
810847 post = TestPost . create!
811848 post . test_comments << TestComment . create!
812849 expect ( TestComment . where ( test_post_id : TestPost . select ( :id ) ) . size ) . to eq ( 1 )
813850 end
851+
852+ it "should handle IN with subquery using Arel::Nodes::In" do
853+ post = TestPost . create!
854+ post . test_comments << TestComment . create!
855+
856+ table = TestComment . arel_table
857+ subquery = TestPost . select ( :id ) . arel
858+ in_node = Arel ::Nodes ::In . new ( table [ :test_post_id ] , subquery )
859+ query = table . where ( in_node ) . project ( Arel . star )
860+
861+ sql = query . to_sql
862+ comments = TestComment . connection . select_all ( sql ) . to_a
863+ expect ( comments . size ) . to eq ( 1 )
864+
865+ # SQL should contain IN with subquery, not split into multiple IN clauses
866+ expect ( sql ) . to match ( /IN \( +SELECT/ )
867+ expect ( sql . scan ( /IN \( / ) . size ) . to eq ( 1 )
868+ end
869+
870+ it "should handle NOT IN with subquery using Arel::Nodes::NotIn" do
871+ post = TestPost . create!
872+ TestComment . create! ( test_post_id : post . id )
873+ orphan_comment = TestComment . create! ( test_post_id : post . id + 1 )
874+
875+ table = TestComment . arel_table
876+ subquery = TestPost . select ( :id ) . arel
877+ not_in_node = Arel ::Nodes ::NotIn . new ( table [ :test_post_id ] , subquery )
878+ query = table . where ( not_in_node ) . project ( Arel . star )
879+
880+ sql = query . to_sql
881+ comments = TestComment . connection . select_all ( sql ) . to_a
882+
883+ expect ( comments . size ) . to eq ( 1 )
884+ expect ( comments . first [ "id" ] ) . to eq ( orphan_comment . id )
885+
886+ # SQL should contain NOT IN with subquery, not split into multiple NOT IN clauses
887+ expect ( sql ) . to match ( /NOT IN \( +SELECT/ )
888+ expect ( sql . scan ( /NOT IN \( / ) . size ) . to eq ( 1 )
889+ end
814890 end
815891end
0 commit comments