<commit_before># frozen_string_literal: true

module ActiveRecord
  module ConnectionAdapters # :nodoc:
    module DatabaseStatements
      def initialize
        super
        reset_transaction
      end

      # Converts an arel AST to SQL
      def to_sql(arel_or_sql_string, binds = [])
        sql, _ = to_sql_and_binds(arel_or_sql_string, binds)
        sql
      end

      def to_sql_and_binds(arel_or_sql_string, binds = []) # :nodoc:
        if arel_or_sql_string.respond_to?(:ast)
          unless binds.empty?
            raise "Passing bind parameters with an arel AST is forbidden. " \
              "The values must be stored on the AST directly"
          end

          if prepared_statements
            sql, binds = visitor.compile(arel_or_sql_string.ast, collector)

            if binds.length > bind_params_length
              unprepared_statement do
                sql, binds = to_sql_and_binds(arel_or_sql_string)
                visitor.preparable = false
              end
            end
          else
            sql = visitor.compile(arel_or_sql_string.ast, collector)
          end
          [sql.freeze, binds]
        else
          visitor.preparable = false if prepared_statements

          arel_or_sql_string = arel_or_sql_string.dup.freeze unless arel_or_sql_string.frozen?
          [arel_or_sql_string, binds]
        end
      end
      private :to_sql_and_binds

      # This is used in the StatementCache object. It returns an object that
      # can be used to query the database repeatedly.
      def cacheable_query(klass, arel) # :nodoc:
        if prepared_statements
          sql, binds = visitor.compile(arel.ast, collector)
          query = klass.query(sql)
        else
          collector = klass.partial_query_collector
          parts, binds = visitor.compile(arel.ast, collector)
          query = klass.partial_query(parts)
        end
        [query, binds]
      end

      # Returns an ActiveRecord::Result instance.
      def select_all(arel, name = nil, binds = [], preparable: nil)
        arel = arel_from_relation(arel)
        sql, binds = to_sql_and_binds(arel, binds)

        if preparable.nil?
          preparable = prepared_statements ? visitor.preparable : false
        end

        if prepared_statements && preparable
          select_prepared(sql, name, binds)
        else
          select(sql, name, binds)
        end
      end

      # Returns a record hash with the column names as keys and column values
      # as values.
      def select_one(arel, name = nil, binds = [])
        select_all(arel, name, binds).first
      end

      # Returns a single value from a record
      def select_value(arel, name = nil, binds = [])
        single_value_from_rows(select_rows(arel, name, binds))
      end

      # Returns an array of the values of the first column in a select:
      #   select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
      def select_values(arel, name = nil, binds = [])
        select_rows(arel, name, binds).map(&:first)
      end

      # Returns an array of arrays containing the field values.
      # Order is the same as that returned by +columns+.
      def select_rows(arel, name = nil, binds = [])
        select_all(arel, name, binds).rows
      end

      def query_value(sql, name = nil) # :nodoc:
        single_value_from_rows(query(sql, name))
      end

      def query_values(sql, name = nil) # :nodoc:
        query(sql, name).map(&:first)
      end

      def query(sql, name = nil) # :nodoc:
        exec_query(sql, name).rows
      end

      # Determines whether the SQL statement is a write query.
      def write_query?(sql)
        raise NotImplementedError
      end

      # Executes the SQL statement in the context of this connection and returns
      # the raw result from the connection adapter.
      # Note: depending on your database connector, the result returned by this
      # method may be manually memory managed. Consider using the exec_query
      # wrapper instead.
      def execute(sql, name = nil)
        raise NotImplementedError
      end

      # Executes +sql+ statement in the context of this connection using
      # +binds+ as the bind substitutes. +name+ is logged along with
      # the executed +sql+ statement.
      def exec_query(sql, name = "SQL", binds = [], prepare: false)
        raise NotImplementedError
      end

      # Executes insert +sql+ statement in the context of this connection using
      # +binds+ as the bind substitutes. +name+ is logged along with
      # the executed +sql+ statement.
      def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
        sql, binds = sql_for_insert(sql, pk, binds)
        exec_query(sql, name, binds)
      end

      # Executes delete +sql+ statement in the context of this connection using
      # +binds+ as the bind substitutes. +name+ is logged along with
      # the executed +sql+ statement.
      def exec_delete(sql, name = nil, binds = [])
        exec_query(sql, name, binds)
      end

      # Executes update +sql+ statement in the context of this connection using
      # +binds+ as the bind substitutes. +name+ is logged along with
      # the executed +sql+ statement.
      def exec_update(sql, name = nil, binds = [])
        exec_query(sql, name, binds)
      end

      def exec_insert_all(sql, name) # :nodoc:
        exec_query(sql, name)
      end

      # Executes an INSERT query and returns the new record's ID
      #
      # +id_value+ will be returned unless the value is +nil+, in
      # which case the database will attempt to calculate the last inserted<commit_msg>Add explain to abstract database statements.<commit_after># frozen_string_literal: true

module ActiveRecord
  module ConnectionAdapters # :nodoc:
    module DatabaseStatements
      def initialize
        super
        reset_transaction
      end

      # Converts an arel AST to SQL
      def to_sql(arel_or_sql_string, binds = [])
        sql, _ = to_sql_and_binds(arel_or_sql_string, binds)
        sql
      end

      def to_sql_and_binds(arel_or_sql_string, binds = []) # :nodoc:
        if arel_or_sql_string.respond_to?(:ast)
          unless binds.empty?
            raise "Passing bind parameters with an arel AST is forbidden. " \
              "The values must be stored on the AST directly"
          end

          if prepared_statements
            sql, binds = visitor.compile(arel_or_sql_string.ast, collector)

            if binds.length > bind_params_length
              unprepared_statement do
                sql, binds = to_sql_and_binds(arel_or_sql_string)
                visitor.preparable = false
              end
            end
          else
            sql = visitor.compile(arel_or_sql_string.ast, collector)
          end
          [sql.freeze, binds]
        else
          visitor.preparable = false if prepared_statements

          arel_or_sql_string = arel_or_sql_string.dup.freeze unless arel_or_sql_string.frozen?
          [arel_or_sql_string, binds]
        end
      end
      private :to_sql_and_binds

      # This is used in the StatementCache object. It returns an object that
      # can be used to query the database repeatedly.
      def cacheable_query(klass, arel) # :nodoc:
        if prepared_statements
          sql, binds = visitor.compile(arel.ast, collector)
          query = klass.query(sql)
        else
          collector = klass.partial_query_collector
          parts, binds = visitor.compile(arel.ast, collector)
          query = klass.partial_query(parts)
        end
        [query, binds]
      end

      # Returns an ActiveRecord::Result instance.
      def select_all(arel, name = nil, binds = [], preparable: nil)
        arel = arel_from_relation(arel)
        sql, binds = to_sql_and_binds(arel, binds)

        if preparable.nil?
          preparable = prepared_statements ? visitor.preparable : false
        end

        if prepared_statements && preparable
          select_prepared(sql, name, binds)
        else
          select(sql, name, binds)
        end
      end

      # Returns a record hash with the column names as keys and column values
      # as values.
      def select_one(arel, name = nil, binds = [])
        select_all(arel, name, binds).first
      end

      # Returns a single value from a record
      def select_value(arel, name = nil, binds = [])
        single_value_from_rows(select_rows(arel, name, binds))
      end

      # Returns an array of the values of the first column in a select:
      #   select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
      def select_values(arel, name = nil, binds = [])
        select_rows(arel, name, binds).map(&:first)
      end

      # Returns an array of arrays containing the field values.
      # Order is the same as that returned by +columns+.
      def select_rows(arel, name = nil, binds = [])
        select_all(arel, name, binds).rows
      end

      def query_value(sql, name = nil) # :nodoc:
        single_value_from_rows(query(sql, name))
      end

      def query_values(sql, name = nil) # :nodoc:
        query(sql, name).map(&:first)
      end

      def query(sql, name = nil) # :nodoc:
        exec_query(sql, name).rows
      end

      # Determines whether the SQL statement is a write query.
      def write_query?(sql)
        raise NotImplementedError
      end

      # Executes the SQL statement in the context of this connection and returns
      # the raw result from the connection adapter.
      # Note: depending on your database connector, the result returned by this
      # method may be manually memory managed. Consider using the exec_query
      # wrapper instead.
      def execute(sql, name = nil)
        raise NotImplementedError
      end

      # Executes +sql+ statement in the context of this connection using
      # +binds+ as the bind substitutes. +name+ is logged along with
      # the executed +sql+ statement.
      def exec_query(sql, name = "SQL", binds = [], prepare: false)
        raise NotImplementedError
      end

      # Executes insert +sql+ statement in the context of this connection using
      # +binds+ as the bind substitutes. +name+ is logged along with
      # the executed +sql+ statement.
      def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
        sql, binds = sql_for_insert(sql, pk, binds)
        exec_query(sql, name, binds)
      end

      # Executes delete +sql+ statement in the context of this connection using
      # +binds+ as the bind substitutes. +name+ is logged along with
      # the executed +sql+ statement.
      def exec_delete(sql, name = nil, binds = [])
        exec_query(sql, name, binds)
      end

      # Executes update +sql+ statement in the context of this connection using
      # +binds+ as the bind substitutes. +name+ is logged along with
      # the executed +sql+ statement.
      def exec_update(sql, name = nil, binds = [])
        exec_query(sql, name, binds)
      end

      def exec_insert_all(sql, name) # :nodoc:
        exec_query(sql, name)
      end

      def explain(arel, binds = []) # :nodoc:
        raise NotImplementedError
      end

      # Executes an INSERT query and returns the new record's ID
      #
      # +id_value+ will be returned unless the value is +nil+, in
      # which case the database will attempt to calculate the last inserted
{'fraction_non_alphanumeric': 0.0742296918767507, 'fraction_numerical': 0.0007002801120448179, 'mean_word_length': 2.2773952954675845, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, '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': '3876347', 'n_tokens_mistral': 3328, 'n_tokens_neox': 3163, 'n_words': 1099}