postgresql_adapter_test.rb 9.9 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
      end

17 18 19 20
      def test_primary_key_works_tables_containing_capital_letters
        assert_equal 'id', @connection.primary_key('CamelCase')
      end

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 52 53 54 55
      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

56
      def test_insert_sql_with_returning_disabled
57 58 59
        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
60 61 62
        assert_equal expect, id
      end

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

      def test_exec_insert_with_returning_disabled_and_no_sequence_name_given
71 72 73
        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 已提交
74 75 76 77
        assert_equal expect, result.rows.first.first
      end

      def test_sql_for_insert_with_returning_disabled
78 79
        connection = connection_without_insert_returning
        result = connection.sql_for_insert('sql', nil, nil, nil, 'binds')
D
Doug Cole 已提交
80 81 82
        assert_equal ['sql', 'binds'], result
      end

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
      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

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 134 135 136 137
      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

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
      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
156 157 158 159 160 161 162
      end

      def test_table_alias_length
        assert_nothing_raised do
          @connection.table_alias_length
        end
      end
163 164

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

        assert_equal [['1', 'foo']], result.rows
      end
178 179 180

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

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

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

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

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

213 214 215 216 217 218
      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

219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
      def test_distinct_zero_orders
        assert_equal "DISTINCT posts.id",
          @connection.distinct("posts.id", [])
      end

      def test_distinct_one_order
        assert_equal "DISTINCT posts.id, posts.created_at AS alias_0",
          @connection.distinct("posts.id", ["posts.created_at desc"])
      end

      def test_distinct_few_orders
        assert_equal "DISTINCT posts.id, posts.created_at AS alias_0, posts.position AS alias_1",
          @connection.distinct("posts.id", ["posts.created_at desc", "posts.position asc"])
      end

      def test_distinct_blank_not_nil_orders
        assert_equal "DISTINCT posts.id, posts.created_at AS alias_0",
          @connection.distinct("posts.id", ["posts.created_at desc", "", "   "])
      end

      def test_distinct_with_arel_order
        order = Object.new
        def order.to_sql
          "posts.created_at desc"
        end
        assert_equal "DISTINCT posts.id, posts.created_at AS alias_0",
          @connection.distinct("posts.id", [order])
      end

K
kennyj 已提交
248 249 250 251 252
      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

253 254 255 256 257 258 259 260 261 262 263 264 265 266
      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
267 268 269 270

      def connection_without_insert_returning
        ActiveRecord::Base.postgresql_connection(ActiveRecord::Base.configurations['arunit'].merge(:insert_returning => false))
      end
271 272 273
    end
  end
end