arel_extensions 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +43 -34
- data/Gemfile +1 -1
- data/README.md +10 -0
- data/gemfiles/rails4.gemfile +2 -2
- data/gemfiles/rails5_0.gemfile +1 -1
- data/gemfiles/{rails5.gemfile → rails5_1_4.gemfile} +5 -4
- data/gemfiles/rails5_2_beta.gemfile +30 -0
- data/lib/arel_extensions.rb +13 -0
- data/lib/arel_extensions/attributes.rb +2 -0
- data/lib/arel_extensions/nodes.rb +1 -0
- data/lib/arel_extensions/nodes/as.rb +1 -1
- data/lib/arel_extensions/nodes/case.rb +69 -0
- data/lib/arel_extensions/nodes/date_diff.rb +2 -4
- data/lib/arel_extensions/nodes/function.rb +1 -1
- data/lib/arel_extensions/nodes/soundex.rb +1 -1
- data/lib/arel_extensions/predications.rb +9 -0
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/mssql.rb +1 -1
- data/lib/arel_extensions/visitors/mysql.rb +1 -1
- data/lib/arel_extensions/visitors/oracle.rb +1 -1
- data/lib/arel_extensions/visitors/postgresql.rb +11 -1
- data/lib/arel_extensions/visitors/sqlite.rb +10 -0
- data/lib/arel_extensions/visitors/to_sql.rb +33 -5
- data/test/visitors/test_to_sql.rb +39 -2
- data/test/with_ar/all_agnostic_test.rb +32 -9
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b227ca895990c123d78d688d01f00a27a563b70
|
4
|
+
data.tar.gz: 21bc450f1776d263294b6d56523adb59843825bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42e41791d3c25cb5c3a5900b992ee7e22e813bdb278406b3dc3eeaa02ec2477d76696c4abb50a93956f1b9bf55be5ef8234e96720bbcfc47de53afb8b5fb3ab3
|
7
|
+
data.tar.gz: 07fd67e1b8fe666bdff49c2baeae98d828cacfc0ae6a6b049e98850df6db4c0b24c370350feb973fb0b9f04e633955fb4375f33e020910a0b896f9629bfde300
|
data/.travis.yml
CHANGED
@@ -3,24 +3,25 @@ sudo: required
|
|
3
3
|
cache:
|
4
4
|
bundler: true
|
5
5
|
directories:
|
6
|
-
- $
|
6
|
+
- $ORACLE_HOME
|
7
7
|
before_install:
|
8
|
-
- chmod +x .travis/sqlite3/extension-functions.sh
|
9
|
-
- chmod +x .travis/oracle/download.sh
|
10
|
-
- chmod +x .travis/oracle/install.sh
|
11
|
-
- chmod +x .travis/setup_accounts.sh
|
8
|
+
- chmod +x .travis/sqlite3/extension-functions.sh
|
9
|
+
- chmod +x .travis/oracle/download.sh
|
10
|
+
- chmod +x .travis/oracle/install.sh
|
11
|
+
- chmod +x .travis/setup_accounts.sh
|
12
|
+
- sudo apt-get install -y sqlite3-pcre curl
|
13
|
+
- .travis/sqlite3/extension-functions.sh
|
14
|
+
- .travis/oracle/download.sh
|
15
|
+
- .travis/oracle/install.sh
|
16
|
+
- .travis/setup_accounts.sh
|
12
17
|
install:
|
13
|
-
-
|
14
|
-
-
|
15
|
-
- .travis/oracle/download.sh
|
16
|
-
- .travis/oracle/install.sh
|
17
|
-
- .travis/setup_accounts.sh
|
18
|
-
- gem install bundler
|
19
|
-
- bundle install
|
18
|
+
- gem install bundler
|
19
|
+
- bundle install
|
20
20
|
gemfile:
|
21
21
|
- gemfiles/rails4.gemfile
|
22
22
|
- gemfiles/rails5_0.gemfile
|
23
|
-
- gemfiles/
|
23
|
+
- gemfiles/rails5_1_4.gemfile
|
24
|
+
- gemfiles/rails5_2_beta.gemfile
|
24
25
|
services:
|
25
26
|
- mysql
|
26
27
|
- postgresql
|
@@ -78,8 +79,6 @@ matrix:
|
|
78
79
|
jdk: openjdk7
|
79
80
|
- rvm: ruby-head
|
80
81
|
jdk: openjdk7
|
81
|
-
- rvm: jruby-head
|
82
|
-
jdk: openjdk7
|
83
82
|
- rvm: rbx-2
|
84
83
|
jdk: oraclejdk8
|
85
84
|
- rvm: 2.0.0
|
@@ -93,39 +92,49 @@ matrix:
|
|
93
92
|
- rvm: 2.4.0
|
94
93
|
jdk: oraclejdk8
|
95
94
|
- rvm: ruby-head
|
96
|
-
jdk: oraclejdk8
|
95
|
+
jdk: oraclejdk8
|
96
|
+
- rvm: jruby-head
|
97
|
+
jdk: openjdk7
|
97
98
|
- rvm: 2.0.0
|
98
|
-
gemfile: gemfiles/
|
99
|
+
gemfile: gemfiles/rails5_1_4.gemfile
|
99
100
|
- rvm: 2.1
|
100
|
-
gemfile: gemfiles/
|
101
|
-
- rvm: rbx-2
|
102
|
-
gemfile: gemfiles/rails5.gemfile
|
101
|
+
gemfile: gemfiles/rails5_1_4.gemfile
|
103
102
|
- rvm: ruby-head
|
104
103
|
gemfile: gemfiles/rails4.gemfile
|
105
104
|
- rvm: 2.0.0
|
106
105
|
gemfile: gemfiles/rails5_0.gemfile
|
107
106
|
- rvm: 2.1
|
108
|
-
gemfile: gemfiles/rails5_0.gemfile
|
109
|
-
- rvm:
|
110
|
-
gemfile: gemfiles/
|
107
|
+
gemfile: gemfiles/rails5_0.gemfile
|
108
|
+
- rvm: jruby-9.0.5.0
|
109
|
+
gemfile: gemfiles/rails5_1_4.gemfile
|
110
|
+
- rvm: 2.0.0
|
111
|
+
gemfile: gemfiles/rails5_2_beta.gemfile
|
112
|
+
- rvm: 2.1
|
113
|
+
gemfile: gemfiles/rails5_2_beta.gemfile
|
114
|
+
- rvm: jruby-9.0.5.0
|
115
|
+
gemfile: gemfiles/rails5_2_beta.gemfile
|
116
|
+
- rvm: jruby-head
|
117
|
+
gemfile: gemfiles/rails5_2_beta.gemfile
|
111
118
|
allow_failures:
|
112
119
|
- rvm: rbx-2
|
113
|
-
gemfile: gemfiles/rails4.gemfile
|
120
|
+
gemfile: gemfiles/rails4.gemfile
|
114
121
|
- rvm: rbx-2
|
115
|
-
gemfile: gemfiles/rails5_0.gemfile
|
116
|
-
- rvm: jruby-9.0.5.0
|
117
|
-
gemfile: gemfiles/rails5_0.gemfile
|
118
|
-
- rvm: jruby-head
|
119
|
-
gemfile: gemfiles/rails5_0.gemfile
|
122
|
+
gemfile: gemfiles/rails5_0.gemfile
|
120
123
|
- rvm: rbx-2
|
121
|
-
gemfile: gemfiles/
|
122
|
-
- rvm:
|
123
|
-
gemfile: gemfiles/
|
124
|
-
- rvm: jruby-head
|
125
|
-
gemfile: gemfiles/rails5.gemfile
|
124
|
+
gemfile: gemfiles/rails5_1_4.gemfile
|
125
|
+
- rvm: rbx-2
|
126
|
+
gemfile: gemfiles/rails5_2_beta.gemfile
|
126
127
|
- rvm: jruby-head
|
127
128
|
gemfile: gemfiles/rails4.gemfile
|
128
129
|
jdk: oraclejdk9
|
130
|
+
- rvm: jruby-head
|
131
|
+
gemfile: gemfiles/rails5_0.gemfile
|
132
|
+
jdk: oraclejdk9
|
133
|
+
- rvm: rbx-2
|
134
|
+
gemfile: gemfiles/rails5_1_4.gemfile
|
135
|
+
- rvm: jruby-head
|
136
|
+
gemfile: gemfiles/rails5_1_4.gemfile
|
137
|
+
jdk: oraclejdk9
|
129
138
|
bundler_args: "--jobs 3 --retry 2"
|
130
139
|
notifications:
|
131
140
|
email:
|
data/Gemfile
CHANGED
@@ -5,7 +5,7 @@ gemspec
|
|
5
5
|
group :development, :test do
|
6
6
|
gem "sqlite3", :platforms => [:mri, :mswin, :x64_mingw, :mingw]
|
7
7
|
gem "mysql2", :platforms => [:mri, :mswin, :x64_mingw, :mingw]
|
8
|
-
gem "pg", :platforms => [:mri, :mingw, :x64_mingw, :mswin]
|
8
|
+
gem "pg", '< 1.0.0', :platforms => [:mri, :mingw, :x64_mingw, :mswin]
|
9
9
|
|
10
10
|
gem "jdbc-sqlite3", :platforms => :jruby
|
11
11
|
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
|
data/README.md
CHANGED
@@ -133,6 +133,16 @@ t[:birthdate].format('%Y-%m-%d').to_sql
|
|
133
133
|
# => (SELECT * FROM my_table WHERE name='str') UNION (SELECT * FROM my_table WHERE name='test')
|
134
134
|
```
|
135
135
|
|
136
|
+
## Case clause
|
137
|
+
|
138
|
+
Arel-extensions allows to use functions on case clause
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
(t[:name].when("smith").then(1).when("doe").then(2).else(0).sum.to_sql
|
142
|
+
# => SUM(CASE "my_table"."name" WHEN 'smith' THEN 1 WHEN 'doe' THEN 2 ELSE 0 END)
|
143
|
+
```
|
144
|
+
|
145
|
+
|
136
146
|
## Stored Procedures and User-defined functions
|
137
147
|
|
138
148
|
To optimize queries, some classical functions are defined in databases missing any alternative native functions.
|
data/gemfiles/rails4.gemfile
CHANGED
@@ -9,7 +9,7 @@ group :development, :test do
|
|
9
9
|
|
10
10
|
gem "sqlite3", :platforms => [:mri, :mswin, :mingw]
|
11
11
|
gem "mysql2", :platforms => [:mri, :mswin, :mingw]
|
12
|
-
gem "pg", :platforms => [:mri, :mingw]
|
12
|
+
gem "pg",'< 1.0.0', :platforms => [:mri, :mingw]
|
13
13
|
|
14
14
|
gem "tiny_tds", :platforms => [:mri, :mingw, :mswin] if RUBY_PLATFORM =~ /windows/
|
15
15
|
gem "activerecord-sqlserver-adapter", '~> 4.2.0', :platforms => [:mri, :mingw, :mswin] if RUBY_PLATFORM =~ /windows/
|
@@ -26,4 +26,4 @@ group :development, :test do
|
|
26
26
|
gem "activerecord-jdbcmssql-adapter", :platforms => :jruby
|
27
27
|
end
|
28
28
|
|
29
|
-
gemspec :path => "../"
|
29
|
+
gemspec :path => "../"
|
data/gemfiles/rails5_0.gemfile
CHANGED
@@ -9,7 +9,7 @@ group :development, :test do
|
|
9
9
|
|
10
10
|
gem "sqlite3", :platforms => [:mri, :mswin, :mingw]
|
11
11
|
gem "mysql2", :platforms => [:mri, :mswin, :mingw]
|
12
|
-
gem "pg", :platforms => [:mri, :mingw]
|
12
|
+
gem "pg",'< 1.0.0', :platforms => [:mri, :mingw]
|
13
13
|
|
14
14
|
gem "tiny_tds", :platforms => [:mri, :mingw] if RUBY_PLATFORM =~ /windows/
|
15
15
|
# gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
|
@@ -1,15 +1,16 @@
|
|
1
1
|
source "https://rubygems.org"
|
2
2
|
|
3
|
+
gem 'rails', '~> 5.1.4'
|
3
4
|
gem 'arel', '~> 8'
|
4
5
|
|
5
6
|
group :development, :test do
|
6
|
-
gem 'activesupport', '~> 5'
|
7
|
-
gem 'activemodel', '~> 5'
|
8
|
-
gem 'activerecord', '~> 5'
|
7
|
+
gem 'activesupport', '~> 5.1.4'
|
8
|
+
gem 'activemodel', '~> 5.1.4'
|
9
|
+
gem 'activerecord', '~> 5.1.4'
|
9
10
|
|
10
11
|
gem "sqlite3", :platforms => [:mri, :mswin, :mingw]
|
11
12
|
gem "mysql2", :platforms => [:mri, :mswin, :mingw]
|
12
|
-
gem "pg", :platforms => [:mri, :mingw]
|
13
|
+
gem "pg",'< 1.0.0', :platforms => [:mri, :mingw]
|
13
14
|
|
14
15
|
gem "tiny_tds", :platforms => [:mri, :mingw] if RUBY_PLATFORM =~ /windows/
|
15
16
|
# gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
|
@@ -0,0 +1,30 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gem 'rails', '~> 5.2.0.beta2'
|
4
|
+
gem 'arel', '~> 9'
|
5
|
+
|
6
|
+
group :development, :test do
|
7
|
+
gem 'activesupport', '~> 5.2.0.beta2'
|
8
|
+
gem 'activemodel', '~> 5.2.0.beta2'
|
9
|
+
gem 'activerecord', '~> 5.2.0.beta2'
|
10
|
+
|
11
|
+
gem "sqlite3", :platforms => [:mri, :mswin, :mingw]
|
12
|
+
gem "mysql2", :platforms => [:mri, :mswin, :mingw]
|
13
|
+
gem "pg",'< 1.0.0', :platforms => [:mri, :mingw]
|
14
|
+
|
15
|
+
gem "tiny_tds", :platforms => [:mri, :mingw] if RUBY_PLATFORM =~ /windows/
|
16
|
+
# gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw]
|
17
|
+
|
18
|
+
gem 'ruby-oci8', :platforms => [:mri, :mswin, :mingw] if ENV.has_key? 'ORACLE_HOME'
|
19
|
+
gem 'activerecord-oracle_enhanced-adapter', '~> 5.2.0.beta1' if ENV.has_key? 'ORACLE_HOME'
|
20
|
+
|
21
|
+
# for JRuby
|
22
|
+
gem 'activerecord-jdbc-adapter', :github => 'jruby/activerecord-jdbc-adapter', :tag => 'v51.0', :platforms => :jruby
|
23
|
+
gem "jdbc-sqlite3", :platforms => :jruby
|
24
|
+
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
|
25
|
+
gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
|
26
|
+
gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
|
27
|
+
gem "activerecord-jdbcmssql-adapter", :platforms => :jruby
|
28
|
+
end
|
29
|
+
|
30
|
+
gemspec :path => "../"
|
data/lib/arel_extensions.rb
CHANGED
@@ -9,6 +9,7 @@ require 'arel_extensions/railtie' if defined?(Rails::Railtie)
|
|
9
9
|
# pure Arel internals improvements
|
10
10
|
Arel::Nodes::Binary.class_eval do
|
11
11
|
include Arel::AliasPredication
|
12
|
+
include Arel::Expressions
|
12
13
|
end
|
13
14
|
|
14
15
|
Arel::Nodes::Unary.class_eval do
|
@@ -28,6 +29,13 @@ Arel::Nodes::Function.class_eval do
|
|
28
29
|
include Arel::Expressions
|
29
30
|
end
|
30
31
|
|
32
|
+
if Arel::VERSION.to_i >= 7
|
33
|
+
Arel::Nodes::Case.class_eval do
|
34
|
+
include Arel::Math
|
35
|
+
include Arel::Expressions
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
31
39
|
require 'arel_extensions/version'
|
32
40
|
require 'arel_extensions/attributes'
|
33
41
|
require 'arel_extensions/visitors'
|
@@ -48,6 +56,8 @@ require 'arel_extensions/common_sql_functions'
|
|
48
56
|
require 'arel_extensions/nodes/union'
|
49
57
|
require 'arel_extensions/nodes/union_all'
|
50
58
|
require 'arel_extensions/nodes/as'
|
59
|
+
require 'arel_extensions/nodes/case'
|
60
|
+
require 'arel_extensions/predications'
|
51
61
|
|
52
62
|
|
53
63
|
|
@@ -69,6 +79,7 @@ Arel::Nodes::Function.class_eval do
|
|
69
79
|
include ArelExtensions::StringFunctions
|
70
80
|
include ArelExtensions::BooleanFunctions
|
71
81
|
include ArelExtensions::NullFunctions
|
82
|
+
include ArelExtensions::Predications
|
72
83
|
end
|
73
84
|
|
74
85
|
Arel::Nodes::Unary.class_eval do
|
@@ -76,6 +87,7 @@ Arel::Nodes::Unary.class_eval do
|
|
76
87
|
include ArelExtensions::Attributes
|
77
88
|
include ArelExtensions::MathFunctions
|
78
89
|
include ArelExtensions::Comparators
|
90
|
+
include ArelExtensions::Predications
|
79
91
|
end
|
80
92
|
|
81
93
|
Arel::Nodes::Binary.class_eval do
|
@@ -84,6 +96,7 @@ Arel::Nodes::Binary.class_eval do
|
|
84
96
|
include ArelExtensions::MathFunctions
|
85
97
|
include ArelExtensions::Comparators
|
86
98
|
include ArelExtensions::BooleanFunctions
|
99
|
+
include ArelExtensions::Predications
|
87
100
|
end
|
88
101
|
|
89
102
|
Arel::Nodes::Equality.class_eval do
|
@@ -4,6 +4,7 @@ require 'arel_extensions/math'
|
|
4
4
|
require 'arel_extensions/math_functions'
|
5
5
|
require 'arel_extensions/null_functions'
|
6
6
|
require 'arel_extensions/string_functions'
|
7
|
+
require 'arel_extensions/predications'
|
7
8
|
|
8
9
|
module ArelExtensions
|
9
10
|
module Attributes
|
@@ -13,6 +14,7 @@ module ArelExtensions
|
|
13
14
|
include ArelExtensions::MathFunctions
|
14
15
|
include ArelExtensions::NullFunctions
|
15
16
|
include ArelExtensions::StringFunctions
|
17
|
+
include ArelExtensions::Predications
|
16
18
|
|
17
19
|
def ==(other)
|
18
20
|
Arel::Nodes::Equality.new self, Arel::Nodes.build_quoted(other, self)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module ArelExtensions
|
2
|
+
module Nodes
|
3
|
+
if Arel::VERSION.to_i < 7
|
4
|
+
class Case < Arel::Nodes::Node
|
5
|
+
include ArelExtensions::Predications
|
6
|
+
include Arel::Expressions
|
7
|
+
|
8
|
+
attr_accessor :case, :conditions, :default
|
9
|
+
|
10
|
+
def initialize expression = nil, default = nil
|
11
|
+
@case = expression
|
12
|
+
@conditions = []
|
13
|
+
@default = default
|
14
|
+
end
|
15
|
+
|
16
|
+
def when condition, expression = nil
|
17
|
+
@conditions << When.new(Arel::Nodes.build_quoted(condition), expression)
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def then expression
|
22
|
+
@conditions.last.right = Arel::Nodes.build_quoted(expression)
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def else expression
|
27
|
+
@default = Else.new Arel::Nodes.build_quoted(expression)
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize_copy other
|
32
|
+
super
|
33
|
+
@case = @case.clone if @case
|
34
|
+
@conditions = @conditions.map { |x| x.clone }
|
35
|
+
@default = @default.clone if @default
|
36
|
+
end
|
37
|
+
|
38
|
+
def hash
|
39
|
+
[@case, @conditions, @default].hash
|
40
|
+
end
|
41
|
+
|
42
|
+
def eql? other
|
43
|
+
self.class == other.class &&
|
44
|
+
self.case == other.case &&
|
45
|
+
self.conditions == other.conditions &&
|
46
|
+
self.default == other.default
|
47
|
+
end
|
48
|
+
alias :== :eql?
|
49
|
+
|
50
|
+
def as other
|
51
|
+
ArelExtensions::Nodes::As.new self, Arel::Nodes::SqlLiteral.new(other)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class When < Arel::Nodes::Binary # :nodoc:
|
56
|
+
end
|
57
|
+
|
58
|
+
class Else < Arel::Nodes::Unary # :nodoc:
|
59
|
+
end
|
60
|
+
|
61
|
+
else
|
62
|
+
|
63
|
+
class Case < Arel::Nodes::Case
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -62,10 +62,8 @@ module ArelExtensions
|
|
62
62
|
def mysql_value(v = nil)
|
63
63
|
v ||= self.expressions.last
|
64
64
|
if defined?(ActiveSupport::Duration) && ActiveSupport::Duration === v
|
65
|
-
if @date_type == :date
|
66
|
-
Arel.sql(
|
67
|
-
elsif @date_type == :datetime
|
68
|
-
Arel.sql((v.value >= 0 ? 'INTERVAL ' : 'INTERVAL -') + v.inspect.sub(/s\Z/, ''))
|
65
|
+
if @date_type == :date || @date_type == :datetime
|
66
|
+
Arel.sql('INTERVAL %s' % v.inspect.sub(/s\Z/, ''))
|
69
67
|
end
|
70
68
|
else
|
71
69
|
v
|
@@ -307,7 +307,7 @@ module ArelExtensions
|
|
307
307
|
def visit_ArelExtensions_Nodes_GroupConcat o, collector
|
308
308
|
collector << "(LISTAGG("
|
309
309
|
collector = visit o.left, collector
|
310
|
-
if o.right
|
310
|
+
if o.right && o.right != 'NULL'
|
311
311
|
collector << Arel::Visitors::Oracle::COMMA
|
312
312
|
collector = visit o.right, collector
|
313
313
|
end
|
@@ -47,7 +47,7 @@ module ArelExtensions
|
|
47
47
|
def visit_ArelExtensions_Nodes_GroupConcat o, collector
|
48
48
|
collector << "GROUP_CONCAT("
|
49
49
|
collector = visit o.left, collector
|
50
|
-
if o.right
|
50
|
+
if o.right && o.right != 'NULL'
|
51
51
|
collector << ' SEPARATOR '
|
52
52
|
collector = visit o.right, collector
|
53
53
|
end
|
@@ -47,7 +47,7 @@ module ArelExtensions
|
|
47
47
|
def visit_ArelExtensions_Nodes_GroupConcat o, collector
|
48
48
|
collector << "(LISTAGG("
|
49
49
|
collector = visit o.left, collector
|
50
|
-
if o.right
|
50
|
+
if o.right && o.right != 'NULL'
|
51
51
|
collector << Arel::Visitors::Oracle::COMMA
|
52
52
|
collector = visit o.right, collector
|
53
53
|
end
|
@@ -35,12 +35,22 @@ module ArelExtensions
|
|
35
35
|
collector = visit o.right, collector
|
36
36
|
collector
|
37
37
|
end
|
38
|
+
|
39
|
+
def visit_ArelExtensions_Nodes_Concat o, collector
|
40
|
+
collector << '('
|
41
|
+
o.expressions.each_with_index { |arg, i|
|
42
|
+
collector = visit arg, collector
|
43
|
+
collector << ' || ' unless i == o.expressions.length - 1
|
44
|
+
}
|
45
|
+
collector << ")"
|
46
|
+
collector
|
47
|
+
end
|
38
48
|
|
39
49
|
def visit_ArelExtensions_Nodes_GroupConcat o, collector
|
40
50
|
collector << "array_to_string(array_agg("
|
41
51
|
collector = visit o.left, collector
|
42
52
|
collector << ")"
|
43
|
-
if o.right
|
53
|
+
if o.right && o.right != 'NULL'
|
44
54
|
collector << Arel::Visitors::PostgreSQL::COMMA
|
45
55
|
collector = visit o.right, collector
|
46
56
|
else
|
@@ -77,6 +77,16 @@ module ArelExtensions
|
|
77
77
|
collector
|
78
78
|
end
|
79
79
|
|
80
|
+
def visit_ArelExtensions_Nodes_Concat o, collector
|
81
|
+
collector << '('
|
82
|
+
o.expressions.each_with_index { |arg, i|
|
83
|
+
collector = visit arg, collector
|
84
|
+
collector << ' || ' unless i == o.expressions.length - 1
|
85
|
+
}
|
86
|
+
collector << ")"
|
87
|
+
collector
|
88
|
+
end
|
89
|
+
|
80
90
|
def visit_ArelExtensions_Nodes_Substring o, collector
|
81
91
|
collector << "SUBSTR("
|
82
92
|
o.expressions.each_with_index { |arg, i|
|
@@ -55,10 +55,10 @@ module ArelExtensions
|
|
55
55
|
|
56
56
|
# String functions
|
57
57
|
def visit_ArelExtensions_Nodes_Concat o, collector
|
58
|
-
collector <<
|
59
|
-
|
58
|
+
collector << "CONCAT("
|
59
|
+
o.expressions.each_with_index { |arg, i|
|
60
|
+
collector << Arel::Visitors::ToSql::COMMA unless i == 0
|
60
61
|
collector = visit arg, collector
|
61
|
-
collector << ' || ' unless i == o.expressions.length - 1
|
62
62
|
}
|
63
63
|
collector << ")"
|
64
64
|
collector
|
@@ -67,7 +67,7 @@ module ArelExtensions
|
|
67
67
|
def visit_ArelExtensions_Nodes_GroupConcat o, collector
|
68
68
|
collector << "GROUP_CONCAT("
|
69
69
|
collector = visit o.left, collector
|
70
|
-
if o.right
|
70
|
+
if o.right && o.right != 'NULL'
|
71
71
|
collector << Arel::Visitors::ToSql::COMMA
|
72
72
|
collector = visit o.right, collector
|
73
73
|
end
|
@@ -406,7 +406,35 @@ module ArelExtensions
|
|
406
406
|
end
|
407
407
|
end
|
408
408
|
|
409
|
-
|
409
|
+
def visit_ArelExtensions_Nodes_Case o, collector
|
410
|
+
collector << "CASE "
|
411
|
+
if o.case
|
412
|
+
visit o.case, collector
|
413
|
+
collector << " "
|
414
|
+
end
|
415
|
+
o.conditions.each do |condition|
|
416
|
+
visit condition, collector
|
417
|
+
collector << " "
|
418
|
+
end
|
419
|
+
if o.default
|
420
|
+
visit o.default, collector
|
421
|
+
collector << " "
|
422
|
+
end
|
423
|
+
collector << "END"
|
424
|
+
end
|
425
|
+
|
426
|
+
def visit_ArelExtensions_Nodes_When o, collector
|
427
|
+
collector << "WHEN "
|
428
|
+
visit o.left, collector
|
429
|
+
collector << " THEN "
|
430
|
+
visit o.right, collector
|
431
|
+
end
|
410
432
|
|
433
|
+
def visit_ArelExtensions_Nodes_Else o, collector
|
434
|
+
collector << "ELSE "
|
435
|
+
visit o.expr, collector
|
436
|
+
end
|
437
|
+
|
438
|
+
end
|
411
439
|
end
|
412
440
|
end
|
@@ -58,8 +58,8 @@ module ArelExtensions
|
|
58
58
|
# String Functions
|
59
59
|
it "should accept functions on strings" do
|
60
60
|
c = @table[:name]
|
61
|
-
compile(c + 'test').must_be_like %{("users"
|
62
|
-
compile(c + 'test' + ' chain').must_be_like %{("users"
|
61
|
+
compile(c + 'test').must_be_like %{CONCAT(\"users\".\"name\", 'test')}
|
62
|
+
compile(c + 'test' + ' chain').must_be_like %{CONCAT(\"users\".\"name\", 'test', ' chain')}
|
63
63
|
compile(c.length).must_be_like %{LENGTH("users"."name")}
|
64
64
|
compile(c.length.round + 42).must_be_like %{(ROUND(LENGTH("users"."name")) + 42)}
|
65
65
|
compile(c.locate('test')).must_be_like %{LOCATE('test', "users"."name")}
|
@@ -110,6 +110,10 @@ module ArelExtensions
|
|
110
110
|
compile(c.idoes_not_match('%test%')).must_be_like %{"users"."name" NOT ILIKE '%test%'}
|
111
111
|
end
|
112
112
|
|
113
|
+
it "should accept comparators on functions" do
|
114
|
+
c = @table[:name]
|
115
|
+
#compile(c.soundex == 'test').must_be_like %{SOUNDEX("users"."name") = 'test'}
|
116
|
+
end
|
113
117
|
|
114
118
|
# Maths
|
115
119
|
# DateDiff
|
@@ -138,6 +142,15 @@ module ArelExtensions
|
|
138
142
|
sql = compile(ArelExtensions::Nodes::DateDiff.new([d1, @table[:updated_at]]))
|
139
143
|
sql.must_match %{DATEDIFF('2015-06-02', "users"."updated_at")}
|
140
144
|
end
|
145
|
+
|
146
|
+
it "should diff between date col and duration" do
|
147
|
+
d1 = 10
|
148
|
+
d2 = -10
|
149
|
+
compile(@table[:created_at] - d1).
|
150
|
+
must_match %{DATE_SUB("users"."created_at", 10)}
|
151
|
+
compile(@table[:created_at] - d2).
|
152
|
+
must_match %{DATE_SUB("users"."created_at", -10)}
|
153
|
+
end
|
141
154
|
|
142
155
|
it "should accept operators on dates with numbers" do
|
143
156
|
c = @table[:created_at]
|
@@ -165,6 +178,13 @@ module ArelExtensions
|
|
165
178
|
).must_be_like %{FLOOR(ROUND(LENGTH("users"."name") / 42, 2)) > CEIL(ABS(TIMEDIFF("users"."updated_at", '2000-03-31 00:00:00 UTC')))}
|
166
179
|
end
|
167
180
|
|
181
|
+
it "should accept aggregator like GROUP CONCAT" do
|
182
|
+
@table.project(@table[:first_name].group_concat).group(@table[:last_name]).to_sql
|
183
|
+
.must_be_like %{SELECT GROUP_CONCAT("users"."first_name") FROM "users" GROUP BY "users"."last_name"}
|
184
|
+
@table.project(@table[:first_name].group_concat('++')).group(@table[:last_name]).to_sql
|
185
|
+
.must_be_like %{SELECT GROUP_CONCAT("users"."first_name", '++') FROM "users" GROUP BY "users"."last_name"}
|
186
|
+
end
|
187
|
+
|
168
188
|
# Unions
|
169
189
|
it "should accept union operators on queries and union nodes" do
|
170
190
|
c = @table.project(@table[:name])
|
@@ -199,6 +219,23 @@ module ArelExtensions
|
|
199
219
|
|
200
220
|
end
|
201
221
|
|
222
|
+
|
223
|
+
puts "AREL VERSION : " + Arel::VERSION.to_s
|
224
|
+
|
225
|
+
# Case
|
226
|
+
it "should accept case clause" do
|
227
|
+
@table[:name].when("smith").then("cool").when("doe").then("fine").else("uncool").to_sql
|
228
|
+
.must_be_like %{CASE "users"."name" WHEN 'smith' THEN 'cool' WHEN 'doe' THEN 'fine' ELSE 'uncool' END}
|
229
|
+
@table[:name].when("smith").then(1).when("doe").then(2).else(0).to_sql
|
230
|
+
.must_be_like %{CASE "users"."name" WHEN 'smith' THEN 1 WHEN 'doe' THEN 2 ELSE 0 END}
|
231
|
+
ArelExtensions::Nodes::Case.new.when(@table[:name] == "smith").then(1).when(@table[:name] == "doe").then(2).else(0).to_sql
|
232
|
+
.must_be_like %{CASE WHEN "users"."name" = 'smith' THEN 1 WHEN "users"."name" = 'doe' THEN 2 ELSE 0 END}
|
233
|
+
ArelExtensions::Nodes::Case.new(@table[:name]).when("smith").then(1).when("doe").then(2).else(0).to_sql
|
234
|
+
.must_be_like %{CASE "users"."name" WHEN 'smith' THEN 1 WHEN 'doe' THEN 2 ELSE 0 END}
|
235
|
+
@table[:name].when("smith").then(1).when("doe").then(2).else(0).sum.to_sql
|
236
|
+
.must_be_like %{SUM(CASE "users"."name" WHEN 'smith' THEN 1 WHEN 'doe' THEN 2 ELSE 0 END)}
|
237
|
+
end
|
238
|
+
|
202
239
|
end
|
203
240
|
end
|
204
241
|
end
|
@@ -147,15 +147,23 @@ module ArelExtensions
|
|
147
147
|
|
148
148
|
# String Functions
|
149
149
|
def test_concat
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
150
|
+
assert_equal 'Camille Camille', t(@camille, @name + ' ' + @name)
|
151
|
+
assert_equal 'Laure 2', t(@laure, @name + ' ' + 2)
|
152
|
+
assert_equal 'Test Laure', t(@laure, Arel::Nodes.build_quoted('Test ') + @name)
|
153
|
+
skip "TODO: find a way... to do group_concat/listagg in SQL Server" if @env_db == 'mssql'
|
154
|
+
if @env_db == 'postgresql'
|
155
|
+
assert_equal "Lucas Sophie", t(User.reorder(nil).from(User.select(:name).where(:name => ['Lucas', 'Sophie']).reorder(:name).as('user_tests')), @name.group_concat(' '))
|
156
|
+
assert_equal "Lucas,Sophie", t(User.reorder(nil).from(User.select(:name).where(:name => ['Lucas', 'Sophie']).reorder(:name).as('user_tests')), @name.group_concat(','))
|
157
|
+
assert_equal "Lucas Sophie", t(User.reorder(nil).from(User.select(:name).where(:name => ['Lucas', 'Sophie']).reorder(:name).as('user_tests')), @name.group_concat)
|
158
|
+
else
|
159
|
+
assert_equal "Lucas Sophie", t(User.where(:name => ['Lucas', 'Sophie']).reorder(:name), @name.group_concat(' '))
|
160
|
+
assert_equal "Lucas,Sophie", t(User.where(:name => ['Lucas', 'Sophie']).reorder(:name), @name.group_concat(','))
|
161
|
+
if @env_db == 'oracle'
|
162
|
+
assert_equal "LucasSophie", t(User.where(:name => ['Lucas', 'Sophie']).reorder(:name), @name.group_concat)
|
163
|
+
else
|
164
|
+
assert_equal "Lucas,Sophie", t(User.where(:name => ['Lucas', 'Sophie']).reorder(:name), @name.group_concat)
|
165
|
+
end
|
166
|
+
end
|
159
167
|
end
|
160
168
|
|
161
169
|
def test_length
|
@@ -361,6 +369,17 @@ module ArelExtensions
|
|
361
369
|
else
|
362
370
|
assert_includes [nil, 0, 'f', false], t(@lucas, (@updated_at - Time.utc(2014, 3, 3, 12, 41, 18)) < -1)
|
363
371
|
end
|
372
|
+
if @env_db == 'mysql'
|
373
|
+
date1 = Date.new(2016, 5, 23)
|
374
|
+
durPos = 10.years
|
375
|
+
durNeg = -10.years
|
376
|
+
date2 = date1 + durPos
|
377
|
+
date3 = date1 - durPos
|
378
|
+
# Pull Request #5 tests
|
379
|
+
assert_includes [date2,"2026-05-23"], t(@test,(@created_at + durPos))
|
380
|
+
assert_includes [date3,"2006-05-23"], t(@test,(@created_at + durNeg))
|
381
|
+
# we test with the ruby object or the string because some adapters don't return an object Date
|
382
|
+
end
|
364
383
|
end
|
365
384
|
end
|
366
385
|
|
@@ -435,6 +454,10 @@ module ArelExtensions
|
|
435
454
|
assert_equal 3, User.select('*').from((@ut.project(@age).where(@age.eq(20)).union_all(@ut.project(@age).where(@age.eq(20))).union_all(@ut.project(@age).where(@age.eq(21)))).as('my_union')).length
|
436
455
|
end
|
437
456
|
|
457
|
+
# Case clause
|
458
|
+
def test_case
|
459
|
+
assert_equal 4, User.find_by_sql(@ut.project(@score.when(20.16).then(1).else(0).as('score_bin')).to_sql).sum(&:score_bin)
|
460
|
+
end
|
438
461
|
|
439
462
|
end
|
440
463
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arel_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yann Azoury
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2018-01-16 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: arel
|
@@ -101,8 +101,9 @@ files:
|
|
101
101
|
- functions.html
|
102
102
|
- gemfiles/rails3.gemfile
|
103
103
|
- gemfiles/rails4.gemfile
|
104
|
-
- gemfiles/rails5.gemfile
|
105
104
|
- gemfiles/rails5_0.gemfile
|
105
|
+
- gemfiles/rails5_1_4.gemfile
|
106
|
+
- gemfiles/rails5_2_beta.gemfile
|
106
107
|
- init/mssql.sql
|
107
108
|
- init/mysql.sql
|
108
109
|
- init/oracle.sql
|
@@ -121,6 +122,7 @@ files:
|
|
121
122
|
- lib/arel_extensions/nodes/abs.rb
|
122
123
|
- lib/arel_extensions/nodes/as.rb
|
123
124
|
- lib/arel_extensions/nodes/blank.rb
|
125
|
+
- lib/arel_extensions/nodes/case.rb
|
124
126
|
- lib/arel_extensions/nodes/ceil.rb
|
125
127
|
- lib/arel_extensions/nodes/change_case.rb
|
126
128
|
- lib/arel_extensions/nodes/coalesce.rb
|
@@ -146,6 +148,7 @@ files:
|
|
146
148
|
- lib/arel_extensions/nodes/union_all.rb
|
147
149
|
- lib/arel_extensions/nodes/wday.rb
|
148
150
|
- lib/arel_extensions/null_functions.rb
|
151
|
+
- lib/arel_extensions/predications.rb
|
149
152
|
- lib/arel_extensions/railtie.rb
|
150
153
|
- lib/arel_extensions/set_functions.rb
|
151
154
|
- lib/arel_extensions/string_functions.rb
|