arel_extensions 0.9.3 → 0.9.4
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 +4 -4
- data/SQL_Challenges.md +0 -1
- data/TODO +3 -2
- data/init/mssql.sql +27 -10
- data/lib/arel_extensions.rb +1 -0
- data/lib/arel_extensions/nodes/function.rb +8 -1
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors/ibm_db.rb +7 -18
- data/lib/arel_extensions/visitors/mssql.rb +49 -12
- data/lib/arel_extensions/visitors/oracle.rb +34 -14
- data/test/with_ar/all_agnostic_test.rb +18 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c99e78c300658b7506cbdf8969ed28c8556e37c0
|
4
|
+
data.tar.gz: 116346eed66e6d9cc920f4b21116db9f8d4f95b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
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
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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;
|
data/lib/arel_extensions.rb
CHANGED
@@ -26,7 +26,14 @@ module ArelExtensions
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def type_of_attribute(att)
|
29
|
-
|
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)
|
@@ -9,24 +9,13 @@ module ArelExtensions
|
|
9
9
|
collector
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
collector <<
|
16
|
-
collector = visit
|
17
|
-
|
18
|
-
|
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
|
-
|
143
|
-
|
144
|
-
|
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
|
-
|
151
|
-
|
152
|
-
|
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
|
-
|
159
|
-
|
160
|
-
|
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
|
-
|
169
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 << "
|
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 << "
|
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
|
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
|
-
|
322
|
-
|
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.
|
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-
|
13
|
+
date: 2016-11-24 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: arel
|