rails / arel

A Relational Algebra
2.06k stars 390 forks source link

multiple arel conditions raise SystemStackError: stack level too deep #506

Closed kivanio closed 6 years ago

kivanio commented 6 years ago

I am trying to build a query to search using multiple conditions.

I have tried use Active Record and Areal, both result same exception: SystemStackError: stack level too deep

def search
    table = Model
    relation = table[:user_id].eq(user.id)
    params.each do |param|
      param.each do |attr, value|
        relation = relation.or(table[attr].eq(value).and(table[attr].eq(value)).and(table[attr].eq(value)))
      end
    end

    Model.where(relation)
  end

This should output a query like:

  WHERE (table.attr1 = '1' AND table.attr2 = '5' AND table.attr3 = '7') OR  (table.attr1 = '4' AND table.attr2 = '3' AND table.attr3.= '5')

It works when params has small number of hash conditions: params=[{attr1: 1, attr2: 2, attr3: 4}, {attr1: 4, attr2: 2, attr3: 8}]

However my params has much more than 1000 hash inside for a big query and it this case i got the exception: SystemStackError: stack level too deep:

/Users/kivanio/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/arel-8.0.0/lib/arel/visitors/reduce.rb:14:in `visit'
/Users/kivanio/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/arel-8.0.0/lib/arel/visitors/to_sql.rb:403:in `visit_Arel_Nodes_Grouping'
/Users/kivanio/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/arel-8.0.0/lib/arel/visitors/reduce.rb:14:in `visit'
/Users/kivanio/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/arel-8.0.0/lib/arel/visitors/to_sql.rb:620:in `visit_Arel_Nodes_Or'
/Users/kivanio/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/arel-8.0.0/lib/arel/visitors/reduce.rb:14:in `visit'

I have tried a lot of different ways to code this but I always got the same exception.

My question is if there is a limit of number of nodes/conditions or I am doing something really bad here? Is there a way to make this work?

kivanio commented 6 years ago

I solved it using DB IN:

SELECT * FROM table
WHERE (attr1, attr2, attr3) IN (('4368','00004694','00122641'));