diff options
Diffstat (limited to 'activerecord/test/cases')
15 files changed, 299 insertions, 69 deletions
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index 8bcecf2ed3..2f0e8d866d 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -182,6 +182,14 @@ module ActiveRecord assert_not_nil error.cause end + def test_not_null_violations_are_translated_to_specific_exception + error = assert_raises(ActiveRecord::NotNullViolation) do + Post.create + end + + assert_not_nil error.cause + end + unless current_adapter?(:SQLite3Adapter) def test_foreign_key_violations_are_translated_to_specific_exception error = assert_raises(ActiveRecord::InvalidForeignKey) do diff --git a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb index a70eb5a094..2a528b2cb1 100644 --- a/activerecord/test/cases/adapters/mysql2/active_schema_test.rb +++ b/activerecord/test/cases/adapters/mysql2/active_schema_test.rb @@ -28,12 +28,15 @@ class Mysql2ActiveSchemaTest < ActiveRecord::Mysql2TestCase expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(15)) " assert_equal expected, add_index(:people, [:last_name, :first_name], length: 15) + assert_equal expected, add_index(:people, ["last_name", "first_name"], length: 15) expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`) " assert_equal expected, add_index(:people, [:last_name, :first_name], length: { last_name: 15 }) + assert_equal expected, add_index(:people, ["last_name", "first_name"], length: { last_name: 15 }) expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(10)) " assert_equal expected, add_index(:people, [:last_name, :first_name], length: { last_name: 15, first_name: 10 }) + assert_equal expected, add_index(:people, ["last_name", :first_name], length: { last_name: 15, "first_name" => 10 }) %w(SPATIAL FULLTEXT UNIQUE).each do |type| expected = "CREATE #{type} INDEX `index_people_on_last_name` ON `people` (`last_name`) " diff --git a/activerecord/test/cases/adapters/mysql2/legacy_migration_test.rb b/activerecord/test/cases/adapters/mysql2/legacy_migration_test.rb new file mode 100644 index 0000000000..5d3125c2be --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/legacy_migration_test.rb @@ -0,0 +1,60 @@ +require "cases/helper" + +class MysqlLegacyMigrationTest < ActiveRecord::Mysql2TestCase + self.use_transactional_tests = false + + class GenerateTableWithoutBigint < ActiveRecord::Migration[5.0] + def change + create_table :legacy_integer_pk do |table| + table.string :foo + end + + create_table :override_pk, id: :bigint do |table| + table.string :bar + end + end + end + + def setup + super + @connection = ActiveRecord::Base.connection + + @migration_verbose_old = ActiveRecord::Migration.verbose + ActiveRecord::Migration.verbose = false + + migrations = [GenerateTableWithoutBigint.new(nil, 1)] + + ActiveRecord::Migrator.new(:up, migrations).migrate + end + + def teardown + ActiveRecord::Migration.verbose = @migration_verbose_old + @connection.drop_table("legacy_integer_pk") + @connection.drop_table("override_pk") + ActiveRecord::SchemaMigration.delete_all rescue nil + super + end + + def test_create_table_uses_integer_as_pkey_by_default + col = column(:legacy_integer_pk, :id) + assert_equal "int(11)", sql_type_for(col) + assert col.auto_increment? + end + + def test_create_tables_respects_pk_column_type_override + col = column(:override_pk, :id) + assert_equal "bigint(20)", sql_type_for(col) + end + + private + + def column(table_name, column_name) + ActiveRecord::Base.connection + .columns(table_name.to_s) + .detect { |c| c.name == column_name.to_s } + end + + def sql_type_for(col) + col && col.sql_type + end +end diff --git a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb index 69336eb906..aab3dcb724 100644 --- a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb +++ b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb @@ -65,6 +65,19 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase @conn.columns_for_distinct("posts.id", [order]) end + def test_errors_for_bigint_fks_on_integer_pk_table + # table old_cars has primary key of integer + + error = assert_raises(ActiveRecord::MismatchedForeignKey) do + @conn.add_reference :engines, :old_car + @conn.add_foreign_key :engines, :old_cars + end + + assert_match "Column `old_car_id` on table `engines` has a type of `bigint(20)`", error.message + assert_not_nil error.cause + @conn.exec_query("ALTER TABLE engines DROP COLUMN old_car_id") + end + private def with_example_table(definition = "id int auto_increment primary key, number int, data varchar(255)", &block) diff --git a/activerecord/test/cases/adapters/postgresql/active_schema_test.rb b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb index d3c65f3d94..b787de8453 100644 --- a/activerecord/test/cases/adapters/postgresql/active_schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb @@ -39,6 +39,10 @@ class PostgresqlActiveSchemaTest < ActiveRecord::PostgreSQLTestCase expected = %(CREATE INDEX CONCURRENTLY "index_people_on_last_name" ON "people" ("last_name")) assert_equal expected, add_index(:people, :last_name, algorithm: :concurrently) + expected = %(CREATE INDEX "index_people_on_last_name_and_first_name" ON "people" ("last_name" DESC, "first_name" ASC)) + assert_equal expected, add_index(:people, [:last_name, :first_name], order: { last_name: :desc, first_name: :asc }) + assert_equal expected, add_index(:people, ["last_name", :first_name], order: { last_name: :desc, "first_name" => :asc }) + %w(gin gist hash btree).each do |type| expected = %(CREATE INDEX "index_people_on_last_name" ON "people" USING #{type} ("last_name")) assert_equal expected, add_index(:people, :last_name, using: type) diff --git a/activerecord/test/cases/adapters/postgresql/legacy_migration_test.rb b/activerecord/test/cases/adapters/postgresql/legacy_migration_test.rb new file mode 100644 index 0000000000..082fe95053 --- /dev/null +++ b/activerecord/test/cases/adapters/postgresql/legacy_migration_test.rb @@ -0,0 +1,54 @@ +require "cases/helper" + +class PostgresqlLegacyMigrationTest < ActiveRecord::PostgreSQLTestCase + class GenerateTableWithoutBigserial < ActiveRecord::Migration[5.0] + def change + create_table :legacy_integer_pk do |table| + table.string :foo + end + + create_table :override_pk, id: :bigint do |table| + table.string :bar + end + end + end + + def setup + super + + @migration_verbose_old = ActiveRecord::Migration.verbose + ActiveRecord::Migration.verbose = false + + migrations = [GenerateTableWithoutBigserial.new(nil, 1)] + ActiveRecord::Migrator.new(:up, migrations).migrate + end + + def teardown + ActiveRecord::Migration.verbose = @migration_verbose_old + + super + end + + def test_create_table_uses_serial_as_pkey_by_default + col = column(:legacy_integer_pk, :id) + assert_equal "integer", sql_type_for(col) + assert col.serial? + end + + def test_create_tables_respects_pk_column_type_override + col = column(:override_pk, :id) + assert_equal "bigint", sql_type_for(col) + end + + private + + def column(table_name, column_name) + ActiveRecord::Base.connection. + columns(table_name.to_s). + detect { |c| c.name == column_name.to_s } + end + + def sql_type_for(col) + col && col.sql_type + end +end diff --git a/activerecord/test/cases/adapters/sqlite3/legacy_migration_test.rb b/activerecord/test/cases/adapters/sqlite3/legacy_migration_test.rb new file mode 100644 index 0000000000..fcca8d66b5 --- /dev/null +++ b/activerecord/test/cases/adapters/sqlite3/legacy_migration_test.rb @@ -0,0 +1,59 @@ +require "cases/helper" + +class SqliteLegacyMigrationTest < ActiveRecord::SQLite3TestCase + self.use_transactional_tests = false + + class GenerateTableWithoutBigint < ActiveRecord::Migration[5.0] + def change + create_table :legacy_integer_pk do |table| + table.string :foo + end + + create_table :override_pk, id: :bigint do |table| + table.string :bar + end + end + end + + def setup + super + @connection = ActiveRecord::Base.connection + + @migration_verbose_old = ActiveRecord::Migration.verbose + ActiveRecord::Migration.verbose = false + + migrations = [GenerateTableWithoutBigint.new(nil, 1)] + + ActiveRecord::Migrator.new(:up, migrations).migrate + end + + def teardown + ActiveRecord::Migration.verbose = @migration_verbose_old + @connection.drop_table("legacy_integer_pk") + @connection.drop_table("override_pk") + ActiveRecord::SchemaMigration.delete_all rescue nil + super + end + + def test_create_table_uses_integer_as_pkey_by_default + col = column(:legacy_integer_pk, :id) + assert_equal "INTEGER", sql_type_for(col) + assert primary_key?(:legacy_integer_pk, "id"), "id is not primary key" + end + + private + + def column(table_name, column_name) + ActiveRecord::Base.connection + .columns(table_name.to_s) + .detect { |c| c.name == column_name.to_s } + end + + def sql_type_for(col) + col && col.sql_type + end + + def primary_key?(table_name, column) + ActiveRecord::Base.connection.execute("PRAGMA table_info(#{table_name})").find { |col| col["name"] == column }["pk"] == 1 + end +end diff --git a/activerecord/test/cases/comment_test.rb b/activerecord/test/cases/comment_test.rb index 262ad319be..a625299e8d 100644 --- a/activerecord/test/cases/comment_test.rb +++ b/activerecord/test/cases/comment_test.rb @@ -2,7 +2,6 @@ require "cases/helper" require "support/schema_dumping_helper" if ActiveRecord::Base.connection.supports_comments? - class CommentTest < ActiveRecord::TestCase include SchemaDumpingHelper @@ -102,6 +101,7 @@ if ActiveRecord::Base.connection.supports_comments? # Do all the stuff from other tests @connection.add_column :commenteds, :rating, :integer, comment: "I am running out of imagination" @connection.change_column :commenteds, :content, :string, comment: "Whoa, content describes itself!" + @connection.change_column :commenteds, :content, :string @connection.change_column :commenteds, :obvious, :string, comment: nil @connection.add_index :commenteds, :obvious, name: "idx_obvious", comment: "We need to see obvious comments" @@ -135,5 +135,4 @@ if ActiveRecord::Base.connection.supports_comments? assert_no_match %r[t\.string\s+"absent_comment", comment:\n], output end end - end diff --git a/activerecord/test/cases/defaults_test.rb b/activerecord/test/cases/defaults_test.rb index fcaff38f82..6532efcf22 100644 --- a/activerecord/test/cases/defaults_test.rb +++ b/activerecord/test/cases/defaults_test.rb @@ -169,7 +169,7 @@ if current_adapter?(:Mysql2Adapter) assert_nil record.non_null_text assert_nil record.non_null_blob - assert_raises(ActiveRecord::StatementInvalid) { klass.create } + assert_raises(ActiveRecord::NotNullViolation) { klass.create } end end end diff --git a/activerecord/test/cases/migration/change_schema_test.rb b/activerecord/test/cases/migration/change_schema_test.rb index bdb90eaa74..03f9c4a9ed 100644 --- a/activerecord/test/cases/migration/change_schema_test.rb +++ b/activerecord/test/cases/migration/change_schema_test.rb @@ -43,7 +43,7 @@ module ActiveRecord t.column :foo, :string, null: false end - assert_raises(ActiveRecord::StatementInvalid) do + assert_raises(ActiveRecord::NotNullViolation) do connection.execute "insert into testings (foo) values (NULL)" end end @@ -233,7 +233,7 @@ module ActiveRecord end connection.add_column :testings, :bar, :string, null: false - assert_raise(ActiveRecord::StatementInvalid) do + assert_raise(ActiveRecord::NotNullViolation) do connection.execute "insert into testings (foo, bar) values ('hello', NULL)" end end @@ -244,12 +244,16 @@ module ActiveRecord t.column :foo, :string end - con = connection - connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')" - assert_nothing_raised { connection.add_column :testings, :bar, :string, null: false, default: "default" } + quoted_id = connection.quote_column_name("id") + quoted_foo = connection.quote_column_name("foo") + quoted_bar = connection.quote_column_name("bar") + connection.execute("insert into testings (#{quoted_id}, #{quoted_foo}) values (1, 'hello')") + assert_nothing_raised do + connection.add_column :testings, :bar, :string, null: false, default: "default" + end - assert_raises(ActiveRecord::StatementInvalid) do - connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) values (2, 'hello', NULL)" + assert_raises(ActiveRecord::NotNullViolation) do + connection.execute("insert into testings (#{quoted_id}, #{quoted_foo}, #{quoted_bar}) values (2, 'hello', NULL)") end end diff --git a/activerecord/test/cases/migration/change_table_test.rb b/activerecord/test/cases/migration/change_table_test.rb index ec817a579b..8a4242cf1d 100644 --- a/activerecord/test/cases/migration/change_table_test.rb +++ b/activerecord/test/cases/migration/change_table_test.rb @@ -101,7 +101,12 @@ module ActiveRecord def test_primary_key_creates_primary_key_column with_change_table do |t| - @connection.expect :add_column, nil, [:delete_me, :id, :primary_key, primary_key: true, first: true] + if current_adapter?(:Mysql2Adapter) + @connection.expect :add_column, nil, [:delete_me, :id, :primary_key, { first: true, auto_increment: true, limit: 8, primary_key: true }] + else + @connection.expect :add_column, nil, [:delete_me, :id, :primary_key, primary_key: true, first: true] + end + t.primary_key :id, first: true end end diff --git a/activerecord/test/cases/migration/foreign_key_test.rb b/activerecord/test/cases/migration/foreign_key_test.rb index cab2069754..1921a4d7c2 100644 --- a/activerecord/test/cases/migration/foreign_key_test.rb +++ b/activerecord/test/cases/migration/foreign_key_test.rb @@ -76,7 +76,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys? end def test_add_foreign_key_with_non_standard_primary_key - with_example_table @connection, "space_shuttles", "pk integer PRIMARY KEY" do + with_example_table @connection, "space_shuttles", "pk BIGINT PRIMARY KEY" do @connection.add_foreign_key(:astronauts, :space_shuttles, column: "rocket_id", primary_key: "pk", name: "custom_pk") @@ -229,7 +229,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys? create_table("cities") { |t| } create_table("houses") do |t| - t.column :city_id, :integer + t.column :city_id, :bigint end add_foreign_key :houses, :cities, column: "city_id" @@ -261,7 +261,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys? create_table(:schools) create_table(:classes) do |t| - t.column :school_id, :integer + t.column :school_id, :bigint end add_foreign_key :classes, :schools end diff --git a/activerecord/test/cases/migration/references_foreign_key_test.rb b/activerecord/test/cases/migration/references_foreign_key_test.rb index 528811db49..4957ab8b3d 100644 --- a/activerecord/test/cases/migration/references_foreign_key_test.rb +++ b/activerecord/test/cases/migration/references_foreign_key_test.rb @@ -42,7 +42,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys? test "options hash can be passed" do @connection.change_table :testing_parents do |t| - t.integer :other_id + t.bigint :other_id t.index :other_id, unique: true end @connection.create_table :testings do |t| @@ -92,7 +92,7 @@ if ActiveRecord::Base.connection.supports_foreign_keys? test "foreign keys accept options when changing the table" do @connection.change_table :testing_parents do |t| - t.integer :other_id + t.bigint :other_id t.index :other_id, unique: true end @connection.create_table :testings @@ -177,8 +177,8 @@ if ActiveRecord::Base.connection.supports_foreign_keys? test "multiple foreign keys can be added to the same table" do @connection.create_table :testings do |t| - t.integer :col_1 - t.integer :col_2 + t.bigint :col_1 + t.bigint :col_2 t.foreign_key :testing_parents, column: :col_1 t.foreign_key :testing_parents, column: :col_2 diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb index eaaf50d14f..b434f4a6b6 100644 --- a/activerecord/test/cases/primary_keys_test.rb +++ b/activerecord/test/cases/primary_keys_test.rb @@ -216,6 +216,43 @@ class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase end end +class PrimaryKeyWithAutoIncrementTest < ActiveRecord::TestCase + self.use_transactional_tests = false + + class AutoIncrement < ActiveRecord::Base + end + + def setup + @connection = ActiveRecord::Base.connection + end + + def teardown + @connection.drop_table(:auto_increments, if_exists: true) + end + + def test_primary_key_with_auto_increment + @connection.create_table(:auto_increments, id: :integer, auto_increment: true, force: true) + assert_auto_incremented + end + + def test_primary_key_with_auto_increment_and_bigint + @connection.create_table(:auto_increments, id: :bigint, auto_increment: true, force: true) + assert_auto_incremented + end + + private + def assert_auto_incremented + record1 = AutoIncrement.create! + assert_not_nil record1.id + + record1.destroy + + record2 = AutoIncrement.create! + assert_not_nil record2.id + assert_operator record2.id, :>, record1.id + end +end + class PrimaryKeyAnyTypeTest < ActiveRecord::TestCase include SchemaDumpingHelper @@ -289,85 +326,69 @@ class CompositePrimaryKeyTest < ActiveRecord::TestCase end if current_adapter?(:Mysql2Adapter) - class PrimaryKeyBigintNilDefaultTest < ActiveRecord::TestCase + class PrimaryKeyIntegerNilDefaultTest < ActiveRecord::TestCase include SchemaDumpingHelper self.use_transactional_tests = false def setup @connection = ActiveRecord::Base.connection - @connection.create_table(:bigint_defaults, id: :bigint, default: nil, force: true) + @connection.create_table(:int_defaults, id: :integer, default: nil, force: true) end def teardown - @connection.drop_table :bigint_defaults, if_exists: true + @connection.drop_table :int_defaults, if_exists: true end - test "primary key with bigint allows default override via nil" do - column = @connection.columns(:bigint_defaults).find { |c| c.name == "id" } - assert column.bigint? + test "primary key with integer allows default override via nil" do + column = @connection.columns(:int_defaults).find { |c| c.name == "id" } + assert_equal :integer, column.type assert_not column.auto_increment? end - test "schema dump primary key with bigint default nil" do - schema = dump_table_schema "bigint_defaults" - assert_match %r{create_table "bigint_defaults", id: :bigint, default: nil}, schema + test "schema dump primary key with int default nil" do + schema = dump_table_schema "int_defaults" + assert_match %r{create_table "int_defaults", id: :integer, default: nil}, schema end end end -if current_adapter?(:PostgreSQLAdapter, :Mysql2Adapter) - class PrimaryKeyBigSerialTest < ActiveRecord::TestCase - include SchemaDumpingHelper +class PrimaryKeyIntegerTest < ActiveRecord::TestCase + include SchemaDumpingHelper - self.use_transactional_tests = false + self.use_transactional_tests = false - class Widget < ActiveRecord::Base - end + class Widget < ActiveRecord::Base + end - setup do - @connection = ActiveRecord::Base.connection - if current_adapter?(:PostgreSQLAdapter) - @connection.create_table(:widgets, id: :bigserial, force: true) - else - @connection.create_table(:widgets, id: :bigint, force: true) - end - end + setup do + @connection = ActiveRecord::Base.connection + @connection.create_table(:widgets, force: true) + end - teardown do - @connection.drop_table :widgets, if_exists: true - Widget.reset_column_information - end + teardown do + @connection.drop_table :widgets, if_exists: true + Widget.reset_column_information + end - test "primary key column type with bigserial" do - column_type = Widget.type_for_attribute(Widget.primary_key) - assert_equal :integer, column_type.type - assert_equal 8, column_type.limit + if current_adapter?(:PostgreSQLAdapter, :Mysql2Adapter) + test "schema dump primary key with bigserial" do + schema = dump_table_schema "widgets" + assert_match %r{create_table "widgets", force: :cascade}, schema end + end - test "primary key with bigserial are automatically numbered" do - widget = Widget.create! - assert_not_nil widget.id - end + test "primary key column type" do + column_type = Widget.type_for_attribute(Widget.primary_key) + assert_equal :integer, column_type.type - test "schema dump primary key with bigserial" do - schema = dump_table_schema "widgets" - if current_adapter?(:PostgreSQLAdapter) - assert_match %r{create_table "widgets", id: :bigserial, force: :cascade}, schema - else - assert_match %r{create_table "widgets", id: :bigint, force: :cascade}, schema - end + if current_adapter?(:PostgreSQLAdapter, :Mysql2Adapter) + assert_equal 8, column_type.limit end if current_adapter?(:Mysql2Adapter) - test "primary key column type with options" do - @connection.create_table(:widgets, id: :primary_key, limit: 8, unsigned: true, force: true) - column = @connection.columns(:widgets).find { |c| c.name == "id" } - assert column.auto_increment? - assert_equal :integer, column.type - assert_equal 8, column.limit - assert column.unsigned? - end + column = @connection.columns(:widgets).find { |c| c.name == "id" } + assert column.auto_increment? end end end diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index 007f976f2e..97096e31e7 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -346,7 +346,7 @@ class SchemaDumperTest < ActiveRecord::TestCase create_table("dogs") do |t| t.column :name, :string - t.column :owner_id, :integer + t.column :owner_id, :bigint t.index [:name] t.foreign_key :dog_owners, column: "owner_id" if supports_foreign_keys? end |