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 +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
|