arel_extensions 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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