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.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -4
- data/.travis.yml +54 -86
- data/README.md +7 -2
- data/Rakefile +38 -27
- data/arel_extensions.gemspec +1 -1
- data/functions.html +2 -2
- data/gemfiles/rails4.gemfile +1 -1
- data/gemfiles/rails6.gemfile +30 -0
- data/gemspec_v2/arel_extensions-v2.gemspec +28 -0
- data/generate_gems.sh +14 -0
- data/lib/arel_extensions.rb +49 -21
- data/lib/arel_extensions/attributes.rb +0 -1
- data/lib/arel_extensions/boolean_functions.rb +38 -13
- data/lib/arel_extensions/common_sql_functions.rb +5 -4
- data/lib/arel_extensions/insert_manager.rb +26 -24
- data/lib/arel_extensions/math.rb +3 -3
- data/lib/arel_extensions/math_functions.rb +4 -4
- data/lib/arel_extensions/nodes/abs.rb +0 -0
- data/lib/arel_extensions/nodes/case.rb +8 -4
- data/lib/arel_extensions/nodes/ceil.rb +0 -0
- data/lib/arel_extensions/nodes/coalesce.rb +0 -0
- data/lib/arel_extensions/nodes/collate.rb +1 -1
- data/lib/arel_extensions/nodes/concat.rb +0 -0
- data/lib/arel_extensions/nodes/date_diff.rb +1 -3
- data/lib/arel_extensions/nodes/duration.rb +0 -2
- data/lib/arel_extensions/nodes/find_in_set.rb +0 -0
- data/lib/arel_extensions/nodes/floor.rb +0 -0
- data/lib/arel_extensions/nodes/formatted_number.rb +20 -20
- data/lib/arel_extensions/nodes/function.rb +0 -0
- data/lib/arel_extensions/nodes/is_null.rb +0 -0
- data/lib/arel_extensions/nodes/json.rb +43 -30
- data/lib/arel_extensions/nodes/length.rb +0 -0
- data/lib/arel_extensions/nodes/locate.rb +0 -0
- data/lib/arel_extensions/nodes/power.rb +5 -4
- data/lib/arel_extensions/nodes/rand.rb +0 -0
- data/lib/arel_extensions/nodes/replace.rb +23 -5
- data/lib/arel_extensions/nodes/round.rb +5 -5
- data/lib/arel_extensions/nodes/soundex.rb +14 -13
- data/lib/arel_extensions/nodes/substring.rb +8 -15
- data/lib/arel_extensions/nodes/trim.rb +1 -1
- data/lib/arel_extensions/nodes/union.rb +0 -1
- data/lib/arel_extensions/nodes/union_all.rb +0 -1
- data/lib/arel_extensions/nodes/wday.rb +0 -0
- data/lib/arel_extensions/predications.rb +35 -33
- data/lib/arel_extensions/set_functions.rb +2 -2
- data/lib/arel_extensions/string_functions.rb +25 -6
- data/lib/arel_extensions/tasks.rb +5 -5
- data/lib/arel_extensions/version.rb +1 -1
- data/lib/arel_extensions/visitors.rb +1 -1
- data/lib/arel_extensions/visitors/ibm_db.rb +1 -1
- data/lib/arel_extensions/visitors/mssql.rb +13 -12
- data/lib/arel_extensions/visitors/mysql.rb +67 -37
- data/lib/arel_extensions/visitors/oracle.rb +14 -14
- data/lib/arel_extensions/visitors/oracle12.rb +1 -1
- data/lib/arel_extensions/visitors/postgresql.rb +46 -28
- data/lib/arel_extensions/visitors/sqlite.rb +52 -44
- data/lib/arel_extensions/visitors/to_sql.rb +73 -59
- data/test/arelx_test_helper.rb +28 -0
- data/test/support/fake_record.rb +4 -0
- data/test/test_comparators.rb +8 -7
- data/test/visitors/test_bulk_insert_oracle.rb +8 -7
- data/test/visitors/test_bulk_insert_sqlite.rb +8 -7
- data/test/visitors/test_bulk_insert_to_sql.rb +3 -3
- data/test/visitors/test_oracle.rb +41 -41
- data/test/visitors/test_to_sql.rb +367 -199
- data/test/with_ar/all_agnostic_test.rb +63 -41
- data/test/with_ar/insert_agnostic_test.rb +1 -1
- data/test/with_ar/test_bulk_sqlite.rb +5 -4
- data/test/with_ar/test_math_sqlite.rb +2 -2
- data/test/with_ar/test_string_mysql.rb +2 -4
- data/test/with_ar/test_string_sqlite.rb +2 -6
- data/version_v1.rb +3 -0
- data/version_v2.rb +3 -0
- metadata +10 -5
- data/test/helper.rb +0 -18
| @@ -23,10 +23,10 @@ module ArelExtensions | |
| 23 23 | 
             
              end
         | 
| 24 24 | 
             
            end
         | 
| 25 25 |  | 
| 26 | 
            -
            Arel::Nodes::Union | 
| 26 | 
            +
            class Arel::Nodes::Union
         | 
| 27 27 | 
             
              include ArelExtensions::SetFunctions
         | 
| 28 28 | 
             
            end
         | 
| 29 29 |  | 
| 30 | 
            -
            Arel::Nodes::UnionAll | 
| 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  | 
| 109 | 
            -
                   | 
| 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 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 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 | 
            -
             | 
| 11 | 
            +
              end
         | 
| 12 12 | 
             
            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 | 
| 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
         | 
| @@ -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 | 
            -
                     | 
| 404 | 
            -
                       | 
| 405 | 
            -
             | 
| 406 | 
            -
                       | 
| 407 | 
            -
             | 
| 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  | 
| 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 | 
            -
                     | 
| 470 | 
            -
                       | 
| 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 | 
            -
             | 
| 484 | 
            -
             | 
| 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 | 
            -
             | 
| 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 | 
| 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 | 
            -
                     | 
| 101 | 
            -
             | 
| 102 | 
            -
                       | 
| 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 | 
            -
             | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 109 | 
            +
                      else
         | 
| 110 | 
            +
                        (o.option == 'latin1') ? 'latin1' : 'utf8'
         | 
| 111 | 
            +
                      end
         | 
| 111 112 | 
             
                    collector = visit o.expressions.first, collector
         | 
| 112 | 
            -
                     | 
| 113 | 
            -
                       | 
| 113 | 
            +
                    collector <<
         | 
| 114 | 
            +
                      if o.ai
         | 
| 115 | 
            +
                        " COLLATE #{charset == 'latin1' ? 'latin1_general_ci' : 'utf8_unicode_ci' }"
         | 
| 114 116 | 
             
                      #doesn't work in latin1
         | 
| 115 | 
            -
             | 
| 116 | 
            -
             | 
| 117 | 
            -
             | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 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 | 
| 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 | 
            -
                     | 
| 366 | 
            -
                       | 
| 367 | 
            -
             | 
| 368 | 
            -
                                 | 
| 369 | 
            -
             | 
| 370 | 
            -
             | 
| 371 | 
            -
             | 
| 372 | 
            -
                                 | 
| 373 | 
            -
             | 
| 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 | 
            -
             | 
| 377 | 
            -
                       | 
| 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 ! | 
| 403 | 
            -
                        warn("Warning : ArelExtensions: Window Functions are not available in the current version  | 
| 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 | 
            -
                     | 
| 442 | 
            -
             | 
| 443 | 
            -
             | 
| 444 | 
            -
             | 
| 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 | 
| 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 | 
            -
                     | 
| 135 | 
            -
                       | 
| 136 | 
            -
             | 
| 137 | 
            -
                       | 
| 138 | 
            -
             | 
| 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 == '' | 
| 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 | 
            -
                         | 
| 470 | 
            -
                         | 
| 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 | 
            -
                         | 
| 493 | 
            -
                         | 
| 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
         | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            module ArelExtensions
         | 
| 2 2 | 
             
              module Visitors
         | 
| 3 | 
            -
                Arel::Visitors::PostgreSQL | 
| 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 | 
            -
                     | 
| 124 | 
            -
                       | 
| 125 | 
            -
             | 
| 126 | 
            -
                       | 
| 127 | 
            -
             | 
| 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 | 
            -
                     | 
| 375 | 
            -
                       | 
| 376 | 
            -
             | 
| 377 | 
            -
             | 
| 378 | 
            -
             | 
| 379 | 
            -
             | 
| 380 | 
            -
                                 | 
| 381 | 
            -
                               | 
| 382 | 
            -
             | 
| 383 | 
            -
             | 
| 384 | 
            -
             | 
| 385 | 
            -
             | 
| 386 | 
            -
                                 | 
| 387 | 
            -
             | 
| 388 | 
            -
             | 
| 389 | 
            -
                       | 
| 390 | 
            -
             | 
| 391 | 
            -
             | 
| 392 | 
            -
             | 
| 393 | 
            -
                             | 
| 394 | 
            -
             | 
| 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 | 
| 487 | 
            +
                        collector = visit v, collector
         | 
| 470 488 | 
             
                      end
         | 
| 471 489 | 
             
                      collector << '])'
         | 
| 472 490 | 
             
                    when Hash
         |