<commit_before>module ArelExtensions
  module Visitors
    class Arel::Visitors::PostgreSQL

      Arel::Visitors::PostgreSQL::DATE_MAPPING = {
        'd' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'DOW',
        'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'
      }.freeze

      Arel::Visitors::PostgreSQL::DATE_FORMAT_DIRECTIVES = {
        '%Y' => 'IYYY', '%C' => 'CC', '%y' => 'YY',
        '%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
        '%d' => 'DD', '%e' => 'FMDD', '%j' => 'DDD', '%w' => '', '%A' => 'Day', # day, weekday
        '%H' => 'HH24', '%k' => '', '%I' => 'HH', '%l' => '', '%P' => 'am', '%p' => 'AM', # hours
        '%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz', # seconds, subseconds
        '%%' => '%',
      }.freeze

      Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING = {
        'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', '
      }.freeze

      def visit_ArelExtensions_Nodes_Rand o, collector
        collector << "RANDOM("
        if(o.left != nil && o.right != nil)
          collector = visit o.left, collector
          collector << Arel::Visitors::PostgreSQL::COMMA
          collector = isit o.right, collector
        end
        collector << ")"
        collector
      end

      def visit_ArelExtensions_Nodes_Power o, collector
        collector << "POWER("
        o.expressions.each_with_index { |arg, i|
          collector << Arel::Visitors::ToSql::COMMA unless i == 0
          collector = visit arg, collector
        }
        collector << ")"
        collector
      end

      def visit_ArelExtensions_Nodes_Log10 o, collector
        collector << "LOG("
        o.expressions.each_with_index { |arg, i|
          collector << Arel::Visitors::ToSql::COMMA unless i == 0
          collector = visit arg, collector
        }
        collector << ")"
        collector
      end


      remove_method(:visit_Arel_Nodes_Regexp) rescue nil
      def visit_Arel_Nodes_Regexp o, collector
        collector = visit o.left, collector
        collector << " ~ "
        collector = visit o.right, collector
        collector
      end

      remove_method(:visit_Arel_Nodes_NotRegexp) rescue nil
      def visit_Arel_Nodes_NotRegexp o, collector
        collector = visit o.left, collector
        collector << " !~ "
        collector = visit o.right, collector
        collector
      end

      def visit_ArelExtensions_Nodes_Concat o, collector
        collector << '('
        o.expressions.each_with_index { |arg, i|
          collector = visit arg, collector
          collector << ' || ' unless i == o.expressions.length - 1
        }
        collector << ")"
        collector
      end

      alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
      def visit_Arel_Nodes_As o, collector
        if o.left.is_a?(Arel::Nodes::Binary)
          collector << '('
          collector = visit o.left, collector
          collector << ')'
        else
          collector = visit o.left, collector
        end
        collector << " AS \""
        collector = visit o.right, collector
        collector << "\""
        collector
      end

      def visit_Aggregate_For_AggregateFunction o, collector
        if !o.order.blank? || !o.group.blank?
          collector << " OVER ("
          if !o.group.blank?
            collector << " PARTITION BY "
            o.group.each_with_index do |group, i|
              collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
              visit group, collector
            end
          end
          if !o.order.blank?
            collector << " ORDER BY "
            o.order.each_with_index do |order, i|
              collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
              visit order, collector
            end
          end
          collector << ")"
        end
        collector
      end

      def visit_ArelExtensions_Nodes_GroupConcat o, collector
        collector << "array_to_string(array_agg("
        collector = visit o.left, collector
        if o.order && !o.order.blank?
          collector << " ORDER BY"
          o.order.each_with_index do |order, i|
            collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
            collector << " "
            visit order, collector
          end
        end
        collector << ")"
        o.order = nil
        visit_Aggregate_For_AggregateFunction o, collector
        collector << Arel::Visitors::PostgreSQL::COMMA
        collector =
          if o.separator && o.separator != 'NULL'
            visit o.separator, collector
          else
            visit Arel::Nodes.build_quoted(','), collector
          end
        collector << ")"
        collector
      end

      def visit_ArelExtensions_Nodes_Trim o, collector
          collector << 'TRIM(BOTH '
          collector = visit o.right, collector
          collector << " FROM "
          collector = visit o.left, collector
          collector << ")"
          collector
      end

      def visit_ArelExtensions_Nodes_Ltrim o, collector
          collector << 'TRIM(LEADING '
          collector = visit o.right, collector
          collector << " FROM "
          collector = visit o.left, collector
          collector << ")"
          collector
      end

      def visit_ArelExtensions_Nodes_Rtrim o, collector
        collector << 'TRIM(TRAILING '
        collector = visit o.right, collector
        collector << " FROM "
        collector = visit o.left, collector
        collector << ")"
        collector
      end

      def visit_ArelExtensions_Nodes_Format o, collector
        collector << "TO_CHAR("
        collector = visit o.left, collector
        collector << Arel::Visitors::PostgreSQL::COMMA

        o.iso_format.dup

        s = StringScanner.new o.iso_format
        f = StringIO.new
        while !s.eos?
          f <<
            case
            when s.scan(/%./)
              if v = Arel::Visitors::PostgreSQL::DATE_FORMAT_DIRECTIVES[s.matched]
                v
              else
                s.matched
              end
            when s.scan(/[^%]+/)
              s.matched
            when s.scan(/./)
              s.matched
            end
        end
        collector = visit Arel::Nodes.build_quoted(f), collector

        collector << ")"
        collector
      end
<commit_msg>pg: actually, some strftime sequences are on more than two chars<commit_after>module ArelExtensions
  module Visitors
    class Arel::Visitors::PostgreSQL

      Arel::Visitors::PostgreSQL::DATE_MAPPING = {
        'd' => 'DAY', 'm' => 'MONTH', 'w' => 'WEEK', 'y' => 'YEAR', 'wd' => 'DOW',
        'h' => 'HOUR', 'mn' => 'MINUTE', 's' => 'SECOND'
      }.freeze

      Arel::Visitors::PostgreSQL::DATE_FORMAT_DIRECTIVES = {
        '%Y' => 'IYYY', '%C' => 'CC', '%y' => 'YY',
        '%m' => 'MM', '%B' => 'Month', '%^B' => 'MONTH', '%b' => 'Mon', '%^b' => 'MON',
        '%d' => 'DD', '%e' => 'FMDD', '%j' => 'DDD', '%w' => '', '%A' => 'Day', # day, weekday
        '%H' => 'HH24', '%k' => '', '%I' => 'HH', '%l' => '', '%P' => 'am', '%p' => 'AM', # hours
        '%M' => 'MI', '%S' => 'SS', '%L' => 'MS', '%N' => 'US', '%z' => 'tz', # seconds, subseconds
        '%%' => '%',
      }.freeze

      DATE_FORMAT_REGEX =
        Regexp.new(
          Arel::Visitors::PostgreSQL::DATE_FORMAT_DIRECTIVES
            .keys
            .map{|k| Regexp.escape(k)}
            .join('|')
        )

      Arel::Visitors::PostgreSQL::NUMBER_COMMA_MAPPING = {
        'en_US' => '.,', 'fr_FR' => ',', 'sv_SE' => ', '
      }.freeze

      def visit_ArelExtensions_Nodes_Rand o, collector
        collector << "RANDOM("
        if(o.left != nil && o.right != nil)
          collector = visit o.left, collector
          collector << Arel::Visitors::PostgreSQL::COMMA
          collector = isit o.right, collector
        end
        collector << ")"
        collector
      end

      def visit_ArelExtensions_Nodes_Power o, collector
        collector << "POWER("
        o.expressions.each_with_index { |arg, i|
          collector << Arel::Visitors::ToSql::COMMA unless i == 0
          collector = visit arg, collector
        }
        collector << ")"
        collector
      end

      def visit_ArelExtensions_Nodes_Log10 o, collector
        collector << "LOG("
        o.expressions.each_with_index { |arg, i|
          collector << Arel::Visitors::ToSql::COMMA unless i == 0
          collector = visit arg, collector
        }
        collector << ")"
        collector
      end


      remove_method(:visit_Arel_Nodes_Regexp) rescue nil
      def visit_Arel_Nodes_Regexp o, collector
        collector = visit o.left, collector
        collector << " ~ "
        collector = visit o.right, collector
        collector
      end

      remove_method(:visit_Arel_Nodes_NotRegexp) rescue nil
      def visit_Arel_Nodes_NotRegexp o, collector
        collector = visit o.left, collector
        collector << " !~ "
        collector = visit o.right, collector
        collector
      end

      def visit_ArelExtensions_Nodes_Concat o, collector
        collector << '('
        o.expressions.each_with_index { |arg, i|
          collector = visit arg, collector
          collector << ' || ' unless i == o.expressions.length - 1
        }
        collector << ")"
        collector
      end

      alias_method :old_visit_Arel_Nodes_As, :visit_Arel_Nodes_As
      def visit_Arel_Nodes_As o, collector
        if o.left.is_a?(Arel::Nodes::Binary)
          collector << '('
          collector = visit o.left, collector
          collector << ')'
        else
          collector = visit o.left, collector
        end
        collector << " AS \""
        collector = visit o.right, collector
        collector << "\""
        collector
      end

      def visit_Aggregate_For_AggregateFunction o, collector
        if !o.order.blank? || !o.group.blank?
          collector << " OVER ("
          if !o.group.blank?
            collector << " PARTITION BY "
            o.group.each_with_index do |group, i|
              collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
              visit group, collector
            end
          end
          if !o.order.blank?
            collector << " ORDER BY "
            o.order.each_with_index do |order, i|
              collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
              visit order, collector
            end
          end
          collector << ")"
        end
        collector
      end

      def visit_ArelExtensions_Nodes_GroupConcat o, collector
        collector << "array_to_string(array_agg("
        collector = visit o.left, collector
        if o.order && !o.order.blank?
          collector << " ORDER BY"
          o.order.each_with_index do |order, i|
            collector << Arel::Visitors::PostgreSQL::COMMA unless i == 0
            collector << " "
            visit order, collector
          end
        end
        collector << ")"
        o.order = nil
        visit_Aggregate_For_AggregateFunction o, collector
        collector << Arel::Visitors::PostgreSQL::COMMA
        collector =
          if o.separator && o.separator != 'NULL'
            visit o.separator, collector
          else
            visit Arel::Nodes.build_quoted(','), collector
          end
        collector << ")"
        collector
      end

      def visit_ArelExtensions_Nodes_Trim o, collector
          collector << 'TRIM(BOTH '
          collector = visit o.right, collector
          collector << " FROM "
          collector = visit o.left, collector
          collector << ")"
          collector
      end

      def visit_ArelExtensions_Nodes_Ltrim o, collector
          collector << 'TRIM(LEADING '
          collector = visit o.right, collector
          collector << " FROM "
          collector = visit o.left, collector
          collector << ")"
          collector
      end

      def visit_ArelExtensions_Nodes_Rtrim o, collector
        collector << 'TRIM(TRAILING '
        collector = visit o.right, collector
        collector << " FROM "
        collector = visit o.left, collector
        collector << ")"
        collector
      end

      def visit_ArelExtensions_Nodes_Format o, collector
        collector << "TO_CHAR("
        collector = visit o.left, collector
        collector << Arel::Visitors::PostgreSQL::COMMA

        o.iso_format.dup

        s = StringScanner.new o.iso_format
        f = StringIO.new
        while !s.eos?
          f <<
            case
            when s.scan(DATE_FORMAT_REGEX)
              if v = Arel::Visitors::PostgreSQL::DATE_FORMAT_DIRECTIVES[s.matched]
                v
              else
                # Should never happen.
                s.matched
              end
            when s.scan(/[^%]+/)
              s.matched
            when s.scan(/./)
              s.matched
            end
        end
        collector = visit Arel::Nodes.build_quoted(f.string), collector

        collector << ")"
        collector
      end

{'fraction_non_alphanumeric': 0.12681436210847977, 'fraction_numerical': 0.0015278838808250573, 'mean_word_length': 1.8062165058949624, 'pattern_counts': {'":': 0, '<': 179, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5514922', 'n_tokens_mistral': 4076, 'n_tokens_neox': 3919, 'n_words': 904}