database_statements.rb 5.5 KB
Newer Older
1 2 3
module ActiveRecord
  module ConnectionAdapters # :nodoc:
    module DatabaseStatements
4 5
      # Returns an array of record hashes with the column names as keys and
      # column values as values.
6
      def select_all(sql, name = nil)
7
        select(sql, name)
8
      end
9

10 11
      # Returns a record hash with the column names as keys and column values
      # as values.
12
      def select_one(sql, name = nil)
13
        result = select_all(sql, name)
14
        result.first if result
15
      end
16 17 18

      # Returns a single value from a record
      def select_value(sql, name = nil)
19 20 21
        if result = select_one(sql, name)
          result.values.first
        end
22 23 24 25 26
      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(sql, name = nil)
27 28
        result = select_rows(sql, name)
        result.map { |v| v[0] }
29 30
      end

31 32
      # Returns an array of arrays containing the field values.
      # Order is the same as that returned by #columns.
33 34 35
      def select_rows(sql, name = nil)
        raise NotImplementedError, "select_rows is an abstract method"
      end
36

37 38 39 40
      # Executes the SQL statement in the context of this connection.
      def execute(sql, name = nil)
        raise NotImplementedError, "execute is an abstract method"
      end
41 42

      # Returns the last auto-generated ID from the affected table.
43
      def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
44
        insert_sql(sql, name, pk, id_value, sequence_name)
45
      end
46 47

      # Executes the update statement and returns the number of rows affected.
48
      def update(sql, name = nil)
49
        update_sql(sql, name)
50
      end
51 52

      # Executes the delete statement and returns the number of rows affected.
53
      def delete(sql, name = nil)
54
        delete_sql(sql, name)
55
      end
56 57 58

      # Wrap a block in a transaction.  Returns result of block.
      def transaction(start_db_transaction = true)
59
        transaction_open = false
60 61
        begin
          if block_given?
62
            if start_db_transaction
63
              begin_db_transaction
64 65
              transaction_open = true
            end
66
            yield
67
          end
68
        rescue Exception => database_transaction_rollback
69 70 71 72
          if transaction_open
            transaction_open = false
            rollback_db_transaction
          end
73
          raise unless database_transaction_rollback.is_a? ActiveRecord::Rollback
74
        end
75
      ensure
76 77 78 79 80 81 82 83
        if transaction_open
          begin
            commit_db_transaction
          rescue Exception => database_transaction_rollback
            rollback_db_transaction
            raise
          end
        end
84 85 86 87 88 89 90 91
      end

      # Begins the transaction (and turns off auto-committing).
      def begin_db_transaction()    end

      # Commits the transaction (and turns on auto-committing).
      def commit_db_transaction()   end

92 93
      # Rolls back the transaction (and turns on auto-committing). Must be
      # done if the transaction block raises an exception or returns false.
94 95
      def rollback_db_transaction() end

96 97
      # Alias for #add_limit_offset!.
      def add_limit!(sql, options)
98
        add_limit_offset!(sql, options) if options
99 100
      end

101 102 103 104 105 106 107
      # Appends +LIMIT+ and +OFFSET+ options to a SQL statement.
      # This method *modifies* the +sql+ parameter.
      # ===== Examples
      #  add_limit_offset!('SELECT * FROM suppliers', {:limit => 10, :offset => 50})
      # generates
      #  SELECT * FROM suppliers LIMIT 10 OFFSET 50
      def add_limit_offset!(sql, options)
108 109 110 111 112 113
        if limit = options[:limit]
          sql << " LIMIT #{limit}"
          if offset = options[:offset]
            sql << " OFFSET #{offset}"
          end
        end
114
      end
115

116 117 118 119 120 121
      # Appends a locking clause to a SQL statement. *Modifies the +sql+ parameter*.
      #   # SELECT * FROM suppliers FOR UPDATE
      #   add_lock! 'SELECT * FROM suppliers', :lock => true
      #   add_lock! 'SELECT * FROM suppliers', :lock => ' FOR UPDATE'
      def add_lock!(sql, options)
        case lock = options[:lock]
122 123
          when true;   sql << ' FOR UPDATE'
          when String; sql << " #{lock}"
124 125 126
        end
      end

127 128 129 130 131 132 133 134
      def default_sequence_name(table, column)
        nil
      end

      # Set the sequence to the max value of the table's column.
      def reset_sequence!(table, column, sequence = nil)
        # Do nothing by default.  Implement for PostgreSQL, Oracle, ...
      end
135

136
      # Inserts the given fixture into the table. Overridden in adapters that require
137 138
      # something beyond a simple insert (eg. Oracle).
      def insert_fixture(fixture, table_name)
139
        execute "INSERT INTO #{table_name} (#{fixture.key_list}) VALUES (#{fixture.value_list})", 'Fixture Insert'
140 141
      end

142 143 144 145 146 147
      protected
        # Returns an array of record hashes with the column names as keys and
        # column values as values.
        def select(sql, name = nil)
          raise NotImplementedError, "select is an abstract method"
        end
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163

        # Returns the last auto-generated ID from the affected table.
        def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
          execute(sql, name)
          id_value
        end

        # Executes the update statement and returns the number of rows affected.
        def update_sql(sql, name = nil)
          execute(sql, name)
        end

        # Executes the delete statement and returns the number of rows affected.
        def delete_sql(sql, name = nil)
          update_sql(sql, name)
        end
164 165
    end
  end
166
end