Skip to content

Commit

Permalink
Improve a dump of the primary key support.
Browse files Browse the repository at this point in the history
If it is not a default primary key, correctly dump the type and options.
  • Loading branch information
kamipo committed Dec 29, 2014
1 parent 73fe108 commit 3628025
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 5 deletions.
7 changes: 7 additions & 0 deletions activerecord/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ def column_spec(column)
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ def schema_creation
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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ def initialize(name, default, cast_type, sql_type = nil, null = true, default_fu

@default_function = default_function
end

def serial?
default_function && default_function =~ /\Anextval\(.*\)\z/
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,21 @@ def schema_creation # :nodoc:
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:
Expand Down
11 changes: 6 additions & 5 deletions activerecord/lib/active_record/schema_dumper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,12 @@ def table(table, stream)
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"
Expand Down
19 changes: 19 additions & 0 deletions activerecord/test/cases/primary_keys_test.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "cases/helper"
require 'support/schema_dumping_helper'
require 'models/topic'
require 'models/reply'
require 'models/subscriber'
Expand Down Expand Up @@ -196,6 +197,8 @@ def test_set_primary_key_with_no_connection
end

class PrimaryKeyAnyTypeTest < ActiveRecord::TestCase
include SchemaDumpingHelper

self.use_transactional_fixtures = false

class Barcode < ActiveRecord::Base
Expand All @@ -217,6 +220,11 @@ def test_any_type_primary_key
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)
Expand All @@ -235,6 +243,8 @@ def test_primary_key_method_with_ansi_quotes

if current_adapter?(:PostgreSQLAdapter, :MysqlAdapter, :Mysql2Adapter)
class PrimaryKeyBigSerialTest < ActiveRecord::TestCase
include SchemaDumpingHelper

self.use_transactional_fixtures = false

class Widget < ActiveRecord::Base
Expand Down Expand Up @@ -263,5 +273,14 @@ class Widget < ActiveRecord::Base
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

0 comments on commit 3628025

Please sign in to comment.