aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
authorYasuo Honda <yasuo.honda@gmail.com>2019-03-13 09:38:18 +0000
committerYasuo Honda <yasuo.honda@gmail.com>2019-04-11 12:54:53 +0000
commit029d05fb4381316ccd5a698b2d285cb563e3b2cd (patch)
tree0b5df052ce3d83707ddb200ff5332254862a975f /activerecord/lib
parentc9e4c848eeeb8999b778fa1ae52185ca5537fffe (diff)
downloadrails-029d05fb4381316ccd5a698b2d285cb563e3b2cd.tar.gz
rails-029d05fb4381316ccd5a698b2d285cb563e3b2cd.tar.bz2
rails-029d05fb4381316ccd5a698b2d285cb563e3b2cd.zip
Address `ORA-01795: maximum number of expressions in a list is 1000`
* To address this error, this commit splits expressions by slices of 1000 elements. * "Oracle Database Error Messages 18c" https://docs.oracle.com/en/database/oracle/oracle-database/18/errmg/ ``` ORA-01795: maximum number of expressions in a list is 1000 Cause: Number of expressions in the query exceeded than 1000. Note that unused column/expressions are also counted Maximum number of expressions that are allowed are 1000. ``` * This commit addresses this ORA-01795 error Note: Actually addressing this error raises another "ORA-00913: too many values" Number of values Oracle database allows is 65535 regardless bind values or literal values. ```ruby $ ARCONN=oracle bin/test test/cases/bind_parameter_test.rb -n test_too_many_binds ... snip ... Error: ActiveRecord::BindParameterTest#test_too_many_binds: ActiveRecord::StatementInvalid: OCIError: ORA-01795: maximum number of expressions in a list is 1000 stmt.c:267:in oci8lib_260.so /home/yahonda/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/ruby-oci8-2.2.7/lib/oci8/cursor.rb:131:in `exec' /home/yahonda/git/oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb:142:in `exec' /home/yahonda/git/oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb:41:in `block in exec_query' /home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:676:in `block (2 levels) in log' /home/yahonda/.rbenv/versions/2.6.2/lib/ruby/2.6.0/monitor.rb:230:in `mon_synchronize' /home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:675:in `block in log' /home/yahonda/git/rails/activesupport/lib/active_support/notifications/instrumenter.rb:24:in `instrument' /home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:666:in `log' /home/yahonda/git/oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb:36:in `log' /home/yahonda/git/oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb:24:in `exec_query' /home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:484:in `select' /home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:70:in `select_all' /home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:106:in `select_all' /home/yahonda/git/rails/activerecord/lib/active_record/relation/calculations.rb:299:in `block in execute_simple_calculation' /home/yahonda/git/rails/activerecord/lib/active_record/relation.rb:755:in `skip_query_cache_if_necessary' /home/yahonda/git/rails/activerecord/lib/active_record/relation/calculations.rb:299:in `execute_simple_calculation' /home/yahonda/git/rails/activerecord/lib/active_record/relation/calculations.rb:251:in `perform_calculation' /home/yahonda/git/rails/activerecord/lib/active_record/relation/calculations.rb:141:in `calculate' /home/yahonda/git/rails/activerecord/lib/active_record/relation/calculations.rb:49:in `count' /home/yahonda/git/rails/activerecord/test/cases/bind_parameter_test.rb:113:in `test_too_many_binds' bin/test test/cases/bind_parameter_test.rb:109 .............................F ```
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/arel/visitors/oracle.rb48
-rw-r--r--activerecord/lib/arel/visitors/oracle12.rb48
2 files changed, 96 insertions, 0 deletions
diff --git a/activerecord/lib/arel/visitors/oracle.rb b/activerecord/lib/arel/visitors/oracle.rb
index f96bf65ee5..500974dff5 100644
--- a/activerecord/lib/arel/visitors/oracle.rb
+++ b/activerecord/lib/arel/visitors/oracle.rb
@@ -87,6 +87,50 @@ module Arel # :nodoc: all
collector << " )"
end
+ def visit_Arel_Nodes_In(o, collector)
+ if Array === o.right && !o.right.empty?
+ o.right.delete_if { |value| unboundable?(value) }
+ end
+
+ if Array === o.right && o.right.empty?
+ collector << "1=0"
+ else
+ first = true
+ o.right.each_slice(in_clause_length) do |sliced_o_right|
+ collector << " OR " unless first
+ first = false
+
+ collector = visit o.left, collector
+ collector << " IN ("
+ visit(sliced_o_right, collector)
+ collector << ")"
+ end
+ end
+ collector
+ end
+
+ def visit_Arel_Nodes_NotIn(o, collector)
+ if Array === o.right && !o.right.empty?
+ o.right.delete_if { |value| unboundable?(value) }
+ end
+
+ if Array === o.right && o.right.empty?
+ collector << "1=1"
+ else
+ first = true
+ o.right.each_slice(in_clause_length) do |sliced_o_right|
+ collector << " AND " unless first
+ first = false
+
+ collector = visit o.left, collector
+ collector << " NOT IN ("
+ visit(sliced_o_right, collector)
+ collector << ")"
+ end
+ end
+ collector
+ end
+
def visit_Arel_Nodes_UpdateStatement(o, collector)
# Oracle does not allow ORDER BY/LIMIT in UPDATEs.
if o.orders.any? && o.limit.nil?
@@ -154,6 +198,10 @@ module Arel # :nodoc: all
collector = visit [o.left, o.right, 0, 1], collector
collector << ")"
end
+
+ def in_clause_length
+ 1000
+ end
end
end
end
diff --git a/activerecord/lib/arel/visitors/oracle12.rb b/activerecord/lib/arel/visitors/oracle12.rb
index 9a7fe4d626..8e0f07fca9 100644
--- a/activerecord/lib/arel/visitors/oracle12.rb
+++ b/activerecord/lib/arel/visitors/oracle12.rb
@@ -41,6 +41,50 @@ module Arel # :nodoc: all
collector << " )"
end
+ def visit_Arel_Nodes_In(o, collector)
+ if Array === o.right && !o.right.empty?
+ o.right.delete_if { |value| unboundable?(value) }
+ end
+
+ if Array === o.right && o.right.empty?
+ collector << "1=0"
+ else
+ first = true
+ o.right.each_slice(in_clause_length) do |sliced_o_right|
+ collector << " OR " unless first
+ first = false
+
+ collector = visit o.left, collector
+ collector << " IN ("
+ visit(sliced_o_right, collector)
+ collector << ")"
+ end
+ end
+ collector
+ end
+
+ def visit_Arel_Nodes_NotIn(o, collector)
+ if Array === o.right && !o.right.empty?
+ o.right.delete_if { |value| unboundable?(value) }
+ end
+
+ if Array === o.right && o.right.empty?
+ collector << "1=1"
+ else
+ first = true
+ o.right.each_slice(in_clause_length) do |sliced_o_right|
+ collector << " AND " unless first
+ first = false
+
+ collector = visit o.left, collector
+ collector << " NOT IN ("
+ visit(sliced_o_right, collector)
+ collector << ")"
+ end
+ end
+ collector
+ end
+
def visit_Arel_Nodes_UpdateStatement(o, collector)
# Oracle does not allow ORDER BY/LIMIT in UPDATEs.
if o.orders.any? && o.limit.nil?
@@ -62,6 +106,10 @@ module Arel # :nodoc: all
collector = visit [o.left, o.right, 0, 1], collector
collector << ")"
end
+
+ def in_clause_length
+ 1000
+ end
end
end
end