diff options
Diffstat (limited to 'activerecord/test/cases/adapters/postgresql')
13 files changed, 293 insertions, 47 deletions
diff --git a/activerecord/test/cases/adapters/postgresql/array_test.rb b/activerecord/test/cases/adapters/postgresql/array_test.rb index fa7bebf08b..db302b6294 100644 --- a/activerecord/test/cases/adapters/postgresql/array_test.rb +++ b/activerecord/test/cases/adapters/postgresql/array_test.rb @@ -1,7 +1,9 @@ # encoding: utf-8 require "cases/helper" +require 'support/schema_dumping_helper' class PostgresqlArrayTest < ActiveRecord::TestCase + include SchemaDumpingHelper include InTimeZone OID = ActiveRecord::ConnectionAdapters::PostgreSQL::OID @@ -108,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 @@ -263,6 +271,21 @@ class PostgresqlArrayTest < ActiveRecord::TestCase assert_instance_of PG::InvalidTextRepresentation, e.original_exception 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 diff --git a/activerecord/test/cases/adapters/postgresql/citext_test.rb b/activerecord/test/cases/adapters/postgresql/citext_test.rb index cb024463c9..85bff979c9 100644 --- a/activerecord/test/cases/adapters/postgresql/citext_test.rb +++ b/activerecord/test/cases/adapters/postgresql/citext_test.rb @@ -1,8 +1,10 @@ # encoding: utf-8 require 'cases/helper' +require 'support/schema_dumping_helper' if ActiveRecord::Base.connection.supports_extensions? class PostgresqlCitextTest < ActiveRecord::TestCase + include SchemaDumpingHelper class Citext < ActiveRecord::Base self.table_name = 'citexts' end @@ -67,5 +69,10 @@ if ActiveRecord::Base.connection.supports_extensions? x = Citext.where(cival: 'cased text').first assert_equal 'Cased Text', x.cival end + + def test_schema_dump_with_shorthand + output = dump_table_schema("citexts") + assert_match %r[t.citext "cival"], output + end end end diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb index 2c4839338c..4f48a7bce3 100644 --- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb +++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb @@ -2,9 +2,6 @@ require "cases/helper" require 'support/ddl_helper' -class PostgresqlNumber < ActiveRecord::Base -end - class PostgresqlTime < ActiveRecord::Base end @@ -20,13 +17,6 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase def setup @connection = ActiveRecord::Base.connection - @connection.execute("INSERT INTO postgresql_numbers (id, single, double) VALUES (1, 123.456, 123456.789)") - @connection.execute("INSERT INTO postgresql_numbers (id, single, double) VALUES (2, '-Infinity', 'Infinity')") - @connection.execute("INSERT INTO postgresql_numbers (id, single, double) VALUES (3, 123.456, 'NaN')") - @first_number = PostgresqlNumber.find(1) - @second_number = PostgresqlNumber.find(2) - @third_number = PostgresqlNumber.find(3) - @connection.execute("INSERT INTO postgresql_times (id, time_interval, scaled_time_interval) VALUES (1, '1 year 2 days ago', '3 weeks ago')") @first_time = PostgresqlTime.find(1) @@ -35,12 +25,7 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase end teardown do - [PostgresqlNumber, PostgresqlTime, PostgresqlOid].each(&:delete_all) - end - - def test_data_type_of_number_types - assert_equal :float, @first_number.column_for_attribute(:single).type - assert_equal :float, @first_number.column_for_attribute(:double).type + [PostgresqlTime, PostgresqlOid].each(&:delete_all) end def test_data_type_of_time_types @@ -52,14 +37,6 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase assert_equal :integer, @first_oid.column_for_attribute(:obj_id).type end - def test_number_values - assert_equal 123.456, @first_number.single - assert_equal 123456.789, @first_number.double - assert_equal(-::Float::INFINITY, @second_number.single) - assert_equal ::Float::INFINITY, @second_number.double - assert_same ::Float::NAN, @third_number.double - end - def test_time_values assert_equal '-1 years -2 days', @first_time.time_interval assert_equal '-21 days', @first_time.scaled_time_interval @@ -69,17 +46,6 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase assert_equal 1234, @first_oid.obj_id end - def test_update_number - new_single = 789.012 - new_double = 789012.345 - @first_number.single = new_single - @first_number.double = new_double - assert @first_number.save - assert @first_number.reload - assert_equal new_single, @first_number.single - assert_equal new_double, @first_number.double - end - def test_update_time @first_time.time_interval = '2 years 3 minutes' assert @first_time.save diff --git a/activerecord/test/cases/adapters/postgresql/full_text_test.rb b/activerecord/test/cases/adapters/postgresql/full_text_test.rb index 9dadb177ca..dca35422b9 100644 --- a/activerecord/test/cases/adapters/postgresql/full_text_test.rb +++ b/activerecord/test/cases/adapters/postgresql/full_text_test.rb @@ -1,11 +1,24 @@ # encoding: utf-8 require "cases/helper" +require 'support/schema_dumping_helper' class PostgresqlFullTextTest < ActiveRecord::TestCase - class PostgresqlTsvector < ActiveRecord::Base; end + include SchemaDumpingHelper + class Tsvector < ActiveRecord::Base; end + + setup do + @connection = ActiveRecord::Base.connection + @connection.create_table('tsvectors') do |t| + t.tsvector 'text_vector' + end + end + + teardown do + @connection.execute 'DROP TABLE IF EXISTS tsvectors;' + end def test_tsvector_column - column = PostgresqlTsvector.columns_hash["text_vector"] + column = Tsvector.columns_hash["text_vector"] assert_equal :tsvector, column.type assert_equal "tsvector", column.sql_type assert_not column.number? @@ -14,8 +27,8 @@ class PostgresqlFullTextTest < ActiveRecord::TestCase end def test_update_tsvector - PostgresqlTsvector.create text_vector: "'text' 'vector'" - tsvector = PostgresqlTsvector.first + Tsvector.create text_vector: "'text' 'vector'" + tsvector = Tsvector.first assert_equal "'text' 'vector'", tsvector.text_vector tsvector.text_vector = "'new' 'text' 'vector'" @@ -23,4 +36,9 @@ class PostgresqlFullTextTest < ActiveRecord::TestCase assert tsvector.reload assert_equal "'new' 'text' 'vector'", tsvector.text_vector end + + def test_schema_dump_with_shorthand + output = dump_table_schema("tsvectors") + assert_match %r{t.tsvector "text_vector"}, output + end end diff --git a/activerecord/test/cases/adapters/postgresql/geometric_test.rb b/activerecord/test/cases/adapters/postgresql/geometric_test.rb index 6c0adbbeaa..228221e034 100644 --- a/activerecord/test/cases/adapters/postgresql/geometric_test.rb +++ b/activerecord/test/cases/adapters/postgresql/geometric_test.rb @@ -11,12 +11,10 @@ class PostgresqlPointTest < ActiveRecord::TestCase def setup @connection = ActiveRecord::Base.connection - @connection.transaction do - @connection.create_table('postgresql_points') do |t| - t.point :x - t.point :y, default: [12.2, 13.3] - t.point :z, default: "(14.4,15.5)" - end + @connection.create_table('postgresql_points') do |t| + t.point :x + t.point :y, default: [12.2, 13.3] + t.point :z, default: "(14.4,15.5)" end end @@ -70,3 +68,72 @@ class PostgresqlPointTest < ActiveRecord::TestCase assert_not p.changed? end end + +class PostgresqlGeometricTest < ActiveRecord::TestCase + class PostgresqlGeometric < ActiveRecord::Base; end + + setup do + @connection = ActiveRecord::Base.connection + @connection.create_table("postgresql_geometrics") do |t| + t.column :a_line_segment, :lseg + t.column :a_box, :box + t.column :a_path, :path + t.column :a_polygon, :polygon + t.column :a_circle, :circle + end + end + + teardown do + @connection.execute 'DROP TABLE IF EXISTS postgresql_geometrics' + end + + def test_geometric_types + g = PostgresqlGeometric.new( + :a_line_segment => '(2.0, 3), (5.5, 7.0)', + :a_box => '2.0, 3, 5.5, 7.0', + :a_path => '[(2.0, 3), (5.5, 7.0), (8.5, 11.0)]', + :a_polygon => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))', + :a_circle => '<(5.3, 10.4), 2>' + ) + + g.save! + + h = PostgresqlGeometric.find(g.id) + + assert_equal '[(2,3),(5.5,7)]', h.a_line_segment + assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner + assert_equal '[(2,3),(5.5,7),(8.5,11)]', h.a_path + assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon + assert_equal '<(5.3,10.4),2>', h.a_circle + end + + def test_alternative_format + g = PostgresqlGeometric.new( + :a_line_segment => '((2.0, 3), (5.5, 7.0))', + :a_box => '(2.0, 3), (5.5, 7.0)', + :a_path => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))', + :a_polygon => '2.0, 3, 5.5, 7.0, 8.5, 11.0', + :a_circle => '((5.3, 10.4), 2)' + ) + + g.save! + + h = PostgresqlGeometric.find(g.id) + assert_equal '[(2,3),(5.5,7)]', h.a_line_segment + assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner + assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_path + assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon + assert_equal '<(5.3,10.4),2>', h.a_circle + end + + def test_geometric_function + PostgresqlGeometric.create! a_path: '[(2.0, 3), (5.5, 7.0), (8.5, 11.0)]' # [ ] is an open path + PostgresqlGeometric.create! a_path: '((2.0, 3), (5.5, 7.0), (8.5, 11.0))' # ( ) is a closed path + + objs = PostgresqlGeometric.find_by_sql "SELECT isopen(a_path) FROM postgresql_geometrics ORDER BY id ASC" + assert_equal [true, false], objs.map(&:isopen) + + objs = PostgresqlGeometric.find_by_sql "SELECT isclosed(a_path) FROM postgresql_geometrics ORDER BY id ASC" + assert_equal [false, true], objs.map(&:isclosed) + end +end diff --git a/activerecord/test/cases/adapters/postgresql/hstore_test.rb b/activerecord/test/cases/adapters/postgresql/hstore_test.rb index 6a9c6483fe..00ff456e16 100644 --- a/activerecord/test/cases/adapters/postgresql/hstore_test.rb +++ b/activerecord/test/cases/adapters/postgresql/hstore_test.rb @@ -1,8 +1,10 @@ # encoding: utf-8 require "cases/helper" +require 'support/schema_dumping_helper' if ActiveRecord::Base.connection.supports_extensions? class PostgresqlHstoreTest < ActiveRecord::TestCase + include SchemaDumpingHelper class Hstore < ActiveRecord::Base self.table_name = 'hstores' @@ -313,6 +315,11 @@ if ActiveRecord::Base.connection.supports_extensions? assert_equal({"one" => "two"}, dupe.tags.to_hash) end + def test_schema_dump_with_shorthand + output = dump_table_schema("hstores") + assert_match %r[t.hstore "tags",\s+default: {}], output + end + private def assert_array_cycle(array) # test creation diff --git a/activerecord/test/cases/adapters/postgresql/ltree_test.rb b/activerecord/test/cases/adapters/postgresql/ltree_test.rb index 2968109346..5a0f505072 100644 --- a/activerecord/test/cases/adapters/postgresql/ltree_test.rb +++ b/activerecord/test/cases/adapters/postgresql/ltree_test.rb @@ -1,7 +1,9 @@ # encoding: utf-8 require "cases/helper" +require 'support/schema_dumping_helper' class PostgresqlLtreeTest < ActiveRecord::TestCase + include SchemaDumpingHelper class Ltree < ActiveRecord::Base self.table_name = 'ltrees' end @@ -43,4 +45,9 @@ class PostgresqlLtreeTest < ActiveRecord::TestCase ltree = Ltree.first assert_equal '1.2.3', ltree.path end + + def test_schema_dump_with_shorthand + output = dump_table_schema("ltrees") + assert_match %r[t.ltree "path"], output + end end diff --git a/activerecord/test/cases/adapters/postgresql/network_test.rb b/activerecord/test/cases/adapters/postgresql/network_test.rb index 4f4c1103fa..4e49ea1e02 100644 --- a/activerecord/test/cases/adapters/postgresql/network_test.rb +++ b/activerecord/test/cases/adapters/postgresql/network_test.rb @@ -1,8 +1,22 @@ # encoding: utf-8 require "cases/helper" +require 'support/schema_dumping_helper' class PostgresqlNetworkTest < ActiveRecord::TestCase - class PostgresqlNetworkAddress < ActiveRecord::Base + include SchemaDumpingHelper + class PostgresqlNetworkAddress < ActiveRecord::Base; end + + setup do + @connection = ActiveRecord::Base.connection + @connection.create_table('postgresql_network_addresses', force: true) do |t| + t.inet 'inet_address', default: "192.168.1.1" + t.cidr 'cidr_address', default: "192.168.1.0/24" + t.macaddr 'mac_address', default: "ff:ff:ff:ff:ff:ff" + end + end + + teardown do + @connection.execute 'DROP TABLE IF EXISTS postgresql_network_addresses' end def test_cidr_column @@ -68,4 +82,11 @@ class PostgresqlNetworkTest < ActiveRecord::TestCase assert_nil invalid_address.cidr_address_before_type_cast assert_nil invalid_address.inet_address_before_type_cast end + + def test_schema_dump_with_shorthand + output = dump_table_schema("postgresql_network_addresses") + assert_match %r{t.inet\s+"inet_address",\s+default: "192.168.1.1"}, output + assert_match %r{t.cidr\s+"cidr_address",\s+default: "192.168.1.0/24"}, output + assert_match %r{t.macaddr\s+"mac_address",\s+default: "ff:ff:ff:ff:ff:ff"}, output + end end diff --git a/activerecord/test/cases/adapters/postgresql/numbers_test.rb b/activerecord/test/cases/adapters/postgresql/numbers_test.rb new file mode 100644 index 0000000000..70aa898439 --- /dev/null +++ b/activerecord/test/cases/adapters/postgresql/numbers_test.rb @@ -0,0 +1,49 @@ +require "cases/helper" + +class PostgresqlNumberTest < ActiveRecord::TestCase + class PostgresqlNumber < ActiveRecord::Base; end + + setup do + @connection = ActiveRecord::Base.connection + @connection.create_table('postgresql_numbers', force: true) do |t| + t.column 'single', 'REAL' + t.column 'double', 'DOUBLE PRECISION' + end + end + + teardown do + @connection.execute 'DROP TABLE IF EXISTS postgresql_numbers' + end + + def test_data_type + assert_equal :float, PostgresqlNumber.columns_hash["single"].type + assert_equal :float, PostgresqlNumber.columns_hash["double"].type + end + + def test_values + @connection.execute("INSERT INTO postgresql_numbers (id, single, double) VALUES (1, 123.456, 123456.789)") + @connection.execute("INSERT INTO postgresql_numbers (id, single, double) VALUES (2, '-Infinity', 'Infinity')") + @connection.execute("INSERT INTO postgresql_numbers (id, single, double) VALUES (3, 123.456, 'NaN')") + + first, second, third = PostgresqlNumber.find(1, 2, 3) + + assert_equal 123.456, first.single + assert_equal 123456.789, first.double + assert_equal(-::Float::INFINITY, second.single) + assert_equal ::Float::INFINITY, second.double + assert_same ::Float::NAN, third.double + end + + def test_update + record = PostgresqlNumber.create! single: "123.456", double: "123456.789" + new_single = 789.012 + new_double = 789012.345 + record.single = new_single + record.double = new_double + record.save! + + record.reload + assert_equal new_single, record.single + assert_equal new_double, record.double + end +end diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb index 92c9a13ee3..e99f1e2867 100644 --- a/activerecord/test/cases/adapters/postgresql/schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb @@ -1,4 +1,5 @@ require "cases/helper" +require 'models/default' require 'support/schema_dumping_helper' class SchemaTest < ActiveRecord::TestCase @@ -88,7 +89,7 @@ class SchemaTest < ActiveRecord::TestCase end def test_schema_names - assert_equal ["public", "schema_1", "test_schema", "test_schema2"], @connection.schema_names + assert_equal ["public", "test_schema", "test_schema2"], @connection.schema_names end def test_create_schema @@ -460,3 +461,52 @@ class SchemaForeignKeyTest < ActiveRecord::TestCase @connection.execute "DROP SCHEMA IF EXISTS my_schema" end end + +class DefaultsUsingMultipleSchemasAndDomainTest < ActiveSupport::TestCase + setup do + @connection = ActiveRecord::Base.connection + @connection.execute "DROP SCHEMA IF EXISTS schema_1 CASCADE" + @connection.execute "CREATE SCHEMA schema_1" + @connection.execute "CREATE DOMAIN schema_1.text AS text" + @connection.execute "CREATE DOMAIN schema_1.varchar AS varchar" + @connection.execute "CREATE DOMAIN schema_1.bpchar AS bpchar" + + @old_search_path = @connection.schema_search_path + @connection.schema_search_path = "schema_1, pg_catalog" + @connection.create_table "defaults" do |t| + t.text "text_col", default: "some value" + t.string "string_col", default: "some value" + end + Default.reset_column_information + end + + teardown do + @connection.schema_search_path = @old_search_path + @connection.execute "DROP SCHEMA IF EXISTS schema_1 CASCADE" + Default.reset_column_information + end + + def test_text_defaults_in_new_schema_when_overriding_domain + assert_equal "some value", Default.new.text_col, "Default of text column was not correctly parsed" + end + + def test_string_defaults_in_new_schema_when_overriding_domain + assert_equal "some value", Default.new.string_col, "Default of string column was not correctly parsed" + end + + def test_bpchar_defaults_in_new_schema_when_overriding_domain + @connection.execute "ALTER TABLE defaults ADD bpchar_col bpchar DEFAULT 'some value'" + Default.reset_column_information + assert_equal "some value", Default.new.bpchar_col, "Default of bpchar column was not correctly parsed" + end + + def test_text_defaults_after_updating_column_default + @connection.execute "ALTER TABLE defaults ALTER COLUMN text_col SET DEFAULT 'some text'::schema_1.text" + assert_equal "some text", Default.new.text_col, "Default of text column was not correctly parsed after updating default using '::text' since postgreSQL will add parens to the default in db" + end + + def test_default_containing_quote_and_colons + @connection.execute "ALTER TABLE defaults ALTER COLUMN string_col SET DEFAULT 'foo''::bar'" + assert_equal "foo'::bar", Default.new.string_col + end +end diff --git a/activerecord/test/cases/adapters/postgresql/type_lookup_test.rb b/activerecord/test/cases/adapters/postgresql/type_lookup_test.rb index 23817198b1..c88259d274 100644 --- a/activerecord/test/cases/adapters/postgresql/type_lookup_test.rb +++ b/activerecord/test/cases/adapters/postgresql/type_lookup_test.rb @@ -12,4 +12,22 @@ class PostgresqlTypeLookupTest < ActiveRecord::TestCase assert_equal ';', box_array.delimiter assert_equal ',', int_array.delimiter end + + test "array types correctly respect registration of subtypes" do + int_array = @connection.type_map.lookup(1007, -1, "integer[]") + bigint_array = @connection.type_map.lookup(1016, -1, "bigint[]") + big_array = [123456789123456789] + + assert_raises(RangeError) { int_array.type_cast_from_user(big_array) } + assert_equal big_array, bigint_array.type_cast_from_user(big_array) + end + + test "range types correctly respect registration of subtypes" do + int_range = @connection.type_map.lookup(3904, -1, "int4range") + bigint_range = @connection.type_map.lookup(3926, -1, "int8range") + big_range = 0..123456789123456789 + + assert_raises(RangeError) { int_range.type_cast_for_database(big_range) } + assert_equal "[0,123456789123456789]", bigint_range.type_cast_for_database(big_range) + end end diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb index 5753da1173..fac21996ed 100644 --- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb +++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb @@ -14,6 +14,7 @@ end class PostgresqlUUIDTest < ActiveRecord::TestCase include PostgresqlUUIDHelper + include SchemaDumpingHelper class UUIDType < ActiveRecord::Base self.table_name = "uuid_data_type" @@ -106,6 +107,11 @@ class PostgresqlUUIDTest < ActiveRecord::TestCase assert_equal "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11", uuid.guid end end + + def test_schema_dump_with_shorthand + output = dump_table_schema "uuid_data_type" + assert_match %r{t.uuid "guid"}, output + end end class PostgresqlLargeKeysTest < ActiveRecord::TestCase diff --git a/activerecord/test/cases/adapters/postgresql/xml_test.rb b/activerecord/test/cases/adapters/postgresql/xml_test.rb index 4165dd5ac9..5aba118518 100644 --- a/activerecord/test/cases/adapters/postgresql/xml_test.rb +++ b/activerecord/test/cases/adapters/postgresql/xml_test.rb @@ -1,7 +1,9 @@ # encoding: utf-8 require 'cases/helper' +require 'support/schema_dumping_helper' class PostgresqlXMLTest < ActiveRecord::TestCase + include SchemaDumpingHelper class XmlDataType < ActiveRecord::Base self.table_name = 'xml_data_type' end @@ -45,4 +47,9 @@ class PostgresqlXMLTest < ActiveRecord::TestCase XmlDataType.update_all(payload: "<bar>baz</bar>") assert_equal "<bar>baz</bar>", data.reload.payload end + + def test_schema_dump_with_shorthand + output = dump_table_schema("xml_data_type") + assert_match %r{t.xml "payload"}, output + end end |