postgresql_adapter_test.rb 8.8 KB
Newer Older
1
# encoding: utf-8
2
require "cases/helper"
3 4 5 6 7 8

module ActiveRecord
  module ConnectionAdapters
    class PostgreSQLAdapterTest < ActiveRecord::TestCase
      def setup
        @connection = ActiveRecord::Base.connection
A
Aaron Patterson 已提交
9
        @connection.exec_query('drop table if exists ex')
10 11 12
        @connection.exec_query('create table ex(id serial primary key, number integer, data character varying(255))')
      end

13
      def test_primary_key
14
        assert_equal 'id', @connection.primary_key('ex')
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
      end

      def test_non_standard_primary_key
        @connection.exec_query('drop table if exists ex')
        @connection.exec_query('create table ex(data character varying(255) primary key)')
        assert_equal 'data', @connection.primary_key('ex')
      end

      def test_primary_key_returns_nil_for_no_pk
        @connection.exec_query('drop table if exists ex')
        @connection.exec_query('create table ex(id integer)')
        assert_nil @connection.primary_key('ex')
      end

      def test_primary_key_raises_error_if_table_not_found
        assert_raises(ActiveRecord::StatementInvalid) do
          @connection.primary_key('unobtainium')
        end
      end

      def test_insert_sql_with_proprietary_returning_clause
        id = @connection.insert_sql("insert into ex (number) values(5150)", nil, "number")
        assert_equal "5150", id
      end

      def test_insert_sql_with_quoted_schema_and_table_name
        id = @connection.insert_sql('insert into "public"."ex" (number) values(5150)')
        expect = @connection.query('select max(id) from ex').first.first
        assert_equal expect, id
      end

      def test_insert_sql_with_no_space_after_table_name
        id = @connection.insert_sql("insert into ex(number) values(5150)")
        expect = @connection.query('select max(id) from ex').first.first
        assert_equal expect, id
      end

52
      def test_insert_sql_with_returning_disabled
53 54 55
        connection = connection_without_insert_returning
        id = connection.insert_sql("insert into postgresql_partitioned_table_parent (number) VALUES (1)")
        expect = connection.query('select max(id) from postgresql_partitioned_table_parent').first.first
56 57 58
        assert_equal expect, id
      end

D
Doug Cole 已提交
59
      def test_exec_insert_with_returning_disabled
60 61 62
        connection = connection_without_insert_returning
        result = connection.exec_insert("insert into postgresql_partitioned_table_parent (number) VALUES (1)", nil, [], 'id', 'postgresql_partitioned_table_parent_id_seq')
        expect = connection.query('select max(id) from postgresql_partitioned_table_parent').first.first
D
Doug Cole 已提交
63 64 65 66
        assert_equal expect, result.rows.first.first
      end

      def test_exec_insert_with_returning_disabled_and_no_sequence_name_given
67 68 69
        connection = connection_without_insert_returning
        result = connection.exec_insert("insert into postgresql_partitioned_table_parent (number) VALUES (1)", nil, [], 'id')
        expect = connection.query('select max(id) from postgresql_partitioned_table_parent').first.first
D
Doug Cole 已提交
70 71 72 73
        assert_equal expect, result.rows.first.first
      end

      def test_sql_for_insert_with_returning_disabled
74 75
        connection = connection_without_insert_returning
        result = connection.sql_for_insert('sql', nil, nil, nil, 'binds')
D
Doug Cole 已提交
76 77 78
        assert_equal ['sql', 'binds'], result
      end

79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
      def test_serial_sequence
        assert_equal 'public.accounts_id_seq',
          @connection.serial_sequence('accounts', 'id')

        assert_raises(ActiveRecord::StatementInvalid) do
          @connection.serial_sequence('zomg', 'id')
        end
      end

      def test_default_sequence_name
        assert_equal 'accounts_id_seq',
          @connection.default_sequence_name('accounts', 'id')

        assert_equal 'accounts_id_seq',
          @connection.default_sequence_name('accounts')
      end

      def test_default_sequence_name_bad_table
        assert_equal 'zomg_id_seq',
          @connection.default_sequence_name('zomg', 'id')

        assert_equal 'zomg_id_seq',
          @connection.default_sequence_name('zomg')
      end

104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
      def test_pk_and_sequence_for
        pk, seq = @connection.pk_and_sequence_for('ex')
        assert_equal 'id', pk
        assert_equal @connection.default_sequence_name('ex', 'id'), seq
      end

      def test_pk_and_sequence_for_with_non_standard_primary_key
        @connection.exec_query('drop table if exists ex')
        @connection.exec_query('create table ex(code serial primary key)')
        pk, seq = @connection.pk_and_sequence_for('ex')
        assert_equal 'code', pk
        assert_equal @connection.default_sequence_name('ex', 'code'), seq
      end

      def test_pk_and_sequence_for_returns_nil_if_no_seq
        @connection.exec_query('drop table if exists ex')
        @connection.exec_query('create table ex(id integer primary key)')
        assert_nil @connection.pk_and_sequence_for('ex')
      end

      def test_pk_and_sequence_for_returns_nil_if_no_pk
        @connection.exec_query('drop table if exists ex')
        @connection.exec_query('create table ex(id integer)')
        assert_nil @connection.pk_and_sequence_for('ex')
      end

      def test_pk_and_sequence_for_returns_nil_if_table_not_found
        assert_nil @connection.pk_and_sequence_for('unobtainium')
      end

134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
      def test_exec_insert_number
        insert(@connection, 'number' => 10)

        result = @connection.exec_query('SELECT number FROM ex WHERE number = 10')

        assert_equal 1, result.rows.length
        assert_equal "10", result.rows.last.last
      end

      def test_exec_insert_string
        str = 'いただきます!'
        insert(@connection, 'number' => 10, 'data' => str)

        result = @connection.exec_query('SELECT number, data FROM ex WHERE number = 10')

        value = result.rows.last.last

        assert_equal str, value
152 153 154 155 156 157 158
      end

      def test_table_alias_length
        assert_nothing_raised do
          @connection.table_alias_length
        end
      end
159 160

      def test_exec_no_binds
A
Aaron Patterson 已提交
161
        result = @connection.exec_query('SELECT id, data FROM ex')
162 163 164 165 166
        assert_equal 0, result.rows.length
        assert_equal 2, result.columns.length
        assert_equal %w{ id data }, result.columns

        string = @connection.quote('foo')
A
Aaron Patterson 已提交
167 168
        @connection.exec_query("INSERT INTO ex (id, data) VALUES (1, #{string})")
        result = @connection.exec_query('SELECT id, data FROM ex')
169 170 171 172 173
        assert_equal 1, result.rows.length
        assert_equal 2, result.columns.length

        assert_equal [['1', 'foo']], result.rows
      end
174 175 176

      def test_exec_with_binds
        string = @connection.quote('foo')
A
Aaron Patterson 已提交
177 178
        @connection.exec_query("INSERT INTO ex (id, data) VALUES (1, #{string})")
        result = @connection.exec_query(
179 180 181 182 183 184 185
          'SELECT id, data FROM ex WHERE id = $1', nil, [[nil, 1]])

        assert_equal 1, result.rows.length
        assert_equal 2, result.columns.length

        assert_equal [['1', 'foo']], result.rows
      end
A
Aaron Patterson 已提交
186 187 188

      def test_exec_typecasts_bind_vals
        string = @connection.quote('foo')
A
Aaron Patterson 已提交
189
        @connection.exec_query("INSERT INTO ex (id, data) VALUES (1, #{string})")
A
Aaron Patterson 已提交
190 191

        column = @connection.columns('ex').find { |col| col.name == 'id' }
A
Aaron Patterson 已提交
192
        result = @connection.exec_query(
A
Aaron Patterson 已提交
193 194 195 196 197 198 199
          'SELECT id, data FROM ex WHERE id = $1', nil, [[column, '1-fuu']])

        assert_equal 1, result.rows.length
        assert_equal 2, result.columns.length

        assert_equal [['1', 'foo']], result.rows
      end
200

201 202
      def test_substitute_at
        bind = @connection.substitute_at(nil, 0)
203 204
        assert_equal Arel.sql('$1'), bind

205
        bind = @connection.substitute_at(nil, 1)
206 207
        assert_equal Arel.sql('$2'), bind
      end
208

209 210 211 212 213 214
      def test_partial_index
        @connection.add_index 'ex', %w{ id number }, :name => 'partial', :where => "number > 100"
        index = @connection.indexes('ex').find { |idx| idx.name == 'partial' }
        assert_equal "(number > 100)", index.where
      end

K
kennyj 已提交
215 216 217 218 219
      def test_distinct_with_nulls
        assert_equal "DISTINCT posts.title, posts.updater_id AS alias_0", @connection.distinct("posts.title", ["posts.updater_id desc nulls first"])
        assert_equal "DISTINCT posts.title, posts.updater_id AS alias_0", @connection.distinct("posts.title", ["posts.updater_id desc nulls last"])
      end

220 221 222 223 224 225 226 227 228 229 230 231 232 233
      private
      def insert(ctx, data)
        binds   = data.map { |name, value|
          [ctx.columns('ex').find { |x| x.name == name }, value]
        }
        columns = binds.map(&:first).map(&:name)

        bind_subs = columns.length.times.map { |x| "$#{x + 1}" }

        sql = "INSERT INTO ex (#{columns.join(", ")})
               VALUES (#{bind_subs.join(', ')})"

        ctx.exec_insert(sql, 'SQL', binds)
      end
234 235 236 237

      def connection_without_insert_returning
        ActiveRecord::Base.postgresql_connection(ActiveRecord::Base.configurations['arunit'].merge(:insert_returning => false))
      end
238 239 240
    end
  end
end