arel_extensions 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2aee321fcafb1aa18404760b6ea01de96837b0bf
4
- data.tar.gz: 008c6af57efc1775384616d797c96eb2895481b2
3
+ metadata.gz: c99e78c300658b7506cbdf8969ed28c8556e37c0
4
+ data.tar.gz: 116346eed66e6d9cc920f4b21116db9f8d4f95b0
5
5
  SHA512:
6
- metadata.gz: daa6d2206846f0eb7d28de5a4392888630d3120a2913b572cb4250609617574983cb708dfc38b1e8a28c39e72aaeaddb18826e379e4b9bc3098c2904d1ad48e6
7
- data.tar.gz: 09080c3f2ae5800ee9722804630450274b61887c5816a52bf42d2580e94e332843607958e6830f35cf30724bf36ca5680dce5cdc6b91a7a91b081e2329e2a02e
6
+ metadata.gz: b16119b4bc898a852af9e7db829ca34bb4afca30779a651b4302847ea515d7d406378d01470535c91f6315c473ee0c59d52f20a5d324f8c9932de84f97a1ec86
7
+ data.tar.gz: 5973956e3049621ea31c4f981fd6fc5dce8b9a1ba20ba33e4e9eee88d454ca6956375447a9681359ecdc5a3c49c89a9476b983122c5688e02a094fee7cb57274
data/SQL_Challenges.md CHANGED
@@ -22,7 +22,6 @@ A good way could be to create user defined functions to ensure a total transpare
22
22
 
23
23
  ## SQL Server (any version > 2005, without extension)
24
24
  - REGEXP
25
- - (L/R)TRIM(str, 'x') -> TRIM with arguments
26
25
  - Maths Operators on string ('a' <= 'b')
27
26
  - GROUP_CONCAT
28
27
  - FIND_IN_SET
data/TODO CHANGED
@@ -19,8 +19,9 @@ Code quality:
19
19
  New features:
20
20
  - POSIX format numbers (%.2f)
21
21
  - easy unions
22
- - cast
22
+ - cast, to_char
23
23
 
24
24
  Tests improvements:
25
25
  - SQL Server
26
- - DB2
26
+ - DB2
27
+ - Informix
data/init/mssql.sql CHANGED
@@ -22,22 +22,39 @@ BEGIN
22
22
 
23
23
  RETURN @value
24
24
  END;
25
-
26
25
  GO
27
26
 
28
- -----------------------------
29
- -- GO
27
+ IF OBJECT_ID (N'dbo.SplitStringWithDelim', N'IF') IS NOT NULL
28
+ DROP FUNCTION dbo.SplitStringWithDelim;
29
+ GO
30
+ CREATE FUNCTION dbo.SplitStringWithDelim(@List NVARCHAR(4000), @Delimiter NCHAR(1))
31
+ RETURNS TABLE AS
32
+ RETURN
33
+ (
34
+ WITH SplitStringCte(stpos,endpos)
35
+ AS(
36
+ SELECT 0 AS stpos, CHARINDEX(@Delimiter, @List) AS endpos
37
+ UNION ALL
38
+ SELECT endpos + 1, CHARINDEX(@Delimiter, @List, endpos + 1)
39
+ FROM SplitStringCte
40
+ WHERE endpos > 0
41
+ )
42
+ SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
43
+ 'Data' = SUBSTRING(@List, stpos, COALESCE(NULLIF(endpos, 0), LEN(@List) + 1) - stpos)
44
+ FROM SplitStringCte
45
+ )
46
+ GO
30
47
 
31
48
  IF OBJECT_ID (N'dbo.FIND_IN_SET', N'FN') IS NOT NULL
32
49
  DROP FUNCTION dbo.FIND_IN_SET;
33
50
  GO
34
- -- CREATE FUNCTION dbo.FIND_IN_SET(@value VARCHAR(MAX), @list VARCHAR(MAX), @delim VARCHAR(MAX))
35
- -- RETURNS VARCHAR(MAX)
36
- -- AS BEGIN
37
- -- RETURN LTRIM(RTRIM(@value));
38
- -- END;
39
-
40
- -- GO
51
+ CREATE FUNCTION dbo.FIND_IN_SET(@Value VARCHAR(MAX), @List VARCHAR(MAX), @Delimiter VARCHAR(MAX))
52
+ RETURNS BIGINT
53
+ AS
54
+ BEGIN
55
+ RETURN COALESCE((SELECT MIN(Id) FROM dbo.SplitStringWithDelim(@List, COALESCE(@Delimiter, ',')) WHERE Data = @Value), 0)
56
+ END
57
+ GO
41
58
 
42
59
  --IF OBJECT_ID (N'dbo.SplitString', N'FN') IS NOT NULL
43
60
  -- DROP FUNCTION dbo.SplitString;
@@ -57,6 +57,7 @@ Arel::Nodes::Function.class_eval do
57
57
  include ArelExtensions::MathFunctions
58
58
  include ArelExtensions::StringFunctions
59
59
  include ArelExtensions::BooleanFunctions
60
+ include ArelExtensions::NullFunctions
60
61
  end
61
62
 
62
63
  Arel::Nodes::Unary.class_eval do
@@ -26,7 +26,14 @@ module ArelExtensions
26
26
  end
27
27
 
28
28
  def type_of_attribute(att)
29
- Arel::Table.engine.connection.schema_cache.columns_hash(att.relation.table_name)[att.name.to_s].type
29
+ case att
30
+ when Arel::Attributes::Attribute
31
+ Arel::Table.engine.connection.schema_cache.columns_hash(att.relation.table_name)[att.name.to_s].type
32
+ when ArelExtensions::Nodes::Function
33
+ att.class.return_type
34
+ else
35
+ nil
36
+ end
30
37
  end
31
38
 
32
39
  def convert_to_node(object)
@@ -1,4 +1,4 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module ArelExtensions
3
- VERSION = "0.9.3".freeze
3
+ VERSION = "0.9.4".freeze
4
4
  end
@@ -9,24 +9,13 @@ module ArelExtensions
9
9
  collector
10
10
  end
11
11
 
12
- def visit_ArelExtensions_Nodes_Concat o, collector
13
- arg = o.left.relation.engine.columns.find{|c| c.name == o.left.name.to_s}.type
14
- if(o.right.is_a?(Arel::Attributes::Attribute))
15
- collector << "CONCAT("
16
- collector = visit o.left, collector
17
- collector<< ","
18
- collector = visit o.right, collector
19
- collector << ")"
20
- elsif ( arg == :date || arg == :datetime)
21
- collector = visit o.left, collector
22
- collector<< "+"
23
- collector << "#{o.right} days"
24
- else
25
- collector << "CONCAT("
26
- collector = visit o.left, collector
27
- collector<< ","
28
- collector <<"#{o.right})"
29
- end
12
+ def visit_ArelExtensions_Nodes_Trim o, collector
13
+ collector << "LTRIM(RTRIM("
14
+ o.expressions.each_with_index { |arg, i|
15
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
16
+ collector = visit arg, collector
17
+ }
18
+ collector << "))"
30
19
  collector
31
20
  end
32
21
 
@@ -137,27 +137,54 @@ module ArelExtensions
137
137
  collector
138
138
  end
139
139
 
140
- # TODO manage 2nd argument
141
140
  def visit_ArelExtensions_Nodes_Trim o, collector
142
- collector << "LTRIM(RTRIM("
143
- collector = visit o.left, collector
144
- collector << "))"
141
+ if o.right
142
+ collector << "REPLACE(REPLACE(LTRIM(RTRIM(REPLACE(REPLACE("
143
+ collector = visit o.left, collector
144
+ collector << ", ' ', '~'), "
145
+ collector = visit o.right, collector
146
+ collector << ", ' '))), ' ', "
147
+ collector = visit o.right, collector
148
+ collector << "), '~', ' ')"
149
+ else
150
+ collector << "LTRIM(RTRIM("
151
+ collector = visit o.left, collector
152
+ collector << "))"
153
+ end
145
154
  collector
146
155
  end
147
156
 
148
- # TODO manage 2nd argument
149
157
  def visit_ArelExtensions_Nodes_Ltrim o, collector
150
- collector << "LTRIM("
151
- collector = visit o.left, collector
152
- collector << ")"
158
+ if o.right
159
+ collector << "REPLACE(REPLACE(LTRIM(REPLACE(REPLACE("
160
+ collector = visit o.left, collector
161
+ collector << ", ' ', '~'), "
162
+ collector = visit o.right, collector
163
+ collector << ", ' ')), ' ', "
164
+ collector = visit o.right, collector
165
+ collector << "), '~', ' ')"
166
+ else
167
+ collector << "LTRIM("
168
+ collector = visit o.left, collector
169
+ collector << ")"
170
+ end
153
171
  collector
154
172
  end
155
173
 
156
- # TODO manage 2nd argument
157
174
  def visit_ArelExtensions_Nodes_Rtrim o, collector
158
- collector << "RTRIM("
159
- collector = visit o.left, collector
160
- collector << ")"
175
+ if o.right
176
+ collector << "REPLACE(REPLACE(RTRIM(REPLACE(REPLACE("
177
+ collector = visit o.left, collector
178
+ collector << ", ' ', '~'), "
179
+ collector = visit o.right, collector
180
+ collector << ", ' ')), ' ', "
181
+ collector = visit o.right, collector
182
+ collector << "), '~', ' ')"
183
+ else
184
+ collector << "RTRIM("
185
+ collector = visit o.left, collector
186
+ collector << ")"
187
+ end
161
188
  collector
162
189
  end
163
190
 
@@ -227,6 +254,16 @@ module ArelExtensions
227
254
  collector
228
255
  end
229
256
 
257
+ def visit_ArelExtensions_Nodes_FindInSet o, collector
258
+ collector << "dbo.FIND_IN_SET("
259
+ o.expressions.each_with_index { |arg, i|
260
+ collector << Arel::Visitors::MSSQL::COMMA unless i == 0
261
+ collector = visit arg, collector
262
+ }
263
+ collector << ")"
264
+ collector
265
+ end
266
+
230
267
 
231
268
  # TODO manage case insensitivity
232
269
  def visit_ArelExtensions_Nodes_IMatches o, collector
@@ -1,6 +1,7 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
3
  Arel::Visitors::Oracle.class_eval do
4
+ SPECIAL_CHARS = {"\t" => 'CHR(9)', "\n" => 'CHR(10)', "\r" => 'CHR(13)'}
4
5
  Arel::Visitors::Oracle::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'IW', 'y' => 'YEAR', 'wd' => 'D', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
5
6
  Arel::Visitors::Oracle::DATE_FORMAT_DIRECTIVES = {
6
7
  '%Y' => 'IYYY', '%C' => 'CC', '%y' => 'YY', '%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
@@ -165,19 +166,25 @@ module ArelExtensions
165
166
 
166
167
  def visit_ArelExtensions_Nodes_Trim o, collector
167
168
  collector << 'TRIM(' # BOTH
168
- case o.right.expr
169
- when "\t"
170
- collector << 'CHR(9)'
171
- when "\n"
172
- collector << 'CHR(10)'
173
- when "\r"
174
- collector << 'CHR(13)'
169
+ if o.right.expr && SPECIAL_CHARS[o.right.expr]
170
+ collector << SPECIAL_CHARS[o.right.expr]
175
171
  else
176
172
  collector = visit o.right, collector
177
173
  end
178
174
  collector << ' FROM '
179
175
  collector << '(' if o.left.is_a? ArelExtensions::Nodes::Trim
180
- collector = visit o.left, collector
176
+ if o.type_of_attribute(o.left) == :text
177
+ collector << 'dbms_lob.substr('
178
+ collector = visit o.left, collector
179
+ collector << Arel::Visitors::Oracle::COMMA
180
+ collector << 'dbms_lob.getlength('
181
+ collector = visit o.left, collector
182
+ collector << ')'
183
+ collector << Arel::Visitors::Oracle::COMMA
184
+ collector << '1)'
185
+ else
186
+ collector = visit o.left, collector
187
+ end
181
188
  collector << ')' if o.left.is_a? ArelExtensions::Nodes::Trim
182
189
  collector << ")"
183
190
  collector
@@ -185,7 +192,11 @@ module ArelExtensions
185
192
 
186
193
  def visit_ArelExtensions_Nodes_Ltrim o, collector
187
194
  collector << 'TRIM(LEADING '
188
- collector = visit o.right, collector
195
+ if o.right.expr && SPECIAL_CHARS[o.right.expr]
196
+ collector << SPECIAL_CHARS[o.right.expr]
197
+ else
198
+ collector = visit o.right, collector
199
+ end
189
200
  collector << ' FROM '
190
201
  collector = visit o.left, collector
191
202
  collector << ")"
@@ -194,24 +205,33 @@ module ArelExtensions
194
205
 
195
206
  def visit_ArelExtensions_Nodes_Rtrim o, collector
196
207
  collector << 'TRIM(TRAILING '
197
- collector = visit o.right, collector
208
+ if o.right.expr && SPECIAL_CHARS[o.right.expr]
209
+ collector << SPECIAL_CHARS[o.right.expr]
210
+ else
211
+ collector = visit o.right, collector
212
+ end
198
213
  collector << ' FROM '
199
214
  collector = visit o.left, collector
200
215
  collector << ")"
201
216
  collector
202
217
  end
203
218
 
219
+ # blank ? <param> : NULL
204
220
  def visit_ArelExtensions_Nodes_Blank o, collector
205
221
  collector << '(CASE WHEN ('
206
- collector = visit o.left, collector
207
- collector << " = '') THEN 1 ELSE 0 END)"
222
+ collector = visit o.left.trim, collector
223
+ collector << " IS NULL) THEN 'blank'"
224
+ collector << " ELSE NULL END)"
208
225
  collector
209
226
  end
210
227
 
228
+ # not blank ? <param> : NULL
211
229
  def visit_ArelExtensions_Nodes_NotBlank o, collector
212
230
  collector << '(CASE WHEN ('
213
- collector = visit o.left, collector
214
- collector << " = '') THEN 0 ELSE 1 END)"
231
+ collector = visit o.left.trim, collector
232
+ collector << " IS NOT NULL) THEN "
233
+ collector = visit o.left.trim, collector
234
+ collector << " ELSE NULL END)"
215
235
  collector
216
236
  end
217
237
 
@@ -81,7 +81,7 @@ module ArelExtensions
81
81
  @camille = User.where(:id => u.id)
82
82
  u = User.create :age => 21, :name => "Arthur", :created_at => d, :score => 65.62
83
83
  @arthur = User.where(:id => u.id)
84
- u = User.create :age => 23, :name => "Myung", :created_at => d, :score => 20.16
84
+ u = User.create :age => 23, :name => "Myung", :created_at => d, :score => 20.16, :comments => ' '
85
85
  @myung = User.where(:id => u.id)
86
86
  u = User.create :age => 25, :name => "Laure", :created_at => d, :score => 20.16
87
87
  @laure = User.where(:id => u.id)
@@ -234,7 +234,6 @@ module ArelExtensions
234
234
  def test_trim
235
235
  assert_equal "Myung", t(@myung, @name.trim)
236
236
  assert_equal "Myung", t(@myung, @name.trim.ltrim.rtrim)
237
- skip "SQL Server does not manage argument for (L/R)TRIM" if @env_db == 'mssql'
238
237
  assert_equal "Myun", t(@myung, @name.rtrim("g"))
239
238
  assert_equal "yung", t(@myung, @name.ltrim("M"))
240
239
  assert_equal "yung", t(@myung, (@name + "M").trim("M"))
@@ -246,9 +245,18 @@ module ArelExtensions
246
245
  if @env_db == 'postgresql'
247
246
  assert_includes [false, 'f'], t(@myung, @name.blank) # depends of adapter
248
247
  assert_includes [true, 't'], t(@myung, @name.not_blank) # depends of adapter
248
+ assert_includes [true, 't'], t(@myung, @comments.blank)
249
+ assert_includes [false, 'f'], t(@myung, @comments.not_blank)
250
+ elsif @env_db == 'oracle'
251
+ assert_equal '42', t(@myung, @name.blank.coalesce('42'))
252
+ assert_equal 'Myung', t(@myung, @name.not_blank.coalesce('42'))
253
+ assert_equal 'blank', t(@myung, @comments.blank.coalesce('42'))
254
+ assert_equal '42', t(@myung, @comments.not_blank.coalesce('42'))
249
255
  else
250
256
  assert_equal 0, t(@myung, @name.blank)
251
257
  assert_equal 1, t(@myung, @name.not_blank)
258
+ assert_equal 1, t(@myung, @comments.blank)
259
+ assert_equal 0, t(@myung, @comments.not_blank)
252
260
  end
253
261
  skip "Oracle requires cast for CLOB" if @env_db == 'oracle' # comments is CLOB, CHAR expected
254
262
  if @env_db == 'postgresql'
@@ -260,7 +268,7 @@ module ArelExtensions
260
268
 
261
269
  def test_format
262
270
  assert_equal '2016-05-23', t(@lucas, @created_at.format('%Y-%m-%d'))
263
- skip "SQL Server does not accept any format" if @env_db == 'mssql'
271
+ skip "SQL Server does not accept any format" if @env_db == 'mssql'
264
272
  assert_equal '2014/03/03 12:42:00', t(@lucas, @updated_at.format('%Y/%m/%d %H:%M:%S'))
265
273
  end
266
274
 
@@ -318,11 +326,15 @@ module ArelExtensions
318
326
 
319
327
  def test_datetime_diff
320
328
  assert_equal 0, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 42)).to_i
321
- assert_equal 42, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 41, 18)).to_i
322
- assert_equal(-3600, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 13, 42)).to_i)
329
+ if @env_db == 'oracle' && Arel::VERSION.to_i > 6 # in rails 5, result is multiplied by 24*60*60 = 86400...
330
+ assert_equal 42 * 86400, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 41, 18)).to_i
331
+ assert_equal(-3600 * 86400, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 13, 42)).to_i)
332
+ else
333
+ assert_equal 42, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 12, 41, 18)).to_i
334
+ assert_equal(-3600, t(@lucas, @updated_at - Time.utc(2014, 3, 3, 13, 42)).to_i)
335
+ end
323
336
  end
324
337
 
325
-
326
338
  def test_cast_types
327
339
  skip "not implemented yet"
328
340
  assert_equal true, t(@arthur, @score =~ /22/)
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.9.3
4
+ version: 0.9.4
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: 2016-11-17 00:00:00.000000000 Z
13
+ date: 2016-11-24 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: arel