Skip to content

Commit c8b3718

Browse files
committed
support LOB equality
1 parent f2561f7 commit c8b3718

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

lib/arel/visitors/oracle_common.rb

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@ module Arel # :nodoc: all
44
module Visitors
55
module OracleCommon
66
private
7+
# Oracle can't compare CLOB columns with standard SQL operators for comparison.
8+
# We need to replace standard equality for text/binary columns to use DBMS_LOB.COMPARE function.
9+
# Fixes ORA-00932: inconsistent datatypes: expected - got CLOB
10+
def visit_Arel_Nodes_Equality(o, collector)
11+
left = o.left
12+
return super unless Arel::Attributes::Attribute === left && %i(text binary).include?(column_for(left).type)
13+
14+
# https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_lob.htm#i1016668
15+
# returns 0 when the comparison succeeds
16+
comparator = Arel::Nodes::NamedFunction.new("DBMS_LOB.COMPARE", [left, o.right])
17+
collector = visit comparator, collector
18+
collector << " = 0"
19+
collector
20+
end
21+
722
def visit_Arel_Nodes_Matches(o, collector)
823
if !o.case_sensitive && o.left && o.right
924
o.left = Arel::Nodes::NamedFunction.new("UPPER", [o.left])
@@ -12,6 +27,28 @@ def visit_Arel_Nodes_Matches(o, collector)
1227

1328
super o, collector
1429
end
30+
31+
def column_for(attr)
32+
return unless attr
33+
name = attr.name.to_s
34+
table = attr.relation.table_name
35+
36+
return nil unless table_exists? table
37+
38+
column_cache(table)[name]
39+
end
40+
41+
def column_cache(table)
42+
schema_cache.columns_hash(table)
43+
end
44+
45+
def schema_cache
46+
@connection.schema_cache
47+
end
48+
49+
def table_exists?(name)
50+
schema_cache.data_source_exists?(name)
51+
end
1552
end
1653
end
1754
end

spec/active_record/oracle_enhanced/type/raw_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,18 @@ class ::TestEmployee < ActiveRecord::Base
119119
@employee.reload
120120
expect(@employee.binary_data).to eq(@binary_data)
121121
end
122+
123+
it "should allow equality on select" do
124+
TestEmployee.create!(
125+
first_name: "First",
126+
last_name: "Last",
127+
binary_data: @binary_data,
128+
)
129+
TestEmployee.create!(
130+
first_name: "First1",
131+
last_name: "Last1",
132+
binary_data: @binary_data2,
133+
)
134+
expect(TestEmployee.where(binary_data: @binary_data)).to have_attributes(count: 1)
135+
end
122136
end

spec/active_record/oracle_enhanced/type/text_spec.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,4 +226,19 @@ class ::TestSerializeEmployee < ActiveRecord::Base
226226
@employee.reload
227227
expect(@employee.comments).to eq(length: { is: 2 })
228228
end
229+
230+
it "should allow equality on select" do
231+
search_data = "text search CLOB"
232+
Test2Employee.create!(
233+
first_name: "First",
234+
last_name: "Last",
235+
comments: search_data,
236+
)
237+
Test2Employee.create!(
238+
first_name: "First1",
239+
last_name: "Last1",
240+
comments: "other data",
241+
)
242+
expect(Test2Employee.where(comments: search_data)).to have_attributes(count: 1)
243+
end
229244
end

0 commit comments

Comments
 (0)