arel_extensions 1.2.5 → 1.2.15

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -4
  3. data/.travis.yml +54 -86
  4. data/README.md +7 -2
  5. data/Rakefile +38 -27
  6. data/arel_extensions.gemspec +1 -1
  7. data/functions.html +2 -2
  8. data/gemfiles/rails4.gemfile +1 -1
  9. data/gemfiles/rails6.gemfile +30 -0
  10. data/gemspec_v2/arel_extensions-v2.gemspec +28 -0
  11. data/generate_gems.sh +14 -0
  12. data/lib/arel_extensions.rb +49 -21
  13. data/lib/arel_extensions/attributes.rb +0 -1
  14. data/lib/arel_extensions/boolean_functions.rb +38 -13
  15. data/lib/arel_extensions/common_sql_functions.rb +5 -4
  16. data/lib/arel_extensions/insert_manager.rb +26 -24
  17. data/lib/arel_extensions/math.rb +3 -3
  18. data/lib/arel_extensions/math_functions.rb +4 -4
  19. data/lib/arel_extensions/nodes/abs.rb +0 -0
  20. data/lib/arel_extensions/nodes/case.rb +8 -4
  21. data/lib/arel_extensions/nodes/ceil.rb +0 -0
  22. data/lib/arel_extensions/nodes/coalesce.rb +0 -0
  23. data/lib/arel_extensions/nodes/collate.rb +1 -1
  24. data/lib/arel_extensions/nodes/concat.rb +0 -0
  25. data/lib/arel_extensions/nodes/date_diff.rb +1 -3
  26. data/lib/arel_extensions/nodes/duration.rb +0 -2
  27. data/lib/arel_extensions/nodes/find_in_set.rb +0 -0
  28. data/lib/arel_extensions/nodes/floor.rb +0 -0
  29. data/lib/arel_extensions/nodes/formatted_number.rb +20 -20
  30. data/lib/arel_extensions/nodes/function.rb +0 -0
  31. data/lib/arel_extensions/nodes/is_null.rb +0 -0
  32. data/lib/arel_extensions/nodes/json.rb +43 -30
  33. data/lib/arel_extensions/nodes/length.rb +0 -0
  34. data/lib/arel_extensions/nodes/locate.rb +0 -0
  35. data/lib/arel_extensions/nodes/power.rb +5 -4
  36. data/lib/arel_extensions/nodes/rand.rb +0 -0
  37. data/lib/arel_extensions/nodes/replace.rb +23 -5
  38. data/lib/arel_extensions/nodes/round.rb +5 -5
  39. data/lib/arel_extensions/nodes/soundex.rb +14 -13
  40. data/lib/arel_extensions/nodes/substring.rb +8 -15
  41. data/lib/arel_extensions/nodes/trim.rb +1 -1
  42. data/lib/arel_extensions/nodes/union.rb +0 -1
  43. data/lib/arel_extensions/nodes/union_all.rb +0 -1
  44. data/lib/arel_extensions/nodes/wday.rb +0 -0
  45. data/lib/arel_extensions/predications.rb +35 -33
  46. data/lib/arel_extensions/set_functions.rb +2 -2
  47. data/lib/arel_extensions/string_functions.rb +25 -6
  48. data/lib/arel_extensions/tasks.rb +5 -5
  49. data/lib/arel_extensions/version.rb +1 -1
  50. data/lib/arel_extensions/visitors.rb +1 -1
  51. data/lib/arel_extensions/visitors/ibm_db.rb +1 -1
  52. data/lib/arel_extensions/visitors/mssql.rb +13 -12
  53. data/lib/arel_extensions/visitors/mysql.rb +67 -37
  54. data/lib/arel_extensions/visitors/oracle.rb +14 -14
  55. data/lib/arel_extensions/visitors/oracle12.rb +1 -1
  56. data/lib/arel_extensions/visitors/postgresql.rb +46 -28
  57. data/lib/arel_extensions/visitors/sqlite.rb +52 -44
  58. data/lib/arel_extensions/visitors/to_sql.rb +73 -59
  59. data/test/arelx_test_helper.rb +28 -0
  60. data/test/support/fake_record.rb +4 -0
  61. data/test/test_comparators.rb +8 -7
  62. data/test/visitors/test_bulk_insert_oracle.rb +8 -7
  63. data/test/visitors/test_bulk_insert_sqlite.rb +8 -7
  64. data/test/visitors/test_bulk_insert_to_sql.rb +3 -3
  65. data/test/visitors/test_oracle.rb +41 -41
  66. data/test/visitors/test_to_sql.rb +367 -199
  67. data/test/with_ar/all_agnostic_test.rb +63 -41
  68. data/test/with_ar/insert_agnostic_test.rb +1 -1
  69. data/test/with_ar/test_bulk_sqlite.rb +5 -4
  70. data/test/with_ar/test_math_sqlite.rb +2 -2
  71. data/test/with_ar/test_string_mysql.rb +2 -4
  72. data/test/with_ar/test_string_sqlite.rb +2 -6
  73. data/version_v1.rb +3 -0
  74. data/version_v2.rb +3 -0
  75. metadata +10 -5
  76. data/test/helper.rb +0 -18
@@ -23,10 +23,10 @@ module ArelExtensions
23
23
  end
24
24
  end
25
25
 
26
- Arel::Nodes::Union.class_eval do
26
+ class Arel::Nodes::Union
27
27
  include ArelExtensions::SetFunctions
28
28
  end
29
29
 
30
- Arel::Nodes::UnionAll.class_eval do
30
+ class Arel::Nodes::UnionAll
31
31
  include ArelExtensions::SetFunctions
32
32
  end
@@ -64,6 +64,19 @@ module ArelExtensions
64
64
  grouping_any :imatches, others, escape
65
65
  end
66
66
 
67
+ # def grouping_any method, others, *extra
68
+ # puts "*******************"
69
+ # puts method
70
+ # puts others.inspect
71
+ # puts extra.inspect
72
+ # puts "-------------------"
73
+ # res = super(method,others,*extra)
74
+ # puts res.to_sql
75
+ # puts res.inspect
76
+ # puts "*******************"
77
+ # res
78
+ # end
79
+
67
80
  def imatches_all others, escape = nil
68
81
  grouping_all :imatches, others, escape, escape
69
82
  end
@@ -100,13 +113,21 @@ module ArelExtensions
100
113
  ArelExtensions::Nodes::Collate.new(self,nil,false,true)
101
114
  end
102
115
 
103
- def collate ai=false,ci=false, option=nil
116
+ def collate ai = false,ci = false, option = nil
104
117
  ArelExtensions::Nodes::Collate.new(self,option,ai,ci)
105
118
  end
106
119
 
107
120
  #REPLACE function replaces a sequence of characters in a string with another set of characters, not case-sensitive.
108
- def replace left, right
109
- ArelExtensions::Nodes::Replace.new [self, left, right]
121
+ def replace pattern, substitute
122
+ if pattern.is_a? Regexp
123
+ ArelExtensions::Nodes::RegexpReplace.new self, pattern, substitute
124
+ else
125
+ ArelExtensions::Nodes::Replace.new self, pattern, substitute
126
+ end
127
+ end
128
+
129
+ def regexp_replace pattern, substitute
130
+ ArelExtensions::Nodes::RegexpReplace.new self, pattern, substitute
110
131
  end
111
132
 
112
133
  def concat other
@@ -114,7 +135,7 @@ module ArelExtensions
114
135
  end
115
136
 
116
137
  #concat elements of a group, separated by sep and ordered by a list of Ascending or Descending
117
- def group_concat(sep= nil, *orders, group: nil, order: nil)
138
+ def group_concat(sep = nil, *orders, group: nil, order: nil)
118
139
  if orders.present?
119
140
  warn("Warning : ArelExtensions: group_concat: you should now use the kwarg 'order' to specify an order in the group_concat.")
120
141
  end
@@ -123,8 +144,6 @@ module ArelExtensions
123
144
  o
124
145
  elsif o.respond_to?(:asc)
125
146
  o.asc
126
- else
127
- nil
128
147
  end
129
148
  }.compact
130
149
  ArelExtensions::Nodes::GroupConcat.new(self, sep, group: group, order: (order || order_tabs))
@@ -1,12 +1,12 @@
1
1
  namespace :arel_extensions do
2
- desc 'Install DB functions into current DB'
3
- task :install_functions => :environment do
4
- @env_db = if ENV['DB'] == 'oracle' && ((defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx") || (RUBY_PLATFORM == 'java')) # not supported
2
+ desc 'Install DB functions into current DB'
3
+ task :install_functions => :environment do
4
+ @env_db = if ENV['DB'] == 'oracle' && ((defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx") || (RUBY_PLATFORM == 'java')) # not supported
5
5
  (RUBY_PLATFORM == 'java' ? "jdbc-sqlite" : 'sqlite')
6
6
  else
7
7
  ENV['DB'] || ActiveRecord::Base.connection.adapter_name
8
8
  end
9
- ActiveRecord::Base.establish_connection(Rails.env)
9
+ ActiveRecord::Base.establish_connection(Rails.env.to_sym)
10
10
  CommonSqlFunctions.new(ActiveRecord::Base.connection).add_sql_functions(@env_db)
11
- end
11
+ end
12
12
  end
@@ -1,3 +1,3 @@
1
1
  module ArelExtensions
2
- VERSION = "1.2.5".freeze
2
+ VERSION = "1.2.15".freeze
3
3
  end
@@ -6,7 +6,7 @@ require 'arel_extensions/visitors/postgresql'
6
6
  require 'arel_extensions/visitors/sqlite'
7
7
  require 'arel_extensions/visitors/mssql'
8
8
 
9
- Arel::Visitors::MSSQL.class_eval do
9
+ class Arel::Visitors::MSSQL
10
10
  include ArelExtensions::Visitors::MSSQL
11
11
 
12
12
  alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
@@ -1,6 +1,6 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- Arel::Visitors::IBM_DB.class_eval do
3
+ class Arel::Visitors::IBM_DB
4
4
 
5
5
  def visit_ArelExtensions_Nodes_Ceil o, collector
6
6
  collector << "CEILING("
@@ -400,13 +400,14 @@ module ArelExtensions
400
400
  collector << "(STRING_AGG("
401
401
  collector = visit o.left, collector
402
402
  collector << Arel::Visitors::Oracle::COMMA
403
- if o.separator && o.selector != 'NULL'
404
- collector = visit o.separator, collector
405
- else
406
- collector = visit Arel::Nodes.build_quoted(','), collector
407
- end
403
+ collector =
404
+ if o.separator && o.separator != 'NULL'
405
+ visit o.separator, collector
406
+ else
407
+ visit Arel::Nodes.build_quoted(','), collector
408
+ end
408
409
  collector << ") WITHIN GROUP (ORDER BY "
409
- if !o.order.blank?
410
+ if o.order.present?
410
411
  o.order.each_with_index do |order,i|
411
412
  collector << Arel::Visitors::Oracle::COMMA unless i == 0
412
413
  collector = visit order, collector
@@ -466,8 +467,9 @@ module ArelExtensions
466
467
  Arel::Nodes.build_quoted(1) :
467
468
  ArelExtensions::Nodes::Case.new.when(col<0).then(1).else(0)
468
469
 
469
- if o.scientific_notation
470
- number = ArelExtensions::Nodes::Concat.new([
470
+ number =
471
+ if o.scientific_notation
472
+ ArelExtensions::Nodes::Concat.new([
471
473
  Arel::Nodes::NamedFunction.new('FORMAT',[
472
474
  col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
473
475
  param,
@@ -480,13 +482,13 @@ module ArelExtensions
480
482
  locale
481
483
  ])
482
484
  ])
483
- else
484
- number = Arel::Nodes::NamedFunction.new('FORMAT',[
485
+ else
486
+ Arel::Nodes::NamedFunction.new('FORMAT',[
485
487
  Arel::Nodes.build_quoted(col.abs),
486
488
  param,
487
489
  locale
488
490
  ])
489
- end
491
+ end
490
492
 
491
493
  repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
492
494
  when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
@@ -548,7 +550,6 @@ module ArelExtensions
548
550
  collector
549
551
  end
550
552
 
551
-
552
553
  end
553
554
  end
554
555
  end
@@ -1,6 +1,6 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- Arel::Visitors::MySQL.class_eval do
3
+ class Arel::Visitors::MySQL
4
4
  Arel::Visitors::MySQL::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'WEEKDAY', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
5
5
  Arel::Visitors::MySQL::DATE_FORMAT_DIRECTIVES = { # ISO C / POSIX
6
6
  '%Y' => '%Y', '%C' => '', '%y' => '%y', '%m' => '%m', '%B' => '%M', '%b' => '%b', '%^b' => '%b', # year, month
@@ -97,26 +97,28 @@ module ArelExtensions
97
97
  end
98
98
 
99
99
  def visit_ArelExtensions_Nodes_Collate o, collector
100
- case o.expressions.first
101
- when Arel::Attributes::Attribute
102
- charset = case o.option
100
+ charset =
101
+ case o.expressions.first
102
+ when Arel::Attributes::Attribute
103
+ case o.option
103
104
  when 'latin1','utf8'
104
105
  o.option
105
106
  else
106
107
  Arel::Table.engine.connection.charset || 'utf8'
107
108
  end
108
- else
109
- charset = (o.option == 'latin1') ? 'latin1' : 'utf8'
110
- end
109
+ else
110
+ (o.option == 'latin1') ? 'latin1' : 'utf8'
111
+ end
111
112
  collector = visit o.expressions.first, collector
112
- if o.ai
113
- collector << " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
113
+ collector <<
114
+ if o.ai
115
+ " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
114
116
  #doesn't work in latin1
115
- elsif o.ci
116
- collector << " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
117
- else
118
- collector << " COLLATE #{charset}_bin"
119
- end
117
+ elsif o.ci
118
+ " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
119
+ else
120
+ " COLLATE #{charset}_bin"
121
+ end
120
122
  collector
121
123
  end
122
124
 
@@ -191,6 +193,13 @@ module ArelExtensions
191
193
  collector
192
194
  end
193
195
 
196
+ def visit_ArelExtensions_Nodes_RegexpReplace o, collector
197
+ if !regexp_replace_supported?
198
+ warn("Warning : ArelExtensions: REGEXP_REPLACE does not seem to be available in the current version of the DBMS, it might crash")
199
+ end
200
+ super(o,collector)
201
+ end
202
+
194
203
  def visit_ArelExtensions_Nodes_Format o, collector
195
204
  case o.col_type
196
205
  when :date, :datetime
@@ -262,7 +271,7 @@ module ArelExtensions
262
271
  else
263
272
  if o.with_interval
264
273
  case o.left
265
- when 'd','m','y'
274
+ when 'd','m','y'
266
275
  interval = 'DAY'
267
276
  when 'h','mn','s'
268
277
  interval = 'SECOND'
@@ -362,20 +371,21 @@ module ArelExtensions
362
371
  else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
363
372
  sign_length = ArelExtensions::Nodes::Length.new([sign])
364
373
 
365
- if o.scientific_notation
366
- number = ArelExtensions::Nodes::Concat.new([
367
- Arel::Nodes::NamedFunction.new('FORMAT',[
368
- col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor)
369
- ]+params),
370
- o.type,
371
- Arel::Nodes::NamedFunction.new('FORMAT',[
372
- col.abs.log10.floor,
373
- 0
374
+ number =
375
+ if o.scientific_notation
376
+ ArelExtensions::Nodes::Concat.new([
377
+ Arel::Nodes::NamedFunction.new('FORMAT',[
378
+ col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor)
379
+ ]+params),
380
+ o.type,
381
+ Arel::Nodes::NamedFunction.new('FORMAT',[
382
+ col.abs.log10.floor,
383
+ 0
384
+ ])
374
385
  ])
375
- ])
376
- else
377
- number = Arel::Nodes::NamedFunction.new('FORMAT',[col.abs]+params)
378
- end
386
+ else
387
+ Arel::Nodes::NamedFunction.new('FORMAT',[col.abs]+params)
388
+ end
379
389
 
380
390
  repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
381
391
  when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
@@ -399,19 +409,19 @@ module ArelExtensions
399
409
  end
400
410
 
401
411
  def visit_Aggregate_For_AggregateFunction o, collector
402
- if !(Arel::Table.engine.connection.send(:version) >= (Arel::Table.engine.connection.send(:mariadb?) ? '10.2.3' : '8.0'))
403
- warn("Warning : ArelExtensions: Window Functions are not available in the current version on the DBMS.")
412
+ if !window_supported?
413
+ warn("Warning : ArelExtensions: Window Functions are not available in the current version of the DBMS.")
404
414
  return collector
405
415
  end
406
416
 
407
- if o.order || o.group
417
+ if !o.order.empty? || !o.group.empty?
408
418
  collector << " OVER ("
409
- if o.group
419
+ if !o.group.empty?
410
420
  collector << " PARTITION BY ("
411
421
  visit o.group, collector
412
422
  collector << ")"
413
423
  end
414
- if o.order
424
+ if !o.order.empty?
415
425
  collector << " ORDER BY ("
416
426
  visit o.order, collector
417
427
  collector << ")"
@@ -433,15 +443,35 @@ module ArelExtensions
433
443
  collector << (o.unbiased_estimator ? "VAR_SAMP(" : "VAR_POP(")
434
444
  visit o.left, collector
435
445
  collector << ")"
446
+ visit_Aggregate_For_AggregateFunction o, collector
436
447
  collector
437
448
  end
438
449
 
439
450
  # JSON if implemented only after 10.2.3 in MariaDb and 5.7 in MySql
440
451
  def json_supported?
441
- Arel::Table.engine.connection.send(:mariadb?) &&
442
- Arel::Table.engine.connection.send(:version) >= '10.2.3' ||
443
- !Arel::Table.engine.connection.send(:mariadb?) &&
444
- Arel::Table.engine.connection.send(:version) >= '5.7.0'
452
+ version_supported?('10.2.3', '5.7.0')
453
+ end
454
+
455
+ def window_supported?
456
+ version_supported?('10.2.3', '8.0')
457
+ end
458
+
459
+ def regexp_replace_supported?
460
+ version_supported?('10.0.5', '8.0')
461
+ end
462
+
463
+ def version_supported?(mariadb_v = '10.2.3', mysql_v = '5.7.0')
464
+ conn = Arel::Table.engine.connection
465
+ conn.send(:mariadb?) && \
466
+ (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mariadb_v || \
467
+ conn.respond_to?(:version) && conn.send(:version) >= mariadb_v || \
468
+ conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mariadb_v) || \
469
+ !conn.send(:mariadb?) && \
470
+ (conn.respond_to?(:get_database_version) && conn.send(:get_database_version) >= mysql_v || \
471
+ conn.respond_to?(:version) && conn.send(:version) >= mysql_v || \
472
+ conn.instance_variable_get(:"@version") && conn.instance_variable_get(:"@version") >= mysql_v)
473
+ # ideally we should parse the instance_variable @full_version because @version contains only the supposedly
474
+ # corresponding mysql version of the current mariadb version (which is not very helpful most of the time)
445
475
  end
446
476
 
447
477
  def visit_ArelExtensions_Nodes_Json o,collector
@@ -1,7 +1,7 @@
1
1
  #require 'oracle_visitor'
2
2
  module ArelExtensions
3
3
  module Visitors
4
- Arel::Visitors::Oracle.class_eval do
4
+ class Arel::Visitors::Oracle
5
5
 
6
6
  SPECIAL_CHARS = {"\t" => 'CHR(9)', "\n" => 'CHR(10)', "\r" => 'CHR(13)'}
7
7
  Arel::Visitors::Oracle::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'IW', 'y' => 'YEAR', 'wd' => 'D', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
@@ -131,11 +131,12 @@ module ArelExtensions
131
131
  collector << "(LISTAGG("
132
132
  collector = visit o.left, collector
133
133
  collector << Arel::Visitors::Oracle::COMMA
134
- if o.separator && o.separator != 'NULL'
135
- collector = visit o.separator, collector
136
- else
137
- collector = visit Arel::Nodes.build_quoted(','), collector
138
- end
134
+ collector =
135
+ if o.separator && o.separator != 'NULL'
136
+ visit o.separator, collector
137
+ else
138
+ visit Arel::Nodes.build_quoted(','), collector
139
+ end
139
140
  collector << ") WITHIN GROUP (ORDER BY "
140
141
  if !o.order.blank?
141
142
  o.order.each_with_index do |order,i|
@@ -154,7 +155,7 @@ module ArelExtensions
154
155
  o.expressions.each_with_index { |arg, i|
155
156
  collector << Arel::Visitors::Oracle::COMMA unless i == 0
156
157
  if i > 0 && o.left_node_type == :text
157
- if arg == '' || (arg.is_a?(Arel::Nodes::Quoted) && (arg.expr == ''))
158
+ if arg == '' || (arg.is_a?(Arel::Nodes::Quoted) && (arg.expr == ''))
158
159
  collector << "NULL"
159
160
  else
160
161
  collector << 'TO_CLOB('
@@ -466,14 +467,12 @@ module ArelExtensions
466
467
  o.left.each_with_index do |row, idx| # values
467
468
  collector << " UNION ALL " if idx != 0
468
469
  collector << "(SELECT "
469
- v = Arel::Nodes::Values.new(row, o.cols)
470
- len = v.expressions.length - 1
471
- v.expressions.each_with_index { |value, i|
470
+ len = row.length - 1
471
+ row.zip(o.cols).each_with_index { |(value, attr), i|
472
472
  case value
473
473
  when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
474
474
  collector = visit value, collector
475
475
  else
476
- attr = v.columns[i]
477
476
  collector << quote(value, attr && column_for(attr)).to_s
478
477
  end
479
478
  collector << Arel::Visitors::Oracle::COMMA unless i == len
@@ -489,12 +488,13 @@ module ArelExtensions
489
488
  o.left.each_with_index do |row, idx|
490
489
  collector << " UNION ALL " if idx != 0
491
490
  collector << "(SELECT "
492
- v = Arel::Nodes::Values.new(row, o.cols)
493
- len = v.expressions.length - 1
494
- v.expressions.zip(v.columns).each_with_index { |(value, attr), i|
491
+ len = row.length - 1
492
+ row.zip(o.cols).each_with_index { |(value, attr), i|
495
493
  case value
496
494
  when Arel::Nodes::SqlLiteral, Arel::Nodes::BindParam
497
495
  collector = visit value, collector
496
+ when Integer
497
+ collector << value.to_s
498
498
  else
499
499
  collector << (attr && attr.able_to_type_cast? ? quote(attr.type_cast_for_database(value)) : quote(value).to_s)
500
500
  end
@@ -68,7 +68,7 @@ module ArelExtensions
68
68
  if i != 0
69
69
  collector << Arel::Visitors::MySQL::COMMA
70
70
  end
71
- collector = visit v, collector
71
+ collector = visit v, collector
72
72
  end
73
73
  collector << ')'
74
74
  when Hash
@@ -1,6 +1,6 @@
1
1
  module ArelExtensions
2
2
  module Visitors
3
- Arel::Visitors::PostgreSQL.class_eval do
3
+ class Arel::Visitors::PostgreSQL
4
4
  Arel::Visitors::PostgreSQL::DATE_MAPPING = {'d' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'DOW', 'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'}
5
5
  Arel::Visitors::PostgreSQL::DATE_FORMAT_DIRECTIVES = {
6
6
  '%Y' => 'IYYY', '%C' => 'CC', '%y' => 'YY', '%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
@@ -120,11 +120,12 @@ module ArelExtensions
120
120
  o.order = nil
121
121
  visit_Aggregate_For_AggregateFunction o, collector
122
122
  collector << Arel::Visitors::PostgreSQL::COMMA
123
- if o.separator && o.separator != 'NULL'
124
- collector = visit o.separator, collector
125
- else
126
- collector = visit Arel::Nodes.build_quoted(','), collector
127
- end
123
+ collector =
124
+ if o.separator && o.separator != 'NULL'
125
+ visit o.separator, collector
126
+ else
127
+ visit Arel::Nodes.build_quoted(','), collector
128
+ end
128
129
  collector << ")"
129
130
  collector
130
131
  end
@@ -302,6 +303,22 @@ module ArelExtensions
302
303
  collector
303
304
  end
304
305
 
306
+ def visit_ArelExtensions_Nodes_RegexpReplace o, collector
307
+ collector << "REGEXP_REPLACE("
308
+ visit o.left, collector
309
+ collector << Arel::Visitors::ToSql::COMMA
310
+ tab = o.pattern.inspect+ 'g' # Make it always global
311
+ pattern = tab.split('/')[1..-2].join('/')
312
+ flags = tab.split('/')[-1]
313
+ visit Arel::Nodes.build_quoted(pattern), collector
314
+ collector << Arel::Visitors::ToSql::COMMA
315
+ visit o.substitute, collector
316
+ collector << Arel::Visitors::ToSql::COMMA
317
+ visit Arel::Nodes.build_quoted(flags+"g"), collector
318
+ collector << ")"
319
+ collector
320
+ end
321
+
305
322
  def visit_ArelExtensions_Nodes_IsNull o, collector
306
323
  collector = visit o.expr, collector
307
324
  collector << ' IS NULL'
@@ -371,27 +388,28 @@ module ArelExtensions
371
388
  else(o.flags.include?('+') ? '+' : (o.flags.include?(' ') ? ' ' : ''))
372
389
  sign_length = ArelExtensions::Nodes::Length.new([sign])
373
390
 
374
- if o.scientific_notation
375
- number = ArelExtensions::Nodes::Concat.new([
376
- Arel::Nodes::NamedFunction.new('TRIM',[
377
- Arel::Nodes::NamedFunction.new('TO_CHAR',[
378
- col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
379
- Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
380
- ])]),
381
- o.type,
382
- Arel::Nodes::NamedFunction.new('TRIM',[
383
- Arel::Nodes::NamedFunction.new('TO_CHAR',[
384
- col.abs.log10.floor,
385
- Arel::Nodes.build_quoted('FM'+nines_before)
386
- ])])
387
- ])
388
- else
389
- number = Arel::Nodes::NamedFunction.new('TRIM',[
390
- Arel::Nodes::NamedFunction.new('TO_CHAR',[
391
- Arel::Nodes.build_quoted(col.abs),
392
- Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
393
- ])])
394
- end
391
+ number =
392
+ if o.scientific_notation
393
+ ArelExtensions::Nodes::Concat.new([
394
+ Arel::Nodes::NamedFunction.new('TRIM',[
395
+ Arel::Nodes::NamedFunction.new('TO_CHAR',[
396
+ col.abs/Arel::Nodes.build_quoted(10).pow(col.abs.log10.floor),
397
+ Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
398
+ ])]),
399
+ o.type,
400
+ Arel::Nodes::NamedFunction.new('TRIM',[
401
+ Arel::Nodes::NamedFunction.new('TO_CHAR',[
402
+ col.abs.log10.floor,
403
+ Arel::Nodes.build_quoted('FM'+nines_before)
404
+ ])])
405
+ ])
406
+ else
407
+ Arel::Nodes::NamedFunction.new('TRIM',[
408
+ Arel::Nodes::NamedFunction.new('TO_CHAR',[
409
+ Arel::Nodes.build_quoted(col.abs),
410
+ Arel::Nodes.build_quoted('FM'+nines_before+'"'+comma+'"V'+nines_after)
411
+ ])])
412
+ end
395
413
 
396
414
  repeated_char = (o.width == 0) ? Arel::Nodes.build_quoted('') : ArelExtensions::Nodes::Case.new().
397
415
  when(Arel::Nodes.build_quoted(o.width).abs-(number.length+sign_length)>0).
@@ -466,7 +484,7 @@ module ArelExtensions
466
484
  if i != 0
467
485
  collector << Arel::Visitors::MySQL::COMMA
468
486
  end
469
- collector = visit v, collector
487
+ collector = visit v, collector
470
488
  end
471
489
  collector << '])'
472
490
  when Hash