提交 5ac4f4d2 编写于 作者: A Ashley Ellis Pierce

Fix sqlite migrations with custom primary keys

Previously, if a record was created with a custom primary key, that
table could not be migrated using sqlite. While attempting to copy the
table, the type of the primary key was ignored.

Once that was corrected, copying the indexes would fail because custom
primary keys are autoindexed by sqlite by default.

To correct that, this skips copying the index if the index name begins
with "sqlite_". This is a reserved word that indicates that the
index is an internal schema object. SQLite prohibits applications from
creating objects whose names begin with "sqlite_", so this string should
be safe to use as a check.
ref https://www.sqlite.org/fileformat2.html#intschema
上级 b852ef26
......@@ -395,10 +395,11 @@ def move_table(from, to, options = {}, &block)
def copy_table(from, to, options = {})
from_primary_key = primary_key(from)
from_primary_key_column = columns(from).select { |column| column.name == from_primary_key }.first
options[:id] = false
create_table(to, options) do |definition|
@definition = definition
@definition.primary_key(from_primary_key) if from_primary_key.present?
@definition.primary_key(from_primary_key, from_primary_key_column.type) if from_primary_key.present?
columns(from).each do |column|
column_name = options[:rename] ?
(options[:rename][column.name] ||
......@@ -422,6 +423,9 @@ def copy_table(from, to, options = {})
def copy_table_indexes(from, to, rename = {})
indexes(from).each do |index|
name = index.name
# indexes sqlite creates for internal use start with `sqlite_` and
# don't need to be copied
next if name.starts_with?("sqlite_")
if to == "a#{from}"
name = "t#{name}"
elsif from == "a#{to}"
......
......@@ -360,6 +360,24 @@ def test_no_primary_key
end
end
class Barcode < ActiveRecord::Base
end
def test_existing_records_have_custom_primary_key
connection = Barcode.connection
connection.create_table(:barcodes, primary_key: "code", id: :string, limit: 42, force: true) do |t|
t.text :other_attr
end
code = "214fe0c2-dd47-46df-b53b-66090b3c1d40"
Barcode.create! code: code, other_attr: "xxx"
connection.change_table "barcodes" do |t|
connection.remove_column("barcodes", "other_attr")
end
assert_equal code, Barcode.first.id
end
def test_supports_extensions
assert_not @conn.supports_extensions?, "does not support extensions"
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册