arel_extensions 0.8.7 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e8d7cc16253e73e976d81b8beb558c2041c2915f
4
- data.tar.gz: 7ff4c6640d063ef79b6ada768ae7b57cb9bf4dd4
3
+ metadata.gz: d3be3f3b4a82f0721265a42e8ae75fe66da12ba3
4
+ data.tar.gz: a1660c2b64388e6e56bf442de63504da32c2c5ca
5
5
  SHA512:
6
- metadata.gz: 2b2748e84a31a944bc2a835036ff81be4528d3a85940ea34ee6d65389bf86c5c67230ec7dea7c726375395733da138cfd80920463475a54c4e97abc024f3cd76
7
- data.tar.gz: 7779b7ef80ab54c3f08e1bf3016d0e9311393576f18be74d5795d7e86d8fc1390afaf12f6d9271cb47e0a5a6e57e947eafb204d9a06ddae5ae9dae04bf278c9f
6
+ metadata.gz: 4465b08c98214889ca8be08d437a49deeb59df7de899095bcb4c4a7e7ff5d11c8c1cf50a7f8961d0f73b39b5ba0da2db36cfadd3fda4a4e8ee2eaacdc5251978
7
+ data.tar.gz: 5781edd20996ca251937563e1fa15a6fa453a250654aa8191fade92b56970edcb205fe1f5cb37659cbd80460451d0cac858a32f8733919aa6b29bf26640eb519
data/.travis.yml CHANGED
@@ -89,6 +89,10 @@ matrix:
89
89
  - rvm: ruby-head
90
90
  gemfile: gemfiles/rails4.gemfile
91
91
  allow_failures:
92
+ - rvm: rbx-2
93
+ gemfile: gemfiles/rails4.gemfile
94
+ - rvm: rbx-2
95
+ gemfile: gemfiles/rails5.gemfile
92
96
  - rvm: jruby-9.0.5.0
93
97
  gemfile: gemfiles/rails5.gemfile
94
98
  - rvm: jruby-head
data/Gemfile CHANGED
@@ -2,7 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- group :test do
5
+ group :development, :test do
6
6
  gem "sqlite3", :platforms => [:mri, :mswin, :mingw, :x64_mingw]
7
7
  gem "mysql2", :platforms => [:mri, :mswin, :mingw, :x64_mingw]
8
8
  gem "pg", :platforms => [:mri, :mingw, :x64_mingw]
@@ -13,7 +13,7 @@ group :test do
13
13
  gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
14
14
 
15
15
  gem "tiny_tds", :platforms => [:mri, :mingw, :x64_mingw]
16
- gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw, :x64_mingw]
16
+ gem "activerecord-sqlserver-adapter", '~> 4.2.0', :platforms => [:mri, :mingw, :x64_mingw]
17
17
 
18
18
  gem 'activesupport', '~> 4.0'
19
19
  gem 'activemodel', '~> 4.0'
data/SQL_Challenges.md ADDED
@@ -0,0 +1,29 @@
1
+ # SQL Challenges
2
+
3
+ It should be possible to do any advanced SQL functions of any RDBMS in any other using classical SQL routines. We hope so.
4
+ But here are some of the features we did not succeed to create in some cases. Any help would be very useful.
5
+ A good way could be to create user defined functions to ensure a total transparent compatibility and to encapsulate these improvements.
6
+
7
+
8
+ ## SQLite (without extension)
9
+ - CEIL and FLOOR without pcre
10
+ - FIND_IN_SET
11
+ - LOCATE
12
+ - REGEXP
13
+ - SOUNDEX
14
+
15
+ ## PostgreSQL (without extension)
16
+ - SOUNDEX
17
+
18
+
19
+ ## Oracle
20
+ - Maths Operators on string ('a' <= 'b')
21
+
22
+
23
+ ## SQL Server (any version > 2005, without extension)
24
+ - REGEXP
25
+ - (L/R)TRIM(str, 'x') -> TRIM with arguments
26
+ - Maths Operators on string ('a' <= 'b')
27
+ - GROUP_CONCAT
28
+ - FIND_IN_SET
29
+ - any date format (YYYY/MM/DD HH:MM:SS:MMM for example)
@@ -1,27 +1,27 @@
1
1
  # # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
- # require "arel_extensions"
3
+ require "arel_extensions/version"
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "arel_extensions"
7
- s.version = '0.8.7'
7
+ s.version = ArelExtensions::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Yann Azoury", "Mathilde Pechdimaldjian", "Félix Bellanger"]
10
10
  s.email = ["yann.azoury@faveod.com", "mathilde.pechdimaldjian@gmail.com", "felix.bellanger@faveod.com"]
11
11
  s.homepage = "https://github.com/Faveod/arel-extensions"
12
12
  s.description = "Adds new features to Arel"
13
13
  s.summary = "Extending Arel"
14
- s.license = %q{MIT}
14
+ s.license = 'MIT'
15
15
 
16
16
  s.rdoc_options = ["--main", "README.md"]
17
- s.extra_rdoc_files = ["MIT-LICENSE.txt", "README.md"]
17
+ s.extra_rdoc_files = ["MIT-LICENSE.txt", "README.md", 'functions.html']
18
18
 
19
19
  # Manifest
20
20
  s.files = `git ls-files`.split("\n")
21
21
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
22
  s.require_paths = ["lib"]
23
23
 
24
- s.add_dependency('arel', '~> 6.0')
24
+ s.add_dependency('arel', '>= 6.0')
25
25
 
26
26
  s.add_development_dependency('minitest', '~> 5.9')
27
27
  s.add_development_dependency('rdoc', '~> 4.0')
data/functions.html CHANGED
@@ -199,7 +199,7 @@
199
199
  <td class="tg-j6lv">TRIM()<br></td>
200
200
  <td class="tg-j6lv">TRIM()</td>
201
201
  <td class="tg-baqh">✔</td>
202
- <td class="tg-baqh">✔</td>
202
+ <td class="tg-baqh">LTRIM(RTRIM())</td>
203
203
  <td class="tg-j6lv">TRIM()</td>
204
204
  </tr>
205
205
  <tr>
@@ -12,7 +12,7 @@ group :development, :test do
12
12
  gem "pg", :platforms => [:mri, :mingw, :x64_mingw]
13
13
 
14
14
  gem "tiny_tds", :platforms => [:mri, :mingw, :x64_mingw]
15
- gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw, :x64_mingw]
15
+ gem "activerecord-sqlserver-adapter", '~> 4.2.0', :platforms => [:mri, :mingw, :x64_mingw]
16
16
 
17
17
  gem 'ruby-oci8', :platforms => [:mri, :mswin, :mingw] if ENV.has_key? 'ORACLE_HOME'
18
18
  gem 'activerecord-oracle_enhanced-adapter', '~> 1.6.0' if ENV.has_key? 'ORACLE_HOME'
data/init/mssql.sql CHANGED
@@ -1,6 +1,44 @@
1
- CREATE FUNCTION TRIM(@string VARCHAR(MAX))
1
+ IF OBJECT_ID (N'dbo.TRIM', N'FN') IS NOT NULL
2
+ DROP FUNCTION dbo.TRIM;
3
+ GO
4
+ CREATE FUNCTION dbo.TRIM (@string VARCHAR(MAX))
2
5
  RETURNS VARCHAR(MAX)
6
+ AS
3
7
  BEGIN
4
- RETURN LTRIM(RTRIM(@string))
5
- END
8
+ RETURN LTRIM(RTRIM(@string));
9
+ END;
10
+ GO
11
+
12
+ -----------------------------
13
+ -- GO
14
+
15
+ IF OBJECT_ID (N'dbo.FIND_IN_SET', N'FN') IS NOT NULL
16
+ DROP FUNCTION dbo.FIND_IN_SET;
6
17
  GO
18
+ -- CREATE FUNCTION dbo.FIND_IN_SET(@value VARCHAR(MAX), @list VARCHAR(MAX), @delim VARCHAR(MAX))
19
+ -- RETURNS VARCHAR(MAX)
20
+ -- AS BEGIN
21
+ -- RETURN LTRIM(RTRIM(@value));
22
+ -- END;
23
+
24
+ -- GO
25
+
26
+ --IF OBJECT_ID (N'dbo.SplitString', N'FN') IS NOT NULL
27
+ -- DROP FUNCTION dbo.SplitString;
28
+ --GO
29
+ --CREATE FUNCTION dbo.SplitString (@List NVARCHAR(MAX), @Delim VARCHAR(255))
30
+ --RETURNS TABLE
31
+ --AS
32
+ --BEGIN
33
+ -- RETURN ( SELECT [Value] FROM
34
+ -- (
35
+ -- SELECT
36
+ -- [Value] = LTRIM(RTRIM(SUBSTRING(@List, [Number],
37
+ -- CHARINDEX(@Delim, @List + @Delim, [Number]) - [Number])))
38
+ -- FROM (SELECT Number = ROW_NUMBER() OVER (ORDER BY name)
39
+ -- FROM sys.all_objects) AS x
40
+ -- WHERE Number <= LEN(@List)
41
+ -- AND SUBSTRING(@Delim + @List, [Number], LEN(@Delim)) = @Delim
42
+ -- ) AS y
43
+ -- );
44
+ --END;
@@ -4,7 +4,8 @@ module ArelExtensions
4
4
  @@return_type = :boolean
5
5
 
6
6
  def initialize expr
7
- super [expr.first.coalesce('').trim.trim("\t").trim("\n")]
7
+ # super [expr.first.coalesce('').trim.trim("\t").trim("\n")]
8
+ super expr
8
9
  end
9
10
  end
10
11
  end
@@ -90,8 +90,32 @@ module ArelExtensions
90
90
  elsif @date_type == :datetime
91
91
  Arel.sql("INTERVAL '%s' SECOND" % v.to_i)
92
92
  end
93
- # elsif Arel::Attributes::Attribute === v
94
- # v
93
+ else
94
+ v
95
+ end
96
+ end
97
+
98
+ def mssql_value(v = nil)
99
+ v ||= self.expressions.last
100
+ if defined?(ActiveSupport::Duration) && ActiveSupport::Duration === v
101
+ if @date_type == :date
102
+ v.inspect.to_i
103
+ elsif @date_type == :datetime
104
+ v.to_i
105
+ end
106
+ else
107
+ v
108
+ end
109
+ end
110
+
111
+ def mssql_datepart(v = nil)
112
+ v ||= self.expressions.last
113
+ if defined?(ActiveSupport::Duration) && ActiveSupport::Duration === v
114
+ if @date_type == :date
115
+ Arel.sql('day')
116
+ elsif @date_type == :datetime
117
+ Arel.sql('second')
118
+ end
95
119
  else
96
120
  v
97
121
  end
@@ -1,4 +1,4 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module ArelExtensions
3
- VERSION = "0.8.7".freeze
3
+ VERSION = "0.9.0".freeze
4
4
  end
@@ -3,4 +3,21 @@ require 'arel_extensions/visitors/mysql'
3
3
  require 'arel_extensions/visitors/oracle'
4
4
  require 'arel_extensions/visitors/postgresql'
5
5
  require 'arel_extensions/visitors/sqlite'
6
- require 'arel_extensions/visitors/mssql'
6
+ require 'arel_extensions/visitors/mssql'
7
+
8
+ Arel::Visitors::MSSQL.class_eval do
9
+ include ArelExtensions::Visitors::MSSQL
10
+ end
11
+
12
+ begin
13
+ require 'arel_sqlserver'
14
+ if Arel::VERSION.to_i == 6
15
+ if Arel::Visitors::VISITORS['sqlserver'] && Arel::Visitors::VISITORS['sqlserver'] != Arel::Visitors::MSSQL
16
+ Arel::Visitors::VISITORS['sqlserver'].class_eval do
17
+ include ArelExtensions::Visitors::MSSQL
18
+ end
19
+ end
20
+ end
21
+ rescue LoadError
22
+ rescue => e
23
+ end
@@ -1,12 +1,25 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- Arel::Visitors::MSSQL.class_eval do
3
+ module MSSQL
4
+ Arel::Visitors::MSSQL::DATE_MAPPING = {'d' => 'day', 'm' => 'month', 'y' => 'year', 'wd' => 'weekday', 'w' => 'week'}
4
5
  Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES = {
5
- '%Y' => 'yy', '%C' => '', '%y' => 'yy', '%m' => 'mm', '%B' => '', '%b' => '', '%^b' => '', # year, month
6
- '%d' => 'dd', '%e' => '', '%j' => '', '%w' => 'dw', '%A' => '', # day, weekday
6
+ '%Y' => 'YYYY', '%C' => '', '%y' => 'YY', '%m' => 'MM', '%B' => '', '%b' => '', '%^b' => '', # year, month
7
+ '%d' => 'DD', '%e' => '', '%j' => '', '%w' => 'dw', '%A' => '', # day, weekday
7
8
  '%H' => 'hh', '%k' => '', '%I' => '', '%l' => '', '%P' => '', '%p' => '', # hours
8
9
  '%M' => 'mi', '%S' => 'ss', '%L' => 'ms', '%N' => 'ns', '%z' => 'tz'
9
10
  }
11
+ # TODO all others... http://www.sql-server-helper.com/tips/date-formats.aspx
12
+ Arel::Visitors::MSSQL::DATE_CONVERT_FORMATS = {
13
+ 'YYYY-MM-DD' => 120,
14
+ 'YY-MM-DD' => 120,
15
+ 'MM/DD/YYYY' => 101,
16
+ 'MM-DD-YYYY' => 110,
17
+ 'YYYY/MM/DD' => 111,
18
+ 'DD-MM-YYYY' => 105,
19
+ 'DD-MM-YY' => 5,
20
+ 'DD.MM.YYYY' => 104,
21
+ 'YYYY-MM-DDTHH:MM:SS:MMM' => 126
22
+ }
10
23
 
11
24
  # Math Functions
12
25
  def visit_ArelExtensions_Nodes_Ceil o, collector
@@ -16,7 +29,16 @@ module ArelExtensions
16
29
  collector
17
30
  end
18
31
 
19
- def visit_ArelExtensions_Nodes_Concat o, collector
32
+ def visit_ArelExtensions_Nodes_IsNull o, collector
33
+ collector << "("
34
+ collector = visit o.left, collector
35
+ # collector << Arel::Visitors::MSSQL::COMMA
36
+ collector << " IS NULL)"
37
+ collector
38
+ end
39
+
40
+ # Deprecated
41
+ def visit_ArelExtensions_Nodes_ConcatOld o, collector
20
42
  arg = o.left.relation.engine.columns.find{|c| c.name == o.left.name.to_s}.type
21
43
  if(o.right.is_a?(Arel::Attributes::Attribute))
22
44
  collector = visit o.left, collector
@@ -24,7 +46,10 @@ module ArelExtensions
24
46
  collector = visit o.right, collector
25
47
  collector
26
48
  elsif ( arg == :date || arg == :datetime)
27
- collector << "DATEADD(day,#{o.right},"
49
+ collector << "DATEADD(day"
50
+ collector << Arel::Visitors::MSSQL::COMMA
51
+ collector = visit o.right, collector
52
+ collector << Arel::Visitors::MSSQL::COMMA
28
53
  collector = visit o.left, collector
29
54
  collector
30
55
  else
@@ -35,8 +60,19 @@ module ArelExtensions
35
60
  end
36
61
  end
37
62
 
63
+ def visit_ArelExtensions_Nodes_Concat o, collector
64
+ collector << "CONCAT("
65
+ o.expressions.each_with_index { |arg, i|
66
+ collector << Arel::Visitors::MSSQL::COMMA unless i == 0
67
+ collector = visit arg, collector
68
+ }
69
+ collector << ")"
70
+ collector
71
+ end
72
+
38
73
  def visit_ArelExtensions_Nodes_DateDiff o, collector
39
- collector << "DATEDIFF(day,"
74
+ collector << "DATEDIFF(day"
75
+ collector << Arel::Visitors::MSSQL::COMMA
40
76
  collector = visit o.left, collector
41
77
  collector << Arel::Visitors::MSSQL::COMMA
42
78
  collector = visit o.right, collector
@@ -44,94 +80,190 @@ module ArelExtensions
44
80
  collector
45
81
  end
46
82
 
83
+ def visit_ArelExtensions_Nodes_DateAdd o, collector
84
+ collector << "DATEADD("
85
+ collector << o.mssql_datepart(o.right)
86
+ collector << Arel::Visitors::MSSQL::COMMA
87
+ collector = visit o.mssql_value(o.right), collector
88
+ collector << Arel::Visitors::MSSQL::COMMA
89
+ collector = visit o.left, collector
90
+ collector << ")"
91
+ collector
92
+ end
47
93
 
48
94
  def visit_ArelExtensions_Nodes_Duration o, collector
49
- #visit left for period
50
- if(o.left == "d")
51
- collector << "DAY("
52
- elsif(o.left == "m")
53
- collector << "MONTH("
54
- elsif (o.left == "w")
55
- collector << "WEEK"
56
- elsif (o.left == "y")
57
- collector << "YEAR("
58
- end
59
- #visit right
95
+ collector << 'DATEPART('
96
+ collector << Arel::Visitors::MSSQL::DATE_MAPPING[o.left]
97
+ collector << Arel::Visitors::MSSQL::COMMA
60
98
  collector = visit o.right, collector
61
99
  collector << ")"
62
100
  collector
63
101
  end
64
102
 
65
- def visit_ArelExtensions_Nodes_Length o, collector
66
- collector << "LEN("
67
- collector = visit o.expr, collector
68
- collector << ")"
69
- collector
70
- end
103
+ def visit_ArelExtensions_Nodes_Length o, collector
104
+ collector << "LEN("
105
+ collector = visit o.expr, collector
106
+ collector << ")"
107
+ collector
108
+ end
71
109
 
110
+ def visit_ArelExtensions_Nodes_Round o, collector
111
+ collector << "ROUND("
112
+ o.expressions.each_with_index { |arg, i|
113
+ collector << Arel::Visitors::MSSQL::COMMA unless i == 0
114
+ collector = visit arg, collector
115
+ }
116
+ if o.expressions.length == 1
117
+ collector << Arel::Visitors::MSSQL::COMMA
118
+ collector << "0"
119
+ end
120
+ collector << ")"
121
+ collector
122
+ end
72
123
 
73
124
  def visit_ArelExtensions_Nodes_Locate o, collector
74
125
  collector << "CHARINDEX("
75
- collector = visit o.val, collector
126
+ collector = visit o.right, collector
76
127
  collector << Arel::Visitors::MSSQL::COMMA
77
- collector = visit o.expr, collector
128
+ collector = visit o.left, collector
78
129
  collector << ")"
79
130
  collector
80
131
  end
81
132
 
82
- def visit_ArelExtensions_Nodes_Format o, collector
83
- collector << "CONCAT("
133
+ # TODO manage 2nd argument
134
+ def visit_ArelExtensions_Nodes_Trim o, collector
135
+ collector << "LTRIM(RTRIM("
136
+ collector = visit o.left, collector
137
+ collector << "))"
138
+ collector
139
+ end
140
+
141
+ # TODO manage 2nd argument
142
+ def visit_ArelExtensions_Nodes_Ltrim o, collector
143
+ collector << "LTRIM("
144
+ collector = visit o.left, collector
145
+ collector << ")"
146
+ collector
147
+ end
148
+
149
+ # TODO manage 2nd argument
150
+ def visit_ArelExtensions_Nodes_Rtrim o, collector
151
+ collector << "RTRIM("
152
+ collector = visit o.left, collector
153
+ collector << ")"
154
+ collector
155
+ end
84
156
 
85
- t = o.iso_format.split('%')
86
- t.each_with_index {|str, i|
87
- if i == 0 && f[0] != '%'
88
- collector = visit Arel::Nodes.build_quoted(str), collector
89
- elsif str.length > 0
90
- if !Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES['%' + str[0]].blank?
91
- collector << 'DATEPART('
92
- collector << Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES['%' + str[0]]
93
- collector << Arel::Visitors::MSSQL::COMMA
94
- collector = visit o.left, collector
95
- collector << ')'
157
+ def visit_ArelExtensions_Nodes_Blank o, collector
158
+ collector << 'CASE WHEN LEN(LTRIM(RTRIM(ISNULL('
159
+ collector = visit o.left, collector
160
+ collector << ", '')))) = 0 THEN 1 ELSE 0 END"
161
+ collector
162
+ end
163
+
164
+ def visit_ArelExtensions_Nodes_Format o, collector
165
+ f = o.iso_format.dup
166
+ Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
167
+ if Arel::Visitors::MSSQL::DATE_CONVERT_FORMATS[f]
168
+ collector << "CONVERT(VARCHAR(#{f.length})"
169
+ collector << Arel::Visitors::MSSQL::COMMA
170
+ collector = visit o.left, collector
171
+ collector << Arel::Visitors::MSSQL::COMMA
172
+ collector << Arel::Visitors::MSSQL::DATE_CONVERT_FORMATS[f].to_s
173
+ collector << ')'
174
+ collector
175
+ else
176
+ collector << "("
177
+ t = o.iso_format.split('%')
178
+ t.each_with_index {|str, i|
179
+ if i == 0 && t[0] != '%'
180
+ collector = visit Arel::Nodes.build_quoted(str), collector
96
181
  if str.length > 1
97
182
  collector << Arel::Visitors::MSSQL::COMMA
98
183
  collector = visit Arel::Nodes.build_quoted(str.sub(/\A./, '')), collector
99
184
  end
185
+ elsif str.length > 0
186
+ if !Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES['%' + str[0]].blank?
187
+ collector << 'LTRIM(STR(DATEPART('
188
+ collector << Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES['%' + str[0]]
189
+ collector << Arel::Visitors::MSSQL::COMMA
190
+ collector = visit o.left, collector
191
+ collector << ')))'
192
+ if str.length > 1
193
+ collector << ' + '
194
+ collector = visit Arel::Nodes.build_quoted(str.sub(/\A./, '')), collector
195
+ end
196
+ end
100
197
  end
101
- end
102
- collector << Arel::Visitors::MSSQL::COMMA unless i < (t.length - 1)
103
- }
198
+ collector << ' + ' if t[i + 1]
199
+ }
104
200
 
105
- collector << ")"
106
- collector
201
+ collector << ')'
202
+ collector
203
+ end
107
204
  end
108
205
 
109
206
  def visit_ArelExtensions_Nodes_Replace o, collector
110
207
  collector << "REPLACE("
111
- collector = visit o.expr,collector
112
- collector << Arel::Visitors::MSSQL::COMMA
113
- collector = visit o.left, collector
114
-
115
- collector << Arel::Visitors::MSSQL::COMMA
116
- collector = visit o.right, collector
208
+ o.expressions.each_with_index { |arg, i|
209
+ collector << Arel::Visitors::MSSQL::COMMA unless i == 0
210
+ collector = visit arg, collector
211
+ }
117
212
  collector << ")"
118
213
  collector
119
214
  end
120
215
 
121
216
 
217
+ # TODO manage case insensitivity
218
+ def visit_ArelExtensions_Nodes_IMatches o, collector
219
+ collector = infix_value o, collector, ' LIKE '
220
+ if o.escape
221
+ collector << ' ESCAPE '
222
+ visit o.escape, collector
223
+ else
224
+ collector
225
+ end
226
+ end
227
+
228
+ # TODO manage case insensitivity
229
+ def visit_ArelExtensions_Nodes_IDoesNotMatch o, collector
230
+ collector = infix_value o, collector, ' NOT LIKE '
231
+ if o.escape
232
+ collector << ' ESCAPE '
233
+ collector = visit o.escape, collector
234
+ end
235
+ collector
236
+ end
237
+
122
238
  # SQL Server does not know about REGEXP
123
239
  def visit_Arel_Nodes_Regexp o, collector
124
240
  collector = visit o.left, collector
125
- collector << "LIKE '% #{o.right}%'"
241
+ collector << "LIKE '%#{o.right}%'"
126
242
  collector
127
243
  end
128
244
 
129
245
  def visit_Arel_Nodes_NotRegexp o, collector
130
246
  collector = visit o.left, collector
131
- collector << "NOT LIKE '% #{o.right}%'"
247
+ collector << "NOT LIKE '%#{o.right}%'"
132
248
  collector
133
249
  end
134
250
 
251
+ # TODO
252
+ def visit_ArelExtensions_Nodes_GroupConcat o, collector
253
+ collector << "(LISTAGG("
254
+ collector = visit o.left, collector
255
+ if o.right
256
+ collector << Arel::Visitors::Oracle::COMMA
257
+ collector = visit o.right, collector
258
+ end
259
+ collector << ") WITHIN GROUP (ORDER BY "
260
+ collector = visit o.left, collector
261
+ collector << "))"
262
+ collector
263
+ end
264
+
265
+
266
+
135
267
  end
136
268
  end
137
- end
269
+ end
@@ -153,9 +153,11 @@ module ArelExtensions
153
153
  end
154
154
 
155
155
  def visit_ArelExtensions_Nodes_Blank o, collector
156
- collector << '('
156
+ collector << 'LENGTH(TRIM(COALESCE('
157
157
  collector = visit o.left, collector
158
- collector << " = '')"
158
+ collector << Arel::Visitors::ToSql::COMMA
159
+ collector = visit Arel::Nodes.build_quoted(''), collector
160
+ collector << "))) = 0"
159
161
  collector
160
162
  end
161
163
 
@@ -271,7 +273,7 @@ module ArelExtensions
271
273
  collector << "DATE_ADD("
272
274
  collector = visit o.left, collector
273
275
  collector << Arel::Visitors::ToSql::COMMA
274
- collector = visit o.right, collector
276
+ collector = visit o.sqlite_value(o.right), collector
275
277
  collector << ")"
276
278
  collector
277
279
  end
data/test/database.yml CHANGED
@@ -3,7 +3,7 @@ sqlite:
3
3
  database: ":memory:"
4
4
  timeout: 500
5
5
  jdbc-sqlite:
6
- adapter: jdbcsqlite3
6
+ adapter: jdbcsqlite3
7
7
  database: ":memory:"
8
8
  timeout: 500
9
9
  mysql:
@@ -41,7 +41,6 @@ ibm_db:
41
41
  mssql:
42
42
  adapter: sqlserver
43
43
  host: localhost
44
- dataserver: localhost\SQL2014
45
44
  database: master
46
45
  username: sa
47
46
  password: Password12!
@@ -45,6 +45,10 @@ module FakeRecord
45
45
  @tables.include? name.to_s
46
46
  end
47
47
 
48
+ def data_source_exists? name
49
+ @tables.include? name.to_s
50
+ end
51
+
48
52
  def columns name, message = nil
49
53
  @columns[name.to_s]
50
54
  end
@@ -110,6 +114,10 @@ module FakeRecord
110
114
  connection.tables.include? name.to_s
111
115
  end
112
116
 
117
+ def data_source_exists? name
118
+ connection.tables.include? name.to_s
119
+ end
120
+
113
121
  def columns_hash
114
122
  connection.columns_hash
115
123
  end
@@ -5,6 +5,7 @@ module ArelExtensions
5
5
  module WthAr
6
6
 
7
7
  class ListTest < Minitest::Test
8
+ require 'minitest/pride'
8
9
  def setup_db
9
10
  ActiveRecord::Base.configurations = YAML.load_file('test/database.yml')
10
11
  if ENV['DB'] == 'oracle' && ((defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx") || (RUBY_PLATFORM == 'java')) # not supported
@@ -39,7 +40,13 @@ module ArelExtensions
39
40
  end
40
41
  if File.exist?("init/#{@env_db}.sql")
41
42
  sql = File.read("init/#{@env_db}.sql")
42
- @cnx.execute(sql) unless sql.blank?
43
+ if @env_db == 'mssql'
44
+ sql.split(/^GO\s*$/).each {|str|
45
+ @cnx.execute(str.strip) unless str.blank?
46
+ }
47
+ else
48
+ @cnx.execute(sql) unless sql.blank?
49
+ end
43
50
  end
44
51
  @cnx.drop_table(:user_tests) rescue nil
45
52
  @cnx.create_table :user_tests do |t|
@@ -138,16 +145,25 @@ module ArelExtensions
138
145
  end
139
146
 
140
147
  def test_sum
141
- assert_equal 68, User.select((@age.sum + 1).as("res")).take(50).first.res
142
- assert_equal 134, User.select((@age.sum + @age.sum).as("res")).take(50).first.res
143
- assert_equal 201, User.select(((@age * 3).sum).as("res")).take(50).first.res
144
- assert_equal 4009, User.select(((@age * @age).sum).as("res")).take(50).first.res
148
+ if @env_db == 'mssql'
149
+ skip "SQL Server forces order?" # TODO
150
+ assert_equal 68, User.select((@age.sum + 1).as("res"), User.arel_table[:id].sum).take(50).reorder(@age).first.res
151
+ assert_equal 134, User.reorder(nil).select((@age.sum + @age.sum).as("res"), User.arel_table[:id].sum).take(50).first.res
152
+ assert_equal 201, User.reorder(nil).select(((@age * 3).sum).as("res"), User.arel_table[:id].sum).take(50).first.res
153
+ assert_equal 4009, User.reorder(nil).select(((@age * @age).sum).as("res"), User.arel_table[:id].sum).take(50).first.res
154
+ else
155
+ assert_equal 68, User.select((@age.sum + 1).as("res")).take(50).first.res
156
+ assert_equal 134, User.select((@age.sum + @age.sum).as("res")).take(50).first.res
157
+ assert_equal 201, User.select(((@age * 3).sum).as("res")).take(50).first.res
158
+ assert_equal 4009, User.select(((@age * @age).sum).as("res")).take(50).first.res
159
+ end
145
160
  end
146
161
 
147
162
  # String Functions
148
163
  def test_concat
149
164
  assert_equal 'Camille Camille', t(@camille, @name + ' ' + @name)
150
165
  assert_equal 'Laure 2', t(@laure, @name + ' ' + 2)
166
+ skip "TODO: find a way... to do group_concat/listagg in SQL Server" if @env_db == 'mssql'
151
167
  if @env_db == 'postgresql'
152
168
  assert_equal "Lucas Sophie", t(User.reorder(nil).from(User.select(:name).where(:name => ['Lucas', 'Sophie']).reorder(:name).as('user_tests')), @name.group_concat(' '))
153
169
  else
@@ -170,12 +186,14 @@ module ArelExtensions
170
186
 
171
187
  def test_find_in_set
172
188
  skip "Sqlite version can't load extension for find_in_set" if $sqlite && $load_extension_disabled
189
+ skip "SQL Server does not know about FIND_IN_SET" if @env_db == 'mssql'
173
190
  assert_equal 5, t(@neg, @comments & 2)
174
191
  assert_equal 0, t(@neg, @comments & 6) # not found
175
192
  end
176
193
 
177
194
  def test_string_comparators
178
195
  skip "Oracle can't use math operators to compare strings" if @env_db == 'oracle' # use GREATEST ?
196
+ skip "SQL Server can't use math operators to compare strings" if @env_db == 'mssql' # use GREATEST ?
179
197
  if @env_db == 'postgresql' # may return real boolean
180
198
  assert t(@neg, @name >= 'Mest') == true || t(@neg, @name >= 'Mest') == 't' # depends of ar version
181
199
  assert t(@neg, @name <= (@name + 'Z')) == true || t(@neg, @name <= (@name + 'Z')) == 't'
@@ -187,6 +205,7 @@ module ArelExtensions
187
205
 
188
206
  def test_regexp_not_regexp
189
207
  skip "Sqlite version can't load extension for regexp" if $sqlite && $load_extension_disabled
208
+ skip "SQL Server does not know about REGEXP without extensions" if @env_db == 'mssql'
190
209
  assert_equal 1, User.where(@name =~ '^M').count
191
210
  assert_equal 6, User.where(@name !~ '^L').count
192
211
  assert_equal 1, User.where(@name =~ /^M/).count
@@ -213,9 +232,10 @@ module ArelExtensions
213
232
 
214
233
  def test_trim
215
234
  assert_equal "Myung", t(@myung, @name.trim)
235
+ assert_equal "Myung", t(@myung, @name.trim.ltrim.rtrim)
236
+ skip "SQL Server does not manage argument for (L/R)TRIM" if @env_db == 'mssql'
216
237
  assert_equal "Myun", t(@myung, @name.rtrim("g"))
217
238
  assert_equal "yung", t(@myung, @name.ltrim("M"))
218
- assert_equal "Myung", t(@myung, @name.trim.ltrim.rtrim)
219
239
  assert_equal "yung", t(@myung, (@name + "M").trim("M"))
220
240
  skip "Oracle does not accept multi char trim" if @env_db == 'oracle'
221
241
  assert_equal "", t(@myung, @name.rtrim(@name))
@@ -237,6 +257,7 @@ module ArelExtensions
237
257
 
238
258
  def test_format
239
259
  assert_equal '2016-05-23', t(@lucas, @created_at.format('%Y-%m-%d'))
260
+ skip "SQL Server does not accept any format" if @env_db == 'mssql'
240
261
  assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S'))
241
262
  end
242
263
 
@@ -276,7 +297,7 @@ module ArelExtensions
276
297
  assert_equal 5, t(@camille, @created_at.month).to_i
277
298
  assert_equal 8, User.where(@created_at.month.eq("05")).count
278
299
  #Week
279
- assert_equal 21, t(@arthur, @created_at.week).to_i
300
+ assert_equal (@env_db == 'mssql' ? 22 : 21), t(@arthur, @created_at.week).to_i
280
301
  assert_equal 8, User.where(@created_at.month.eq("05")).count
281
302
  #Day
282
303
  assert_equal 23, t(@laure, @created_at.day).to_i
@@ -327,7 +348,7 @@ module ArelExtensions
327
348
 
328
349
  def test_wday
329
350
  d = Date.new(2016, 6, 26)
330
- assert_equal(@env_db == 'oracle' ? 2 : 1, t(@myung, @created_at.wday).to_i) # monday
351
+ assert_equal(@env_db == 'oracle' || @env_db == 'mssql' ? 2 : 1, t(@myung, @created_at.wday).to_i) # monday
331
352
  assert_equal 0, User.select(d.wday).as("res").first.to_i
332
353
  end
333
354
 
@@ -19,7 +19,9 @@ module ArelExtensions
19
19
  Arel::Table.engine = ActiveRecord::Base
20
20
  if File.exist?("init/#{@env_db}.sql")
21
21
  sql = File.read("init/#{@env_db}.sql")
22
- @cnx.execute(sql) unless sql.blank?
22
+ unless sql.blank?
23
+ @cnx.execute(sql) rescue $stderr << "can't create functions"
24
+ end
23
25
  end
24
26
  @cnx.drop_table(:user_tests) rescue nil
25
27
  @cnx.create_table :user_tests do |t|
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: 0.8.7
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yann Azoury
@@ -10,20 +10,20 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-09-28 00:00:00.000000000 Z
13
+ date: 2016-11-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: arel
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - "~>"
19
+ - - ">="
20
20
  - !ruby/object:Gem::Version
21
21
  version: '6.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - "~>"
26
+ - - ">="
27
27
  - !ruby/object:Gem::Version
28
28
  version: '6.0'
29
29
  - !ruby/object:Gem::Dependency
@@ -78,6 +78,7 @@ extensions: []
78
78
  extra_rdoc_files:
79
79
  - MIT-LICENSE.txt
80
80
  - README.md
81
+ - functions.html
81
82
  files:
82
83
  - ".gitignore"
83
84
  - ".travis.yml"
@@ -90,6 +91,7 @@ files:
90
91
  - MIT-LICENSE.txt
91
92
  - README.md
92
93
  - Rakefile
94
+ - SQL_Challenges.md
93
95
  - TODO
94
96
  - appveyor.yml
95
97
  - arel_extensions.gemspec