arel_extensions 1.3.5 → 2.0.0.rc3

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.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +2 -1
  3. data/.gitignore +6 -7
  4. data/.rubocop.yml +3 -67
  5. data/.travis/oracle/download.js +152 -0
  6. data/.travis/oracle/download.sh +30 -0
  7. data/.travis/oracle/download_ojdbc.js +116 -0
  8. data/.travis/oracle/install.sh +34 -0
  9. data/.travis/setup_accounts.sh +9 -0
  10. data/.travis/sqlite3/extension-functions.sh +6 -0
  11. data/.travis.yml +223 -0
  12. data/Gemfile +21 -16
  13. data/README.md +13 -125
  14. data/Rakefile +30 -41
  15. data/TODO +1 -0
  16. data/appveyor.yml +22 -51
  17. data/arel_extensions.gemspec +14 -14
  18. data/functions.html +3 -3
  19. data/gemfiles/rails3.gemfile +10 -10
  20. data/gemfiles/rails4.gemfile +14 -14
  21. data/gemfiles/rails5_0.gemfile +14 -14
  22. data/gemfiles/rails5_1_4.gemfile +14 -14
  23. data/gemfiles/rails5_2.gemfile +14 -16
  24. data/init/mssql.sql +4 -4
  25. data/init/mysql.sql +38 -38
  26. data/init/oracle.sql +0 -0
  27. data/init/postgresql.sql +21 -21
  28. data/init/sqlite.sql +0 -0
  29. data/lib/arel_extensions/attributes.rb +3 -4
  30. data/lib/arel_extensions/boolean_functions.rb +14 -53
  31. data/lib/arel_extensions/common_sql_functions.rb +17 -16
  32. data/lib/arel_extensions/comparators.rb +28 -27
  33. data/lib/arel_extensions/date_duration.rb +14 -13
  34. data/lib/arel_extensions/insert_manager.rb +15 -18
  35. data/lib/arel_extensions/math.rb +53 -55
  36. data/lib/arel_extensions/math_functions.rb +39 -46
  37. data/lib/arel_extensions/nodes/abs.rb +1 -0
  38. data/lib/arel_extensions/nodes/blank.rb +2 -1
  39. data/lib/arel_extensions/nodes/case.rb +16 -16
  40. data/lib/arel_extensions/nodes/cast.rb +8 -10
  41. data/lib/arel_extensions/nodes/ceil.rb +1 -1
  42. data/lib/arel_extensions/nodes/coalesce.rb +4 -3
  43. data/lib/arel_extensions/nodes/collate.rb +10 -9
  44. data/lib/arel_extensions/nodes/concat.rb +18 -9
  45. data/lib/arel_extensions/nodes/date_diff.rb +26 -42
  46. data/lib/arel_extensions/nodes/duration.rb +3 -0
  47. data/lib/arel_extensions/nodes/find_in_set.rb +1 -0
  48. data/lib/arel_extensions/nodes/floor.rb +1 -1
  49. data/lib/arel_extensions/nodes/format.rb +8 -35
  50. data/lib/arel_extensions/nodes/formatted_number.rb +23 -22
  51. data/lib/arel_extensions/nodes/function.rb +37 -42
  52. data/lib/arel_extensions/nodes/is_null.rb +0 -0
  53. data/lib/arel_extensions/nodes/json.rb +39 -48
  54. data/lib/arel_extensions/nodes/length.rb +0 -5
  55. data/lib/arel_extensions/nodes/levenshtein_distance.rb +1 -1
  56. data/lib/arel_extensions/nodes/locate.rb +2 -1
  57. data/lib/arel_extensions/nodes/log10.rb +2 -1
  58. data/lib/arel_extensions/nodes/matches.rb +7 -5
  59. data/lib/arel_extensions/nodes/md5.rb +1 -0
  60. data/lib/arel_extensions/nodes/power.rb +5 -5
  61. data/lib/arel_extensions/nodes/rand.rb +1 -0
  62. data/lib/arel_extensions/nodes/repeat.rb +5 -3
  63. data/lib/arel_extensions/nodes/replace.rb +8 -16
  64. data/lib/arel_extensions/nodes/round.rb +6 -5
  65. data/lib/arel_extensions/nodes/soundex.rb +15 -15
  66. data/lib/arel_extensions/nodes/std.rb +21 -18
  67. data/lib/arel_extensions/nodes/substring.rb +16 -8
  68. data/lib/arel_extensions/nodes/then.rb +1 -1
  69. data/lib/arel_extensions/nodes/trim.rb +6 -4
  70. data/lib/arel_extensions/nodes/union.rb +8 -5
  71. data/lib/arel_extensions/nodes/union_all.rb +7 -4
  72. data/lib/arel_extensions/nodes/wday.rb +4 -0
  73. data/lib/arel_extensions/nodes.rb +1 -1
  74. data/lib/arel_extensions/null_functions.rb +7 -5
  75. data/lib/arel_extensions/predications.rb +43 -44
  76. data/lib/arel_extensions/railtie.rb +5 -5
  77. data/lib/arel_extensions/set_functions.rb +7 -5
  78. data/lib/arel_extensions/string_functions.rb +29 -58
  79. data/lib/arel_extensions/tasks.rb +6 -6
  80. data/lib/arel_extensions/version.rb +1 -1
  81. data/lib/arel_extensions/visitors/ibm_db.rb +31 -24
  82. data/lib/arel_extensions/visitors/mssql.rb +181 -279
  83. data/lib/arel_extensions/visitors/mysql.rb +210 -280
  84. data/lib/arel_extensions/visitors/oracle.rb +180 -201
  85. data/lib/arel_extensions/visitors/oracle12.rb +31 -18
  86. data/lib/arel_extensions/visitors/postgresql.rb +173 -252
  87. data/lib/arel_extensions/visitors/sqlite.rb +126 -140
  88. data/lib/arel_extensions/visitors/to_sql.rb +237 -272
  89. data/lib/arel_extensions/visitors.rb +59 -75
  90. data/lib/arel_extensions.rb +31 -159
  91. data/test/database.yml +7 -15
  92. data/test/helper.rb +18 -0
  93. data/test/real_db_test.rb +116 -105
  94. data/test/support/fake_record.rb +3 -3
  95. data/test/test_comparators.rb +17 -14
  96. data/test/visitors/test_bulk_insert_oracle.rb +11 -11
  97. data/test/visitors/test_bulk_insert_sqlite.rb +13 -12
  98. data/test/visitors/test_bulk_insert_to_sql.rb +13 -11
  99. data/test/visitors/test_oracle.rb +55 -55
  100. data/test/visitors/test_to_sql.rb +226 -419
  101. data/test/with_ar/all_agnostic_test.rb +361 -578
  102. data/test/with_ar/insert_agnostic_test.rb +21 -27
  103. data/test/with_ar/test_bulk_sqlite.rb +16 -17
  104. data/test/with_ar/test_math_sqlite.rb +26 -26
  105. data/test/with_ar/test_string_mysql.rb +33 -31
  106. data/test/with_ar/test_string_sqlite.rb +34 -30
  107. metadata +22 -29
  108. data/.github/workflows/ruby.yml +0 -341
  109. data/gemfiles/rails6.gemfile +0 -30
  110. data/gemfiles/rails6_1.gemfile +0 -30
  111. data/gemfiles/rails7.gemfile +0 -23
  112. data/gemspecs/arel_extensions-v1.gemspec +0 -28
  113. data/gemspecs/arel_extensions-v2.gemspec +0 -28
  114. data/generate_gems.sh +0 -15
  115. data/lib/arel_extensions/aliases.rb +0 -14
  116. data/lib/arel_extensions/helpers.rb +0 -51
  117. data/lib/arel_extensions/nodes/aggregate_function.rb +0 -13
  118. data/lib/arel_extensions/nodes/sum.rb +0 -7
  119. data/lib/arel_extensions/visitors/convert_format.rb +0 -37
  120. data/test/arelx_test_helper.rb +0 -71
  121. data/version_v1.rb +0 -3
  122. data/version_v2.rb +0 -3
@@ -1,45 +1,17 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
3
  module MSSQL
4
-
5
- mssql_class = Arel::Visitors.constants.select { |c|
6
- Arel::Visitors.const_get(c).is_a?(Class) && %i[MSSQL SQLServer].include?(c)
7
- }.first
8
-
9
- LOADED_VISITOR = Arel::Visitors.const_get(mssql_class) || Arel::Visitors.const_get('MSSQL')
10
-
11
- LOADED_VISITOR::DATE_MAPPING = {
12
- 'd' => 'day', 'm' => 'month', 'y' => 'year', 'wd' => 'weekday', 'w' => 'week', 'h' => 'hour', 'mn' => 'minute', 's' => 'second'
13
- }.freeze
14
-
15
- LOADED_VISITOR::DATE_FORMAT_DIRECTIVES = {
16
- '%Y' => 'YYYY', '%C' => '', '%y' => 'YY', '%m' => 'MM', '%B' => 'month', '%^B' => '', '%b' => '', '%^b' => '', # year, month
17
- '%V' => 'iso_week', '%G' => '', # ISO week number and year of week
18
- '%d' => 'DD', '%e' => '' , '%j' => '' , '%w' => 'dw', %'a' => '', '%A' => 'weekday', # day, weekday
19
- '%H' => 'hh', '%k' => '' , '%I' => '' , '%l' => '' , '%P' => '', '%p' => '', # hours
4
+ Arel::Visitors::MSSQL::DATE_MAPPING = {'d' => 'day', 'm' => 'month', 'y' => 'year', 'wd' => 'weekday', 'w' => 'week', 'h' => 'hour', 'mn' => 'minute', 's' => 'second'}
5
+ Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES = {
6
+ '%Y' => 'YYYY', '%C' => '', '%y' => 'YY', '%m' => 'MM', '%B' => '', '%b' => '', '%^b' => '', # year, month
7
+ '%d' => 'DD', '%e' => '', '%j' => '', '%w' => 'dw', '%A' => '', # day, weekday
8
+ '%H' => 'hh', '%k' => '', '%I' => '', '%l' => '', '%P' => '', '%p' => '', # hours
20
9
  '%M' => 'mi', '%S' => 'ss', '%L' => 'ms', '%N' => 'ns', '%z' => 'tz'
21
- }.freeze
22
-
23
- LOADED_VISITOR::DATE_FORMAT_FORMAT = {
24
- 'YY' => '0#', 'MM' => '0#', 'DD' => '0#', 'hh' => '0#', 'mi' => '0#', 'ss' => '0#', 'iso_week' => '0#'
25
10
  }
26
-
27
- LOADED_VISITOR::DATE_NAME = [
28
- '%B', '%A'
29
- ]
30
-
31
- LOADED_VISITOR::DATE_FORMAT_REGEX =
32
- Regexp.new(
33
- LOADED_VISITOR::DATE_FORMAT_DIRECTIVES
34
- .keys
35
- .map{|k| Regexp.escape(k)}
36
- .join('|')
37
- ).freeze
38
-
39
11
  # TODO; all others... http://www.sql-server-helper.com/tips/date-formats.aspx
40
- LOADED_VISITOR::DATE_CONVERT_FORMATS = {
12
+ Arel::Visitors::MSSQL::DATE_CONVERT_FORMATS = {
41
13
  'YYYY-MM-DD' => 120,
42
- 'YY-MM-DD' => 120,
14
+ 'YY-MM-DD' => 120,
43
15
  'MM/DD/YYYY' => 101,
44
16
  'MM-DD-YYYY' => 110,
45
17
  'YYYY/MM/DD' => 111,
@@ -47,108 +19,108 @@ module ArelExtensions
47
19
  'DD-MM-YY' => 5,
48
20
  'DD.MM.YYYY' => 104,
49
21
  'YYYY-MM-DDTHH:MM:SS:MMM' => 126
50
- }.freeze
22
+ }
51
23
 
52
24
  # Math Functions
53
25
  def visit_ArelExtensions_Nodes_Ceil o, collector
54
- collector << 'CEILING('
26
+ collector << "CEILING("
55
27
  collector = visit o.expr, collector
56
- collector << ')'
28
+ collector << ")"
57
29
  collector
58
30
  end
59
31
 
60
32
  def visit_ArelExtensions_Nodes_Log10 o, collector
61
- collector << 'LOG10('
33
+ collector << "LOG10("
62
34
  o.expressions.each_with_index { |arg, i|
63
- collector << Arel::Visitors::ToSql::COMMA if i != 0
35
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
64
36
  collector = visit arg, collector
65
37
  }
66
- collector << ')'
38
+ collector << ")"
67
39
  collector
68
40
  end
69
41
 
70
42
  def visit_ArelExtensions_Nodes_Power o, collector
71
- collector << 'POWER('
43
+ collector << "POWER("
72
44
  o.expressions.each_with_index { |arg, i|
73
- collector << Arel::Visitors::ToSql::COMMA if i != 0
45
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
74
46
  collector = visit arg, collector
75
47
  }
76
- collector << ')'
48
+ collector << ")"
77
49
  collector
78
50
  end
79
51
 
80
52
  def visit_ArelExtensions_Nodes_IsNull o, collector
81
- collector << '('
53
+ collector << "("
82
54
  collector = visit o.expr, collector
83
- collector << ' IS NULL)'
55
+ collector << " IS NULL)"
84
56
  collector
85
57
  end
86
58
 
87
59
  def visit_ArelExtensions_Nodes_IsNotNull o, collector
88
- collector << '('
60
+ collector << "("
89
61
  collector = visit o.expr, collector
90
- collector << ' IS NOT NULL)'
62
+ collector << " IS NOT NULL)"
91
63
  collector
92
64
  end
93
65
 
94
66
  def visit_ArelExtensions_Nodes_Concat o, collector
95
- collector << 'CONCAT('
67
+ collector << "CONCAT("
96
68
  o.expressions.each_with_index { |arg, i|
97
- collector << LOADED_VISITOR::COMMA if i != 0
69
+ collector << Arel::Visitors::MSSQL::COMMA unless i == 0
98
70
  collector = visit arg, collector
99
71
  }
100
- collector << ')'
72
+ collector << ")"
101
73
  collector
102
74
  end
103
75
 
104
76
  def visit_ArelExtensions_Nodes_Repeat o, collector
105
- collector << 'REPLICATE('
77
+ collector << "REPLICATE("
106
78
  o.expressions.each_with_index { |arg, i|
107
- collector << Arel::Visitors::ToSql::COMMA if i != 0
79
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
108
80
  collector = visit arg, collector
109
81
  }
110
- collector << ')'
82
+ collector << ")"
111
83
  collector
112
84
  end
113
85
 
114
86
 
115
87
 
116
88
  def visit_ArelExtensions_Nodes_DateDiff o, collector
117
- case o.right_node_type
118
- when :ruby_date, :ruby_time, :date, :datetime, :time
119
- collector << case o.left_node_type
120
- when :ruby_time, :datetime, :time then 'DATEDIFF(second'
121
- else 'DATEDIFF(day'
89
+ if o.right_node_type == :ruby_date || o.right_node_type == :ruby_time || o.right_node_type == :date || o.right_node_type == :datetime || o.right_node_type == :time
90
+ collector << if o.left_node_type == :ruby_time || o.left_node_type == :datetime || o.left_node_type == :time
91
+ 'DATEDIFF(second'
92
+ else
93
+ 'DATEDIFF(day'
122
94
  end
123
- collector << LOADED_VISITOR::COMMA
95
+ collector << Arel::Visitors::MSSQL::COMMA
124
96
  collector = visit o.right, collector
125
- collector << LOADED_VISITOR::COMMA
97
+ collector << Arel::Visitors::MSSQL::COMMA
126
98
  collector = visit o.left, collector
127
99
  collector << ')'
128
100
  else
129
101
  da = ArelExtensions::Nodes::DateAdd.new([])
130
- collector << 'DATEADD('
102
+ collector << "DATEADD("
131
103
  collector = visit da.mssql_datepart(o.right), collector
132
- collector << LOADED_VISITOR::COMMA
133
- collector << '-('
104
+ collector << Arel::Visitors::MSSQL::COMMA
105
+ collector << "-("
134
106
  collector = visit da.mssql_value(o.right), collector
135
- collector << ')'
136
- collector << LOADED_VISITOR::COMMA
107
+ collector << ")"
108
+ collector << Arel::Visitors::MSSQL::COMMA
137
109
  collector = visit o.left, collector
138
- collector << ')'
110
+ collector << ")"
139
111
  collector
140
112
  end
141
113
  collector
142
114
  end
143
115
 
144
116
  def visit_ArelExtensions_Nodes_DateAdd o, collector
145
- collector << 'DATEADD('
117
+ collector << "DATEADD("
146
118
  collector = visit o.mssql_datepart(o.right), collector
147
- collector << LOADED_VISITOR::COMMA
119
+ collector << Arel::Visitors::MSSQL::COMMA
148
120
  collector = visit o.mssql_value(o.right), collector
149
- collector << LOADED_VISITOR::COMMA
121
+ collector << Arel::Visitors::MSSQL::COMMA
150
122
  collector = visit o.left, collector
151
- collector << ')'
123
+ collector << ")"
152
124
  collector
153
125
  end
154
126
 
@@ -157,77 +129,68 @@ module ArelExtensions
157
129
  collector = visit o.right, collector
158
130
  else
159
131
  left = o.left.end_with?('i') ? o.left[0..-2] : o.left
160
- conv = %w[h mn s].include?(o.left)
132
+ conv = ['h', 'mn', 's'].include?(o.left)
161
133
  collector << 'DATEPART('
162
- collector << LOADED_VISITOR::DATE_MAPPING[left]
163
- collector << LOADED_VISITOR::COMMA
134
+ collector << Arel::Visitors::MSSQL::DATE_MAPPING[left]
135
+ collector << Arel::Visitors::MSSQL::COMMA
164
136
  collector << 'CONVERT(datetime,' if conv
165
137
  collector = visit o.right, collector
166
138
  collector << ')' if conv
167
- collector << ')'
139
+ collector << ")"
168
140
  end
169
141
  collector
170
142
  end
171
143
 
172
144
  def visit_ArelExtensions_Nodes_Length o, collector
173
- if o.bytewise
174
- collector << '(DATALENGTH('
175
- collector = visit o.expr, collector
176
- collector << ') / ISNULL(NULLIF(DATALENGTH(LEFT(COALESCE('
177
- collector = visit o.expr, collector
178
- collector << ", '#' ), 1 )), 0), 1))"
179
- collector
180
- else
181
- collector << 'LEN('
182
- collector = visit o.expr, collector
183
- collector << ')'
184
- collector
185
- end
145
+ collector << "LEN("
146
+ collector = visit o.expr, collector
147
+ collector << ")"
148
+ collector
186
149
  end
187
150
 
188
151
  def visit_ArelExtensions_Nodes_Round o, collector
189
- collector << 'ROUND('
152
+ collector << "ROUND("
190
153
  o.expressions.each_with_index { |arg, i|
191
- collector << LOADED_VISITOR::COMMA if i != 0
154
+ collector << Arel::Visitors::MSSQL::COMMA unless i == 0
192
155
  collector = visit arg, collector
193
156
  }
194
157
  if o.expressions.length == 1
195
- collector << LOADED_VISITOR::COMMA
196
- collector << '0'
158
+ collector << Arel::Visitors::MSSQL::COMMA
159
+ collector << "0"
197
160
  end
198
- collector << ')'
161
+ collector << ")"
199
162
  collector
200
163
  end
201
164
 
202
165
  def visit_ArelExtensions_Nodes_Locate o, collector
203
- collector << 'CHARINDEX('
166
+ collector << "CHARINDEX("
204
167
  collector = visit o.right, collector
205
- collector << LOADED_VISITOR::COMMA
168
+ collector << Arel::Visitors::MSSQL::COMMA
206
169
  collector = visit o.left, collector
207
- collector << ')'
170
+ collector << ")"
208
171
  collector
209
172
  end
210
173
 
211
174
  def visit_ArelExtensions_Nodes_Substring o, collector
212
175
  collector << 'SUBSTRING('
213
176
  collector = visit o.expressions[0], collector
214
- collector << LOADED_VISITOR::COMMA
177
+ collector << Arel::Visitors::MSSQL::COMMA
215
178
  collector = visit o.expressions[1], collector
216
- collector << LOADED_VISITOR::COMMA
179
+ collector << Arel::Visitors::MSSQL::COMMA
217
180
  collector = o.expressions[2] ? visit(o.expressions[2], collector) : visit(o.expressions[0].length, collector)
218
181
  collector << ')'
219
182
  collector
220
183
  end
221
184
 
222
185
  def visit_ArelExtensions_Nodes_Trim o, collector
223
- # NOTE: in MSSQL's `blank`, o.right is the space char so we need to
224
- # account for it.
225
- if o.right && !/\A\s\Z/.match(o.right.expr)
226
- collector << 'dbo.TrimChar('
186
+ if o.right
187
+ collector << "REPLACE(REPLACE(LTRIM(RTRIM(REPLACE(REPLACE("
227
188
  collector = visit o.left, collector
228
- collector << Arel::Visitors::MSSQL::COMMA
189
+ collector << ", ' ', '~'), "
229
190
  collector = visit o.right, collector
230
- collector << ')'
191
+ collector << ", ' '))), ' ', "
192
+ collector = visit o.right, collector
193
+ collector << "), '~', ' ')"
231
194
  else
232
195
  collector << "LTRIM(RTRIM("
233
196
  collector = visit o.left, collector
@@ -238,7 +201,7 @@ module ArelExtensions
238
201
 
239
202
  def visit_ArelExtensions_Nodes_Ltrim o, collector
240
203
  if o.right
241
- collector << 'REPLACE(REPLACE(LTRIM(REPLACE(REPLACE('
204
+ collector << "REPLACE(REPLACE(LTRIM(REPLACE(REPLACE("
242
205
  collector = visit o.left, collector
243
206
  collector << ", ' ', '~'), "
244
207
  collector = visit o.right, collector
@@ -246,16 +209,16 @@ module ArelExtensions
246
209
  collector = visit o.right, collector
247
210
  collector << "), '~', ' ')"
248
211
  else
249
- collector << 'LTRIM('
212
+ collector << "LTRIM("
250
213
  collector = visit o.left, collector
251
- collector << ')'
214
+ collector << ")"
252
215
  end
253
216
  collector
254
217
  end
255
218
 
256
219
  def visit_ArelExtensions_Nodes_Rtrim o, collector
257
220
  if o.right
258
- collector << 'REPLACE(REPLACE(RTRIM(REPLACE(REPLACE('
221
+ collector << "REPLACE(REPLACE(RTRIM(REPLACE(REPLACE("
259
222
  collector = visit o.left, collector
260
223
  collector << ", ' ', '~'), "
261
224
  collector = visit o.right, collector
@@ -263,9 +226,9 @@ module ArelExtensions
263
226
  collector = visit o.right, collector
264
227
  collector << "), '~', ' ')"
265
228
  else
266
- collector << 'RTRIM('
229
+ collector << "RTRIM("
267
230
  collector = visit o.left, collector
268
- collector << ')'
231
+ collector << ")"
269
232
  end
270
233
  collector
271
234
  end
@@ -279,98 +242,64 @@ module ArelExtensions
279
242
  end
280
243
 
281
244
  def visit_ArelExtensions_Nodes_Format o, collector
282
- f = ArelExtensions::Visitors::strftime_to_format(o.iso_format, LOADED_VISITOR::DATE_FORMAT_DIRECTIVES)
283
- if fmt = LOADED_VISITOR::DATE_CONVERT_FORMATS[f]
245
+ f = o.iso_format.dup
246
+ Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
247
+ if Arel::Visitors::MSSQL::DATE_CONVERT_FORMATS[f]
284
248
  collector << "CONVERT(VARCHAR(#{f.length})"
285
- collector << LOADED_VISITOR::COMMA
286
- if o.time_zone
287
- collector << 'CONVERT(datetime'
288
- collector << LOADED_VISITOR::COMMA
289
- collector << ' '
290
- end
249
+ collector << Arel::Visitors::MSSQL::COMMA
291
250
  collector = visit o.left, collector
292
- case o.time_zone
293
- when Hash
294
- src_tz, dst_tz = o.time_zone.first
295
- collector << ') AT TIME ZONE '
296
- collector = visit Arel.quoted(src_tz), collector
297
- collector << ' AT TIME ZONE '
298
- collector = visit Arel.quoted(dst_tz), collector
299
- when String
300
- collector << ') AT TIME ZONE '
301
- collector = visit Arel.quoted(o.time_zone), collector
302
- end
303
- collector << LOADED_VISITOR::COMMA
304
- collector << fmt.to_s
251
+ collector << Arel::Visitors::MSSQL::COMMA
252
+ collector << Arel::Visitors::MSSQL::DATE_CONVERT_FORMATS[f].to_s
305
253
  collector << ')'
306
254
  collector
307
255
  else
308
- s = StringScanner.new o.iso_format
309
- collector << '('
310
- sep = ''
311
- while !s.eos?
312
- collector << sep
313
- sep = ' + '
314
- case
315
- when s.scan(LOADED_VISITOR::DATE_FORMAT_REGEX)
316
- dir = LOADED_VISITOR::DATE_FORMAT_DIRECTIVES[s.matched]
317
- fmt = LOADED_VISITOR::DATE_FORMAT_FORMAT[dir]
318
- date_name = LOADED_VISITOR::DATE_NAME.include?(s.matched)
319
- collector << 'LTRIM(RTRIM('
320
- collector << 'FORMAT(' if fmt
321
- collector << 'STR(' if !fmt && !date_name
322
- collector << (date_name ? 'DATENAME(' : 'DATEPART(')
323
- collector << dir
324
- collector << LOADED_VISITOR::COMMA
325
- if o.time_zone
326
- collector << 'CONVERT(datetime'
327
- collector << LOADED_VISITOR::COMMA
328
- collector << ' '
256
+ collector << "("
257
+ t = o.iso_format.split('%')
258
+ t.each_with_index {|str, i|
259
+ if i == 0 && t[0] != '%'
260
+ collector = visit Arel::Nodes.build_quoted(str), collector
261
+ if str.length > 1
262
+ collector << Arel::Visitors::MSSQL::COMMA
263
+ collector = visit Arel::Nodes.build_quoted(str.sub(/\A./, '')), collector
329
264
  end
330
- collector = visit o.left, collector
331
- case o.time_zone
332
- when Hash
333
- src_tz, dst_tz = o.time_zone.first.first, o.time_zone.first.second
334
- collector << ') AT TIME ZONE '
335
- collector = visit Arel.quoted(src_tz), collector
336
- collector << ' AT TIME ZONE '
337
- collector = visit Arel.quoted(dst_tz), collector
338
- when String
339
- collector << ') AT TIME ZONE '
340
- collector = visit Arel.quoted(o.time_zone), collector
265
+ elsif str.length > 0
266
+ if !Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES['%' + str[0]].blank?
267
+ collector << 'LTRIM(STR(DATEPART('
268
+ collector << Arel::Visitors::MSSQL::DATE_FORMAT_DIRECTIVES['%' + str[0]]
269
+ collector << Arel::Visitors::MSSQL::COMMA
270
+ collector = visit o.left, collector
271
+ collector << ')))'
272
+ if str.length > 1
273
+ collector << ' + '
274
+ collector = visit Arel::Nodes.build_quoted(str.sub(/\A./, '')), collector
275
+ end
341
276
  end
342
- collector << ')'
343
- collector << ')' if !fmt && !date_name
344
- collector << LOADED_VISITOR::COMMA << "'#{fmt}')" if fmt
345
- collector << '))'
346
- when s.scan(/^%%/)
347
- collector = visit Arel.quoted('%'), collector
348
- when s.scan(/[^%]+|./)
349
- collector = visit Arel.quoted(s.matched), collector
350
277
  end
351
- end
278
+ collector << ' + ' if t[i + 1]
279
+ }
280
+
352
281
  collector << ')'
353
282
  collector
354
283
  end
355
284
  end
356
285
 
357
286
  def visit_ArelExtensions_Nodes_Replace o, collector
358
- collector << 'REPLACE('
287
+ collector << "REPLACE("
359
288
  o.expressions.each_with_index { |arg, i|
360
- collector << LOADED_VISITOR::COMMA if i != 0
289
+ collector << Arel::Visitors::MSSQL::COMMA unless i == 0
361
290
  collector = visit arg, collector
362
291
  }
363
- collector << ')'
292
+ collector << ")"
364
293
  collector
365
294
  end
366
295
 
367
296
  def visit_ArelExtensions_Nodes_FindInSet o, collector
368
- collector << 'dbo.FIND_IN_SET('
297
+ collector << "dbo.FIND_IN_SET("
369
298
  o.expressions.each_with_index { |arg, i|
370
- collector << LOADED_VISITOR::COMMA if i != 0
299
+ collector << Arel::Visitors::MSSQL::COMMA unless i == 0
371
300
  collector = visit arg, collector
372
301
  }
373
- collector << ')'
302
+ collector << ")"
374
303
  collector
375
304
  end
376
305
 
@@ -413,9 +342,9 @@ module ArelExtensions
413
342
  end
414
343
 
415
344
  def visit_ArelExtensions_Nodes_AiIMatches o, collector
416
- collector = visit o.left.collate(true, true), collector
345
+ collector = visit o.left.collate(true,true), collector
417
346
  collector << ' LIKE '
418
- collector = visit o.right.collate(true, true), collector
347
+ collector = visit o.right.collate(true,true), collector
419
348
  if o.escape
420
349
  collector << ' ESCAPE '
421
350
  visit o.escape, collector
@@ -453,27 +382,6 @@ module ArelExtensions
453
382
  collector
454
383
  end
455
384
 
456
- alias_method(:old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As) rescue nil
457
- def visit_Arel_Nodes_As o, collector
458
- if o.left.is_a?(Arel::Nodes::Binary)
459
- collector << '('
460
- collector = visit o.left, collector
461
- collector << ')'
462
- else
463
- collector = visit o.left, collector
464
- end
465
- collector << ' AS '
466
-
467
- # sometimes these values are already quoted, if they are, don't double quote it
468
- quote = o.right.is_a?(Arel::Nodes::SqlLiteral) && o.right[0] != '"' && o.right[-1] != '"'
469
-
470
- collector << '"' if quote
471
- collector = visit o.right, collector
472
- collector << '"' if quote
473
-
474
- collector
475
- end
476
-
477
385
  # SQL Server does not know about REGEXP
478
386
  def visit_Arel_Nodes_Regexp o, collector
479
387
  collector = visit o.left, collector
@@ -489,114 +397,106 @@ module ArelExtensions
489
397
 
490
398
  # TODO;
491
399
  def visit_ArelExtensions_Nodes_GroupConcat o, collector
492
- collector << '(STRING_AGG('
400
+ collector << "(STRING_AGG("
493
401
  collector = visit o.left, collector
494
402
  collector << Arel::Visitors::Oracle::COMMA
495
- collector =
496
- if o.separator && o.separator != 'NULL'
497
- visit o.separator, collector
498
- else
499
- visit Arel.quoted(','), collector
500
- end
501
- collector << ') WITHIN GROUP (ORDER BY '
502
- if o.order.present?
503
- o.order.each_with_index do |order, i|
504
- collector << Arel::Visitors::Oracle::COMMA if i != 0
403
+ if o.right && o.right != 'NULL'
404
+ collector = visit o.right, collector
405
+ else
406
+ collector = visit Arel::Nodes.build_quoted(','), collector
407
+ end
408
+ collector << ") WITHIN GROUP (ORDER BY "
409
+ if !o.orders.blank?
410
+ o.orders.each_with_index do |order,i|
411
+ collector << Arel::Visitors::Oracle::COMMA unless i == 0
505
412
  collector = visit order, collector
506
413
  end
507
414
  else
508
415
  collector = visit o.left, collector
509
416
  end
510
- collector << '))'
417
+ collector << "))"
511
418
  collector
512
419
  end
513
420
 
514
421
  def visit_ArelExtensions_Nodes_MD5 o, collector
515
422
  collector << "LOWER(CONVERT(NVARCHAR(32),HashBytes('MD5',CONVERT(VARCHAR,"
516
423
  collector = visit o.left, collector
517
- collector << ')),2))'
424
+ collector << ")),2))"
518
425
  collector
519
426
  end
520
427
 
521
428
  def visit_ArelExtensions_Nodes_Cast o, collector
522
- as_attr =
523
- case o.as_attr
524
- when :string
525
- 'varchar'
526
- when :time
527
- 'time'
528
- when :date
529
- 'date'
530
- when :datetime
531
- 'datetime'
532
- when :number, :decimal, :float
533
- 'decimal(10,6)'
534
- when :int
535
- collector << 'CAST(CAST('
536
- collector = visit o.left, collector
537
- collector << ' AS decimal(10,0)) AS int)'
538
- return collector
539
- when :binary
540
- 'binary'
541
- else
542
- o.as_attr.to_s
543
- end
544
- collector << 'CAST('
429
+ case o.as_attr
430
+ when :string
431
+ as_attr = Arel::Nodes::SqlLiteral.new('varchar')
432
+ when :time
433
+ as_attr = Arel::Nodes::SqlLiteral.new('time')
434
+ when :date
435
+ as_attr = Arel::Nodes::SqlLiteral.new('date')
436
+ when :datetime
437
+ as_attr = Arel::Nodes::SqlLiteral.new('datetime')
438
+ when :number,:decimal, :float
439
+ as_attr = Arel::Nodes::SqlLiteral.new('decimal(10,6)')
440
+ when :int
441
+ collector << "CAST(CAST("
442
+ collector = visit o.left, collector
443
+ collector << " AS decimal(10,0)) AS int)"
444
+ return collector
445
+ when :binary
446
+ as_attr = Arel::Nodes::SqlLiteral.new('binary')
447
+ else
448
+ as_attr = Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
449
+ end
450
+ collector << "CAST("
545
451
  collector = visit o.left, collector
546
- collector << ' AS '
547
- collector = visit Arel::Nodes::SqlLiteral.new(as_attr), collector
548
- collector << ')'
452
+ collector << " AS "
453
+ collector = visit as_attr, collector
454
+ collector << ")"
549
455
  collector
550
456
  end
551
457
 
552
458
  def visit_ArelExtensions_Nodes_FormattedNumber o, collector
553
459
  col = o.left.coalesce(0)
554
- locale = Arel.quoted(o.locale.tr('_', '-'))
555
- param = Arel.quoted("N#{o.precision}")
556
- sign = Arel.when(col < 0).
460
+ locale = Arel::Nodes.build_quoted(o.locale.tr('_','-'))
461
+ param = Arel::Nodes.build_quoted("N#{o.precision}")
462
+ sign = ArelExtensions::Nodes::Case.new.when(col<0).
557
463
  then('-').
558
464
  else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
559
465
  sign_length = o.flags.include?('+') || o.flags.include?(' ') ?
560
- Arel.quoted(1) :
561
- Arel.when(col < 0).then(1).else(0)
562
-
563
- number =
564
- if o.scientific_notation
565
- ArelExtensions::Nodes::Concat.new([
566
- Arel::Nodes::NamedFunction.new('FORMAT', [
567
- col.abs / Arel.quoted(10).pow(col.abs.log10.floor),
466
+ Arel::Nodes.build_quoted(1) :
467
+ ArelExtensions::Nodes::Case.new.when(col<0).then(1).else(0)
468
+
469
+ if o.scientific_notation
470
+ number = ArelExtensions::Nodes::Concat.new([
471
+ Arel::Nodes::NamedFunction.new('FORMAT',[
472
+ col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
568
473
  param,
569
474
  locale
570
475
  ]),
571
476
  o.type,
572
- Arel::Nodes::NamedFunction.new('FORMAT', [
477
+ Arel::Nodes::NamedFunction.new('FORMAT',[
573
478
  col.abs.log10.floor,
574
- Arel.quoted('N0'),
479
+ Arel::Nodes.build_quoted('N0'),
575
480
  locale
576
481
  ])
577
482
  ])
578
- else
579
- Arel::Nodes::NamedFunction.new('FORMAT', [
580
- Arel.quoted(col.abs),
483
+ else
484
+ number = Arel::Nodes::NamedFunction.new('FORMAT',[
485
+ Arel::Nodes.build_quoted(col.abs),
581
486
  param,
582
487
  locale
583
488
  ])
584
- end
489
+ end
585
490
 
586
- repeated_char =
587
- if o.width == 0
588
- Arel.quoted('')
589
- else
590
- Arel
591
- .when(Arel.quoted(o.width).abs - (number.length + sign_length) > 0)
592
- .then(Arel.quoted(
593
- o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
594
- ).repeat(Arel.quoted(o.width).abs - (number.length + sign_length))
595
- )
596
- .else('')
597
- end
598
- before = !o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
599
- middle = o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
491
+ repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
492
+ when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
493
+ then(Arel::Nodes.build_quoted(
494
+ o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
495
+ ).repeat(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length))
496
+ ).
497
+ else('')
498
+ before = (!o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
499
+ middle = (o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
600
500
  after = o.flags.include?('-') ? repeated_char : ''
601
501
  full_number =
602
502
  ArelExtensions::Nodes::Concat.new([
@@ -606,27 +506,27 @@ module ArelExtensions
606
506
  number,
607
507
  after
608
508
  ])
609
- collector = visit ArelExtensions::Nodes::Concat.new([Arel.quoted(o.prefix), full_number, Arel.quoted(o.suffix)]), collector
509
+ collector = visit ArelExtensions::Nodes::Concat.new([Arel::Nodes.build_quoted(o.prefix),full_number,Arel::Nodes.build_quoted(o.suffix)]), collector
610
510
  collector
611
511
  end
612
512
 
613
513
  def visit_ArelExtensions_Nodes_Std o, collector
614
- collector << (o.unbiased_estimator ? 'STDEV(' : 'STDEVP(')
514
+ collector << (o.unbiased_estimator ? "STDEV(" : "STDEVP(")
615
515
  visit o.left, collector
616
- collector << ')'
516
+ collector << ")"
617
517
  collector
618
518
  end
619
519
 
620
520
  def visit_ArelExtensions_Nodes_Variance o, collector
621
- collector << (o.unbiased_estimator ? 'VAR(' : 'VARP(')
521
+ collector << (o.unbiased_estimator ? "VAR(" : "VARP(")
622
522
  visit o.left, collector
623
- collector << ')'
523
+ collector << ")"
624
524
  collector
625
525
  end
626
526
 
627
527
 
628
528
  def visit_ArelExtensions_Nodes_LevenshteinDistance o, collector
629
- collector << 'dbo.LEVENSHTEIN_DISTANCE('
529
+ collector << "dbo.LEVENSHTEIN_DISTANCE("
630
530
  collector = visit o.left, collector
631
531
  collector << Arel::Visitors::ToSql::COMMA
632
532
  collector = visit o.right, collector
@@ -635,18 +535,20 @@ module ArelExtensions
635
535
  end
636
536
 
637
537
 
638
- def visit_ArelExtensions_Nodes_JsonGet o, collector
538
+ def visit_ArelExtensions_Nodes_JsonGet o,collector
639
539
  collector << 'JSON_VALUE('
640
540
  collector = visit o.dict, collector
641
541
  collector << Arel::Visitors::MySQL::COMMA
642
542
  if o.key.is_a?(Integer)
643
543
  collector << "\"$[#{o.key}]\""
644
544
  else
645
- collector = visit Arel.quoted('$.') + o.key, collector
545
+ collector = visit Arel::Nodes.build_quoted('$.')+o.key, collector
646
546
  end
647
547
  collector << ')'
648
548
  collector
649
549
  end
550
+
551
+
650
552
  end
651
553
  end
652
554
  end