aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/adapters/postgresql/array_test.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test/cases/adapters/postgresql/array_test.rb')
-rw-r--r--activerecord/test/cases/adapters/postgresql/array_test.rb114
1 files changed, 96 insertions, 18 deletions
diff --git a/activerecord/test/cases/adapters/postgresql/array_test.rb b/activerecord/test/cases/adapters/postgresql/array_test.rb
index 0b1e3295cc..042beab23f 100644
--- a/activerecord/test/cases/adapters/postgresql/array_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/array_test.rb
@@ -1,8 +1,11 @@
# encoding: utf-8
require "cases/helper"
+require 'support/schema_dumping_helper'
class PostgresqlArrayTest < ActiveRecord::TestCase
+ include SchemaDumpingHelper
include InTimeZone
+ OID = ActiveRecord::ConnectionAdapters::PostgreSQL::OID
class PgArray < ActiveRecord::Base
self.table_name = 'pg_arrays'
@@ -10,11 +13,15 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
def setup
@connection = ActiveRecord::Base.connection
+
+ enable_extension!('hstore', @connection)
+
@connection.transaction do
@connection.create_table('pg_arrays') do |t|
t.string 'tags', array: true
t.integer 'ratings', array: true
t.datetime :datetimes, array: true
+ t.hstore :hstores, array: true
end
end
@column = PgArray.columns_hash['tags']
@@ -22,13 +29,13 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
teardown do
@connection.execute 'drop table if exists pg_arrays'
+ disable_extension!('hstore', @connection)
end
def test_column
assert_equal :string, @column.type
assert_equal "character varying", @column.sql_type
assert @column.array
- assert_not @column.text?
assert_not @column.number?
assert_not @column.binary?
@@ -41,9 +48,8 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
def test_default
@connection.add_column 'pg_arrays', 'score', :integer, array: true, default: [4, 4, 2]
PgArray.reset_column_information
- column = PgArray.columns_hash["score"]
- assert_equal([4, 4, 2], column.default)
+ assert_equal([4, 4, 2], PgArray.column_defaults['score'])
assert_equal([4, 4, 2], PgArray.new.score)
ensure
PgArray.reset_column_information
@@ -52,9 +58,8 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
def test_default_strings
@connection.add_column 'pg_arrays', 'names', :string, array: true, default: ["foo", "bar"]
PgArray.reset_column_information
- column = PgArray.columns_hash["names"]
- assert_equal(["foo", "bar"], column.default)
+ assert_equal(["foo", "bar"], PgArray.column_defaults['names'])
assert_equal(["foo", "bar"], PgArray.new.names)
ensure
PgArray.reset_column_information
@@ -68,7 +73,7 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
column = PgArray.columns_hash['snippets']
assert_equal :text, column.type
- assert_equal [], column.default
+ assert_equal [], PgArray.column_defaults['snippets']
assert column.array
end
@@ -85,8 +90,7 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
@connection.change_column_default :pg_arrays, :tags, []
PgArray.reset_column_information
- column = PgArray.columns_hash['tags']
- assert_equal [], column.default
+ assert_equal [], PgArray.column_defaults['tags']
end
def test_type_cast_array
@@ -106,6 +110,12 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
assert_equal([1, 2], x.ratings)
end
+ def test_schema_dump_with_shorthand
+ output = dump_table_schema "pg_arrays"
+ assert_match %r[t.string\s+"tags",\s+array: true], output
+ assert_match %r[t.integer\s+"ratings",\s+array: true], output
+ end
+
def test_select_with_strings
@connection.execute "insert into pg_arrays (tags) VALUES ('{1,2,3}')"
x = PgArray.first
@@ -185,16 +195,6 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
assert_equal("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...]", record.attribute_for_inspect(:ratings))
end
- def test_update_all
- pg_array = PgArray.create! tags: ["one", "two", "three"]
-
- PgArray.update_all tags: ["four", "five"]
- assert_equal ["four", "five"], pg_array.reload.tags
-
- PgArray.update_all tags: []
- assert_equal [], pg_array.reload.tags
- end
-
def test_escaping
unknown = 'foo\\",bar,baz,\\'
tags = ["hello_#{unknown}"]
@@ -203,6 +203,45 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
assert_equal tags, ar.tags
end
+ def test_string_quoting_rules_match_pg_behavior
+ tags = ["", "one{", "two}", %(three"), "four\\", "five ", "six\t", "seven\n", "eight,", "nine", "ten\r", "NULL"]
+ x = PgArray.create!(tags: tags)
+ x.reload
+
+ assert_equal x.tags_before_type_cast, PgArray.columns_hash['tags'].type_cast_for_database(tags)
+ end
+
+ def test_quoting_non_standard_delimiters
+ strings = ["hello,", "world;"]
+ comma_delim = OID::Array.new(ActiveRecord::Type::String.new, ',')
+ semicolon_delim = OID::Array.new(ActiveRecord::Type::String.new, ';')
+
+ assert_equal %({"hello,",world;}), comma_delim.type_cast_for_database(strings)
+ assert_equal %({hello,;"world;"}), semicolon_delim.type_cast_for_database(strings)
+ end
+
+ def test_mutate_array
+ x = PgArray.create!(tags: %w(one two))
+
+ x.tags << "three"
+ x.save!
+ x.reload
+
+ assert_equal %w(one two three), x.tags
+ assert_not x.changed?
+ end
+
+ def test_mutate_value_in_array
+ x = PgArray.create!(hstores: [{ a: 'a' }, { b: 'b' }])
+
+ x.hstores.first['a'] = 'c'
+ x.save!
+ x.reload
+
+ assert_equal [{ 'a' => 'c' }, { 'b' => 'b' }], x.hstores
+ assert_not x.changed?
+ end
+
def test_datetime_with_timezone_awareness
tz = "Pacific Time (US & Canada)"
@@ -223,6 +262,45 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
end
end
+ def test_assigning_non_array_value
+ record = PgArray.new(tags: "not-an-array")
+ assert_equal [], record.tags
+ assert_equal "not-an-array", record.tags_before_type_cast
+ assert record.save
+ assert_equal record.tags, record.reload.tags
+ end
+
+ def test_assigning_empty_string
+ record = PgArray.new(tags: "")
+ assert_equal [], record.tags
+ assert_equal "", record.tags_before_type_cast
+ assert record.save
+ assert_equal record.tags, record.reload.tags
+ end
+
+ def test_assigning_valid_pg_array_literal
+ record = PgArray.new(tags: "{1,2,3}")
+ assert_equal ["1", "2", "3"], record.tags
+ assert_equal "{1,2,3}", record.tags_before_type_cast
+ assert record.save
+ assert_equal record.tags, record.reload.tags
+ end
+
+ def test_uniqueness_validation
+ klass = Class.new(PgArray) do
+ validates_uniqueness_of :tags
+
+ def self.model_name; ActiveModel::Name.new(PgArray) end
+ end
+ e1 = klass.create("tags" => ["black", "blue"])
+ assert e1.persisted?, "Saving e1"
+
+ e2 = klass.create("tags" => ["black", "blue"])
+ assert !e2.persisted?, "e2 shouldn't be valid"
+ assert e2.errors[:tags].any?, "Should have errors for tags"
+ assert_equal ["has already been taken"], e2.errors[:tags], "Should have uniqueness message for tags"
+ end
+
private
def assert_cycle field, array
# test creation