<commit_before># frozen_string_literal: true

module ActiveRecord
  module ConnectionAdapters
    module OracleEnhanced
      module DatabaseStatements
        # DATABASE STATEMENTS ======================================
        #
        # see: abstract/database_statements.rb

        # Executes a SQL statement
        def execute(sql, name = nil)
          log(sql, name) { @connection.exec(sql) }
        end

        def clear_cache! # :nodoc:
          reload_type_map
          super
        end

        def exec_query(sql, name = "SQL", binds = [], prepare: false)
          type_casted_binds = type_casted_binds(binds)

          log(sql, name, binds, type_casted_binds) do
            cursor = nil
            cached = false
            with_retry do
              if without_prepared_statement?(binds)
                cursor = @connection.prepare(sql)
              else
                unless @statements.key? sql
                  @statements[sql] = @connection.prepare(sql)
                end

                cursor = @statements[sql]

                cursor.bind_params(type_casted_binds)

                cached = true
              end

              cursor.exec
            end

            if (name == "EXPLAIN") && sql =~ /^EXPLAIN/
              res = true
            else
              columns = cursor.get_col_names.map do |col_name|
                oracle_downcase(col_name)
              end
              rows = []
              fetch_options = { get_lob_value: (name != "Writable Large Object") }
              while row = cursor.fetch(fetch_options)
                rows << row
              end
              res = build_result(columns, rows)
            end

            cursor.close unless cached
            res
          end
        end

        def supports_explain?
          true
        end

        def explain(arel, binds = [])
          sql = "EXPLAIN PLAN FOR #{to_sql(arel, binds)}"
          return if /FROM all_/.match?(sql)
          if ORACLE_ENHANCED_CONNECTION == :jdbc
            exec_query(sql, "EXPLAIN", binds)
          else
            exec_query(sql, "EXPLAIN")
          end
          select_values("SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)", "EXPLAIN").join("\n")
        end

        # New method in ActiveRecord 3.1
        # Will add RETURNING clause in case of trigger generated primary keys
        def sql_for_insert(sql, pk, binds)
          unless pk == false || pk.nil? || pk.is_a?(Array)
            sql = "#{sql} RETURNING #{quote_column_name(pk)} INTO :returning_id"
            (binds = binds.dup) << ActiveRecord::Relation::QueryAttribute.new("returning_id", nil, Type::OracleEnhanced::Integer.new)
          end
          super
        end

        def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
          pk = nil if id_value
          super
        end

        # New method in ActiveRecord 3.1
        def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
          sql, binds = sql_for_insert(sql, pk, binds)
          type_casted_binds = type_casted_binds(binds)

          log(sql, name, binds, type_casted_binds) do
            cached = false
            cursor = nil
            returning_id_col = returning_id_index = nil
            with_retry do
              if without_prepared_statement?(binds)
                cursor = @connection.prepare(sql)
              else
                unless @statements.key?(sql)
                  @statements[sql] = @connection.prepare(sql)
                end

                cursor = @statements[sql]

                cursor.bind_params(type_casted_binds)

                if /:returning_id/.match?(sql)
                  # it currently expects that returning_id comes last part of binds
                  returning_id_index = binds.size
                  cursor.bind_returning_param(returning_id_index, Integer)
                end

                cached = true
              end

              cursor.exec_update
            end

            rows = []
            if returning_id_index
              returning_id = cursor.get_returning_param(returning_id_index, Integer).to_i
              rows << [returning_id]
            end
            cursor.close unless cached
            build_result(returning_id_col || [], rows)
          end
        end

        # New method in ActiveRecord 3.1
        def exec_update(sql, name = nil, binds = [])
          type_casted_binds = type_casted_binds(binds)

          log(sql, name, binds, type_casted_binds) do
            with_retry do
              cached = false
              if without_prepared_statement?(binds)
                cursor = @connection.prepare(sql)
              else
                if @statements.key?(sql)
                  cursor = @statements[sql]
                else
                  cursor = @statements[sql] = @connection.prepare(sql)
                end

                cursor.bind_params(type_casted_binds)

                cached = true
              end

              res = cursor.exec_update
              cursor.close unless cached
              res
            end<commit_msg>Use the new API for build_results<commit_after># frozen_string_literal: true

module ActiveRecord
  module ConnectionAdapters
    module OracleEnhanced
      module DatabaseStatements
        # DATABASE STATEMENTS ======================================
        #
        # see: abstract/database_statements.rb

        # Executes a SQL statement
        def execute(sql, name = nil)
          log(sql, name) { @connection.exec(sql) }
        end

        def clear_cache! # :nodoc:
          reload_type_map
          super
        end

        def exec_query(sql, name = "SQL", binds = [], prepare: false)
          type_casted_binds = type_casted_binds(binds)

          log(sql, name, binds, type_casted_binds) do
            cursor = nil
            cached = false
            with_retry do
              if without_prepared_statement?(binds)
                cursor = @connection.prepare(sql)
              else
                unless @statements.key? sql
                  @statements[sql] = @connection.prepare(sql)
                end

                cursor = @statements[sql]

                cursor.bind_params(type_casted_binds)

                cached = true
              end

              cursor.exec
            end

            if (name == "EXPLAIN") && sql =~ /^EXPLAIN/
              res = true
            else
              columns = cursor.get_col_names.map do |col_name|
                oracle_downcase(col_name)
              end
              rows = []
              fetch_options = { get_lob_value: (name != "Writable Large Object") }
              while row = cursor.fetch(fetch_options)
                rows << row
              end
              res = build_result(columns: columns, rows: rows)
            end

            cursor.close unless cached
            res
          end
        end

        def supports_explain?
          true
        end

        def explain(arel, binds = [])
          sql = "EXPLAIN PLAN FOR #{to_sql(arel, binds)}"
          return if /FROM all_/.match?(sql)
          if ORACLE_ENHANCED_CONNECTION == :jdbc
            exec_query(sql, "EXPLAIN", binds)
          else
            exec_query(sql, "EXPLAIN")
          end
          select_values("SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY)", "EXPLAIN").join("\n")
        end

        # New method in ActiveRecord 3.1
        # Will add RETURNING clause in case of trigger generated primary keys
        def sql_for_insert(sql, pk, binds)
          unless pk == false || pk.nil? || pk.is_a?(Array)
            sql = "#{sql} RETURNING #{quote_column_name(pk)} INTO :returning_id"
            (binds = binds.dup) << ActiveRecord::Relation::QueryAttribute.new("returning_id", nil, Type::OracleEnhanced::Integer.new)
          end
          super
        end

        def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
          pk = nil if id_value
          super
        end

        # New method in ActiveRecord 3.1
        def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
          sql, binds = sql_for_insert(sql, pk, binds)
          type_casted_binds = type_casted_binds(binds)

          log(sql, name, binds, type_casted_binds) do
            cached = false
            cursor = nil
            returning_id_col = returning_id_index = nil
            with_retry do
              if without_prepared_statement?(binds)
                cursor = @connection.prepare(sql)
              else
                unless @statements.key?(sql)
                  @statements[sql] = @connection.prepare(sql)
                end

                cursor = @statements[sql]

                cursor.bind_params(type_casted_binds)

                if /:returning_id/.match?(sql)
                  # it currently expects that returning_id comes last part of binds
                  returning_id_index = binds.size
                  cursor.bind_returning_param(returning_id_index, Integer)
                end

                cached = true
              end

              cursor.exec_update
            end

            rows = []
            if returning_id_index
              returning_id = cursor.get_returning_param(returning_id_index, Integer).to_i
              rows << [returning_id]
            end
            cursor.close unless cached
            build_result(columns: returning_id_col || [], rows: rows)
          end
        end

        # New method in ActiveRecord 3.1
        def exec_update(sql, name = nil, binds = [])
          type_casted_binds = type_casted_binds(binds)

          log(sql, name, binds, type_casted_binds) do
            with_retry do
              cached = false
              if without_prepared_statement?(binds)
                cursor = @connection.prepare(sql)
              else
                if @statements.key?(sql)
                  cursor = @statements[sql]
                else
                  cursor = @statements[sql] = @connection.prepare(sql)
                end

                cursor.bind_params(type_casted_binds)

                cached = true
              end

              res = cursor.exec_update
              cursor.close unless cached
              res
            end
{'fraction_non_alphanumeric': 0.08391337973704563, 'fraction_numerical': 0.001160092807424594, 'mean_word_length': 1.4903707270101108, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 3, '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': '536010', 'n_tokens_mistral': 2895, 'n_tokens_neox': 2724, 'n_words': 666}