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
        @connection.disable_insert_returning!
54 55 56 57
        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
        assert_equal expect, id
      ensure
58
        @connection.enable_insert_returning!
59 60
      end

D
Doug Cole 已提交
61
      def test_exec_insert_with_returning_disabled
62
        @connection.disable_insert_returning!
D
Doug Cole 已提交
63 64 65 66
        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
        assert_equal expect, result.rows.first.first
      ensure
67
        @connection.enable_insert_returning!
D
Doug Cole 已提交
68 69 70
      end

      def test_exec_insert_with_returning_disabled_and_no_sequence_name_given
71
        @connection.disable_insert_returning!
D
Doug Cole 已提交
72 73 74 75
        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
        assert_equal expect, result.rows.first.first
      ensure
76
        @connection.enable_insert_returning!
D
Doug Cole 已提交
77 78 79
      end

      def test_sql_for_insert_with_returning_disabled
80
        @connection.disable_insert_returning!
D
Doug Cole 已提交
81 82 83
        result = @connection.sql_for_insert('sql', nil, nil, nil, 'binds')
        assert_equal ['sql', 'binds'], result
      ensure
84
        @connection.enable_insert_returning!
D
Doug Cole 已提交
85 86
      end

87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
      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

112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
      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

142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
      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
160 161 162 163 164 165 166
      end

      def test_table_alias_length
        assert_nothing_raised do
          @connection.table_alias_length
        end
      end
167 168

      def test_exec_no_binds
A
Aaron Patterson 已提交
169
        result = @connection.exec_query('SELECT id, data FROM ex')
170 171 172 173 174
        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 已提交
175 176
        @connection.exec_query("INSERT INTO ex (id, data) VALUES (1, #{string})")
        result = @connection.exec_query('SELECT id, data FROM ex')
177 178 179 180 181
        assert_equal 1, result.rows.length
        assert_equal 2, result.columns.length

        assert_equal [['1', 'foo']], result.rows
      end
182 183 184

      def test_exec_with_binds
        string = @connection.quote('foo')
A
Aaron Patterson 已提交
185 186
        @connection.exec_query("INSERT INTO ex (id, data) VALUES (1, #{string})")
        result = @connection.exec_query(
187 188 189 190 191 192 193
          '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 已提交
194 195 196

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

        column = @connection.columns('ex').find { |col| col.name == 'id' }
A
Aaron Patterson 已提交
200
        result = @connection.exec_query(
A
Aaron Patterson 已提交
201 202 203 204 205 206 207
          '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
208

209 210
      def test_substitute_at
        bind = @connection.substitute_at(nil, 0)
211 212
        assert_equal Arel.sql('$1'), bind

213
        bind = @connection.substitute_at(nil, 1)
214 215
        assert_equal Arel.sql('$2'), bind
      end
216

217 218 219 220 221 222
      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 已提交
223 224 225 226 227
      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

228 229 230 231 232 233 234 235 236 237 238 239 240 241
      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
242 243 244
    end
  end
end