arel_extensions 2.0.0 → 2.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -4
  3. data/.travis.yml +59 -91
  4. data/Gemfile +14 -19
  5. data/README.md +17 -12
  6. data/Rakefile +38 -27
  7. data/appveyor.yml +1 -1
  8. data/arel_extensions.gemspec +2 -2
  9. data/functions.html +3 -3
  10. data/gemfiles/rails4.gemfile +1 -1
  11. data/gemfiles/rails6.gemfile +30 -0
  12. data/gemspec_v2/arel_extensions-v2.gemspec +28 -0
  13. data/generate_gems.sh +14 -0
  14. data/init/mssql.sql +4 -4
  15. data/init/mysql.sql +38 -38
  16. data/init/postgresql.sql +21 -21
  17. data/lib/arel_extensions.rb +63 -19
  18. data/lib/arel_extensions/attributes.rb +0 -1
  19. data/lib/arel_extensions/boolean_functions.rb +38 -13
  20. data/lib/arel_extensions/common_sql_functions.rb +5 -4
  21. data/lib/arel_extensions/comparators.rb +4 -2
  22. data/lib/arel_extensions/insert_manager.rb +15 -13
  23. data/lib/arel_extensions/math.rb +3 -3
  24. data/lib/arel_extensions/math_functions.rb +10 -5
  25. data/lib/arel_extensions/nodes.rb +1 -1
  26. data/lib/arel_extensions/nodes/abs.rb +0 -0
  27. data/lib/arel_extensions/nodes/aggregate_function.rb +14 -0
  28. data/lib/arel_extensions/nodes/case.rb +8 -4
  29. data/lib/arel_extensions/nodes/ceil.rb +0 -0
  30. data/lib/arel_extensions/nodes/coalesce.rb +2 -2
  31. data/lib/arel_extensions/nodes/collate.rb +1 -1
  32. data/lib/arel_extensions/nodes/concat.rb +6 -13
  33. data/lib/arel_extensions/nodes/date_diff.rb +3 -5
  34. data/lib/arel_extensions/nodes/duration.rb +0 -2
  35. data/lib/arel_extensions/nodes/find_in_set.rb +0 -0
  36. data/lib/arel_extensions/nodes/floor.rb +0 -0
  37. data/lib/arel_extensions/nodes/format.rb +8 -8
  38. data/lib/arel_extensions/nodes/formatted_number.rb +23 -23
  39. data/lib/arel_extensions/nodes/function.rb +2 -0
  40. data/lib/arel_extensions/nodes/is_null.rb +0 -0
  41. data/lib/arel_extensions/nodes/json.rb +28 -30
  42. data/lib/arel_extensions/nodes/length.rb +0 -0
  43. data/lib/arel_extensions/nodes/locate.rb +0 -0
  44. data/lib/arel_extensions/nodes/matches.rb +4 -4
  45. data/lib/arel_extensions/nodes/power.rb +6 -5
  46. data/lib/arel_extensions/nodes/rand.rb +0 -0
  47. data/lib/arel_extensions/nodes/repeat.rb +2 -2
  48. data/lib/arel_extensions/nodes/replace.rb +24 -6
  49. data/lib/arel_extensions/nodes/round.rb +5 -5
  50. data/lib/arel_extensions/nodes/soundex.rb +16 -15
  51. data/lib/arel_extensions/nodes/std.rb +19 -21
  52. data/lib/arel_extensions/nodes/substring.rb +8 -15
  53. data/lib/arel_extensions/nodes/sum.rb +7 -0
  54. data/lib/arel_extensions/nodes/trim.rb +3 -3
  55. data/lib/arel_extensions/nodes/union.rb +2 -3
  56. data/lib/arel_extensions/nodes/union_all.rb +0 -1
  57. data/lib/arel_extensions/nodes/wday.rb +0 -0
  58. data/lib/arel_extensions/null_functions.rb +2 -2
  59. data/lib/arel_extensions/predications.rb +35 -33
  60. data/lib/arel_extensions/set_functions.rb +2 -2
  61. data/lib/arel_extensions/string_functions.rb +34 -12
  62. data/lib/arel_extensions/tasks.rb +5 -5
  63. data/lib/arel_extensions/version.rb +1 -1
  64. data/lib/arel_extensions/visitors.rb +1 -1
  65. data/lib/arel_extensions/visitors/ibm_db.rb +1 -1
  66. data/lib/arel_extensions/visitors/mssql.rb +14 -13
  67. data/lib/arel_extensions/visitors/mysql.rb +90 -37
  68. data/lib/arel_extensions/visitors/oracle.rb +15 -15
  69. data/lib/arel_extensions/visitors/oracle12.rb +1 -1
  70. data/lib/arel_extensions/visitors/postgresql.rb +78 -32
  71. data/lib/arel_extensions/visitors/sqlite.rb +61 -53
  72. data/lib/arel_extensions/visitors/to_sql.rb +70 -58
  73. data/test/arelx_test_helper.rb +28 -0
  74. data/test/real_db_test.rb +1 -1
  75. data/test/support/fake_record.rb +1 -1
  76. data/test/test_comparators.rb +9 -8
  77. data/test/visitors/test_bulk_insert_oracle.rb +8 -7
  78. data/test/visitors/test_bulk_insert_sqlite.rb +9 -8
  79. data/test/visitors/test_bulk_insert_to_sql.rb +8 -10
  80. data/test/visitors/test_oracle.rb +41 -40
  81. data/test/visitors/test_to_sql.rb +367 -193
  82. data/test/with_ar/all_agnostic_test.rb +68 -35
  83. data/test/with_ar/insert_agnostic_test.rb +3 -2
  84. data/test/with_ar/test_bulk_sqlite.rb +6 -5
  85. data/test/with_ar/test_math_sqlite.rb +4 -4
  86. data/test/with_ar/test_string_mysql.rb +4 -6
  87. data/test/with_ar/test_string_sqlite.rb +3 -7
  88. data/version_v1.rb +3 -0
  89. data/version_v2.rb +3 -0
  90. metadata +14 -7
  91. data/test/helper.rb +0 -18
@@ -0,0 +1,28 @@
1
+ require 'rubygems'
2
+ require 'minitest/autorun'
3
+ require 'fileutils'
4
+ require 'arel'
5
+ require 'active_record'
6
+
7
+ require 'support/fake_record'
8
+
9
+ require 'arel_extensions'
10
+ Arel::Table.engine = FakeRecord::Base.new
11
+
12
+ $arel_silence_type_casting_deprecation = true
13
+
14
+ module Minitest::Assertions
15
+ #
16
+ # Fails unless +expected and +actual are the same string, modulo extraneous spaces.
17
+ #
18
+ def assert_like(expected, actual, msg = nil)
19
+ msg ||= "Expected #{expected.inspect} and #{actual.inspect} to be alike"
20
+ assert_equal expected.gsub(/\s+/, ' ').strip, actual.gsub(/\s+/, ' ').strip
21
+ end
22
+ end
23
+
24
+ module Minitest::Expectations
25
+
26
+ infect_an_assertion :assert_like, :must_be_like
27
+
28
+ end
@@ -29,7 +29,7 @@ def setup_db
29
29
  func.result = value1.index(value2)
30
30
  end
31
31
  end
32
- @cnx.drop_table(:users) rescue nil
32
+ @cnx.drop_table(:users) rescue nil
33
33
  @cnx.create_table :users do |t|
34
34
  t.column :age, :integer
35
35
  t.column :name, :string
@@ -66,7 +66,7 @@ module FakeRecord
66
66
  end
67
67
 
68
68
  def in_clause_length
69
- 6
69
+ 10000
70
70
  end
71
71
 
72
72
  def quote thing, column = nil
@@ -1,4 +1,4 @@
1
- require 'helper'
1
+ require 'arelx_test_helper'
2
2
 
3
3
  module ArelExtensions
4
4
  module Nodes
@@ -20,26 +20,27 @@ module ArelExtensions
20
20
  end
21
21
 
22
22
  it "< is equal lt" do
23
- compile(@table[:id] < 10).must_be_like('"users"."id" < 10')
23
+ _(compile(@table[:id] < 10)).must_be_like('"users"."id" < 10')
24
24
  end
25
-
25
+
26
26
  it "<= is equal lteq" do
27
- compile(@table[:id] <= 10).must_be_like('"users"."id" <= 10')
27
+ _(compile(@table[:id] <= 10)).must_be_like('"users"."id" <= 10')
28
28
  end
29
29
 
30
30
  it "> is equal gt" do
31
- compile(@table[:id] > 10).must_be_like('"users"."id" > 10')
31
+ _(compile(@table[:id] > 10)).must_be_like('"users"."id" > 10')
32
32
  end
33
33
 
34
34
  it "< is equal gteq" do
35
- compile(@table[:id] >= 10).must_be_like('"users"."id" >= 10')
35
+ _(compile(@table[:id] >= 10)).must_be_like('"users"."id" >= 10')
36
36
  end
37
37
 
38
38
  it "should compare with dates" do
39
- compile(@table[:created_at] >= Date.new(2016, 3, 31)).must_be_like %{"users"."created_at" >= '2016-03-31'}
39
+ _(compile(@table[:created_at] >= Date.new(2016, 3, 31)))
40
+ .must_be_like %{"users"."created_at" >= '2016-03-31'}
40
41
  end
41
42
 
42
43
  end
43
44
 
44
45
  end
45
- end
46
+ end
@@ -1,4 +1,4 @@
1
- require 'helper'
1
+ require 'arelx_test_helper'
2
2
 
3
3
  module ArelExtensions
4
4
  module BulkInsertOracle
@@ -9,8 +9,8 @@ module ArelExtensions
9
9
  @table = Arel::Table.new(:users)
10
10
  @cols = ['name', 'comments', 'created_at']
11
11
  @data = [
12
- ['nom1', "sdfdsfdsfsdf", '2016-01-01'],
13
- ['nom2', "sdfdsfdsfsdf", '2016-01-01']
12
+ ['nom1', "sdfdsfdsfsdf", '2016-01-01'],
13
+ ['nom2', "sdfdsfdsfsdf", '2016-01-01']
14
14
  ]
15
15
  end
16
16
 
@@ -24,11 +24,12 @@ module ArelExtensions
24
24
 
25
25
  it "should import large set of data in Oracle" do
26
26
  insert_manager = Arel::VERSION.to_i > 6 ? Arel::InsertManager.new().into(@table) : Arel::InsertManager.new(@conn).into(@table)
27
- insert_manager.bulk_insert(@cols, @data)
28
- sql = compile(insert_manager.ast)
29
- sql.must_be_like %Q[INSERT INTO "users" ("name", "comments", "created_at") ((SELECT 'nom1', 'sdfdsfdsfsdf', '2016-01-01' FROM DUAL) UNION ALL (SELECT 'nom2', 'sdfdsfdsfsdf', '2016-01-01' FROM DUAL))]
27
+ insert_manager.bulk_insert(@cols, @data)
28
+ _(compile(insert_manager.ast))
29
+ .must_be_like %Q[INSERT INTO "users" ("name", "comments", "created_at")
30
+ ((SELECT 'nom1', 'sdfdsfdsfsdf', '2016-01-01' FROM DUAL) UNION ALL (SELECT 'nom2', 'sdfdsfdsfsdf', '2016-01-01' FROM DUAL))]
30
31
  end
31
32
 
32
- end
33
+ end
33
34
  end
34
35
  end
@@ -1,4 +1,4 @@
1
- require 'helper'
1
+ require 'arelx_test_helper'
2
2
 
3
3
  module ArelExtensions
4
4
  module BulkInsertSQLlite
@@ -11,11 +11,11 @@ module ArelExtensions
11
11
  Arel::Table.engine = @conn
12
12
  @cols = ['id', 'name', 'comments', 'created_at']
13
13
  @data = [
14
- [23, 'nom1', "sdfdsfdsfsdf", '2016-01-01'],
15
- [25, 'nom2', "sdfdsfdsfsdf", '2016-01-01']
14
+ [23, 'nom1', "sdfdsfdsfsdf", '2016-01-01'],
15
+ [25, 'nom2', "sdfdsfdsfsdf", '2016-01-01']
16
16
  ]
17
17
  end
18
-
18
+
19
19
  def compile node
20
20
  if Arel::VERSION.to_i > 5
21
21
  @visitor.accept(node, Arel::Collectors::SQLString.new).value
@@ -27,10 +27,11 @@ module ArelExtensions
27
27
  it "should import large set of data" do
28
28
  insert_manager = Arel::VERSION.to_i > 6 ? Arel::InsertManager.new().into(@table) : Arel::InsertManager.new(@conn).into(@table)
29
29
  insert_manager.bulk_insert(@cols, @data)
30
- sql = compile(insert_manager.ast)
31
- sql.must_be_like %Q[INSERT INTO "users" ("id", "name", "comments", "created_at") SELECT 23 AS 'id', 'nom1' AS 'name', 'sdfdsfdsfsdf' AS 'comments', '2016-01-01' AS 'created_at' UNION ALL SELECT 25, 'nom2', 'sdfdsfdsfsdf', '2016-01-01']
30
+ _(compile(insert_manager.ast))
31
+ .must_be_like %Q[INSERT INTO "users" ("id", "name", "comments", "created_at")
32
+ SELECT 23 AS 'id', 'nom1' AS 'name', 'sdfdsfdsfsdf' AS 'comments', '2016-01-01' AS 'created_at' UNION ALL SELECT 25, 'nom2', 'sdfdsfdsfsdf', '2016-01-01']
32
33
  end
33
34
 
34
- end
35
+ end
35
36
  end
36
- end
37
+ end
@@ -1,4 +1,4 @@
1
- require 'helper'
1
+ require 'arelx_test_helper'
2
2
 
3
3
  module ArelExtensions
4
4
  module BulkInsertToSql
@@ -10,8 +10,8 @@ module ArelExtensions
10
10
  @table = Arel::Table.new(:users)
11
11
  @cols = ['id', 'name', 'comments', 'created_at']
12
12
  @data = [
13
- [23, 'nom1', "sdfdsfdsfsdf", '2016-01-01'],
14
- [25, 'nom2', "sdfdsfdsfsdf", '2016-01-01']
13
+ [23, 'nom1', "sdfdsfdsfsdf", '2016-01-01'],
14
+ [25, 'nom2', "sdfdsfdsfsdf", '2016-01-01']
15
15
  ]
16
16
  end
17
17
 
@@ -26,12 +26,10 @@ module ArelExtensions
26
26
 
27
27
  it "should import large set of data using ToSql" do
28
28
  insert_manager = Arel::VERSION.to_i > 6 ? Arel::InsertManager.new().into(@table) : Arel::InsertManager.new(@conn).into(@table)
29
- insert_manager.bulk_insert(@cols, @data)
30
- sql = compile(insert_manager.ast)
31
- sql.must_be_like %Q[INSERT INTO "users" ("id", "name", "comments", "created_at") VALUES (23, 'nom1', 'sdfdsfdsfsdf', '2016-01-01'), (25, 'nom2', 'sdfdsfdsfsdf', '2016-01-01')]
29
+ insert_manager.bulk_insert(@cols, @data)
30
+ _(compile(insert_manager.ast))
31
+ .must_be_like %Q[INSERT INTO "users" ("id", "name", "comments", "created_at") VALUES (23, 'nom1', 'sdfdsfdsfsdf', '2016-01-01'), (25, 'nom2', 'sdfdsfdsfsdf', '2016-01-01')]
32
32
  end
33
-
34
-
35
- end
33
+ end
36
34
  end
37
- end
35
+ end
@@ -1,4 +1,4 @@
1
- require 'helper'
1
+ require 'arelx_test_helper'
2
2
 
3
3
  module ArelExtensions
4
4
  module VisitorOracle
@@ -23,85 +23,86 @@ module ArelExtensions
23
23
  # Comparators
24
24
 
25
25
  it "should accept comparators on integers" do
26
- compile(@table[:id] == 42).must_match %{"users"."id" = 42}
27
- compile(@table[:id] == @table[:id]).must_be_like %{"users"."id" = "users"."id"}
28
- compile(@table[:id] != 42).must_match %{"users"."id" != 42}
29
- compile(@table[:id] > 42).must_match %{"users"."id" > 42}
30
- compile(@table[:id] >= 42).must_match %{"users"."id" >= 42}
31
- compile(@table[:id] >= @table[:id]).must_be_like %{"users"."id" >= "users"."id"}
32
- compile(@table[:id] < 42).must_match %{"users"."id" < 42}
33
- compile(@table[:id] <= 42).must_match %{"users"."id" <= 42}
34
- compile((@table[:id] <= 42).as('new_name')).must_match %{("users"."id" <= 42) AS new_name}
26
+ _(compile(@table[:id] == 42)).must_match %{"users"."id" = 42}
27
+ _(compile(@table[:id] == @table[:id])).must_be_like %{"users"."id" = "users"."id"}
28
+ _(compile(@table[:id] != 42)).must_match %{"users"."id" != 42}
29
+ _(compile(@table[:id] > 42)).must_match %{"users"."id" > 42}
30
+ _(compile(@table[:id] >= 42)).must_match %{"users"."id" >= 42}
31
+ _(compile(@table[:id] >= @table[:id])).must_be_like %{"users"."id" >= "users"."id"}
32
+ _(compile(@table[:id] < 42)).must_match %{"users"."id" < 42}
33
+ _(compile(@table[:id] <= 42)).must_match %{"users"."id" <= 42}
34
+ _(compile((@table[:id] <= 42).as('new_name'))).must_match %{("users"."id" <= 42) AS new_name}
35
35
  end
36
36
 
37
37
  it "should accept comparators on dates" do
38
38
  c = @table[:created_at]
39
39
  u = @table[:updated_at]
40
- compile(c > @date).must_be_like %{"users"."created_at" > '2016-03-31'}
41
- compile(u >= @date).must_be_like %{"users"."updated_at" >= '2016-03-31'}
42
- compile(c < u).must_be_like %{"users"."created_at" < "users"."updated_at"}
40
+ _(compile(c > @date)).must_be_like %{"users"."created_at" > '2016-03-31'}
41
+ _(compile(u >= @date)).must_be_like %{"users"."updated_at" >= '2016-03-31'}
42
+ _(compile(c < u)).must_be_like %{"users"."created_at" < "users"."updated_at"}
43
43
  end
44
44
 
45
45
  it "should accept comparators on strings" do
46
46
  c = @table[:name]
47
- compile(c == 'test').must_be_like %{"users"."name" = 'test'}
48
- compile(c != 'test').must_be_like %{"users"."name" != 'test'}
49
- compile(c > 'test').must_be_like %{"users"."name" > 'test'}
50
- compile((c >= 'test').as('new_name')).must_be_like %{("users"."name" >= 'test') AS new_name}
51
- compile(c <= @table[:comments]).must_be_like %{"users"."name" <= "users"."comments"}
52
- compile(c =~ /\Atest\Z/).must_be_like %{REGEXP_LIKE("users"."name", '^test$')}
53
- compile(c =~ '^test$').must_be_like %{REGEXP_LIKE("users"."name", '^test$')}
54
- compile(c !~ /\Ate\Dst\Z/).must_be_like %{NOT REGEXP_LIKE("users"."name", '^te[^0-9]st$')}
55
- compile(c.imatches('%test%')).must_be_like %{LOWER("users"."name") LIKE LOWER('%test%')}
56
- compile(c.imatches_any(['%test%', 't2'])).must_be_like %{((LOWER("users"."name") LIKE LOWER('%test%')) OR (LOWER("users"."name") LIKE LOWER('t2')))}
57
- compile(c.idoes_not_match('%test%')).must_be_like %{LOWER("users"."name") NOT LIKE LOWER('%test%')}
47
+ _(compile(c == 'test')).must_be_like %{"users"."name" = 'test'}
48
+ _(compile(c != 'test')).must_be_like %{"users"."name" != 'test'}
49
+ _(compile(c > 'test')).must_be_like %{"users"."name" > 'test'}
50
+ _(compile((c >= 'test').as('new_name'))).must_be_like %{("users"."name" >= 'test') AS new_name}
51
+ _(compile(c <= @table[:comments])).must_be_like %{"users"."name" <= "users"."comments"}
52
+ _(compile(c =~ /\Atest\Z/)).must_be_like %{REGEXP_LIKE("users"."name", '^test$')}
53
+ _(compile(c =~ /\Atest\z/)).must_be_like %{REGEXP_LIKE("users"."name", '^test$')}
54
+ _(compile(c =~ '^test$')).must_be_like %{REGEXP_LIKE("users"."name", '^test$')}
55
+ _(compile(c !~ /\Ate\Dst\Z/)).must_be_like %{NOT REGEXP_LIKE("users"."name", '^te[^0-9]st$')}
56
+ _(compile(c.imatches('%test%'))).must_be_like %{LOWER("users"."name") LIKE LOWER('%test%')}
57
+ _(compile(c.imatches_any(['%test%', 't2']))).must_be_like %{((LOWER("users"."name") LIKE LOWER('%test%')) OR (LOWER("users"."name") LIKE LOWER('t2')))}
58
+ _(compile(c.idoes_not_match('%test%'))).must_be_like %{LOWER("users"."name") NOT LIKE LOWER('%test%')}
58
59
  end
59
60
 
60
61
  # Maths
61
62
  # DateDiff
62
63
  it "should diff date col and date" do
63
- compile(@table[:created_at] - Date.new(2016, 3, 31)).must_match %{"users"."created_at" - TO_DATE('2016-03-31')}
64
+ _(compile(@table[:created_at] - Date.new(2016, 3, 31))).must_match %{"users"."created_at" - TO_DATE('2016-03-31')}
64
65
  end
65
66
 
66
67
  it "should diff date col and datetime col" do
67
- compile(@table[:created_at] - @table[:updated_at]).must_match %{"users"."created_at" - "users"."updated_at"}
68
+ _(compile(@table[:created_at] - @table[:updated_at])).must_match %{"users"."created_at" - "users"."updated_at"}
68
69
  end
69
70
 
70
71
  it "should diff date col and datetime col with AS" do
71
72
  sql = compile((@table[:updated_at] - @table[:created_at]).as('new_name'))
72
73
  # sql.must_be_like %{(TO_DATE("users"."updated_at") - "users"."created_at") * 86400 AS new_name}
73
- sql.must_be_like %{("users"."updated_at" - "users"."created_at") * (CASE WHEN (TRUNC("users"."updated_at", 'DDD') = "users"."updated_at") THEN 1 ELSE 86400 END) AS new_name}
74
+ _(sql).must_be_like %{("users"."updated_at" - "users"."created_at") * (CASE WHEN (TRUNC("users"."updated_at", 'DDD') = "users"."updated_at") THEN 1 ELSE 86400 END) AS new_name}
74
75
  end
75
76
 
76
77
  it "should diff between time values" do
77
78
  d2 = Time.new(2015,6,1)
78
79
  d1 = DateTime.new(2015,6,2)
79
- sql = compile(ArelExtensions::Nodes::DateDiff.new([d1,d2]))
80
- sql.must_match("TO_DATE('2015-06-02') - TO_DATE('2015-06-01')")
80
+ _(compile(ArelExtensions::Nodes::DateDiff.new([d1,d2])))
81
+ .must_match("TO_DATE('2015-06-02') - TO_DATE('2015-06-01')")
81
82
  end
82
83
 
83
84
  it "should diff between time values and time col" do
84
85
  d1 = DateTime.new(2015,6,2)
85
- sql = compile(ArelExtensions::Nodes::DateDiff.new([d1, @table[:updated_at]]))
86
- sql.must_match %{TO_DATE('2015-06-02') - "users"."updated_at"}
86
+ _(compile(ArelExtensions::Nodes::DateDiff.new([d1, @table[:updated_at]])))
87
+ .must_match %{TO_DATE('2015-06-02') - "users"."updated_at"}
87
88
  end
88
89
 
89
90
  it "should accept operators on dates with numbers" do
90
91
  c = @table[:created_at]
91
- compile(c - 42).must_be_like %{DATE_SUB("users"."created_at", 42)}
92
- compile(c - @table[:id]).must_be_like %{DATE_SUB("users"."created_at", "users"."id")}
92
+ _(compile(c - 42)).must_be_like %{DATE_SUB("users"."created_at", 42)}
93
+ _(compile(c - @table[:id])).must_be_like %{DATE_SUB("users"."created_at", "users"."id")}
93
94
  end
94
95
 
95
96
  # Maths on sums
96
97
  it "should accept math operators on anything" do
97
98
  c = @table[:name]
98
- (c == 'test').to_sql.must_be_like %{"users"."name" = 'test'}
99
- (c != 'test').to_sql.must_be_like %{"users"."name" != 'test'}
100
- (c > 'test').to_sql.must_be_like %{"users"."name" > 'test'}
101
- compile((c >= 'test').as('new_name')).must_be_like %{("users"."name" >= 'test') AS new_name}
102
- compile(c <= @table[:comments]).must_be_like %{"users"."name" <= "users"."comments"}
103
- compile(c =~ /\Atest\Z/).must_be_like %{REGEXP_LIKE("users"."name", '^test$')}
104
- compile(c !~ /\Ate\Dst\Z/).must_be_like %{NOT REGEXP_LIKE("users"."name", '^te[^0-9]st$')}
99
+ _((c == 'test').to_sql).must_be_like %{"users"."name" = 'test'}
100
+ _((c != 'test').to_sql).must_be_like %{"users"."name" != 'test'}
101
+ _((c > 'test').to_sql).must_be_like %{"users"."name" > 'test'}
102
+ _(compile((c >= 'test').as('new_name'))).must_be_like %{("users"."name" >= 'test') AS new_name}
103
+ _(compile(c <= @table[:comments])).must_be_like %{"users"."name" <= "users"."comments"}
104
+ _(compile(c =~ /\Atest\Z/)).must_be_like %{REGEXP_LIKE("users"."name", '^test$')}
105
+ _(compile(c !~ /\Ate\Dst\Z/)).must_be_like %{NOT REGEXP_LIKE("users"."name", '^te[^0-9]st$')}
105
106
  end
106
107
 
107
108
  end
@@ -1,4 +1,4 @@
1
- require 'helper'
1
+ require 'arelx_test_helper'
2
2
  require 'set'
3
3
 
4
4
  module ArelExtensions
@@ -22,365 +22,539 @@ module ArelExtensions
22
22
  end
23
23
  end
24
24
 
25
+ describe "primitive methods" do
26
+
27
+ it "should be able to recognize equal nodes" do
28
+ c = @table[:id]
29
+ _(c == 1).must_be :eql?, (c == 1)
30
+ _((c == 1).right.hash).must_equal (c == 1).right.hash
31
+ _((c == 1).hash).must_equal (c == 1).hash
32
+
33
+ _([c == 1, c == 1].uniq).must_equal [c == 1]
34
+ end
35
+
36
+ end
37
+
25
38
  # Math Functions
26
39
  it "should not break Arel functions" do
27
- compile(@price + 42).must_be_like %{("products"."price" + 42)}
28
- compile(@table[:id] + @table[:pas_en_base])
40
+ _(compile(@price + 42)).must_be_like %{("products"."price" + 42)}
41
+ _(compile(@table[:id] + @table[:pas_en_base]))
29
42
  .must_be_like %{("users"."id" + "users"."pas_en_base")}
30
- compile(@table[:pas_en_base] + @table[:id])
43
+ _(compile(@table[:pas_en_base] + @table[:id]))
31
44
  .must_be_like %{("users"."pas_en_base" + "users"."id")}
32
- compile(@table[:id] - @table[:pas_en_base])
45
+ _(compile(@table[:id] - @table[:pas_en_base]))
33
46
  .must_be_like %{("users"."id" - "users"."pas_en_base")}
34
- compile(@table[:pas_en_base] - @table[:id])
47
+ _(compile(@table[:pas_en_base] - @table[:id]))
35
48
  .must_be_like %{("users"."pas_en_base" - "users"."id")}
36
- compile(@table[:id] * @table[:pas_en_base])
49
+ _(compile(@table[:id] * @table[:pas_en_base]))
37
50
  .must_be_like %{"users"."id" * "users"."pas_en_base"}
38
- compile(@table[:pas_en_base] * @table[:id])
51
+ _(compile(@table[:pas_en_base] * @table[:id]))
39
52
  .must_be_like %{"users"."pas_en_base" * "users"."id"}
40
53
  end
41
54
 
42
55
  it "should return right calculations on numbers" do
43
56
  #puts (@price.abs + 42).inspect
44
- compile(@price.abs + 42).must_be_like %{(ABS("products"."price") + 42)}
45
- compile(@price.ceil + 42).must_be_like %{(CEIL("products"."price") + 42)}
46
- compile(@price.floor + 42).must_be_like %{(FLOOR("products"."price") + 42)}
47
- compile(@price.log10 + 42).must_be_like %{(LOG10("products"."price") + 42)}
48
- compile(@price.power(42) + 42).must_be_like %{(POW("products"."price", 42) + 42)}
49
- compile(@price.pow(42) + 42).must_be_like %{(POW("products"."price", 42) + 42)}
50
- compile(@price.ceil + @price.floor).must_be_like %{(CEIL("products"."price") + FLOOR("products"."price"))}
51
- compile((@price.ceil + @price.floor).abs).must_be_like %{ABS((CEIL("products"."price") + FLOOR("products"."price")))}
52
- compile(@price.round + 42).must_be_like %{(ROUND("products"."price") + 42)}
53
- compile(@price.round(2) + 42).must_be_like %{(ROUND("products"."price", 2) + 42)}
54
- compile(Arel.rand + 42).must_be_like %{(RAND() + 42)}
55
- compile(@price.sum + 42).must_be_like %{(SUM("products"."price") + 42)}
56
- compile((@price + 42).sum).must_be_like %{SUM(("products"."price" + 42))}
57
- compile((@price + 42).average).must_be_like %{AVG(("products"."price" + 42))}
58
- compile((Arel.rand * 9).round + 42).must_be_like %{(ROUND(RAND() * 9) + 42)}
59
- compile((Arel.rand * @price).round(2) + @price).must_be_like %{(ROUND(RAND() * "products"."price", 2) + "products"."price")}
60
-
61
- compile(@price.std + 42).must_be_like %{(STD("products"."price") + 42)}
62
- compile(@price.variance + 42).must_be_like %{(VARIANCE("products"."price") + 42)}
63
-
64
- compile(@price.coalesce(0) - 42).must_be_like %{(COALESCE("products"."price", 0) - 42)}
65
- compile(@price.sum - 42).must_be_like %{(SUM("products"."price") - 42)}
66
- compile(@price.std - 42).must_be_like %{(STD("products"."price") - 42)}
67
- compile(@price.variance - 42).must_be_like %{(VARIANCE("products"."price") - 42)}
68
-
69
- compile(@price * 42.0).must_be_like %{"products"."price" * 42.0}
70
- compile(@price / 42.0).must_be_like %{"products"."price" / 42.0}
57
+ _(compile(@price.abs + 42)).must_be_like %{(ABS("products"."price") + 42)}
58
+ _(compile(@price.ceil + 42)).must_be_like %{(CEIL("products"."price") + 42)}
59
+ _(compile(@price.floor + 42)).must_be_like %{(FLOOR("products"."price") + 42)}
60
+ _(compile(@price.log10 + 42)).must_be_like %{(LOG10("products"."price") + 42)}
61
+ _(compile(@price.power(42) + 42)).must_be_like %{(POW("products"."price", 42) + 42)}
62
+ _(compile(@price.pow(42) + 42)).must_be_like %{(POW("products"."price", 42) + 42)}
63
+ _(compile(@price.ceil + @price.floor)).must_be_like %{(CEIL("products"."price") + FLOOR("products"."price"))}
64
+ _(compile((@price.ceil + @price.floor).abs)).must_be_like %{ABS((CEIL("products"."price") + FLOOR("products"."price")))}
65
+ _(compile(@price.round + 42)).must_be_like %{(ROUND("products"."price") + 42)}
66
+ _(compile(@price.round(2) + 42)).must_be_like %{(ROUND("products"."price", 2) + 42)}
67
+ _(compile(Arel.rand + 42)).must_be_like %{(RAND() + 42)}
68
+ _(compile(@price.sum + 42)).must_be_like %{(SUM("products"."price") + 42)}
69
+ _(compile((@price + 42).sum)).must_be_like %{SUM(("products"."price" + 42))}
70
+ _(compile((@price + 42).average)).must_be_like %{AVG(("products"."price" + 42))}
71
+ _(compile((Arel.rand * 9).round + 42)).must_be_like %{(ROUND(RAND() * 9) + 42)}
72
+ _(compile((Arel.rand * @price).round(2) + @price)).must_be_like %{(ROUND(RAND() * "products"."price", 2) + "products"."price")}
73
+
74
+ _(compile(@price.std + 42)).must_be_like %{(STD("products"."price") + 42)}
75
+ _(compile(@price.variance + 42)).must_be_like %{(VARIANCE("products"."price") + 42)}
76
+
77
+ _(compile(@price.coalesce(0) - 42)).must_be_like %{(COALESCE("products"."price", 0) - 42)}
78
+ _(compile(@price.sum - 42)).must_be_like %{(SUM("products"."price") - 42)}
79
+ _(compile(@price.std - 42)).must_be_like %{(STD("products"."price") - 42)}
80
+ _(compile(@price.variance - 42)).must_be_like %{(VARIANCE("products"."price") - 42)}
81
+
82
+ _(compile(@price * 42.0)).must_be_like %{"products"."price" * 42.0}
83
+ _(compile(@price / 42.0)).must_be_like %{"products"."price" / 42.0}
71
84
 
72
85
  fake_table = Arel::Table.new('fake_tables')
73
86
 
74
- compile(fake_table[:fake_att] - 42).must_be_like %{("fake_tables"."fake_att" - 42)}
75
- compile(fake_table[:fake_att].coalesce(0) - 42).must_be_like %{(COALESCE("fake_tables"."fake_att", 0) - 42)}
87
+ _(compile(fake_table[:fake_att] - 42)).must_be_like %{("fake_tables"."fake_att" - 42)}
88
+ _(compile(fake_table[:fake_att].coalesce(0) - 42)).must_be_like %{(COALESCE("fake_tables"."fake_att", 0) - 42)}
76
89
  end
77
90
 
78
91
  # String Functions
79
92
  it "should accept functions on strings" do
80
93
  c = @table[:name]
81
- compile(c + 'test').must_be_like %{CONCAT(\"users\".\"name\", 'test')}
82
- compile(c.length).must_be_like %{LENGTH("users"."name")}
94
+ _(compile(c + 'test')).must_be_like %{CONCAT(\"users\".\"name\", 'test')}
95
+ _(compile(c.length)).must_be_like %{LENGTH("users"."name")}
83
96
  #puts (c.length.round + 42).inspect
84
- compile(c.length.round + 42).must_be_like %{(ROUND(LENGTH("users"."name")) + 42)}
85
- compile(c.locate('test')).must_be_like %{LOCATE('test', "users"."name")}
86
- compile(c & 42).must_be_like %{FIND_IN_SET(42, "users"."name")}
87
-
88
- compile((c >= 'test').as('new_name')).must_be_like %{("users"."name" >= 'test') AS new_name}
89
- compile(c <= @table[:comments]).must_be_like %{"users"."name" <= "users"."comments"}
90
- compile(c =~ /\Atest\Z/).must_be_like %{"users"."name" REGEXP '^test$'}
91
- compile(c !~ /\Ate\Dst\Z/).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
92
- compile(c.imatches('%test%')).must_be_like %{"users"."name" ILIKE '%test%'}
93
- compile(c.imatches_any(['%test%', 't2'])).must_be_like %{(("users"."name" ILIKE '%test%') OR ("users"."name" ILIKE 't2'))}
94
- compile(c.idoes_not_match('%test%')).must_be_like %{"users"."name" NOT ILIKE '%test%'}
95
-
96
- compile(c.substring(1)).must_be_like %{SUBSTRING("users"."name", 1)}
97
- compile(c + '0').must_be_like %{CONCAT("users"."name", '0')}
98
- compile(c.substring(1) + '0').must_be_like %{CONCAT(SUBSTRING("users"."name", 1), '0')}
99
- compile(c.substring(1) + c.substring(2)).must_be_like %{CONCAT(SUBSTRING("users"."name", 1), SUBSTRING("users"."name", 2))}
100
- compile(c.concat(c).concat(c)).must_be_like %{CONCAT("users"."name", "users"."name", "users"."name")}
101
- compile(c + c + c).must_be_like %{CONCAT("users"."name", "users"."name", "users"."name")}
97
+ _(compile(c.length.round + 42)).must_be_like %{(ROUND(LENGTH("users"."name")) + 42)}
98
+ _(compile(c.locate('test'))).must_be_like %{LOCATE('test', "users"."name")}
99
+ _(compile(c & 42)).must_be_like %{FIND_IN_SET(42, "users"."name")}
100
+
101
+ _(compile((c >= 'test').as('new_name'))).must_be_like %{("users"."name" >= 'test') AS new_name}
102
+ _(compile(c <= @table[:comments])).must_be_like %{"users"."name" <= "users"."comments"}
103
+ _(compile(c =~ /\Atest\Z/)).must_be_like %{"users"."name" REGEXP '^test$'}
104
+ _(compile(c =~ /\Atest\z/)).must_be_like %{"users"."name" REGEXP '^test$'}
105
+ _(compile(c !~ /\Ate\Dst\Z/)).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
106
+ _(compile(c.imatches('%test%'))).must_be_like %{"users"."name" ILIKE '%test%'}
107
+ _(compile(c.imatches_any(['%test%', 't2']))).must_be_like %{(("users"."name" ILIKE '%test%') OR ("users"."name" ILIKE 't2'))}
108
+ _(compile(c.idoes_not_match('%test%'))).must_be_like %{"users"."name" NOT ILIKE '%test%'}
109
+
110
+ _(compile(c.substring(1))).must_be_like %{SUBSTRING("users"."name", 1)}
111
+ _(compile(c + '0')).must_be_like %{CONCAT("users"."name", '0')}
112
+ _(compile(c.substring(1) + '0')).must_be_like %{CONCAT(SUBSTRING("users"."name", 1), '0')}
113
+ _(compile(c.substring(1) + c.substring(2))).must_be_like %{CONCAT(SUBSTRING("users"."name", 1), SUBSTRING("users"."name", 2))}
114
+ _(compile(c.concat(c).concat(c))).must_be_like %{CONCAT("users"."name", "users"."name", "users"."name")}
115
+ _(compile(c + c + c)).must_be_like %{CONCAT("users"."name", "users"."name", "users"."name")}
102
116
 
103
117
  # some optimization on concat
104
- compile(c + 'test' + ' chain').must_be_like %{CONCAT(\"users\".\"name\", 'test chain')}
105
- compile(Arel::Nodes.build_quoted('test') + ' chain').must_be_like %{'test chain'}
106
- compile(c + '' + c).must_be_like %{CONCAT(\"users\".\"name\", \"users\".\"name\")}
118
+ _(compile(c + 'test' + ' chain')).must_be_like %{CONCAT(\"users\".\"name\", 'test chain')}
119
+ _(compile(Arel::Nodes.build_quoted('test') + ' chain')).must_be_like %{'test chain'}
120
+ _(compile(c + '' + c)).must_be_like %{CONCAT(\"users\".\"name\", \"users\".\"name\")}
107
121
 
108
- compile(c.md5).must_be_like %{MD5(\"users\".\"name\")}
122
+ _(compile(c.md5)).must_be_like %{MD5(\"users\".\"name\")}
109
123
  end
110
124
 
111
125
  # Comparators
112
126
 
113
127
  it "should accept comparators on integers" do
114
- compile(@table[:id] == 42).must_match %{"users"."id" = 42}
115
- compile(@table[:id] == @table[:id]).must_be_like %{"users"."id" = "users"."id"}
116
- compile(@table[:id] != 42).must_match %{"users"."id" != 42}
117
- compile(@table[:id] > 42).must_match %{"users"."id" > 42}
118
- compile(@table[:id] >= 42).must_match %{"users"."id" >= 42}
119
- compile(@table[:id] >= @table[:id]).must_be_like %{"users"."id" >= "users"."id"}
120
- compile(@table[:id] < 42).must_match %{"users"."id" < 42}
121
- compile(@table[:id] <= 42).must_match %{"users"."id" <= 42}
122
- compile((@table[:id] <= 42).as('new_name')).must_match %{("users"."id" <= 42) AS new_name}
128
+ _(compile(@table[:id] == 42)).must_match %{"users"."id" = 42}
129
+ _(compile(@table[:id] == @table[:id])).must_be_like %{"users"."id" = "users"."id"}
130
+ _(compile(@table[:id] != 42)).must_match %{"users"."id" != 42}
131
+ _(compile(@table[:id] > 42)).must_match %{"users"."id" > 42}
132
+ _(compile(@table[:id] >= 42)).must_match %{"users"."id" >= 42}
133
+ _(compile(@table[:id] >= @table[:id])).must_be_like %{"users"."id" >= "users"."id"}
134
+ _(compile(@table[:id] < 42)).must_match %{"users"."id" < 42}
135
+ _(compile(@table[:id] <= 42)).must_match %{"users"."id" <= 42}
136
+ _(compile((@table[:id] <= 42).as('new_name'))).must_match %{("users"."id" <= 42) AS new_name}
137
+ _(compile(@table[:id].count.eq 42)).must_match %{COUNT("users"."id") = 42}
138
+ #_(compile(@table[:id].count == 42)).must_match %{COUNT("users"."id") = 42} # TODO
139
+ #_(compile(@table[:id].count != 42)).must_match %{COUNT("users"."id") != 42}
140
+ #_(compile(@table[:id].count >= 42)).must_match %{COUNT("users"."id") >= 42}
123
141
  end
124
142
 
125
143
  it "should accept comparators on dates" do
126
144
  c = @table[:created_at]
127
145
  u = @table[:updated_at]
128
- compile(c > @date).must_be_like %{"users"."created_at" > '2016-03-31'}
129
- compile(u >= @date).must_be_like %{"users"."updated_at" >= '2016-03-31'}
130
- compile(c < u).must_be_like %{"users"."created_at" < "users"."updated_at"}
146
+ _(compile(c > @date)).must_be_like %{"users"."created_at" > '2016-03-31'}
147
+ _(compile(u >= @date)).must_be_like %{"users"."updated_at" >= '2016-03-31'}
148
+ _(compile(c < u)).must_be_like %{"users"."created_at" < "users"."updated_at"}
131
149
  end
132
150
 
133
151
  it "should accept comparators on strings" do
134
152
  c = @table[:name]
135
- compile(c == 'test').must_be_like %{"users"."name" = 'test'}
136
- compile(c != 'test').must_be_like %{"users"."name" != 'test'}
137
- compile(c > 'test').must_be_like %{"users"."name" > 'test'}
138
- compile((c >= 'test').as('new_name')).must_be_like %{("users"."name" >= 'test') AS new_name}
139
- compile(c <= @table[:comments]).must_be_like %{"users"."name" <= "users"."comments"}
140
- compile(c =~ /\Atest\Z/).must_be_like %{"users"."name" REGEXP '^test$'}
141
- compile(c !~ /\Ate\Dst\Z/).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
142
- compile(c.imatches('%test%')).must_be_like %{"users"."name" ILIKE '%test%'}
143
- compile(c.imatches_any(['%test%', 't2'])).must_be_like %{(("users"."name" ILIKE '%test%') OR ("users"."name" ILIKE 't2'))}
144
- compile(c.idoes_not_match('%test%')).must_be_like %{"users"."name" NOT ILIKE '%test%'}
153
+ _(compile(c == 'test')).must_be_like %{"users"."name" = 'test'}
154
+ _(compile(c != 'test')).must_be_like %{"users"."name" != 'test'}
155
+ _(compile(c > 'test')).must_be_like %{"users"."name" > 'test'}
156
+ _(compile((c >= 'test').as('new_name'))).must_be_like %{("users"."name" >= 'test') AS new_name}
157
+ _(compile(c <= @table[:comments])).must_be_like %{"users"."name" <= "users"."comments"}
158
+ _(compile(c =~ /\Atest\Z/)).must_be_like %{"users"."name" REGEXP '^test$'}
159
+ _(compile(c !~ /\Ate\Dst\Z/)).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
160
+ _(compile(c.imatches('%test%'))).must_be_like %{"users"."name" ILIKE '%test%'}
161
+ _(compile(c.imatches_any(['%test%', 't2']))).must_be_like %{(("users"."name" ILIKE '%test%') OR ("users"."name" ILIKE 't2'))}
162
+ _(compile(c.idoes_not_match('%test%'))).must_be_like %{"users"."name" NOT ILIKE '%test%'}
145
163
  end
146
164
 
147
165
  # Maths
148
166
  # DateDiff
149
167
  it "should diff date col and date" do
150
- compile(@table[:created_at] - Date.new(2016, 3, 31)).must_match %{DATEDIFF("users"."created_at", '2016-03-31')}
168
+ _(compile(@table[:created_at] - Date.new(2016, 3, 31))).must_match %{DATEDIFF("users"."created_at", '2016-03-31')}
151
169
  end
152
170
 
153
171
  it "should diff date col and datetime col" do
154
- compile(@table[:created_at] - @table[:updated_at]).must_match %{DATEDIFF("users"."created_at", "users"."updated_at")}
172
+ _(compile(@table[:created_at] - @table[:updated_at])).must_match %{DATEDIFF("users"."created_at", "users"."updated_at")}
155
173
  end
156
174
 
157
175
  it "should diff date col and datetime col with AS" do
158
- sql = compile((@table[:updated_at] - @table[:created_at]).as('new_name'))
159
- sql.must_match %{TIMEDIFF("users"."updated_at", "users"."created_at") AS new_name}
176
+ _(compile((@table[:updated_at] - @table[:created_at]).as('new_name')))
177
+ .must_match %{TIMEDIFF("users"."updated_at", "users"."created_at") AS new_name}
160
178
  end
161
179
 
162
180
  it "should diff between time values" do
163
181
  d2 = Time.new(2015,6,1)
164
182
  d1 = DateTime.new(2015,6,2)
165
- sql = compile(ArelExtensions::Nodes::DateDiff.new([d1, d2]))
166
- sql.must_match("DATEDIFF('2015-06-02', '2015-06-01')")
183
+ _(compile(ArelExtensions::Nodes::DateDiff.new([d1, d2])))
184
+ .must_match("DATEDIFF('2015-06-02', '2015-06-01')")
167
185
  end
168
186
 
169
187
  it "should diff between time values and time col" do
170
188
  d1 = DateTime.new(2015,6,2)
171
- sql = compile(ArelExtensions::Nodes::DateDiff.new([d1, @table[:updated_at]]))
172
- sql.must_match %{DATEDIFF('2015-06-02', "users"."updated_at")}
189
+ _(compile(ArelExtensions::Nodes::DateDiff.new([d1, @table[:updated_at]])))
190
+ .must_match %{DATEDIFF('2015-06-02', "users"."updated_at")}
173
191
  end
174
192
 
175
193
  it "should diff between date col and duration" do
176
194
  d1 = 10
177
195
  d2 = -10
178
- compile(@table[:created_at] - d1).
179
- must_match %{DATE_SUB("users"."created_at", 10)}
180
- compile(@table[:created_at] - d2).
181
- must_match %{DATE_SUB("users"."created_at", -10)}
196
+ _(compile(@table[:created_at] - d1))
197
+ .must_match %{DATE_SUB("users"."created_at", 10)}
198
+ _(compile(@table[:created_at] - d2))
199
+ .must_match %{DATE_SUB("users"."created_at", -10)}
182
200
  end
183
201
 
184
202
  it "should accept operators on dates with numbers" do
185
203
  c = @table[:created_at]
186
204
  #u = @table[:updated_at]
187
- compile(c - 42).must_be_like %{DATE_SUB("users"."created_at", 42)}
188
- compile(c - @table[:id]).must_be_like %{DATE_SUB("users"."created_at", "users"."id")}
205
+ _(compile(c - 42)).must_be_like %{DATE_SUB("users"."created_at", 42)}
206
+ _(compile(c - @table[:id])).must_be_like %{DATE_SUB("users"."created_at", "users"."id")}
189
207
  end
190
208
 
191
209
  # Maths on sums
192
210
  it "should accept math operators on anything" do
193
211
  c = @table[:name]
194
- (c == 'test').to_sql.must_be_like %{"users"."name" = 'test'}
195
- (c != 'test').to_sql.must_be_like %{"users"."name" != 'test'}
196
- (c > 'test').to_sql.must_be_like %{"users"."name" > 'test'}
197
- compile((c >= 'test').as('new_name')).must_be_like %{("users"."name" >= 'test') AS new_name}
198
- compile(c <= @table[:comments]).must_be_like %{"users"."name" <= "users"."comments"}
199
- compile(c =~ /\Atest\Z/).must_be_like %{"users"."name" REGEXP '^test$'}
200
- compile(c !~ /\Ate\Dst\Z/).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
212
+ _((c == 'test').to_sql)
213
+ .must_be_like %{"users"."name" = 'test'}
214
+ _((c != 'test').to_sql)
215
+ .must_be_like %{"users"."name" != 'test'}
216
+ _((c > 'test').to_sql)
217
+ .must_be_like %{"users"."name" > 'test'}
218
+ _(compile((c >= 'test').as('new_name'))).must_be_like %{("users"."name" >= 'test') AS new_name}
219
+ _(compile(c <= @table[:comments])).must_be_like %{"users"."name" <= "users"."comments"}
220
+ _(compile(c =~ /\Atest\Z/)).must_be_like %{"users"."name" REGEXP '^test$'}
221
+ _(compile(c !~ /\Ate\Dst\Z/)).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
201
222
  end
202
223
 
203
224
  it "should manage complex formulas" do
204
225
  c = @table[:name]
205
- compile(
206
- (c.length / 42).round(2).floor > (@table[:updated_at] - Date.new(2000, 3, 31)).abs.ceil
207
- ).must_be_like %{FLOOR(ROUND(LENGTH("users"."name") / 42, 2)) > CEIL(ABS(TIMEDIFF("users"."updated_at", '2000-03-31 00:00:00 UTC')))}
226
+ _(compile(
227
+ (c.length / 42).round(2).floor > (@table[:updated_at] - Date.new(2000, 3, 31)).abs.ceil
228
+ ))
229
+ .must_be_like %{FLOOR(ROUND(LENGTH("users"."name") / 42, 2)) > CEIL(ABS(TIMEDIFF("users"."updated_at", '2000-03-31 00:00:00 UTC')))}
208
230
  end
209
231
 
210
232
  it "should accept aggregator like GROUP CONCAT" do
211
- @table.project(@table[:first_name].group_concat).group(@table[:last_name]).to_sql
233
+ _(@table.project(@table[:first_name].group_concat).group(@table[:last_name]).to_sql)
212
234
  .must_be_like %{SELECT GROUP_CONCAT("users"."first_name") FROM "users" GROUP BY "users"."last_name"}
213
- @table.project(@table[:first_name].group_concat('++')).group(@table[:last_name]).to_sql
235
+ _(@table.project(@table[:first_name].group_concat('++')).group(@table[:last_name]).to_sql)
214
236
  .must_be_like %{SELECT GROUP_CONCAT("users"."first_name", '++') FROM "users" GROUP BY "users"."last_name"}
215
237
  end
216
238
 
217
239
  # Unions
218
240
  it "should accept union operators on queries and union nodes" do
219
241
  c = @table.project(@table[:name])
220
- compile(c + c)
242
+ _(compile(c + c))
221
243
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users")}
222
- (c + c).to_sql
244
+ _((c + c).to_sql)
223
245
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users")}
224
- (c + (c + c)).to_sql
246
+ _((c + (c + c)).to_sql)
225
247
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users")}
226
- ((c + c) + c).to_sql
248
+ _(((c + c) + c).to_sql)
227
249
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users")}
228
- (c + c + c).to_sql
250
+ _((c + c + c).to_sql)
229
251
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users")}
230
- (c + c).as('union_table').to_sql
252
+ _((c + c).as('union_table').to_sql)
231
253
  .must_be_like %{((SELECT "users"."name" FROM "users") UNION (SELECT "users"."name" FROM "users")) union_table}
232
254
  c = @table.project(@table[:name])
233
- compile(c.union_all(c))
255
+ _(compile(c.union_all(c)))
234
256
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users")}
235
- (c.union_all(c)).to_sql
257
+ _((c.union_all(c)).to_sql)
236
258
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users")}
237
- (c.union_all(c.union_all(c))).to_sql
259
+ _((c.union_all(c.union_all(c))).to_sql)
238
260
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users")}
239
- ((c.union_all(c)).union_all(c)).to_sql
261
+ _(((c.union_all(c)).union_all(c)).to_sql)
240
262
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users")}
241
- (c.union_all(c).union_all(c)).to_sql
263
+ _((c.union_all(c).union_all(c)).to_sql)
242
264
  .must_be_like %{(SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users")}
243
- (c.union_all(c)).as('union_table').to_sql
265
+ _((c.union_all(c)).as('union_table').to_sql)
244
266
  .must_be_like %{((SELECT "users"."name" FROM "users") UNION ALL (SELECT "users"."name" FROM "users")) union_table}
245
267
  end
246
268
 
247
269
  # Case
248
270
  it "should accept case clause" do
249
- @table[:name].when("smith").then("cool").when("doe").then("fine").else("uncool").to_sql
271
+ _(@table[:name].when("smith").then("cool").when("doe").then("fine").else("uncool").to_sql)
250
272
  .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' WHEN 'doe' THEN 'fine' ELSE 'uncool' END}
251
- @table[:name].when("smith").then(1).when("doe").then(2).else(0).to_sql
273
+ _(@table[:name].when("smith").then(1).when("doe").then(2).else(0).to_sql)
252
274
  .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 1 WHEN 'doe' THEN 2 ELSE 0 END}
253
- ArelExtensions::Nodes::Case.new.when(@table[:name] == "smith").then(1).when(@table[:name] == "doe").then(2).else(0).to_sql
275
+ _(ArelExtensions::Nodes::Case.new.when(@table[:name] == "smith").then(1).when(@table[:name] == "doe").then(2).else(0).to_sql)
254
276
  .must_be_like %{CASE WHEN "users"."name" = 'smith' THEN 1 WHEN "users"."name" = 'doe' THEN 2 ELSE 0 END}
255
- ArelExtensions::Nodes::Case.new(@table[:name]).when("smith").then(1).when("doe").then(2).else(0).to_sql
277
+ _(ArelExtensions::Nodes::Case.new(@table[:name]).when("smith").then(1).when("doe").then(2).else(0).to_sql)
256
278
  .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 1 WHEN 'doe' THEN 2 ELSE 0 END}
257
- @table[:name].when("smith").then(1).when("doe").then(2).else(0).sum.to_sql
279
+ _(@table[:name].when("smith").then(1).when("doe").then(2).else(0).sum.to_sql)
258
280
  .must_be_like %{SUM(CASE "users"."name" WHEN 'smith' THEN 1 WHEN 'doe' THEN 2 ELSE 0 END)}
259
- @table[:name].when("smith").then("cool").else("uncool").matches('value',false).to_sql
281
+ _(@table[:name].when("smith").then("cool").else("uncool").matches('value',false).to_sql)
260
282
  .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END LIKE 'value'}
261
- @table[:name].when("smith").then("cool").else("uncool").imatches('value',false).to_sql
283
+ _(@table[:name].when("smith").then("cool").else("uncool").imatches('value',false).to_sql)
262
284
  .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END ILIKE 'value'}
263
285
  end
264
286
 
265
287
  it "should be possible to use as on anything" do
266
- compile(@table[:name].as('alias')).must_be_like %{"users"."name" AS alias}
267
- compile(@table[:name].concat(' test').as('alias')).must_be_like %{CONCAT("users"."name", ' test') AS alias}
268
- compile((@table[:name] + ' test').as('alias')).must_be_like %{CONCAT("users"."name", ' test') AS alias}
269
- compile((@table[:age] + 42).as('alias')).must_be_like %{("users"."age" + 42) AS alias}
270
- compile(@table[:name].coalesce('').as('alias')).must_be_like %{COALESCE("users"."name", '') AS alias}
271
- compile(Arel::Nodes.build_quoted('test').as('alias')).must_be_like %{'test' AS alias}
272
- compile(@table.project(@table[:name]).as('alias')).must_be_like %{(SELECT "users"."name" FROM "users") alias}
273
- compile(@table[:name].when("smith").then("cool").else("uncool").as('alias')).
274
- must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END AS alias}
288
+ _(compile(@table[:name].as('alias'))).must_be_like %{"users"."name" AS alias}
289
+ _(compile(@table[:name].concat(' test').as('alias'))).must_be_like %{CONCAT("users"."name", ' test') AS alias}
290
+ _(compile((@table[:name] + ' test').as('alias'))).must_be_like %{CONCAT("users"."name", ' test') AS alias}
291
+ _(compile((@table[:age] + 42).as('alias'))).must_be_like %{("users"."age" + 42) AS alias}
292
+ _(compile(@table[:name].coalesce('').as('alias'))).must_be_like %{COALESCE("users"."name", '') AS alias}
293
+ _(compile(Arel::Nodes.build_quoted('test').as('alias'))).must_be_like %{'test' AS alias}
294
+ _(compile(@table.project(@table[:name]).as('alias'))).must_be_like %{(SELECT "users"."name" FROM "users") alias}
295
+ _(compile(@table[:name].when("smith").then("cool").else("uncool").as('alias')))
296
+ .must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' ELSE 'uncool' END AS alias}
275
297
  end
276
298
 
277
299
  it "should accept comparators on functions" do
278
300
  c = @table[:name]
279
- compile(c.soundex == 'test').must_be_like %{SOUNDEX("users"."name") = 'test'}
280
- compile(c.soundex != 'test').must_be_like %{SOUNDEX("users"."name") != 'test'}
281
- compile(c.length >= 0 ).must_be_like %{LENGTH("users"."name") >= 0}
301
+ _(compile(c.soundex == 'test')).must_be_like %{SOUNDEX("users"."name") = 'test'}
302
+ _(compile(c.soundex != 'test')).must_be_like %{SOUNDEX("users"."name") != 'test'}
303
+ _(compile(c.length >= 0 )).must_be_like %{LENGTH("users"."name") >= 0}
282
304
  end
283
305
 
284
306
  it "should accept in on select statement" do
285
307
  c = @table[:name]
286
- compile(c.in(@table.project(@table[:name])))
308
+ _(compile(c.in(@table.project(@table[:name]))))
287
309
  .must_be_like %{"users"."name" IN (SELECT "users"."name" FROM "users")}
288
310
  end
289
311
 
290
312
  it "should accept coalesce function properly even on none actual tables and attributes" do
291
313
  fake_at = Arel::Table.new('fake_table')
292
- compile(fake_at['fake_attribute'].coalesce('other_value'))
314
+ _(compile(fake_at['fake_attribute'].coalesce('other_value')))
293
315
  .must_be_like %{COALESCE("fake_table"."fake_attribute", 'other_value')}
294
- compile(fake_at['fake_attribute'].coalesce('other_value1','other_value2'))
316
+ _(compile(fake_at['fake_attribute'].coalesce('other_value1','other_value2')))
295
317
  .must_be_like %{COALESCE("fake_table"."fake_attribute", 'other_value1', 'other_value2')}
296
- compile(fake_at['fake_attribute'].coalesce('other_value1').coalesce('other_value2'))
318
+ _(compile(fake_at['fake_attribute'].coalesce('other_value1').coalesce('other_value2')))
297
319
  .must_be_like %{COALESCE(COALESCE("fake_table"."fake_attribute", 'other_value1'), 'other_value2')}
298
- compile(fake_at['fake_attribute'].coalesce('other_value').matches('truc'))
320
+ _(compile(fake_at['fake_attribute'].coalesce('other_value').matches('truc')))
299
321
  .must_be_like %{COALESCE("fake_table"."fake_attribute", 'other_value') LIKE 'truc'}
300
- compile(fake_at['fake_attribute'].coalesce('other_value').imatches('truc'))
322
+ _(compile(fake_at['fake_attribute'].coalesce('other_value').imatches('truc')))
301
323
  .must_be_like %{COALESCE("fake_table"."fake_attribute", 'other_value') ILIKE 'truc'}
302
324
  end
303
325
 
304
326
  it "should be possible to cast nodes types" do
305
- compile(@table[:id].cast('char'))
327
+ _(compile(@table[:id].cast('char')))
306
328
  .must_be_like %{CAST("users"."id" AS char)}
307
- compile(@table[:id].coalesce(' ').cast('char'))
329
+ _(compile(@table[:id].coalesce(' ').cast('char')))
308
330
  .must_be_like %{CAST(COALESCE("users"."id", ' ') AS char)}
309
- compile(@table[:id].coalesce(' ').cast(:string))
331
+ _(compile(@table[:id].coalesce(' ').cast(:string)))
310
332
  .must_be_like %{CAST(COALESCE("users"."id", ' ') AS char)}
311
- compile(@table[:id].cast(:string).coalesce(' '))
333
+ _(compile(@table[:id].cast(:string).coalesce(' ')))
312
334
  .must_be_like %{COALESCE(CAST(\"users\".\"id\" AS char), ' ')}
313
- compile(@table[:id].cast('char') + ' ')
335
+ _(compile(@table[:id].cast('char') + ' '))
314
336
  .must_be_like %{CONCAT(CAST("users"."id" AS char), ' ')}
315
- compile(@table[:id].cast('int') + 2)
337
+ _(compile(@table[:id].cast('int') + 2))
316
338
  .must_be_like %{(CAST("users"."id" AS int) + 2)}
317
339
  end
318
340
 
319
- it "should be possible to have nil element in the function NIL" do
320
- compile(@table[:id].in(nil))
321
- .must_be_like %{ISNULL("users"."id")}
322
- compile(@table[:id].in([nil]))
323
- .must_be_like %{ISNULL("users"."id")}
324
- compile(@table[:id].in([nil,1]))
325
- .must_be_like %{(ISNULL("users"."id")) OR ("users"."id" = 1)}
326
- compile(@table[:id].in([nil,1,2]))
327
- .must_be_like %{(ISNULL("users"."id")) OR ("users"."id" IN (1, 2))}
328
- compile(@table[:id].in(1))
329
- .must_be_like %{"users"."id" IN (1)}
330
- compile(@table[:id].in([1]))
331
- .must_be_like %{"users"."id" IN (1)}
332
- compile(@table[:id].in([1,2]))
333
- .must_be_like %{"users"."id" IN (1, 2)}
341
+ describe "the function in" do
342
+
343
+ it "should be possible to have nil element in the function IN" do
344
+ _(compile(@table[:id].in(nil)))
345
+ .must_be_like %{ISNULL("users"."id")}
346
+ _(compile(@table[:id].in([nil])))
347
+ .must_be_like %{ISNULL("users"."id")}
348
+ _(compile(@table[:id].in([nil,1])))
349
+ .must_be_like %{(ISNULL("users"."id")) OR ("users"."id" = 1)}
350
+ _(compile(@table[:id].in([nil,1,2])))
351
+ .must_be_like %{(ISNULL("users"."id")) OR ("users"."id" IN (1, 2))}
352
+ _(compile(@table[:id].in(1)))
353
+ .must_be_like %{"users"."id" IN (1)}
354
+ _(compile(@table[:id].in([1])))
355
+ .must_be_like %{"users"."id" = 1}
356
+ _(compile(@table[:id].in([1,2])))
357
+ .must_be_like %{"users"."id" IN (1, 2)}
358
+ _(compile(@table[:id].in([])))
359
+ .must_be_like %{1 = 0}
360
+ end
361
+
362
+ it "should be possible to correctly use a Range on an IN" do
363
+ _(compile(@table[:id].in(1..4)))
364
+ .must_be_like %{"users"."id" BETWEEN (1) AND (4)}
365
+ _(compile(@table[:created_at].in(Date.new(2016, 3, 31) .. Date.new(2017, 3, 31))))
366
+ .must_be_like %{"users"."created_at" BETWEEN ('2016-03-31') AND ('2017-03-31')}
367
+ end
368
+
369
+ it "should be possible to use a list of values and ranges on an IN" do
370
+ _(compile(@table[:id].in [1..10, 20, 30, 40..50]))
371
+ .must_be_like %{("users"."id" IN (20, 30)) OR ("users"."id" BETWEEN (1) AND (10)) OR ("users"."id" BETWEEN (40) AND (50))}
372
+ _(compile(@table[:created_at].in(Date.new(2016, 1, 1), Date.new(2016, 2, 1)..Date.new(2016, 2, 28), Date.new(2016, 3, 31) .. Date.new(2017, 3, 31), Date.new(2018, 1, 1))))
373
+ .must_be_like %{ ("users"."created_at" IN ('2016-01-01', '2018-01-01'))
374
+ OR ("users"."created_at" BETWEEN ('2016-02-01') AND ('2016-02-28'))
375
+ OR ("users"."created_at" BETWEEN ('2016-03-31') AND ('2017-03-31'))}
376
+ end
377
+
378
+ it "should respecting Grouping" do
379
+ g = ->(*v) { Arel::Nodes::Grouping.new(v) }
380
+ _(compile(g[@table[:id], @table[:age]].in [g[1, 42]]))
381
+ .must_be_like %{("users"."id", "users"."age") IN ((1, 42))}
382
+ _(compile(g[@table[:id], @table[:age]].in [g[1, 42], g[2, 51]]))
383
+ .must_be_like %{("users"."id", "users"."age") IN ((1, 42), (2, 51))}
384
+
385
+ _(compile(g[@table[:id], @table[:age]].in(g[1, 42], g[2, 51])))
386
+ .must_be_like %{("users"."id", "users"."age") IN ((1, 42), (2, 51))}
387
+ end
388
+
389
+
334
390
  end
335
391
 
336
- it "should be possible to correctly use a Range on an IN" do
337
- compile(@table[:id].in(1..4))
338
- .must_be_like %{"users"."id" BETWEEN (1) AND (4)}
339
- compile(@table[:created_at].in(@date .. Date.new(2017, 3, 31))) # @date = Date.new(2016, 3, 31)
340
- .must_be_like %{"users"."created_at" BETWEEN ('2016-03-31') AND ('2017-03-31')}
392
+ describe "the function not_in" do
393
+
394
+ it "should be possible to have nil element in the function IN" do
395
+ _(compile(@table[:id].not_in nil))
396
+ .must_be_like %{NOT ISNULL("users"."id")}
397
+ _(compile(@table[:id].not_in [nil]))
398
+ .must_be_like %{NOT ISNULL("users"."id")}
399
+ _(compile(@table[:id].not_in [nil,1]))
400
+ .must_be_like %{(NOT ISNULL("users"."id")) AND ("users"."id" != 1)}
401
+ _(compile(@table[:id].not_in [nil,1,2]))
402
+ .must_be_like %{(NOT ISNULL("users"."id")) AND ("users"."id" NOT IN (1, 2))}
403
+ _(compile(@table[:id].not_in 1))
404
+ .must_be_like %{"users"."id" NOT IN (1)}
405
+ _(compile(@table[:id].not_in [1]))
406
+ .must_be_like %{"users"."id" != 1}
407
+ _(compile(@table[:id].not_in [1,2]))
408
+ .must_be_like %{"users"."id" NOT IN (1, 2)}
409
+ _(compile(@table[:id].not_in []))
410
+ .must_be_like %{1 = 1}
411
+ end
412
+
413
+ it "should be possible to correctly use a Range on an IN" do
414
+ # FIXME: Should use NOT BETWEEN
415
+ _(compile(@table[:id].not_in 1..4))
416
+ .must_be_like %{NOT ("users"."id" BETWEEN (1) AND (4))}
417
+ # FIXME: Should use NOT BETWEEN
418
+ _(compile(@table[:created_at].not_in Date.new(2016, 3, 31) .. Date.new(2017, 3, 31)))
419
+ .must_be_like %{NOT ("users"."created_at" BETWEEN ('2016-03-31') AND ('2017-03-31'))}
420
+ end
421
+
422
+ it "should be possible to use a list of values and ranges on an IN" do
423
+ _(compile(@table[:id].not_in [1..10, 20, 30, 40..50]))
424
+ .must_be_like %{ ("users"."id" NOT IN (20, 30))
425
+ AND (NOT ("users"."id" BETWEEN (1) AND (10)))
426
+ AND (NOT ("users"."id" BETWEEN (40) AND (50)))}
427
+ _(compile(@table[:created_at].not_in Date.new(2016, 1, 1), Date.new(2016, 2, 1)..Date.new(2016, 2, 28), Date.new(2016, 3, 31) .. Date.new(2017, 3, 31), Date.new(2018, 1, 1)))
428
+ .must_be_like %{ ("users"."created_at" NOT IN ('2016-01-01', '2018-01-01'))
429
+ AND (NOT ("users"."created_at" BETWEEN ('2016-02-01') AND ('2016-02-28')))
430
+ AND (NOT ("users"."created_at" BETWEEN ('2016-03-31') AND ('2017-03-31')))}
431
+ end
432
+
341
433
  end
342
434
 
343
435
  it "should be possible to add and substract as much as we want" do
344
436
  c = @table[:name]
345
- compile(c.locate('test')+1)
437
+ _(compile(c.locate('test')+1))
346
438
  .must_be_like %{(LOCATE('test', "users"."name") + 1)}
347
- compile(c.locate('test')-1)
439
+ _(compile(c.locate('test')-1))
348
440
  .must_be_like %{(LOCATE('test', "users"."name") - 1)}
349
- compile(c.locate('test')+c.locate('test'))
441
+ _(compile(c.locate('test')+c.locate('test')))
350
442
  .must_be_like %{(LOCATE('test', "users"."name") + LOCATE('test', "users"."name"))}
351
- compile(c.locate('test')+1+c.locate('test')-1 + 1)
443
+ _(compile(c.locate('test')+1+c.locate('test')-1 + 1))
352
444
  .must_be_like %{((((LOCATE('test', "users"."name") + 1) + LOCATE('test', "users"."name")) - 1) + 1)}
353
445
  end
354
446
 
355
447
  it "should be possible to add and substract on some nodes" do
356
448
  c = @table[:name]
357
- compile(c.when(0,0).else(42) + 42).must_be_like %{(CASE "users"."name" WHEN 0 THEN 0 ELSE 42 END + 42)}
358
- compile(c.when(0,0).else(42) - 42).must_be_like %{(CASE "users"."name" WHEN 0 THEN 0 ELSE 42 END - 42)}
359
- compile(c.when(0,"0").else("42") + "42").must_be_like %{CONCAT(CASE "users"."name" WHEN 0 THEN '0' ELSE '42' END, '42')}
449
+ _(compile(c.when(0,0).else(42) + 42)).must_be_like %{(CASE "users"."name" WHEN 0 THEN 0 ELSE 42 END + 42)}
450
+ _(compile(c.when(0,0).else(42) - 42)).must_be_like %{(CASE "users"."name" WHEN 0 THEN 0 ELSE 42 END - 42)}
451
+ _(compile(c.when(0,"0").else("42") + "42")).must_be_like %{CONCAT(CASE "users"."name" WHEN 0 THEN '0' ELSE '42' END, '42')}
360
452
  end
361
453
 
362
454
  it "should be possible to desc and asc on functions" do
363
455
  c = @table[:name]
364
- compile(c.asc)
456
+ _(compile(c.asc))
365
457
  .must_be_like %{"users"."name" ASC}
366
- compile(c.substring(2).asc)
458
+ _(compile(c.substring(2).asc))
367
459
  .must_be_like %{SUBSTRING("users"."name", 2) ASC}
368
- compile(c.substring(2).desc)
460
+ _(compile(c.substring(2).desc))
369
461
  .must_be_like %{SUBSTRING("users"."name", 2) DESC}
370
- compile((c.locate('test')+1).asc)
462
+ _(compile((c.locate('test')+1).asc))
371
463
  .must_be_like %{(LOCATE('test', "users"."name") + 1) ASC}
372
464
  end
373
465
 
374
- it "should be possible to have multiple arguments on an OR or an AND node" do
375
- c = @table[:id]
376
- compile((c == 1).and(c == 2, c == 3)).
377
- must_be_like %{("users"."id" = 1) AND ("users"."id" = 2) AND ("users"."id" = 3)}
378
- compile((c == 1).and([c == 2, c == 3])).
379
- must_be_like %{("users"."id" = 1) AND ("users"."id" = 2) AND ("users"."id" = 3)}
380
- compile((c == 1).or(c == 2, c == 3)).
381
- must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3)}
382
- compile((c == 1).or([c == 2, c == 3])).
383
- must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3)}
466
+ it "should be possible to call Table function on TableAlias" do
467
+ t = @table
468
+ a = t.alias("aliased_users")
469
+ _(compile(a.join(t).join_sources))
470
+ .must_be_like %{INNER JOIN \"users\"}
471
+ end
472
+
473
+ describe "logical functions" do
474
+
475
+ it "should know about truth" do
476
+ _(compile(Arel.false))
477
+ .must_be_like %{1 = 0}
478
+
479
+ _(compile(Arel::true))
480
+ .must_be_like %{1 = 1}
481
+ end
482
+
483
+ it "boolean nodes should be variadic" do
484
+ c = @table[:id]
485
+
486
+ _(compile(Arel::Nodes::And.new))
487
+ .must_be_like %{1 = 1}
488
+ _(compile(Arel::Nodes::And.new(c == 1)))
489
+ .must_be_like %{"users"."id" = 1}
490
+ _(compile(Arel::Nodes::And.new(c == 1, c == 2)))
491
+ .must_be_like %{("users"."id" = 1) AND ("users"."id" = 2)}
492
+ _(compile(Arel::Nodes::And.new [c == 1, c == 2, c == 3]))
493
+ .must_be_like %{("users"."id" = 1) AND ("users"."id" = 2) AND ("users"."id" = 3)}
494
+
495
+
496
+ _(compile(Arel::Nodes::Or.new))
497
+ .must_be_like %{1 = 0}
498
+ _(compile(Arel::Nodes::Or.new(c == 1)))
499
+ .must_be_like %{"users"."id" = 1}
500
+ _(compile(Arel::Nodes::Or.new(c == 1, c == 2)))
501
+ .must_be_like %{("users"."id" = 1) OR ("users"."id" = 2)}
502
+ _(compile(Arel::Nodes::Or.new(c == 1, c == 2, c == 3)))
503
+ .must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3)}
504
+ _(compile(Arel::Nodes::Or.new [c == 1, c == 2, c == 3]))
505
+ .must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3)}
506
+ end
507
+
508
+ it "should know trivial identities" do
509
+ skip "For future optimization"
510
+ c = @table[:id]
511
+ _(compile(Arel::Nodes::And.new(Arel.true, c == 1)))
512
+ .must_be_like %{"users"."id" = 1}
513
+ _(compile(Arel::Nodes::And.new(Arel.false, c == 1)))
514
+ .must_be_like %{1 = 0}
515
+ _(compile(Arel::Nodes::And.new(c == 1, c == 1)))
516
+ .must_be_like %{"users"."id" = 1}
517
+
518
+ _(compile(Arel::Nodes::Or.new(Arel.true, c == 1)))
519
+ .must_be_like %{1 = 1}
520
+ _(compile(Arel::Nodes::Or.new(Arel.false, c == 1)))
521
+ .must_be_like %{"users"."id" = 1}
522
+ _(compile(Arel::Nodes::Or.new(c == 1, c == 1)))
523
+ .must_be_like %{"users"."id" = 1}
524
+ end
525
+
526
+ it "should be possible to have multiple arguments on an OR or an AND node" do
527
+ c = @table[:id]
528
+ _(compile((c == 1).and))
529
+ .must_be_like %{"users"."id" = 1}
530
+
531
+ _(compile((c == 1).and(c == 2, c == 3)))
532
+ .must_be_like %{("users"."id" = 1) AND ("users"."id" = 2) AND ("users"."id" = 3)}
533
+ _(compile((c == 1).and([c == 2, c == 3])))
534
+ .must_be_like %{("users"."id" = 1) AND ("users"."id" = 2) AND ("users"."id" = 3)}
535
+
536
+ _(compile((c == 1).or))
537
+ .must_be_like %{"users"."id" = 1}
538
+
539
+ _(compile((c == 1).or(c == 2, c == 3)))
540
+ .must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3)}
541
+ _(compile((c == 1).or([c == 2, c == 3])))
542
+ .must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3)}
543
+ end
544
+
545
+ it "should avoid useless nesting" do
546
+ c = @table[:id]
547
+ _(compile(((c == 1).and(c == 2)) .and ((c == 3).and(c == 4))))
548
+ .must_be_like %{("users"."id" = 1) AND ("users"."id" = 2) AND ("users"."id" = 3) AND ("users"."id" = 4)}
549
+ _(compile(((c == 1).or(c == 2)) .or ((c == 3).or(c == 4))))
550
+ .must_be_like %{("users"."id" = 1) OR ("users"."id" = 2) OR ("users"."id" = 3) OR ("users"."id" = 4)}
551
+
552
+ _(compile(((c == 1).or(c == 2)) .and ((c == 3).or(c == 4))))
553
+ .must_be_like %{(("users"."id" = 1) OR ("users"."id" = 2)) AND (("users"."id" = 3) OR ("users"."id" = 4))}
554
+ _(compile(((c == 1).and(c == 2)) .or ((c == 3).and(c == 4))))
555
+ .must_be_like %{(("users"."id" = 1) AND ("users"."id" = 2)) OR (("users"."id" = 3) AND ("users"."id" = 4))}
556
+ end
557
+
384
558
  end
385
559
 
386
560
  puts "AREL VERSION : " + Arel::VERSION.to_s