arel_extensions 1.2.2 → 1.2.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +7 -4
  3. data/.travis.yml +59 -91
  4. data/Gemfile +2 -2
  5. data/README.md +17 -12
  6. data/Rakefile +38 -27
  7. data/appveyor.yml +1 -1
  8. data/arel_extensions.gemspec +1 -1
  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 +26 -24
  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/blank.rb +14 -11
  29. data/lib/arel_extensions/nodes/case.rb +8 -4
  30. data/lib/arel_extensions/nodes/ceil.rb +0 -0
  31. data/lib/arel_extensions/nodes/change_case.rb +2 -2
  32. data/lib/arel_extensions/nodes/coalesce.rb +2 -2
  33. data/lib/arel_extensions/nodes/collate.rb +12 -12
  34. data/lib/arel_extensions/nodes/concat.rb +6 -13
  35. data/lib/arel_extensions/nodes/date_diff.rb +3 -5
  36. data/lib/arel_extensions/nodes/duration.rb +0 -2
  37. data/lib/arel_extensions/nodes/find_in_set.rb +0 -0
  38. data/lib/arel_extensions/nodes/floor.rb +0 -0
  39. data/lib/arel_extensions/nodes/format.rb +8 -8
  40. data/lib/arel_extensions/nodes/formatted_number.rb +23 -23
  41. data/lib/arel_extensions/nodes/function.rb +10 -0
  42. data/lib/arel_extensions/nodes/is_null.rb +10 -8
  43. data/lib/arel_extensions/nodes/json.rb +28 -30
  44. data/lib/arel_extensions/nodes/length.rb +0 -0
  45. data/lib/arel_extensions/nodes/levenshtein_distance.rb +5 -5
  46. data/lib/arel_extensions/nodes/locate.rb +7 -7
  47. data/lib/arel_extensions/nodes/matches.rb +4 -4
  48. data/lib/arel_extensions/nodes/power.rb +6 -5
  49. data/lib/arel_extensions/nodes/rand.rb +0 -0
  50. data/lib/arel_extensions/nodes/repeat.rb +2 -2
  51. data/lib/arel_extensions/nodes/replace.rb +24 -6
  52. data/lib/arel_extensions/nodes/round.rb +5 -5
  53. data/lib/arel_extensions/nodes/soundex.rb +16 -15
  54. data/lib/arel_extensions/nodes/std.rb +19 -21
  55. data/lib/arel_extensions/nodes/substring.rb +8 -15
  56. data/lib/arel_extensions/nodes/sum.rb +7 -0
  57. data/lib/arel_extensions/nodes/trim.rb +3 -3
  58. data/lib/arel_extensions/nodes/union.rb +2 -3
  59. data/lib/arel_extensions/nodes/union_all.rb +1 -2
  60. data/lib/arel_extensions/nodes/wday.rb +0 -0
  61. data/lib/arel_extensions/null_functions.rb +2 -2
  62. data/lib/arel_extensions/predications.rb +35 -33
  63. data/lib/arel_extensions/set_functions.rb +16 -16
  64. data/lib/arel_extensions/string_functions.rb +34 -12
  65. data/lib/arel_extensions/tasks.rb +5 -5
  66. data/lib/arel_extensions/version.rb +1 -1
  67. data/lib/arel_extensions/visitors.rb +1 -1
  68. data/lib/arel_extensions/visitors/ibm_db.rb +1 -1
  69. data/lib/arel_extensions/visitors/mssql.rb +18 -17
  70. data/lib/arel_extensions/visitors/mysql.rb +92 -46
  71. data/lib/arel_extensions/visitors/oracle.rb +40 -28
  72. data/lib/arel_extensions/visitors/oracle12.rb +1 -1
  73. data/lib/arel_extensions/visitors/postgresql.rb +80 -34
  74. data/lib/arel_extensions/visitors/sqlite.rb +54 -46
  75. data/lib/arel_extensions/visitors/to_sql.rb +75 -62
  76. data/test/arelx_test_helper.rb +28 -0
  77. data/test/real_db_test.rb +1 -1
  78. data/test/support/fake_record.rb +4 -0
  79. data/test/test_comparators.rb +9 -8
  80. data/test/visitors/test_bulk_insert_oracle.rb +8 -7
  81. data/test/visitors/test_bulk_insert_sqlite.rb +9 -8
  82. data/test/visitors/test_bulk_insert_to_sql.rb +8 -10
  83. data/test/visitors/test_oracle.rb +41 -40
  84. data/test/visitors/test_to_sql.rb +367 -193
  85. data/test/with_ar/all_agnostic_test.rb +85 -39
  86. data/test/with_ar/insert_agnostic_test.rb +3 -2
  87. data/test/with_ar/test_bulk_sqlite.rb +6 -5
  88. data/test/with_ar/test_math_sqlite.rb +4 -4
  89. data/test/with_ar/test_string_mysql.rb +4 -6
  90. data/test/with_ar/test_string_sqlite.rb +3 -7
  91. data/version_v1.rb +3 -0
  92. data/version_v2.rb +3 -0
  93. metadata +13 -7
  94. 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
@@ -65,6 +65,10 @@ module FakeRecord
65
65
  self
66
66
  end
67
67
 
68
+ def in_clause_length
69
+ 10000
70
+ end
71
+
68
72
  def quote thing, column = nil
69
73
  if column && !thing.nil?
70
74
  case column.type
@@ -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