From 3628025c0dea3e08ea386700ec5eea27a26ce5d6 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 11 Dec 2014 22:57:28 +0900 Subject: Improve a dump of the primary key support. If it is not a default primary key, correctly dump the type and options. --- activerecord/CHANGELOG.md | 7 +++++++ .../connection_adapters/abstract/schema_dumper.rb | 6 ++++++ .../connection_adapters/abstract_mysql_adapter.rb | 12 ++++++++++++ .../connection_adapters/postgresql/column.rb | 4 ++++ .../connection_adapters/postgresql_adapter.rb | 15 +++++++++++++++ activerecord/lib/active_record/schema_dumper.rb | 11 ++++++----- activerecord/test/cases/primary_keys_test.rb | 19 +++++++++++++++++++ 7 files changed, 69 insertions(+), 5 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index d9966f0ad7..9515570260 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,10 @@ +* Improve a dump of the primary key support. If it is not a default primary key, + correctly dump the type and options. + + Fixes #14169, #16599. + + *Ryuta Kamizono* + * Provide `:touch` option to `save()` to accommodate saving without updating timestamps. diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb index 0834105079..42ea599a74 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper.rb @@ -12,6 +12,12 @@ module ActiveRecord spec end + def column_spec_for_primary_key(column) + return if column.type == :integer + spec = { id: column.type.inspect } + spec.merge!(prepare_column_options(column).delete_if { |key, _| [:name, :type].include?(key) }) + end + # This can be overridden on a Adapter level basis to support other # extended datatypes (Example: Adding an array option in the # PostgreSQLAdapter) diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index a3c124bae6..0f7af7de79 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -65,6 +65,18 @@ module ActiveRecord SchemaCreation.new self end + def column_spec_for_primary_key(column) + spec = {} + if column.extra == 'auto_increment' + return unless column.limit == 8 + spec[:id] = ':bigint' + else + spec[:id] = column.type.inspect + spec.merge!(prepare_column_options(column).delete_if { |key, _| [:name, :type, :null].include?(key) }) + end + spec + end + class Column < ConnectionAdapters::Column # :nodoc: attr_reader :collation, :strict, :extra diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb index 37e5c3859c..1458fbf496 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb @@ -15,6 +15,10 @@ module ActiveRecord @default_function = default_function end + + def serial? + default_function && default_function =~ /\Anextval\(.*\)\z/ + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 02cafc8079..6053e33a20 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -125,6 +125,21 @@ module ActiveRecord PostgreSQL::SchemaCreation.new self end + def column_spec_for_primary_key(column) + spec = {} + if column.serial? + return unless column.sql_type == 'bigint' + spec[:id] = ':bigserial' + elsif column.type == :uuid + spec[:id] = ':uuid' + spec[:default] = column.default_function.inspect + else + spec[:id] = column.type.inspect + spec.merge!(prepare_column_options(column).delete_if { |key, _| [:name, :type, :null].include?(key) }) + end + spec + end + # Adds +:array+ option to the default set provided by the # AbstractAdapter def prepare_column_options(column) # :nodoc: diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index 2a570e1323..da95920571 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -117,11 +117,12 @@ HEADER if pkcol if pk != 'id' tbl.print %Q(, primary_key: "#{pk}") - elsif pkcol.sql_type == 'bigint' - tbl.print ", id: :bigserial" - elsif pkcol.sql_type == 'uuid' - tbl.print ", id: :uuid" - tbl.print %Q(, default: #{pkcol.default_function.inspect}) + end + pkcolspec = @connection.column_spec_for_primary_key(pkcol) + if pkcolspec + pkcolspec.each do |key, value| + tbl.print ", #{key}: #{value}" + end end else tbl.print ", id: false" diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb index 2dfc53f132..751eccc015 100644 --- a/activerecord/test/cases/primary_keys_test.rb +++ b/activerecord/test/cases/primary_keys_test.rb @@ -1,4 +1,5 @@ require "cases/helper" +require 'support/schema_dumping_helper' require 'models/topic' require 'models/reply' require 'models/subscriber' @@ -196,6 +197,8 @@ class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase end class PrimaryKeyAnyTypeTest < ActiveRecord::TestCase + include SchemaDumpingHelper + self.use_transactional_fixtures = false class Barcode < ActiveRecord::Base @@ -217,6 +220,11 @@ class PrimaryKeyAnyTypeTest < ActiveRecord::TestCase assert_equal :string, column_type.type assert_equal 42, column_type.limit end + + test "schema dump primary key includes type and options" do + schema = dump_table_schema "barcodes" + assert_match %r{create_table "barcodes", primary_key: "code", id: :string, limit: 42}, schema + end end if current_adapter?(:MysqlAdapter, :Mysql2Adapter) @@ -235,6 +243,8 @@ end if current_adapter?(:PostgreSQLAdapter, :MysqlAdapter, :Mysql2Adapter) class PrimaryKeyBigSerialTest < ActiveRecord::TestCase + include SchemaDumpingHelper + self.use_transactional_fixtures = false class Widget < ActiveRecord::Base @@ -263,5 +273,14 @@ if current_adapter?(:PostgreSQLAdapter, :MysqlAdapter, :Mysql2Adapter) widget = Widget.create! assert_not_nil widget.id end + + 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}, schema + else + assert_match %r{create_table "widgets", id: :bigint}, schema + end + end end end -- cgit v1.2.3