diff options
author | Matthew Draper <matthew@trebex.net> | 2014-09-26 08:21:01 +0930 |
---|---|---|
committer | Matthew Draper <matthew@trebex.net> | 2014-09-26 08:21:01 +0930 |
commit | cdae8216f582e035370b84edd236af7d22702e75 (patch) | |
tree | 6f607b2c312db046a488629f39bd8755b4cbc5c9 | |
parent | b57a11cb8abfca345f63084ce841c6f412c1156e (diff) | |
parent | fef9ce493ec3eab3cf120550abd0257f89eaddf7 (diff) | |
download | rails-cdae8216f582e035370b84edd236af7d22702e75.tar.gz rails-cdae8216f582e035370b84edd236af7d22702e75.tar.bz2 rails-cdae8216f582e035370b84edd236af7d22702e75.zip |
Merge pull request #318 from tamird/match-escape
{Matches,DoesNotMatch} support the ESCAPE clause
-rw-r--r-- | lib/arel/nodes.rb | 1 | ||||
-rw-r--r-- | lib/arel/nodes/binary.rb | 2 | ||||
-rw-r--r-- | lib/arel/nodes/matches.rb | 14 | ||||
-rw-r--r-- | lib/arel/predications.rb | 33 | ||||
-rw-r--r-- | lib/arel/visitors/to_sql.rb | 16 | ||||
-rw-r--r-- | test/visitors/test_to_sql.rb | 14 |
6 files changed, 60 insertions, 20 deletions
diff --git a/lib/arel/nodes.rb b/lib/arel/nodes.rb index c6bde8c3cc..ccccd471e2 100644 --- a/lib/arel/nodes.rb +++ b/lib/arel/nodes.rb @@ -28,6 +28,7 @@ require 'arel/nodes/delete_statement' require 'arel/nodes/table_alias' require 'arel/nodes/infix_operation' require 'arel/nodes/over' +require 'arel/nodes/matches' # nary require 'arel/nodes/and' diff --git a/lib/arel/nodes/binary.rb b/lib/arel/nodes/binary.rb index 939684957f..e35d2fd2e7 100644 --- a/lib/arel/nodes/binary.rb +++ b/lib/arel/nodes/binary.rb @@ -31,13 +31,11 @@ module Arel As Assignment Between - DoesNotMatch GreaterThan GreaterThanOrEqual Join LessThan LessThanOrEqual - Matches NotEqual NotIn NotRegexp diff --git a/lib/arel/nodes/matches.rb b/lib/arel/nodes/matches.rb new file mode 100644 index 0000000000..583fb97c9b --- /dev/null +++ b/lib/arel/nodes/matches.rb @@ -0,0 +1,14 @@ +module Arel + module Nodes + class Matches < Binary + attr_reader :escape + + def initialize(left, right, escape = nil) + super(left, right) + @escape = escape && Nodes.build_quoted(escape) + end + end + + class DoesNotMatch < Matches; end + end +end diff --git a/lib/arel/predications.rb b/lib/arel/predications.rb index 1941383068..3050526a43 100644 --- a/lib/arel/predications.rb +++ b/lib/arel/predications.rb @@ -100,28 +100,28 @@ module Arel grouping_all :not_in, others end - def matches other - Nodes::Matches.new self, Nodes.build_quoted(other, self) + def matches other, escape = nil + Nodes::Matches.new self, Nodes.build_quoted(other, self), escape end - def matches_any others - grouping_any :matches, others + def matches_any others, escape = nil + grouping_any :matches, others, escape end - def matches_all others - grouping_all :matches, others + def matches_all others, escape = nil + grouping_all :matches, others, escape end - def does_not_match other - Nodes::DoesNotMatch.new self, Nodes.build_quoted(other, self) + def does_not_match other, escape = nil + Nodes::DoesNotMatch.new self, Nodes.build_quoted(other, self), escape end - def does_not_match_any others - grouping_any :does_not_match, others + def does_not_match_any others, escape = nil + grouping_any :does_not_match, others, escape end - def does_not_match_all others - grouping_all :does_not_match, others + def does_not_match_all others, escape = nil + grouping_all :does_not_match, others, escape end def gteq right @@ -174,15 +174,16 @@ module Arel private - def grouping_any method_id, others - nodes = others.map {|expr| send(method_id, expr)} + def grouping_any method_id, others, *extras + nodes = others.map {|expr| send(method_id, expr, *extras)} Nodes::Grouping.new nodes.inject { |memo,node| Nodes::Or.new(memo, node) } end - def grouping_all method_id, others - Nodes::Grouping.new Nodes::And.new(others.map {|expr| send(method_id, expr)}) + def grouping_all method_id, others, *extras + nodes = others.map {|expr| send(method_id, expr, *extras)} + Nodes::Grouping.new Nodes::And.new(nodes) end end end diff --git a/lib/arel/visitors/to_sql.rb b/lib/arel/visitors/to_sql.rb index 7bef8feded..7fa3322148 100644 --- a/lib/arel/visitors/to_sql.rb +++ b/lib/arel/visitors/to_sql.rb @@ -539,13 +539,25 @@ module Arel def visit_Arel_Nodes_Matches o, collector collector = visit o.left, collector collector << " LIKE " - visit o.right, collector + collector = visit o.right, collector + if o.escape + collector << ' ESCAPE ' + visit o.escape, collector + else + collector + end end def visit_Arel_Nodes_DoesNotMatch o, collector collector = visit o.left, collector collector << " NOT LIKE " - visit o.right, collector + collector = visit o.right, collector + if o.escape + collector << ' ESCAPE ' + visit o.escape, collector + else + collector + end end def visit_Arel_Nodes_JoinSource o, collector diff --git a/test/visitors/test_to_sql.rb b/test/visitors/test_to_sql.rb index 195566902b..abd8cfe356 100644 --- a/test/visitors/test_to_sql.rb +++ b/test/visitors/test_to_sql.rb @@ -312,6 +312,13 @@ module Arel } end + it "can handle ESCAPE" do + node = @table[:name].matches('foo!%', '!') + compile(node).must_be_like %{ + "users"."name" LIKE 'foo!%' ESCAPE '!' + } + end + it 'can handle subqueries' do subquery = @table.project(:id).where(@table[:name].matches('foo%')) node = @attr.in subquery @@ -329,6 +336,13 @@ module Arel } end + it "can handle ESCAPE" do + node = @table[:name].does_not_match('foo!%', '!') + compile(node).must_be_like %{ + "users"."name" NOT LIKE 'foo!%' ESCAPE '!' + } + end + it 'can handle subqueries' do subquery = @table.project(:id).where(@table[:name].does_not_match('foo%')) node = @attr.in subquery |