arel_extensions 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +46 -0
- data/Gemfile +10 -0
- data/MIT-LICENSE.txt +20 -0
- data/README.md +101 -0
- data/Rakefile +14 -0
- data/arel_extensions.gemspec +32 -0
- data/functions.html +344 -0
- data/gemfiles/Gemfile.rails3 +10 -0
- data/gemfiles/Gemfile.rails5 +10 -0
- data/init/mssql.sql +6 -0
- data/init/mysql.sql +0 -0
- data/init/oracle.sql +31 -0
- data/init/postgresql.sql +12 -0
- data/init/sqlite.sql +1 -0
- data/lib/arel_extensions.rb +84 -0
- data/lib/arel_extensions/attributes.rb +26 -0
- data/lib/arel_extensions/comparators.rb +59 -0
- data/lib/arel_extensions/date_duration.rb +28 -0
- data/lib/arel_extensions/insert_manager.rb +33 -0
- data/lib/arel_extensions/math.rb +48 -0
- data/lib/arel_extensions/math_functions.rb +35 -0
- data/lib/arel_extensions/nodes.rb +27 -0
- data/lib/arel_extensions/nodes/abs.rb +6 -0
- data/lib/arel_extensions/nodes/ceil.rb +6 -0
- data/lib/arel_extensions/nodes/coalesce.rb +22 -0
- data/lib/arel_extensions/nodes/concat.rb +33 -0
- data/lib/arel_extensions/nodes/date_diff.rb +106 -0
- data/lib/arel_extensions/nodes/duration.rb +30 -0
- data/lib/arel_extensions/nodes/find_in_set.rb +16 -0
- data/lib/arel_extensions/nodes/floor.rb +6 -0
- data/lib/arel_extensions/nodes/function.rb +17 -0
- data/lib/arel_extensions/nodes/isnull.rb +30 -0
- data/lib/arel_extensions/nodes/length.rb +6 -0
- data/lib/arel_extensions/nodes/locate.rb +33 -0
- data/lib/arel_extensions/nodes/ltrim.rb +28 -0
- data/lib/arel_extensions/nodes/matches.rb +22 -0
- data/lib/arel_extensions/nodes/rand.rb +23 -0
- data/lib/arel_extensions/nodes/replace.rb +36 -0
- data/lib/arel_extensions/nodes/round.rb +15 -0
- data/lib/arel_extensions/nodes/rtrim.rb +29 -0
- data/lib/arel_extensions/nodes/soundex.rb +23 -0
- data/lib/arel_extensions/nodes/sum.rb +23 -0
- data/lib/arel_extensions/nodes/trim.rb +26 -0
- data/lib/arel_extensions/nodes/wday.rb +23 -0
- data/lib/arel_extensions/null_functions.rb +16 -0
- data/lib/arel_extensions/string_functions.rb +68 -0
- data/lib/arel_extensions/version.rb +4 -0
- data/lib/arel_extensions/visitors.rb +6 -0
- data/lib/arel_extensions/visitors/ibm_db.rb +206 -0
- data/lib/arel_extensions/visitors/mssql.rb +213 -0
- data/lib/arel_extensions/visitors/mysql.rb +184 -0
- data/lib/arel_extensions/visitors/oracle.rb +267 -0
- data/lib/arel_extensions/visitors/postgresql.rb +258 -0
- data/lib/arel_extensions/visitors/sqlite.rb +218 -0
- data/lib/arel_extensions/visitors/to_sql.rb +199 -0
- data/test/helper.rb +18 -0
- data/test/real_db_test.rb +251 -0
- data/test/support/fake_record.rb +137 -0
- data/test/test_comparators.rb +49 -0
- data/test/visitors/test_bulk_insert_oracle.rb +30 -0
- data/test/visitors/test_bulk_insert_sqlite.rb +31 -0
- data/test/visitors/test_bulk_insert_to_sql.rb +32 -0
- data/test/visitors/test_oracle.rb +105 -0
- data/test/visitors/test_to_sql.rb +148 -0
- data/test/with_ar/test_bulk_sqlite.rb +44 -0
- data/test/with_ar/test_math_sqlite.rb +59 -0
- data/test/with_ar/test_string_sqlite.rb +69 -0
- 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
|