arel_extensions 1.7.0 → 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 (146) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +2 -1
  3. data/.gitignore +6 -8
  4. data/.rubocop.yml +4 -194
  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 +28 -2
  13. data/README.md +89 -265
  14. data/Rakefile +30 -50
  15. data/TODO +1 -0
  16. data/appveyor.yml +22 -60
  17. data/arel_extensions.gemspec +17 -14
  18. data/functions.html +3 -3
  19. data/gemfiles/rails3.gemfile +20 -0
  20. data/gemfiles/rails4.gemfile +29 -0
  21. data/gemfiles/rails5_0.gemfile +29 -0
  22. data/gemfiles/rails5_1_4.gemfile +17 -19
  23. data/gemfiles/rails5_2.gemfile +17 -26
  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 +25 -24
  28. data/init/sqlite.sql +0 -0
  29. data/lib/arel_extensions/attributes.rb +3 -9
  30. data/lib/arel_extensions/boolean_functions.rb +16 -57
  31. data/lib/arel_extensions/common_sql_functions.rb +20 -21
  32. data/lib/arel_extensions/comparators.rb +28 -31
  33. data/lib/arel_extensions/date_duration.rb +13 -19
  34. data/lib/arel_extensions/insert_manager.rb +15 -22
  35. data/lib/arel_extensions/math.rb +70 -68
  36. data/lib/arel_extensions/math_functions.rb +52 -57
  37. data/lib/arel_extensions/nodes/abs.rb +1 -0
  38. data/lib/arel_extensions/nodes/blank.rb +5 -6
  39. data/lib/arel_extensions/nodes/case.rb +27 -31
  40. data/lib/arel_extensions/nodes/cast.rb +12 -12
  41. data/lib/arel_extensions/nodes/ceil.rb +1 -1
  42. data/lib/arel_extensions/nodes/coalesce.rb +5 -4
  43. data/lib/arel_extensions/nodes/collate.rb +10 -9
  44. data/lib/arel_extensions/nodes/concat.rb +22 -13
  45. data/lib/arel_extensions/nodes/date_diff.rb +70 -77
  46. data/lib/arel_extensions/nodes/duration.rb +5 -2
  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 +39 -50
  52. data/lib/arel_extensions/nodes/is_null.rb +0 -2
  53. data/lib/arel_extensions/nodes/json.rb +47 -72
  54. data/lib/arel_extensions/nodes/length.rb +0 -5
  55. data/lib/arel_extensions/nodes/levenshtein_distance.rb +2 -2
  56. data/lib/arel_extensions/nodes/locate.rb +3 -2
  57. data/lib/arel_extensions/nodes/log10.rb +2 -1
  58. data/lib/arel_extensions/nodes/matches.rb +8 -6
  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 +3 -2
  62. data/lib/arel_extensions/nodes/repeat.rb +6 -4
  63. data/lib/arel_extensions/nodes/replace.rb +8 -16
  64. data/lib/arel_extensions/nodes/round.rb +7 -6
  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 -58
  68. data/lib/arel_extensions/nodes/then.rb +2 -2
  69. data/lib/arel_extensions/nodes/trim.rb +7 -5
  70. data/lib/arel_extensions/nodes/union.rb +9 -6
  71. data/lib/arel_extensions/nodes/union_all.rb +8 -5
  72. data/lib/arel_extensions/nodes/wday.rb +6 -2
  73. data/lib/arel_extensions/nodes.rb +1 -1
  74. data/lib/arel_extensions/null_functions.rb +6 -18
  75. data/lib/arel_extensions/predications.rb +49 -54
  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 +55 -110
  79. data/lib/arel_extensions/tasks.rb +6 -6
  80. data/lib/arel_extensions/version.rb +1 -3
  81. data/lib/arel_extensions/visitors/ibm_db.rb +36 -29
  82. data/lib/arel_extensions/visitors/mssql.rb +248 -493
  83. data/lib/arel_extensions/visitors/mysql.rb +244 -420
  84. data/lib/arel_extensions/visitors/oracle.rb +258 -311
  85. data/lib/arel_extensions/visitors/oracle12.rb +34 -20
  86. data/lib/arel_extensions/visitors/postgresql.rb +239 -350
  87. data/lib/arel_extensions/visitors/sqlite.rb +169 -191
  88. data/lib/arel_extensions/visitors/to_sql.rb +299 -371
  89. data/lib/arel_extensions/visitors.rb +62 -83
  90. data/lib/arel_extensions.rb +32 -243
  91. data/test/database.yml +10 -20
  92. data/test/helper.rb +18 -0
  93. data/test/real_db_test.rb +120 -123
  94. data/test/support/fake_record.rb +3 -11
  95. data/test/test_comparators.rb +17 -14
  96. data/test/visitors/test_bulk_insert_oracle.rb +12 -12
  97. data/test/visitors/test_bulk_insert_sqlite.rb +14 -13
  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 +375 -912
  102. data/test/with_ar/insert_agnostic_test.rb +22 -28
  103. data/test/with_ar/test_bulk_sqlite.rb +17 -18
  104. data/test/with_ar/test_math_sqlite.rb +27 -27
  105. data/test/with_ar/test_string_mysql.rb +34 -32
  106. data/test/with_ar/test_string_sqlite.rb +35 -31
  107. metadata +64 -50
  108. data/.github/workflows/publish.yml +0 -30
  109. data/.github/workflows/release.yml +0 -30
  110. data/.github/workflows/ruby.yml +0 -452
  111. data/CONTRIBUTING.md +0 -102
  112. data/Makefile +0 -48
  113. data/NEWS.md +0 -131
  114. data/bin/build +0 -15
  115. data/bin/publish +0 -8
  116. data/dev/arelx.dockerfile +0 -41
  117. data/dev/compose.yaml +0 -69
  118. data/dev/postgres.dockerfile +0 -5
  119. data/dev/rbenv +0 -189
  120. data/gemfiles/rails5.gemfile +0 -36
  121. data/gemfiles/rails6.gemfile +0 -40
  122. data/gemfiles/rails6_1.gemfile +0 -48
  123. data/gemfiles/rails7.gemfile +0 -48
  124. data/gemfiles/rails7_1.gemfile +0 -48
  125. data/gemfiles/rails7_2.gemfile +0 -47
  126. data/gemfiles/rails8.gemfile +0 -40
  127. data/gemfiles/rails8_1.gemfile +0 -41
  128. data/gemspecs/arel_extensions-v1.gemspec +0 -25
  129. data/gemspecs/arel_extensions-v2.gemspec +0 -25
  130. data/generate_gems.sh +0 -15
  131. data/lib/arel_extensions/aliases.rb +0 -14
  132. data/lib/arel_extensions/constants.rb +0 -13
  133. data/lib/arel_extensions/helpers.rb +0 -61
  134. data/lib/arel_extensions/nodes/aggregate_function.rb +0 -13
  135. data/lib/arel_extensions/nodes/byte_size.rb +0 -11
  136. data/lib/arel_extensions/nodes/char_length.rb +0 -11
  137. data/lib/arel_extensions/nodes/formatted_date.rb +0 -42
  138. data/lib/arel_extensions/nodes/rollup.rb +0 -36
  139. data/lib/arel_extensions/nodes/select.rb +0 -10
  140. data/lib/arel_extensions/nodes/sum.rb +0 -7
  141. data/lib/arel_extensions/visitors/convert_format.rb +0 -37
  142. data/lib/arel_extensions/warning.rb +0 -42
  143. data/test/arelx_test_helper.rb +0 -94
  144. data/test/config_loader.rb +0 -9
  145. data/version_v1.rb +0 -5
  146. data/version_v2.rb +0 -5
@@ -1,96 +1,75 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- class Arel::Visitors::PostgreSQL
4
- DATE_MAPPING = {
5
- 'd' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'DOW',
6
- 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'
7
- }.freeze
8
-
9
- DATE_FORMAT_DIRECTIVES = {
10
- '%Y' => 'YYYY', '%C' => 'CC', '%y' => 'YY',
11
- '%m' => 'MM', '%B' => 'TMMonth', '%^B' => 'TMMONTH', '%b' => 'TMMon', '%^b' => 'TMMON',
12
- '%V' => 'IW', '%G' => 'IYYY', # ISO week number and year of week
13
- '%d' => 'DD', '%e' => 'FMDD', '%j' => 'DDD', '%w' => '', '%a' => 'TMDy', '%A' => 'TMDay', # day, weekday
14
- '%H' => 'HH24', '%k' => '', '%I' => 'HH', '%l' => '', '%P' => 'am', '%p' => 'AM', # hours
15
- '%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz', # seconds, subseconds
16
- '%%' => '%',
17
- }.freeze
18
-
19
- NUMBER_COMMA_MAPPING = {
20
- 'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', '
21
- }.freeze
22
-
23
- def visit_ArelExtensions_Nodes_ByteSize(o, collector)
24
- collector << 'octet_length('
25
- collector = visit o.expr.coalesce(''), collector
26
- collector << ')'
27
- collector
28
- end
29
-
30
- def visit_ArelExtensions_Nodes_CharLength(o, collector)
31
- collector << 'length('
32
- collector = visit o.expr.coalesce(''), collector
33
- collector << ')'
34
- collector
35
- end
36
-
37
- def visit_ArelExtensions_Nodes_Rand(o, collector)
38
- collector << 'RANDOM('
39
- if !o.left.nil? && !o.right.nil?
3
+ Arel::Visitors::PostgreSQL.class_eval do
4
+ Arel::Visitors::PostgreSQL::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'DOW', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
5
+ Arel::Visitors::PostgreSQL::DATE_FORMAT_DIRECTIVES = {
6
+ '%Y' => 'IYYY', '%C' => 'CC', '%y' => 'YY', '%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
7
+ '%d' => 'DD', '%e' => 'FMDD', '%j' => 'DDD', '%w' => '', '%A' => 'Day', # day, weekday
8
+ '%H' => 'HH24', '%k' => '', '%I' => 'HH', '%l' => '', '%P' => 'am', '%p' => 'AM', # hours
9
+ '%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz' # seconds, subseconds
10
+ }
11
+ Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING = { 'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', ' }
12
+
13
+ def visit_ArelExtensions_Nodes_Rand o, collector
14
+ collector << "RANDOM("
15
+ if(o.left != nil && o.right != nil)
40
16
  collector = visit o.left, collector
41
- collector << COMMA
17
+ collector << Arel::Visitors::PostgreSQL::COMMA
42
18
  collector = isit o.right, collector
43
19
  end
44
- collector << ')'
20
+ collector << ")"
45
21
  collector
46
22
  end
47
23
 
48
- def visit_ArelExtensions_Nodes_Power(o, collector)
49
- collector << 'POWER('
24
+ def visit_ArelExtensions_Nodes_Power o, collector
25
+ collector << "POWER("
50
26
  o.expressions.each_with_index { |arg, i|
51
- collector << COMMA if i != 0
27
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
52
28
  collector = visit arg, collector
53
29
  }
54
- collector << ')'
30
+ collector << ")"
55
31
  collector
56
32
  end
57
33
 
58
- def visit_ArelExtensions_Nodes_Log10(o, collector)
59
- collector << 'LOG('
34
+ def visit_ArelExtensions_Nodes_Log10 o, collector
35
+ collector << "LOG("
60
36
  o.expressions.each_with_index { |arg, i|
61
- collector << COMMA if i != 0
37
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
62
38
  collector = visit arg, collector
63
39
  }
64
- collector << ')'
40
+ collector << ")"
65
41
  collector
66
42
  end
67
43
 
44
+
68
45
  remove_method(:visit_Arel_Nodes_Regexp) rescue nil
69
- def visit_Arel_Nodes_Regexp(o, collector)
46
+ def visit_Arel_Nodes_Regexp o, collector
70
47
  collector = visit o.left, collector
71
- collector << ' ~ '
72
- visit o.right, collector
48
+ collector << " ~ "
49
+ collector = visit o.right, collector
50
+ collector
73
51
  end
74
52
 
75
53
  remove_method(:visit_Arel_Nodes_NotRegexp) rescue nil
76
- def visit_Arel_Nodes_NotRegexp(o, collector)
54
+ def visit_Arel_Nodes_NotRegexp o, collector
77
55
  collector = visit o.left, collector
78
- collector << ' !~ '
79
- visit o.right, collector
56
+ collector << " !~ "
57
+ collector = visit o.right, collector
58
+ collector
80
59
  end
81
60
 
82
- def visit_ArelExtensions_Nodes_Concat(o, collector)
61
+ def visit_ArelExtensions_Nodes_Concat o, collector
83
62
  collector << '('
84
63
  o.expressions.each_with_index { |arg, i|
85
64
  collector = visit arg, collector
86
65
  collector << ' || ' unless i == o.expressions.length - 1
87
66
  }
88
- collector << ')'
67
+ collector << ")"
89
68
  collector
90
69
  end
91
70
 
92
- alias old_visit_Arel_Nodes_As visit_Arel_Nodes_As rescue nil
93
- def visit_Arel_Nodes_As(o, collector)
71
+ alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
72
+ def visit_Arel_Nodes_As o, collector
94
73
  if o.left.is_a?(Arel::Nodes::Binary)
95
74
  collector << '('
96
75
  collector = visit o.left, collector
@@ -98,130 +77,84 @@ module ArelExtensions
98
77
  else
99
78
  collector = visit o.left, collector
100
79
  end
101
- collector << ' AS '
102
-
103
- # sometimes these values are already quoted, if they are, don't double quote it
104
- quote = o.right.is_a?(Arel::Nodes::SqlLiteral) && o.right[0] != '"' && o.right[-1] != '"'
105
-
106
- collector << '"' if quote
80
+ collector << " AS \""
107
81
  collector = visit o.right, collector
108
- collector << '"' if quote
109
-
82
+ collector << "\""
110
83
  collector
111
84
  end
112
85
 
113
- def visit_Aggregate_For_AggregateFunction(o, collector)
114
- if !o.order.blank? || !o.group.blank?
115
- collector << ' OVER ('
116
- if !o.group.blank?
117
- collector << ' PARTITION BY '
118
- o.group.each_with_index do |group, i|
119
- collector << COMMA if i != 0
120
- visit group, collector
121
- end
122
- end
123
- if !o.order.blank?
124
- collector << ' ORDER BY '
125
- o.order.each_with_index do |order, i|
126
- collector << COMMA if i != 0
127
- visit order, collector
128
- end
129
- end
130
- collector << ')'
131
- end
132
- collector
133
- end
134
-
135
- def visit_ArelExtensions_Nodes_GroupConcat(o, collector)
136
- collector << 'array_to_string(array_agg('
86
+ def visit_ArelExtensions_Nodes_GroupConcat o, collector
87
+ collector << "array_to_string(array_agg("
137
88
  collector = visit o.left, collector
138
- if o.order && !o.order.blank?
139
- collector << ' ORDER BY'
140
- o.order.each_with_index do |order, i|
141
- collector << COMMA if i != 0
142
- collector << ' '
143
- visit order, collector
89
+ if !o.orders.blank?
90
+ collector << ' ORDER BY '
91
+ o.orders.each_with_index do |order,i|
92
+ collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
93
+ collector = visit order, collector
144
94
  end
145
95
  end
146
- collector << ')'
147
- o.order = nil
148
- visit_Aggregate_For_AggregateFunction o, collector
149
- collector << COMMA
150
- sep = o.separator.is_a?(Arel::Nodes::Quoted) ? o.separator.expr : o.separator
151
- collector =
152
- if 'NULL' == sep
153
- visit Arel.quoted(','), collector
154
- else
155
- visit o.separator, collector
156
- end
157
- collector << ')'
96
+ collector << ")"
97
+ collector << Arel::Visitors::PostgreSQL::COMMA
98
+ if o.right && o.right != 'NULL'
99
+ collector = visit o.right, collector
100
+ else
101
+ collector = visit Arel::Nodes.build_quoted(','), collector
102
+ end
103
+ collector << ")"
158
104
  collector
159
105
  end
160
106
 
161
- def visit_ArelExtensions_Nodes_Trim(o, collector)
162
- collector << 'TRIM(BOTH '
163
- collector = visit o.right, collector
164
- collector << ' FROM '
165
- collector = visit o.left, collector
166
- collector << ')'
167
- collector
107
+ def visit_ArelExtensions_Nodes_Trim o, collector
108
+ collector << 'TRIM(BOTH '
109
+ collector = visit o.right, collector
110
+ collector << " FROM "
111
+ collector = visit o.left, collector
112
+ collector << ")"
113
+ collector
168
114
  end
169
115
 
170
- def visit_ArelExtensions_Nodes_Ltrim(o, collector)
171
- collector << 'TRIM(LEADING '
172
- collector = visit o.right, collector
173
- collector << ' FROM '
174
- collector = visit o.left, collector
175
- collector << ')'
176
- collector
116
+ def visit_ArelExtensions_Nodes_Ltrim o, collector
117
+ collector << 'TRIM(LEADING '
118
+ collector = visit o.right, collector
119
+ collector << " FROM "
120
+ collector = visit o.left, collector
121
+ collector << ")"
122
+ collector
177
123
  end
178
124
 
179
- def visit_ArelExtensions_Nodes_Rtrim(o, collector)
125
+ def visit_ArelExtensions_Nodes_Rtrim o, collector
180
126
  collector << 'TRIM(TRAILING '
181
127
  collector = visit o.right, collector
182
- collector << ' FROM '
128
+ collector << " FROM "
183
129
  collector = visit o.left, collector
184
- collector << ')'
130
+ collector << ")"
185
131
  collector
186
132
  end
187
133
 
188
- def visit_ArelExtensions_Nodes_Format(o, collector)
189
- visit_ArelExtensions_Nodes_FormattedDate o, collector
190
- end
191
-
192
- def visit_ArelExtensions_Nodes_FormattedDate(o, collector)
193
- fmt = ArelExtensions::Visitors.strftime_to_format(o.iso_format, DATE_FORMAT_DIRECTIVES)
194
- collector << 'TO_CHAR('
195
- collector << '(' if o.time_zone
134
+ def visit_ArelExtensions_Nodes_Format o, collector
135
+ collector << "TO_CHAR("
196
136
  collector = visit o.left, collector
197
- case o.time_zone
198
- when Hash
199
- src_tz, dst_tz = o.time_zone.first
200
- collector << ') AT TIME ZONE '
201
- collector = visit Arel.quoted(src_tz), collector
202
- collector << ' AT TIME ZONE '
203
- collector = visit Arel.quoted(dst_tz), collector
204
- when String
205
- collector << ") AT TIME ZONE 'UTC' AT TIME ZONE "
206
- collector = visit Arel.quoted(o.time_zone), collector
207
- end
208
- collector << COMMA
209
- collector = visit Arel.quoted(fmt), collector
210
- collector << ')'
137
+ collector << Arel::Visitors::PostgreSQL::COMMA
138
+
139
+ f = o.iso_format.dup
140
+ Arel::Visitors::PostgreSQL::DATE_FORMAT_DIRECTIVES.each { |d, r| f.gsub!(d, r) }
141
+ collector = visit Arel::Nodes.build_quoted(f), collector
142
+
143
+ collector << ")"
211
144
  collector
212
145
  end
213
146
 
214
- def visit_ArelExtensions_Nodes_Repeat(o, collector)
215
- collector << 'REPEAT('
147
+ def visit_ArelExtensions_Nodes_Repeat o, collector
148
+ collector << "REPEAT("
216
149
  o.expressions.each_with_index { |arg, i|
217
- collector << COMMA if i != 0
150
+ collector << Arel::Visitors::ToSql::COMMA unless i == 0
218
151
  collector = visit arg, collector
219
152
  }
220
- collector << ')'
153
+ collector << ")"
221
154
  collector
222
155
  end
223
156
 
224
- def visit_ArelExtensions_Nodes_AiMatches(o, collector)
157
+ def visit_ArelExtensions_Nodes_AiMatches o, collector
225
158
  collector = visit o.left.ai_collate, collector
226
159
  collector << ' LIKE '
227
160
  collector = visit o.right.ai_collate, collector
@@ -233,7 +166,7 @@ module ArelExtensions
233
166
  end
234
167
  end
235
168
 
236
- def visit_ArelExtensions_Nodes_AiIMatches(o, collector)
169
+ def visit_ArelExtensions_Nodes_AiIMatches o, collector
237
170
  collector = visit o.left.ai_collate, collector
238
171
  collector << ' ILIKE '
239
172
  collector = visit o.right.ai_collate, collector
@@ -245,7 +178,7 @@ module ArelExtensions
245
178
  end
246
179
  end
247
180
 
248
- def visit_ArelExtensions_Nodes_SMatches(o, collector)
181
+ def visit_ArelExtensions_Nodes_SMatches o, collector
249
182
  collector = visit o.left, collector
250
183
  collector << ' LIKE '
251
184
  collector = visit o.right, collector
@@ -257,11 +190,11 @@ module ArelExtensions
257
190
  end
258
191
  end
259
192
 
260
- def visit_ArelExtensions_Nodes_Collate(o, collector)
193
+ def visit_ArelExtensions_Nodes_Collate o, collector
261
194
  if o.ai
262
- collector << 'unaccent('
195
+ collector << "unaccent("
263
196
  collector = visit o.expressions.first, collector
264
- collector << ')'
197
+ collector << ")"
265
198
  elsif o.ci
266
199
  collector = visit o.expressions.first, collector
267
200
  else
@@ -270,25 +203,26 @@ module ArelExtensions
270
203
  collector
271
204
  end
272
205
 
273
- def visit_ArelExtensions_Nodes_DateAdd(o, collector)
206
+ def visit_ArelExtensions_Nodes_DateAdd o, collector
274
207
  collector = visit o.left, collector
275
- collector << ' + ' # (o.right.value >= 0 ? ' + ' : ' - ')
276
- visit o.postgresql_value(o.right), collector
208
+ collector << ' + ' #(o.right.value >= 0 ? ' + ' : ' - ')
209
+ collector = visit o.postgresql_value(o.right), collector
210
+ collector
277
211
  end
278
212
 
279
- def visit_ArelExtensions_Nodes_DateDiff(o, collector)
280
- if %i[ruby_date ruby_time date datetime time].include?(o.right_node_type)
281
- collector << if %i[ruby_time datetime time].include?(o.left_node_type)
282
- "DATEDIFF('second', "
283
- else
284
- "DATEDIFF('day', "
285
- end
213
+ def visit_ArelExtensions_Nodes_DateDiff o, collector
214
+ 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
215
+ collector << if o.left_node_type == :ruby_time || o.left_node_type == :datetime || o.left_node_type == :time
216
+ "DATEDIFF('second', "
217
+ else
218
+ "DATEDIFF('day', "
219
+ end
286
220
  collector = visit o.right, collector
287
221
  collector << (o.right_node_type == :date ? '::date' : '::timestamp')
288
- collector << COMMA
222
+ collector << Arel::Visitors::PostgreSQL::COMMA
289
223
  collector = visit o.left, collector
290
224
  collector << (o.left_node_type == :date ? '::date' : '::timestamp')
291
- collector << ')'
225
+ collector << ")"
292
226
  else
293
227
  collector << '('
294
228
  collector = visit o.left, collector
@@ -302,178 +236,146 @@ module ArelExtensions
302
236
  collector
303
237
  end
304
238
 
305
- def visit_ArelExtensions_Nodes_Duration(o, collector)
239
+ def visit_ArelExtensions_Nodes_Duration o, collector
306
240
  if o.with_interval
307
- interval =
308
- case o.left
309
- when 'd', 'm', 'y'
241
+ interval = case o.left
242
+ when 'd','m','y'
310
243
  'DAY'
311
- when 'h', 'mn', 's'
244
+ when 'h','mn','s'
312
245
  'SECOND'
313
246
  when /i\z/
314
- collector << '('
247
+ collector << "("
315
248
  collector = visit o.right, collector
316
- collector << ')'
317
- collector << " * (INTERVAL '1' #{DATE_MAPPING[o.left[0..-2]]})"
249
+ collector << ")"
250
+ collector << " * (INTERVAL '1' #{Arel::Visitors::PostgreSQL::DATE_MAPPING[o.left[0..-2]]})"
318
251
  return collector
319
252
  end
320
253
  end
321
- collector << "EXTRACT(#{DATE_MAPPING[o.left]} FROM CAST("
254
+ collector << "EXTRACT(#{Arel::Visitors::PostgreSQL::DATE_MAPPING[o.left]} FROM "
322
255
  collector = visit o.right, collector
323
- collector << ' AS TIMESTAMP WITH TIME ZONE))'
256
+ collector << ")"
324
257
  collector << " * (INTERVAL '1' #{interval})" if interval && o.with_interval
325
258
  collector
326
259
  end
327
260
 
328
- def visit_ArelExtensions_Nodes_Locate(o, collector)
329
- collector << 'POSITION('
261
+ def visit_ArelExtensions_Nodes_Locate o, collector
262
+ collector << "POSITION("
330
263
  collector = visit o.right, collector
331
- collector << ' IN '
264
+ collector << " IN "
332
265
  collector = visit o.left, collector
333
- collector << ')'
266
+ collector << ")"
334
267
  collector
335
268
  end
336
269
 
337
- def visit_ArelExtensions_Nodes_Substring(o, collector)
338
- return visit(o.range_substring_node, collector) if o.range?
339
-
340
- collector << 'SUBSTR('
270
+ def visit_ArelExtensions_Nodes_Substring o, collector
271
+ collector << "SUBSTR("
341
272
  o.expressions.each_with_index { |arg, i|
342
- collector << COMMA if i != 0
273
+ collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
343
274
  collector = visit arg, collector
344
275
  }
345
- collector << ')'
276
+ collector << ")"
346
277
  collector
347
278
  end
348
279
 
349
- def visit_ArelExtensions_Nodes_RegexpReplace(o, collector)
350
- collector << 'REGEXP_REPLACE('
351
- visit o.left, collector
352
- collector << COMMA
353
- tab = o.pattern.inspect + 'g' # Make it always global
354
- pattern = tab.split('/')[1..-2].join('/')
355
- flags = tab.split('/')[-1]
356
- visit Arel.quoted(pattern), collector
357
- collector << COMMA
358
- visit o.substitute, collector
359
- collector << COMMA
360
- visit Arel.quoted(flags + 'g'), collector
361
- collector << ')'
362
- collector
363
- end
364
-
365
- def visit_ArelExtensions_Nodes_IsNull(o, collector)
280
+ def visit_ArelExtensions_Nodes_IsNull o, collector
366
281
  collector = visit o.expr, collector
367
282
  collector << ' IS NULL'
368
283
  collector
369
284
  end
370
285
 
371
- def visit_ArelExtensions_Nodes_IsNotNull(o, collector)
372
- collector = visit o.expr, collector
373
- collector << ' IS NOT NULL'
374
- collector
286
+ def visit_ArelExtensions_Nodes_IsNotNull o, collector
287
+ collector = visit o.expr, collector
288
+ collector << ' IS NOT NULL'
289
+ collector
375
290
  end
376
291
 
377
- def visit_ArelExtensions_Nodes_Sum(o, collector)
378
- collector << 'sum('
292
+ def visit_ArelExtensions_Nodes_Sum o, collector
293
+ collector << "sum("
379
294
  collector = visit o.expr, collector
380
- collector << ')'
381
- visit_Aggregate_For_AggregateFunction o, collector
295
+ collector << ")"
382
296
  collector
383
297
  end
384
298
 
385
- def visit_ArelExtensions_Nodes_Wday(o, collector)
386
- collector << 'EXRTACT(DOW, '
299
+ def visit_ArelExtensions_Nodes_Wday o, collector
300
+ collector << "EXRTACT(DOW, "
387
301
  collector = visit o.date, collector
388
302
  collector << ')'
389
303
  collector
390
304
  end
391
305
 
392
- def visit_ArelExtensions_Nodes_Cast(o, collector)
393
- as_attr =
394
- case o.as_attr
395
- when :string
396
- 'varchar'
397
- when :text, :ntext
398
- 'text'
399
- when :time
400
- 'time'
401
- when :int
402
- collector << 'CAST(CAST('
403
- collector = visit o.left, collector
404
- collector << ' AS numeric) AS int)'
405
- return collector
406
- when :number, :decimal, :float
407
- 'numeric'
408
- when :datetime
409
- 'timestamp without time zone'
410
- when :date
411
- 'date'
412
- when :binary
413
- 'binary'
414
- when :jsonb
415
- 'jsonb'
416
- else
417
- o.as_attr.to_s
418
- end
419
-
420
- collector << 'CAST('
306
+ def visit_ArelExtensions_Nodes_Cast o, collector
307
+ as_attr = case o.as_attr
308
+ when :string
309
+ Arel::Nodes::SqlLiteral.new('varchar')
310
+ when :time
311
+ Arel::Nodes::SqlLiteral.new('time')
312
+ when :int
313
+ collector << "CAST(CAST("
314
+ collector = visit o.left, collector
315
+ collector << " AS numeric) AS int)"
316
+ return collector
317
+ when :number, :decimal, :float
318
+ Arel::Nodes::SqlLiteral.new('numeric')
319
+ when :datetime
320
+ Arel::Nodes::SqlLiteral.new('timestamp')
321
+ when :date
322
+ Arel::Nodes::SqlLiteral.new('date')
323
+ when :binary
324
+ Arel::Nodes::SqlLiteral.new('binary')
325
+ else
326
+ Arel::Nodes::SqlLiteral.new(o.as_attr.to_s)
327
+ end
328
+ collector << "CAST("
421
329
  collector = visit o.left, collector
422
- collector << ' AS '
423
- collector = visit Arel::Nodes::SqlLiteral.new(as_attr), collector
424
- collector << ')'
330
+ collector << " AS "
331
+ collector = visit as_attr, collector
332
+ collector << ")"
425
333
  collector
426
334
  end
427
335
 
428
- def visit_ArelExtensions_Nodes_FormattedNumber(o, collector)
336
+ def visit_ArelExtensions_Nodes_FormattedNumber o, collector
429
337
  col = o.left.coalesce(0)
430
- comma = o.precision == 0 ? '' : (NUMBER_COMMA_MAPPING[o.locale][0] || '.')
431
- thousand_separator = NUMBER_COMMA_MAPPING[o.locale][1] || (NUMBER_COMMA_MAPPING[o.locale] ? '' : 'G')
432
- nines_after = (1..o.precision).map { '9' }.join('')
433
- nines_before = ("999#{thousand_separator}" * 4 + '990')
338
+ comma = o.precision == 0 ? '' : (Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING[o.locale][0] || '.')
339
+ thousand_separator = Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING[o.locale][1] || (Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING[o.locale] ? '' : 'G')
340
+ nines_after = (1..o.precision).map{'9'}.join('')
341
+ nines_before = ("999#{thousand_separator}"*4+"990")
434
342
 
435
- sign = Arel.when(col < 0).
343
+ sign = ArelExtensions::Nodes::Case.new.when(col<0).
436
344
  then('-').
437
345
  else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
438
346
  sign_length = ArelExtensions::Nodes::Length.new([sign])
439
347
 
440
- number =
441
- if o.scientific_notation
442
- ArelExtensions::Nodes::Concat.new([
443
- Arel::Nodes::NamedFunction.new('TRIM', [
444
- Arel::Nodes::NamedFunction.new('TO_CHAR', [
445
- Arel.when(col.not_eq 0).then(col.abs / Arel.quoted(10).pow(col.abs.log10.floor)).else(1),
446
- Arel.quoted("FM#{nines_before}\"#{comma}\"V#{nines_after}")
447
- ])]),
448
- o.type,
449
- Arel::Nodes::NamedFunction.new('TRIM', [
450
- Arel::Nodes::NamedFunction.new('TO_CHAR', [
451
- Arel.when(col.not_eq 0).then(col.abs.log10.floor).else(0),
452
- Arel.quoted("FM#{nines_before}")
453
- ])])
454
- ])
455
- else
456
- Arel::Nodes::NamedFunction.new('TRIM', [
457
- Arel::Nodes::NamedFunction.new('TO_CHAR', [
458
- Arel.quoted(col.abs),
459
- Arel.quoted("FM#{nines_before}\"#{comma}\"V#{nines_after}")
460
- ])])
461
- end
348
+ if o.scientific_notation
349
+ number = ArelExtensions::Nodes::Concat.new([
350
+ Arel::Nodes::NamedFunction.new('TRIM',[
351
+ Arel::Nodes::NamedFunction.new('TO_CHAR',[
352
+ col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
353
+ Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
354
+ ])]),
355
+ o.type,
356
+ Arel::Nodes::NamedFunction.new('TRIM',[
357
+ Arel::Nodes::NamedFunction.new('TO_CHAR',[
358
+ col.abs.log10.floor,
359
+ Arel::Nodes.build_quoted('FM'+nines_before)
360
+ ])])
361
+ ])
362
+ else
363
+ number = Arel::Nodes::NamedFunction.new('TRIM',[
364
+ Arel::Nodes::NamedFunction.new('TO_CHAR',[
365
+ Arel::Nodes.build_quoted(col.abs),
366
+ Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
367
+ ])])
368
+ end
462
369
 
463
- repeated_char =
464
- if o.width == 0
465
- Arel.quoted('')
466
- else
467
- Arel
468
- .when(Arel.quoted(o.width).abs - (number.length + sign_length) > 0)
469
- .then(Arel.quoted(
470
- o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
471
- ).repeat(Arel.quoted(o.width).abs - (number.length + sign_length))
472
- )
473
- .else('')
474
- end
475
- before = !o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
476
- middle = o.flags.include?('0') && !o.flags.include?('-') ? repeated_char : ''
370
+ repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
371
+ when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
372
+ then(Arel::Nodes.build_quoted(
373
+ o.flags.include?('-') ? ' ' : (o.flags.include?('0') ? '0' : ' ')
374
+ ).repeat(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length))
375
+ ).
376
+ else('')
377
+ before = (!o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
378
+ middle = (o.flags.include?('0'))&&(!o.flags.include?('-')) ? repeated_char : ''
477
379
  after = o.flags.include?('-') ? repeated_char : ''
478
380
  full_number = ArelExtensions::Nodes::Concat.new([
479
381
  before,
@@ -482,29 +384,31 @@ module ArelExtensions
482
384
  number,
483
385
  after
484
386
  ])
485
- collector = visit ArelExtensions::Nodes::Concat.new([Arel.quoted(o.prefix), full_number, Arel.quoted(o.suffix)]), collector
387
+ collector = visit ArelExtensions::Nodes::Concat.new([Arel::Nodes.build_quoted(o.prefix),full_number,Arel::Nodes.build_quoted(o.suffix)]), collector
486
388
  collector
487
389
  end
488
390
 
489
- alias old_visit_Arel_Nodes_SelectStatement visit_Arel_Nodes_SelectStatement rescue nil
490
- def visit_Arel_Nodes_SelectStatement(o, collector)
391
+
392
+ alias_method :old_visit_Arel_Nodes_SelectStatement, :visit_Arel_Nodes_SelectStatement
393
+ def visit_Arel_Nodes_SelectStatement o, collector
394
+
491
395
  if !(collector.value.blank? || (collector.value.is_a?(Array) && collector.value[0].blank?)) && o.limit.blank? && o.offset.blank?
492
396
  o = o.dup
493
397
  o.orders = []
494
398
  end
495
- old_visit_Arel_Nodes_SelectStatement(o, collector)
399
+ old_visit_Arel_Nodes_SelectStatement(o,collector)
496
400
  end
497
401
 
498
- alias old_visit_Arel_Nodes_TableAlias visit_Arel_Nodes_TableAlias rescue nil
499
- def visit_Arel_Nodes_TableAlias(o, collector)
402
+ alias_method :old_visit_Arel_Nodes_TableAlias, :visit_Arel_Nodes_TableAlias
403
+ def visit_Arel_Nodes_TableAlias o, collector
500
404
  if o.name.length > 63
501
405
  o = Arel::Table.new(o.table_name).alias(Arel.shorten(o.name))
502
406
  end
503
- old_visit_Arel_Nodes_TableAlias(o, collector)
407
+ old_visit_Arel_Nodes_TableAlias(o,collector)
504
408
  end
505
409
 
506
- alias old_visit_Arel_Attributes_Attribute visit_Arel_Attributes_Attribute rescue nil
507
- def visit_Arel_Attributes_Attribute(o, collector)
410
+ alias_method :old_visit_Arel_Attributes_Attribute, :visit_Arel_Attributes_Attribute
411
+ def visit_Arel_Attributes_Attribute o, collector
508
412
  join_name = o.relation.table_alias || o.relation.name
509
413
  if join_name.length > 63
510
414
  join_name = Arel.shorten(join_name)
@@ -512,73 +416,58 @@ module ArelExtensions
512
416
  collector << "#{quote_table_name join_name}.#{quote_column_name o.name}"
513
417
  end
514
418
 
515
- def visit_ArelExtensions_Nodes_Std(o, collector)
516
- collector << (o.unbiased_estimator ? 'STDDEV_SAMP(' : 'STDDEV_POP(')
419
+ def visit_ArelExtensions_Nodes_Std o, collector
420
+ collector << (o.unbiased_estimator ? "STDDEV_SAMP(" : "STDDEV_POP(")
517
421
  visit o.left, collector
518
- collector << ')'
519
- visit_Aggregate_For_AggregateFunction o, collector
422
+ collector << ")"
520
423
  collector
521
424
  end
522
425
 
523
- def visit_ArelExtensions_Nodes_Variance(o, collector)
524
- collector << (o.unbiased_estimator ? 'VAR_SAMP(' : 'VAR_POP(')
426
+ def visit_ArelExtensions_Nodes_Variance o, collector
427
+ collector << (o.unbiased_estimator ? "VAR_SAMP(" : "VAR_POP(")
525
428
  visit o.left, collector
526
- collector << ')'
527
- visit_Aggregate_For_AggregateFunction o, collector
429
+ collector << ")"
528
430
  collector
529
431
  end
530
432
 
531
- def visit_ArelExtensions_Nodes_Json(o, collector)
433
+ def visit_ArelExtensions_Nodes_Json o,collector
532
434
  case o.dict
533
435
  when Array
534
- if o.dict.empty?
535
- # `to_jsonb(array[])` would raise "cannot determine type of empty array";
536
- # an empty array is simply the `[]` JSON literal.
537
- collector << %('[]'::jsonb)
538
- else
539
- collector << 'to_jsonb(array['
540
- o.dict.each.with_index do |v, i|
541
- if i != 0
542
- collector << COMMA
543
- end
544
- collector = visit v, collector
436
+ collector << 'to_jsonb(array['
437
+ o.dict.each.with_index do |v,i|
438
+ if i != 0
439
+ collector << Arel::Visitors::MySQL::COMMA
545
440
  end
546
- collector << '])'
441
+ collector = visit v, collector
547
442
  end
443
+ collector << '])'
548
444
  when Hash
549
445
  collector << 'jsonb_build_object('
550
- o.dict.each.with_index do |(k, v), i|
446
+ o.dict.each.with_index do |(k,v),i|
551
447
  if i != 0
552
- collector << COMMA
448
+ collector << Arel::Visitors::MySQL::COMMA
553
449
  end
554
450
  collector = visit k, collector
555
- collector << COMMA
451
+ collector << Arel::Visitors::MySQL::COMMA
556
452
  collector = visit v, collector
557
453
  end
558
454
  collector << ')'
559
- when String, Numeric, TrueClass, FalseClass
560
- collector = visit Arel.quoted("#{o.dict}"), collector
455
+ when String,Numeric,TrueClass,FalseClass
456
+ collector = visit Arel::Nodes.build_quoted("#{o.dict}"), collector
561
457
  collector << '::jsonb'
562
458
  when NilClass
563
- collector << %('null'::jsonb)
459
+ collector << %Q['null'::jsonb]
460
+ when Arel::Attributes::Attribute
461
+ collector = visit o.dict.cast(:jsonb), collector
564
462
  else
565
- if o.dict.is_a?(Arel::Nodes::Quoted) && o.dict.expr.nil?
566
- # `Arel.null` must mean the JSON null member, not SQL NULL:
567
- # `to_jsonb(NULL)` would raise a polymorphic-type error.
568
- collector << %('null'::jsonb)
569
- else
570
- # `to_jsonb` rather than `::jsonb` so a non-JSON value (e.g. a text column) is
571
- # encoded as a JSON string instead of rejected by the server.
572
- collector << 'to_jsonb('
573
- collector = visit o.dict, collector
574
- collector << ')'
575
- end
463
+ collector = visit o.dict, collector
464
+ collector << '::jsonb'
576
465
  end
577
466
  collector
578
467
  end
579
468
 
580
- def visit_ArelExtensions_Nodes_JsonMerge(o, collector)
581
- o.expressions.each.with_index do |v, i|
469
+ def visit_ArelExtensions_Nodes_JsonMerge o,collector
470
+ o.expressions.each.with_index do |v,i|
582
471
  if i != 0
583
472
  collector << ' || '
584
473
  end
@@ -587,29 +476,28 @@ module ArelExtensions
587
476
  collector
588
477
  end
589
478
 
590
- def visit_ArelExtensions_Nodes_JsonGet(o, collector)
479
+ def visit_ArelExtensions_Nodes_JsonGet o,collector
591
480
  collector = visit o.dict, collector
592
- collector << ' ->> '
593
- visit o.key, collector
481
+ collector << ' -> '
482
+ collector = visit o.key, collector
483
+ collector
594
484
  end
595
485
 
596
- def visit_ArelExtensions_Nodes_JsonSet(o, collector)
486
+ def visit_ArelExtensions_Nodes_JsonSet o,collector
597
487
  collector << 'jsonb_set('
598
488
  collector = visit o.dict, collector
599
- collector << COMMA
489
+ collector << Arel::Visitors::MySQL::COMMA
600
490
  collector << 'array['
601
491
  collector = visit o.key, collector
602
492
  collector << ']'
603
- collector << COMMA
604
- collector << 'COALESCE('
493
+ collector << Arel::Visitors::MySQL::COMMA
605
494
  collector = visit o.value, collector
606
- collector << ", 'null'::jsonb)"
607
- collector << COMMA
495
+ collector << Arel::Visitors::MySQL::COMMA
608
496
  collector << 'true)'
609
497
  collector
610
498
  end
611
499
 
612
- def visit_ArelExtensions_Nodes_JsonGroup(o, collector)
500
+ def visit_ArelExtensions_Nodes_JsonGroup o, collector
613
501
  if o.as_array
614
502
  collector << 'jsonb_agg('
615
503
  collector = visit o.dict, collector
@@ -617,13 +505,13 @@ module ArelExtensions
617
505
  else
618
506
  case o.dict
619
507
  when Hash
620
- o.dict.each.with_index do |(k, v), i|
508
+ o.dict.each.with_index do |(k,v),i|
621
509
  if i != 0
622
510
  collector << ' || '
623
511
  end
624
512
  collector << 'jsonb_object_agg('
625
513
  collector = visit k, collector
626
- collector << COMMA
514
+ collector << Arel::Visitors::MySQL::COMMA
627
515
  collector = visit v, collector
628
516
  collector << ')'
629
517
  end
@@ -635,6 +523,7 @@ module ArelExtensions
635
523
  end
636
524
  collector
637
525
  end
526
+
638
527
  end
639
528
  end
640
529
  end