dkubb/axiom-do-adapter

View on GitHub
lib/axiom/adapter/data_objects/statement.rb

Summary

Maintainability
A
0 mins
Test Coverage
# encoding: utf-8

module Axiom
  module Adapter
    class DataObjects

      # Executes generated SQL statements
      class Statement
        include Enumerable, Adamantium::Flat

        # Initialize a statement
        #
        # @param [::DataObjects::Connection] connection
        #   the database connection
        # @param [Relation] relation
        #   the relation to generate the SQL from
        # @param [#visit] visitor
        #   optional object to visit the relation and generate SQL with
        #
        # @return [undefined]
        #
        # @api private
        def initialize(connection, relation, visitor = SQL::Generator::Relation)
          @connection = connection
          @relation   = relation
          @visitor    = visitor
        end

        # Iterate over each row in the results
        #
        # @example
        #   statement = Statement.new(connection, relation, visitor)
        #   statement.each { |row| ... }
        #
        # @yield [row]
        #
        # @yieldparam [Array] row
        #   each row in the results
        #
        # @return [self]
        #
        # @api public
        def each
          return to_enum unless block_given?
          each_row { |row| yield row }
          self
        end

        # Return the SQL query
        #
        # @example
        #   statement.to_s  # => SQL representation of the relation
        #
        # @return [String]
        #
        # @api public
        def to_s
          @visitor.visit(@relation).to_sql.freeze
        end

      private

        # Yield each row in the result
        #
        # @yield [row]
        #
        # @yieldparam [Array] row
        #   each row in the results
        #
        # @return [undefined]
        #
        # @api private
        def each_row
          reader = command.execute_reader
          yield reader.values while reader.next!
        ensure
          reader.close if reader
        end

        # Return the command for the SQL query and column types
        #
        # @return [::DataObjects::Command]
        #
        # @api private
        def command
          command = @connection.create_command(to_s)
          command.set_types(column_types)
          command
        end

        # Return the list of types for each column
        #
        # @return [Array<Class>]
        #
        # @api private
        def column_types
          @relation.header.map { |attribute| attribute.type.primitive }
        end

        memoize :to_s
        memoize :command, freezer: :flat

      end # class Statement
    end # class DataObjects
  end # module Adapter
end # module Axiom