Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions lib/arel/visitors/oracle_common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,21 @@ module Arel # :nodoc: all
module Visitors
module OracleCommon
private
# Oracle can't compare CLOB columns with standard SQL operators for comparison.
# We need to replace standard equality for text/binary columns to use DBMS_LOB.COMPARE function.
# Fixes ORA-00932: inconsistent datatypes: expected - got CLOB
def visit_Arel_Nodes_Equality(o, collector)
left = o.left
return super unless %i(text binary).include?(cached_column_for(left)&.type)

# https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_lob.htm#i1016668
# returns 0 when the comparison succeeds
comparator = Arel::Nodes::NamedFunction.new("DBMS_LOB.COMPARE", [left, o.right])
collector = visit comparator, collector
collector << " = 0"
collector
end

def visit_Arel_Nodes_Matches(o, collector)
if !o.case_sensitive && o.left && o.right
o.left = Arel::Nodes::NamedFunction.new("UPPER", [o.left])
Expand All @@ -12,6 +27,20 @@ def visit_Arel_Nodes_Matches(o, collector)

super o, collector
end

def cached_column_for(attr)
return unless Arel::Attributes::Attribute === attr

table = attr.relation.table_name
return unless schema_cache.columns_hash?(table)

column = attr.name.to_s
schema_cache.columns_hash(table)[column]
end

def schema_cache
@connection.schema_cache
end
Comment on lines +30 to +43
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two methods are mostly logic from arel 7.1.4 with the difference that we only obtain cached columns. Otherwise we go into troubles trying to build the cache.

end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ class Group < ActiveRecord::Base
expect(@logger.logged(:debug).last).to match(/\["table_name", "TEST_POSTS"\]/)
end

it "should not raise missing IN/OUT parameter like issue 1687 " do
it "should not raise missing IN/OUT parameter like issue 1678 " do
# "to_sql" enforces unprepared_statement including dictionary access SQLs
expect { User.joins(:group).to_sql }.not_to raise_exception
end
Expand Down
15 changes: 15 additions & 0 deletions spec/active_record/oracle_enhanced/type/raw_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,19 @@ class ::TestEmployee < ActiveRecord::Base
@employee.reload
expect(@employee.binary_data).to eq(@binary_data)
end

it "should allow equality on select" do
TestEmployee.delete_all
TestEmployee.create!(
first_name: "First",
last_name: "Last",
binary_data: @binary_data,
)
TestEmployee.create!(
first_name: "First1",
last_name: "Last1",
binary_data: @binary_data2,
)
expect(TestEmployee.where(binary_data: @binary_data)).to have_attributes(count: 1)
end
end
15 changes: 15 additions & 0 deletions spec/active_record/oracle_enhanced/type/text_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -226,4 +226,19 @@ class ::TestSerializeEmployee < ActiveRecord::Base
@employee.reload
expect(@employee.comments).to eq(length: { is: 2 })
end

it "should allow equality on select" do
search_data = "text search CLOB"
Test2Employee.create!(
first_name: "First",
last_name: "Last",
comments: search_data,
)
Test2Employee.create!(
first_name: "First1",
last_name: "Last1",
comments: "other data",
)
expect(Test2Employee.where(comments: search_data)).to have_attributes(count: 1)
end
end