arel_extensions 0.8.0

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 (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +46 -0
  4. data/Gemfile +10 -0
  5. data/MIT-LICENSE.txt +20 -0
  6. data/README.md +101 -0
  7. data/Rakefile +14 -0
  8. data/arel_extensions.gemspec +32 -0
  9. data/functions.html +344 -0
  10. data/gemfiles/Gemfile.rails3 +10 -0
  11. data/gemfiles/Gemfile.rails5 +10 -0
  12. data/init/mssql.sql +6 -0
  13. data/init/mysql.sql +0 -0
  14. data/init/oracle.sql +31 -0
  15. data/init/postgresql.sql +12 -0
  16. data/init/sqlite.sql +1 -0
  17. data/lib/arel_extensions.rb +84 -0
  18. data/lib/arel_extensions/attributes.rb +26 -0
  19. data/lib/arel_extensions/comparators.rb +59 -0
  20. data/lib/arel_extensions/date_duration.rb +28 -0
  21. data/lib/arel_extensions/insert_manager.rb +33 -0
  22. data/lib/arel_extensions/math.rb +48 -0
  23. data/lib/arel_extensions/math_functions.rb +35 -0
  24. data/lib/arel_extensions/nodes.rb +27 -0
  25. data/lib/arel_extensions/nodes/abs.rb +6 -0
  26. data/lib/arel_extensions/nodes/ceil.rb +6 -0
  27. data/lib/arel_extensions/nodes/coalesce.rb +22 -0
  28. data/lib/arel_extensions/nodes/concat.rb +33 -0
  29. data/lib/arel_extensions/nodes/date_diff.rb +106 -0
  30. data/lib/arel_extensions/nodes/duration.rb +30 -0
  31. data/lib/arel_extensions/nodes/find_in_set.rb +16 -0
  32. data/lib/arel_extensions/nodes/floor.rb +6 -0
  33. data/lib/arel_extensions/nodes/function.rb +17 -0
  34. data/lib/arel_extensions/nodes/isnull.rb +30 -0
  35. data/lib/arel_extensions/nodes/length.rb +6 -0
  36. data/lib/arel_extensions/nodes/locate.rb +33 -0
  37. data/lib/arel_extensions/nodes/ltrim.rb +28 -0
  38. data/lib/arel_extensions/nodes/matches.rb +22 -0
  39. data/lib/arel_extensions/nodes/rand.rb +23 -0
  40. data/lib/arel_extensions/nodes/replace.rb +36 -0
  41. data/lib/arel_extensions/nodes/round.rb +15 -0
  42. data/lib/arel_extensions/nodes/rtrim.rb +29 -0
  43. data/lib/arel_extensions/nodes/soundex.rb +23 -0
  44. data/lib/arel_extensions/nodes/sum.rb +23 -0
  45. data/lib/arel_extensions/nodes/trim.rb +26 -0
  46. data/lib/arel_extensions/nodes/wday.rb +23 -0
  47. data/lib/arel_extensions/null_functions.rb +16 -0
  48. data/lib/arel_extensions/string_functions.rb +68 -0
  49. data/lib/arel_extensions/version.rb +4 -0
  50. data/lib/arel_extensions/visitors.rb +6 -0
  51. data/lib/arel_extensions/visitors/ibm_db.rb +206 -0
  52. data/lib/arel_extensions/visitors/mssql.rb +213 -0
  53. data/lib/arel_extensions/visitors/mysql.rb +184 -0
  54. data/lib/arel_extensions/visitors/oracle.rb +267 -0
  55. data/lib/arel_extensions/visitors/postgresql.rb +258 -0
  56. data/lib/arel_extensions/visitors/sqlite.rb +218 -0
  57. data/lib/arel_extensions/visitors/to_sql.rb +199 -0
  58. data/test/helper.rb +18 -0
  59. data/test/real_db_test.rb +251 -0
  60. data/test/support/fake_record.rb +137 -0
  61. data/test/test_comparators.rb +49 -0
  62. data/test/visitors/test_bulk_insert_oracle.rb +30 -0
  63. data/test/visitors/test_bulk_insert_sqlite.rb +31 -0
  64. data/test/visitors/test_bulk_insert_to_sql.rb +32 -0
  65. data/test/visitors/test_oracle.rb +105 -0
  66. data/test/visitors/test_to_sql.rb +148 -0
  67. data/test/with_ar/test_bulk_sqlite.rb +44 -0
  68. data/test/with_ar/test_math_sqlite.rb +59 -0
  69. data/test/with_ar/test_string_sqlite.rb +69 -0
  70. metadata +230 -0
@@ -0,0 +1,137 @@
1
+ module FakeRecord
2
+ class Column < Struct.new(:name, :type)
3
+ end
4
+
5
+ class Connection
6
+ attr_reader :tables
7
+ attr_accessor :visitor
8
+
9
+ def initialize(visitor = nil)
10
+ @tables = %w{ users photos developers products}
11
+ @columns = {
12
+ 'users' => [
13
+ Column.new('id', :integer),
14
+ Column.new('name', :string),
15
+ Column.new('comments', :text),
16
+ Column.new('bool', :boolean),
17
+ Column.new('created_at', :date),
18
+ Column.new('updated_at', :datetime)
19
+ ],
20
+ 'products' => [
21
+ Column.new('id', :integer),
22
+ Column.new('price', :decimal)
23
+ ]
24
+ }
25
+ @columns_hash = {
26
+ 'users' => Hash[@columns['users'].map { |x| [x.name, x] }],
27
+ 'products' => Hash[@columns['products'].map { |x| [x.name, x] }]
28
+ }
29
+ @primary_keys = {
30
+ 'users' => 'id',
31
+ 'products' => 'id'
32
+ }
33
+ @visitor = visitor
34
+ end
35
+
36
+ def columns_hash table_name
37
+ @columns_hash[table_name]
38
+ end
39
+
40
+ def primary_key name
41
+ @primary_keys[name.to_s]
42
+ end
43
+
44
+ def table_exists? name
45
+ @tables.include? name.to_s
46
+ end
47
+
48
+ def columns name, message = nil
49
+ @columns[name.to_s]
50
+ end
51
+
52
+ def quote_table_name name
53
+ "\"#{name.to_s}\""
54
+ end
55
+
56
+ def quote_column_name name
57
+ "\"#{name.to_s}\""
58
+ end
59
+
60
+ def schema_cache
61
+ self
62
+ end
63
+
64
+ def quote thing, column = nil
65
+ if column && !thing.nil?
66
+ case column.type
67
+ when :integer
68
+ thing = thing.to_i
69
+ when :string
70
+ thing = thing.to_s
71
+ end
72
+ end
73
+
74
+ case thing
75
+ when DateTime
76
+ "'#{thing.strftime("%Y-%m-%d %H:%M:%S")}'"
77
+ when Date
78
+ "'#{thing.strftime("%Y-%m-%d")}'"
79
+ when true
80
+ "'t'"
81
+ when false
82
+ "'f'"
83
+ when nil
84
+ 'NULL'
85
+ when Numeric
86
+ thing
87
+ else
88
+ "'#{thing.to_s.gsub("'", "\\\\'")}'"
89
+ end
90
+ end
91
+ end
92
+
93
+ class ConnectionPool
94
+ class Spec < Struct.new(:config)
95
+ end
96
+
97
+ attr_reader :spec, :connection
98
+
99
+ def initialize
100
+ @spec = Spec.new(:adapter => 'america')
101
+ @connection = Connection.new
102
+ @connection.visitor = Arel::Visitors::ToSql.new(connection)
103
+ end
104
+
105
+ def with_connection
106
+ yield connection
107
+ end
108
+
109
+ def table_exists? name
110
+ connection.tables.include? name.to_s
111
+ end
112
+
113
+ def columns_hash
114
+ connection.columns_hash
115
+ end
116
+
117
+ def schema_cache
118
+ connection
119
+ end
120
+
121
+ def quote thing, column = nil
122
+ connection.quote thing, column
123
+ end
124
+ end
125
+
126
+ class Base
127
+ attr_accessor :connection_pool
128
+
129
+ def initialize
130
+ @connection_pool = ConnectionPool.new
131
+ end
132
+
133
+ def connection
134
+ connection_pool.connection
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,49 @@
1
+ require 'helper'
2
+
3
+ module Arel
4
+ module Nodes
5
+
6
+ describe ArelExtensions::Comparators do
7
+ it "< is equal lt" do
8
+ relation = Arel::Table.new(:users)
9
+ mgr = relation.project relation[:id]
10
+ mgr.where relation[:id]<(10)
11
+ res = mgr.to_sql
12
+ res.must_be_like('SELECT "users"."id" FROM "users" WHERE "users"."id" < 10')
13
+ end
14
+
15
+ it "<= is equal lteq" do
16
+ relation = Arel::Table.new(:users)
17
+ mgr = relation.project relation[:id]
18
+ mgr.where relation[:id]<=(10)
19
+ res = mgr.to_sql
20
+ res.must_be_like('SELECT "users"."id" FROM "users" WHERE "users"."id" <= 10')
21
+ end
22
+
23
+ it "> is equal gt" do
24
+ relation = Arel::Table.new(:users)
25
+ mgr = relation.project relation[:id]
26
+ mgr.where relation[:id]>(10)
27
+ res = mgr.to_sql
28
+ res.must_be_like('SELECT "users"."id" FROM "users" WHERE "users"."id" > 10')
29
+ end
30
+
31
+ it "< is equal gteq" do
32
+ relation = Arel::Table.new(:users)
33
+ mgr = relation.project relation[:id]
34
+ mgr.where relation[:id]>=(10)
35
+ res = mgr.to_sql
36
+ res.must_be_like('SELECT "users"."id" FROM "users" WHERE "users"."id" >= 10')
37
+ end
38
+
39
+ it "should compare with dates" do
40
+ relation = Table.new(:users)
41
+ mgr = relation.project relation[:created_at]
42
+ mgr.where(relation[:created_at] >= Date.new(2016, 3, 31))
43
+ mgr.to_sql.must_match %{"users"."created_at" >= '2016-03-31'}
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,30 @@
1
+ require 'helper'
2
+
3
+ module ArelExtensions
4
+ module BulkInsertOracle
5
+ describe 'the oracle bulk insert visitor' do
6
+ before do
7
+ @conn = FakeRecord::Base.new
8
+ @visitor = Arel::Visitors::Oracle.new @conn.connection
9
+ @table = Arel::Table.new(:users)
10
+ @cols = ['id', 'name', 'comments', 'created_at']
11
+ @data = [
12
+ [23, 'nom1', "sdfdsfdsfsdf", '2016-01-01'],
13
+ [25, 'nom2', "sdfdsfdsfsdf", '2016-01-01']
14
+ ]
15
+ end
16
+
17
+ def compile node
18
+ @visitor.accept(node, Arel::Collectors::SQLString.new).value
19
+ end
20
+
21
+ it "should import large set of data in Oracle" do
22
+ insert_manager = Arel::InsertManager.new(@conn).into(@table)
23
+ insert_manager.bulk_insert(@cols, @data)
24
+ sql = compile(insert_manager.ast)
25
+ sql.must_be_like %Q[INSERT ALL INTO "users" ("id", "name", "comments", "created_at") VALUES (23, 'nom1', 'sdfdsfdsfsdf', '2016-01-01') INTO "users" ("id", "name", "comments", "created_at") VALUES (25, 'nom2', 'sdfdsfdsfsdf', '2016-01-01') SELECT 1 FROM dual]
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,31 @@
1
+ require 'helper'
2
+
3
+ module ArelExtensions
4
+ module BulkInsertSQLlite
5
+
6
+ describe 'the sqlite visitor can bulk insert' do
7
+ before do
8
+ @conn = FakeRecord::Base.new
9
+ @visitor = Arel::Visitors::SQLite.new @conn.connection
10
+ @table = Arel::Table.new(:users)
11
+ @cols = ['id', 'name', 'comments', 'created_at']
12
+ @data = [
13
+ [23, 'nom1', "sdfdsfdsfsdf", '2016-01-01'],
14
+ [25, 'nom2', "sdfdsfdsfsdf", '2016-01-01']
15
+ ]
16
+ end
17
+
18
+ def compile node
19
+ @visitor.accept(node, Arel::Collectors::SQLString.new).value
20
+ end
21
+
22
+ it "should import large set of data" do
23
+ insert_manager = Arel::InsertManager.new(@conn).into(@table)
24
+ insert_manager.bulk_insert(@cols, @data)
25
+ sql = compile(insert_manager.ast)
26
+ 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')]
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ require 'helper'
2
+
3
+ module ArelExtensions
4
+ module BulkInsertToSql
5
+ describe 'the to_sql visitor can bulk insert' do
6
+ before do
7
+ @conn = FakeRecord::Base.new
8
+ @visitor = Arel::Visitors::ToSql.new @conn.connection
9
+ @table = Arel::Table.new(:users)
10
+ @cols = ['id', 'name', 'comments', 'created_at']
11
+ @data = [
12
+ [23, 'nom1', "sdfdsfdsfsdf", '2016-01-01'],
13
+ [25, 'nom2', "sdfdsfdsfsdf", '2016-01-01']
14
+ ]
15
+ end
16
+
17
+ def compile node
18
+ @visitor.accept(node, Arel::Collectors::SQLString.new).value
19
+ end
20
+
21
+
22
+ it "should import large set of data using ToSql" do
23
+ insert_manager = Arel::InsertManager.new(@conn).into(@table)
24
+ insert_manager.bulk_insert(@cols, @data)
25
+ sql = compile(insert_manager.ast)
26
+ 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')]
27
+ end
28
+
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,105 @@
1
+ require 'helper'
2
+
3
+ module ArelExtensions
4
+ module VisitorOracle
5
+ describe 'the Oracle visitor' do
6
+ before do
7
+ @conn = FakeRecord::Base.new
8
+ @visitor = Arel::Visitors::Oracle.new @conn.connection
9
+ @table = Arel::Table.new(:users)
10
+ @attr = @table[:id]
11
+ @date = Date.new(2016, 3, 31)
12
+ end
13
+
14
+ def compile node
15
+ @visitor.accept(node, Arel::Collectors::SQLString.new).value
16
+ end
17
+
18
+ # Comparators
19
+
20
+ it "should accept comparators on integers" do
21
+ compile(@table[:id] == 42).must_match %{"users"."id" = 42}
22
+ compile(@table[:id] == @table[:id]).must_be_like %{"users"."id" = "users"."id"}
23
+ compile(@table[:id] != 42).must_match %{"users"."id" != 42}
24
+ compile(@table[:id] > 42).must_match %{"users"."id" > 42}
25
+ compile(@table[:id] >= 42).must_match %{"users"."id" >= 42}
26
+ compile(@table[:id] >= @table[:id]).must_be_like %{"users"."id" >= "users"."id"}
27
+ compile(@table[:id] < 42).must_match %{"users"."id" < 42}
28
+ compile(@table[:id] <= 42).must_match %{"users"."id" <= 42}
29
+ compile((@table[:id] <= 42).as('new_name')).must_match %{("users"."id" <= 42) AS new_name}
30
+ end
31
+
32
+ it "should accept comparators on dates" do
33
+ c = @table[:created_at]
34
+ u = @table[:updated_at]
35
+ compile(c > @date).must_be_like %{"users"."created_at" > '2016-03-31'}
36
+ compile(u >= @date).must_be_like %{"users"."updated_at" >= '2016-03-31'}
37
+ compile(c < u).must_be_like %{"users"."created_at" < "users"."updated_at"}
38
+ end
39
+
40
+ it "should accept comparators on strings" do
41
+ c = @table[:name]
42
+ compile(c == 'test').must_be_like %{"users"."name" = 'test'}
43
+ compile(c != 'test').must_be_like %{"users"."name" != 'test'}
44
+ compile(c > 'test').must_be_like %{"users"."name" > 'test'}
45
+ compile((c >= 'test').as('new_name')).must_be_like %{("users"."name" >= 'test') AS new_name}
46
+ compile(c <= @table[:comments]).must_be_like %{"users"."name" <= "users"."comments"}
47
+ compile(c =~ /\Atest\Z/).must_be_like %{REGEXP_LIKE("users"."name", '^test$')}
48
+ compile(c =~ '^test$').must_be_like %{REGEXP_LIKE("users"."name", '^test$')}
49
+ compile(c !~ /\Ate\Dst\Z/).must_be_like %{NOT REGEXP_LIKE("users"."name", '^te[^0-9]st$')}
50
+ compile(c.imatches('%test%')).must_be_like %{LOWER("users"."name") LIKE LOWER('%test%')}
51
+ compile(c.imatches_any(['%test%', 't2'])).must_be_like %{(LOWER("users"."name") LIKE LOWER('%test%') OR LOWER("users"."name") LIKE LOWER('t2'))}
52
+ compile(c.idoes_not_match('%test%')).must_be_like %{LOWER("users"."name") NOT LIKE LOWER('%test%')}
53
+ end
54
+
55
+
56
+ # Maths
57
+ # DateDiff
58
+ it "should diff date col and date" do
59
+ compile(@table[:created_at] - Date.new(2016, 3, 31)).must_match %{"users"."created_at" - '2016-03-31'}
60
+ end
61
+
62
+ it "should diff date col and datetime col" do
63
+ compile(@table[:created_at] - @table[:updated_at]).must_match %{"users"."created_at" - "users"."updated_at"}
64
+ end
65
+
66
+ it "should diff date col and datetime col with AS" do
67
+ sql = compile((@table[:updated_at] - @table[:created_at]).as('new_name'))
68
+ sql.must_be_like %{("users"."updated_at" - "users"."created_at") AS new_name}
69
+ end
70
+
71
+ it "should diff between time values" do
72
+ d2 = Time.new(2015,6,1)
73
+ d1 = DateTime.new(2015,6,2)
74
+ sql = compile(ArelExtensions::Nodes::DateDiff.new(d1,d2))
75
+ sql.must_match("'2015-06-02' - '2015-06-01'")
76
+ end
77
+
78
+ it "should diff between time values and time col" do
79
+ d1 = DateTime.new(2015,6,2)
80
+ sql = compile(ArelExtensions::Nodes::DateDiff.new(d1, @table[:updated_at]))
81
+ sql.must_match %{'2015-06-02' - "users"."updated_at"}
82
+ end
83
+
84
+ it "should accept operators on dates with numbers" do
85
+ c = @table[:created_at]
86
+ # u = @table[:updated_at]
87
+ compile(c - 42).must_be_like %{DATE_SUB("users"."created_at", 42)}
88
+ compile(c - @table[:id]).must_be_like %{DATE_SUB("users"."created_at", "users"."id")}
89
+ end
90
+
91
+ # Maths on sums
92
+ it "should accept math operators on anything" do
93
+ c = @table[:name]
94
+ (c == 'test').to_sql.must_be_like %{"users"."name" = 'test'}
95
+ (c != 'test').to_sql.must_be_like %{"users"."name" != 'test'}
96
+ (c > 'test').to_sql.must_be_like %{"users"."name" > 'test'}
97
+ compile((c >= 'test').as('new_name')).must_be_like %{("users"."name" >= 'test') AS new_name}
98
+ compile(c <= @table[:comments]).must_be_like %{"users"."name" <= "users"."comments"}
99
+ compile(c =~ /\Atest\Z/).must_be_like %{REGEXP_LIKE("users"."name", '^test$')}
100
+ compile(c !~ /\Ate\Dst\Z/).must_be_like %{NOT REGEXP_LIKE("users"."name", '^te[^0-9]st$')}
101
+ end
102
+
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,148 @@
1
+ require 'helper'
2
+ require 'set'
3
+
4
+ module ArelExtensions
5
+ module VisitorToSql
6
+ describe 'the to_sql visitor' do
7
+ before do
8
+ @conn = FakeRecord::Base.new
9
+ Arel::Table.engine = @conn
10
+ @visitor = Arel::Visitors::ToSql.new @conn.connection
11
+ @table = Arel::Table.new(:users)
12
+ @attr = @table[:id]
13
+ @date = Date.new(2016, 3, 31)
14
+ @price = Arel::Table.new(:products)[:price]
15
+ end
16
+
17
+ def compile node
18
+ @visitor.accept(node, Arel::Collectors::SQLString.new).value
19
+ end
20
+
21
+ # Math Functions
22
+
23
+ it "should not break Arel functions" do
24
+ compile(@price + 42).must_be_like %{("products"."price" + 42)}
25
+ end
26
+
27
+ it "should return right calculations on numbers" do
28
+ compile(@price.abs + 42).must_be_like %{(ABS("products"."price") + 42)}
29
+ compile(@price.ceil + 42).must_be_like %{(CEIL("products"."price") + 42)}
30
+ compile(@price.floor + 42).must_be_like %{(FLOOR("products"."price") + 42)}
31
+ compile(@price.ceil + @price.floor).must_be_like %{(CEIL("products"."price") + FLOOR("products"."price"))}
32
+ compile((@price.ceil + @price.floor).abs).must_be_like %{ABS((CEIL("products"."price") + FLOOR("products"."price")))}
33
+ compile(@price.round + 42).must_be_like %{(ROUND("products"."price") + 42)}
34
+ compile(@price.round(2) + 42).must_be_like %{(ROUND("products"."price", 2) + 42)}
35
+ compile(Arel.rand + 42).must_be_like %{(RAND() + 42)}
36
+ compile(@price.sum + 42).must_be_like %{(SUM("products"."price") + 42)}
37
+ compile((@price + 42).sum).must_be_like %{SUM(("products"."price" + 42))}
38
+ compile((@price + 42).average).must_be_like %{AVG(("products"."price" + 42))}
39
+ compile((Arel.rand * 9).round + 42).must_be_like %{(ROUND(RAND() * 9) + 42)}
40
+ compile((Arel.rand * @price).round(2) + @price).must_be_like %{(ROUND(RAND() * "products"."price", 2) + "products"."price")}
41
+ end
42
+
43
+ # String Functions
44
+ it "should accept functions on strings" do
45
+ c = @table[:name]
46
+ compile(c + 'test').must_be_like %{"users"."name" || 'test'}
47
+ compile(c + 'test' + ' chain').must_be_like %{"users"."name" || 'test' || ' chain'}
48
+ compile(c.length).must_be_like %{LENGTH("users"."name")}
49
+ compile(c.length.round + 42).must_be_like %{(ROUND(LENGTH("users"."name")) + 42)}
50
+ compile(c.locate('test')).must_be_like %{LOCATE("users"."name", 'test')}
51
+ compile(c & 42).must_be_like %{FIND_IN_SET(42, "users"."name")}
52
+
53
+ compile((c >= 'test').as('new_name')).must_be_like %{("users"."name" >= 'test') AS new_name}
54
+ compile(c <= @table[:comments]).must_be_like %{"users"."name" <= "users"."comments"}
55
+ compile(c =~ /\Atest\Z/).must_be_like %{"users"."name" REGEXP '^test$'}
56
+ compile(c !~ /\Ate\Dst\Z/).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
57
+ compile(c.imatches('%test%')).must_be_like %{"users"."name" ILIKE '%test%'}
58
+ compile(c.imatches_any(['%test%', 't2'])).must_be_like %{("users"."name" ILIKE '%test%' OR "users"."name" ILIKE 't2')}
59
+ compile(c.idoes_not_match('%test%')).must_be_like %{"users"."name" NOT ILIKE '%test%'}
60
+ end
61
+
62
+ # Comparators
63
+
64
+ it "should accept comparators on integers" do
65
+ compile(@table[:id] == 42).must_match %{"users"."id" = 42}
66
+ compile(@table[:id] == @table[:id]).must_be_like %{"users"."id" = "users"."id"}
67
+ compile(@table[:id] != 42).must_match %{"users"."id" != 42}
68
+ compile(@table[:id] > 42).must_match %{"users"."id" > 42}
69
+ compile(@table[:id] >= 42).must_match %{"users"."id" >= 42}
70
+ compile(@table[:id] >= @table[:id]).must_be_like %{"users"."id" >= "users"."id"}
71
+ compile(@table[:id] < 42).must_match %{"users"."id" < 42}
72
+ compile(@table[:id] <= 42).must_match %{"users"."id" <= 42}
73
+ compile((@table[:id] <= 42).as('new_name')).must_match %{("users"."id" <= 42) AS new_name}
74
+ end
75
+
76
+ it "should accept comparators on dates" do
77
+ c = @table[:created_at]
78
+ u = @table[:updated_at]
79
+ compile(c > @date).must_be_like %{"users"."created_at" > '2016-03-31'}
80
+ compile(u >= @date).must_be_like %{"users"."updated_at" >= '2016-03-31'}
81
+ compile(c < u).must_be_like %{"users"."created_at" < "users"."updated_at"}
82
+ end
83
+
84
+ it "should accept comparators on strings" do
85
+ c = @table[:name]
86
+ compile(c == 'test').must_be_like %{"users"."name" = 'test'}
87
+ compile(c != 'test').must_be_like %{"users"."name" != 'test'}
88
+ compile(c > 'test').must_be_like %{"users"."name" > 'test'}
89
+ compile((c >= 'test').as('new_name')).must_be_like %{("users"."name" >= 'test') AS new_name}
90
+ compile(c <= @table[:comments]).must_be_like %{"users"."name" <= "users"."comments"}
91
+ compile(c =~ /\Atest\Z/).must_be_like %{"users"."name" REGEXP '^test$'}
92
+ compile(c !~ /\Ate\Dst\Z/).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
93
+ compile(c.imatches('%test%')).must_be_like %{"users"."name" ILIKE '%test%'}
94
+ compile(c.imatches_any(['%test%', 't2'])).must_be_like %{("users"."name" ILIKE '%test%' OR "users"."name" ILIKE 't2')}
95
+ compile(c.idoes_not_match('%test%')).must_be_like %{"users"."name" NOT ILIKE '%test%'}
96
+ end
97
+
98
+
99
+ # Maths
100
+ # DateDiff
101
+ it "should diff date col and date" do
102
+ compile(@table[:created_at] - Date.new(2016, 3, 31)).must_match %{DATEDIFF("users"."created_at", '2016-03-31')}
103
+ end
104
+
105
+ it "should diff date col and datetime col" do
106
+ compile(@table[:created_at] - @table[:updated_at]).must_match %{DATEDIFF("users"."created_at", "users"."updated_at")}
107
+ end
108
+
109
+ it "should diff date col and datetime col with AS" do
110
+ sql = compile((@table[:updated_at] - @table[:created_at]).as('new_name'))
111
+ sql.must_match %{DATEDIFF("users"."updated_at", "users"."created_at") AS new_name}
112
+ end
113
+
114
+ it "should diff between time values" do
115
+ d2 = Time.new(2015,6,1)
116
+ d1 = DateTime.new(2015,6,2)
117
+ sql = compile(ArelExtensions::Nodes::DateDiff.new(d1,d2))
118
+ sql.must_match("DATEDIFF('2015-06-02', '2015-06-01')")
119
+ end
120
+
121
+ it "should diff between time values and time col" do
122
+ d1 = DateTime.new(2015,6,2)
123
+ sql = compile(ArelExtensions::Nodes::DateDiff.new(d1, @table[:updated_at]))
124
+ sql.must_match %{DATEDIFF('2015-06-02', "users"."updated_at")}
125
+ end
126
+
127
+ it "should accept operators on dates with numbers" do
128
+ c = @table[:created_at]
129
+ # u = @table[:updated_at]
130
+ compile(c - 42).must_be_like %{DATE_SUB("users"."created_at", 42)}
131
+ compile(c - @table[:id]).must_be_like %{DATE_SUB("users"."created_at", "users"."id")}
132
+ end
133
+
134
+ # Maths on sums
135
+ it "should accept math operators on anything" do
136
+ c = @table[:name]
137
+ (c == 'test').to_sql.must_be_like %{"users"."name" = 'test'}
138
+ (c != 'test').to_sql.must_be_like %{"users"."name" != 'test'}
139
+ (c > 'test').to_sql.must_be_like %{"users"."name" > 'test'}
140
+ compile((c >= 'test').as('new_name')).must_be_like %{("users"."name" >= 'test') AS new_name}
141
+ compile(c <= @table[:comments]).must_be_like %{"users"."name" <= "users"."comments"}
142
+ compile(c =~ /\Atest\Z/).must_be_like %{"users"."name" REGEXP '^test$'}
143
+ compile(c !~ /\Ate\Dst\Z/).must_be_like %{"users"."name" NOT REGEXP '^te[^0-9]st$'}
144
+ end
145
+
146
+ end
147
+ end
148
+ end