From 4c7e50f9328aca4e294b41fce0832bf6ac4a939a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Bu=CC=88nemann?= Date: Sat, 19 Dec 2015 19:40:46 +0100 Subject: Implement CASE Conditional Expression --- test/nodes/test_case.rb | 82 +++++++++++++++++++++++++++++++++++++++ test/visitors/test_depth_first.rb | 12 ++++++ test/visitors/test_to_sql.rb | 60 ++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 test/nodes/test_case.rb (limited to 'test') diff --git a/test/nodes/test_case.rb b/test/nodes/test_case.rb new file mode 100644 index 0000000000..a813ec7e69 --- /dev/null +++ b/test/nodes/test_case.rb @@ -0,0 +1,82 @@ +require 'helper' + +module Arel + module Nodes + describe 'Case' do + describe '#initialize' do + it 'sets case expression from first argument' do + node = Case.new 'foo' + + assert_equal 'foo', node.case + end + + it 'sets default case from second argument' do + node = Case.new nil, 'bar' + + assert_equal 'bar', node.default + end + end + + describe '#clone' do + it 'clones case, conditions and default' do + foo = Nodes.build_quoted 'foo' + + node = Case.new + node.case = foo + node.conditions = [When.new(foo, foo)] + node.default = foo + + dolly = node.clone + + assert_equal dolly.case, node.case + refute_same dolly.case, node.case + + assert_equal dolly.conditions, node.conditions + refute_same dolly.conditions, node.conditions + + assert_equal dolly.default, node.default + refute_same dolly.default, node.default + end + end + + describe 'equality' do + it 'is equal with equal ivars' do + foo = Nodes.build_quoted 'foo' + one = Nodes.build_quoted 1 + zero = Nodes.build_quoted 0 + + case1 = Case.new foo + case1.conditions = [When.new(foo, one)] + case1.default = Else.new zero + + case2 = Case.new foo + case2.conditions = [When.new(foo, one)] + case2.default = Else.new zero + + array = [case1, case2] + + assert_equal 1, array.uniq.size + end + + it 'is not equal with different ivars' do + foo = Nodes.build_quoted 'foo' + bar = Nodes.build_quoted 'bar' + one = Nodes.build_quoted 1 + zero = Nodes.build_quoted 0 + + case1 = Case.new foo + case1.conditions = [When.new(foo, one)] + case1.default = Else.new zero + + case2 = Case.new foo + case2.conditions = [When.new(bar, one)] + case2.default = Else.new zero + + array = [case1, case2] + + assert_equal 2, array.uniq.size + end + end + end + end +end diff --git a/test/visitors/test_depth_first.rb b/test/visitors/test_depth_first.rb index 3356759b7d..1a72789f83 100644 --- a/test/visitors/test_depth_first.rb +++ b/test/visitors/test_depth_first.rb @@ -34,6 +34,7 @@ module Arel Arel::Nodes::UnqualifiedColumn, Arel::Nodes::Top, Arel::Nodes::Limit, + Arel::Nodes::Else, ].each do |klass| define_method("test_#{klass.name.gsub('::', '_')}") do op = klass.new(:a) @@ -118,6 +119,7 @@ module Arel Arel::Nodes::As, Arel::Nodes::DeleteStatement, Arel::Nodes::JoinSource, + Arel::Nodes::When, ].each do |klass| define_method("test_#{klass.name.gsub('::', '_')}") do binary = klass.new(:a, :b) @@ -247,6 +249,16 @@ module Arel assert_equal [:a, :b, stmt.columns, :c, stmt], @collector.calls end + def test_case + node = Arel::Nodes::Case.new + node.case = :a + node.conditions << :b + node.default = :c + + @visitor.accept node + assert_equal [:a, :b, node.conditions, :c, node], @collector.calls + end + def test_node node = Nodes::Node.new @visitor.accept node diff --git a/test/visitors/test_to_sql.rb b/test/visitors/test_to_sql.rb index 7ae5d5b3af..ea58039529 100644 --- a/test/visitors/test_to_sql.rb +++ b/test/visitors/test_to_sql.rb @@ -607,6 +607,66 @@ module Arel end end end + + describe 'Nodes::Case' do + it 'supports simple case expressions' do + node = Arel::Nodes::Case.new(@table[:name]) + .when('foo').then(1) + .else(0) + + compile(node).must_be_like %{ + CASE "users"."name" WHEN 'foo' THEN 1 ELSE 0 END + } + end + + it 'supports extended case expressions' do + node = Arel::Nodes::Case.new + .when(@table[:name].in(%w(foo bar))).then(1) + .else(0) + + compile(node).must_be_like %{ + CASE WHEN "users"."name" IN ('foo', 'bar') THEN 1 ELSE 0 END + } + end + + it 'works without default branch' do + node = Arel::Nodes::Case.new(@table[:name]) + .when('foo').then(1) + + compile(node).must_be_like %{ + CASE "users"."name" WHEN 'foo' THEN 1 END + } + end + + it 'allows chaining multiple conditions' do + node = Arel::Nodes::Case.new(@table[:name]) + .when('foo').then(1) + .when('bar').then(2) + .else(0) + + compile(node).must_be_like %{ + CASE "users"."name" WHEN 'foo' THEN 1 WHEN 'bar' THEN 2 ELSE 0 END + } + end + + it 'supports #when with two arguments and no #then' do + node = Arel::Nodes::Case.new @table[:name] + + { foo: 1, bar: 0 }.reduce(node) { |node, pair| node.when *pair } + + compile(node).must_be_like %{ + CASE "users"."name" WHEN 'foo' THEN 1 WHEN 'bar' THEN 0 END + } + end + + it 'can be chained as a predicate' do + node = @table[:name].when('foo').then('bar').else('baz') + + compile(node).must_be_like %{ + CASE "users"."name" WHEN 'foo' THEN 'bar' ELSE 'baz' END + } + end + end end end end -- cgit v1.2.3