aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAshley Ellis Pierce <anellis12@gmail.com>2017-12-04 16:44:33 -0500
committerAshley Ellis Pierce <anellis12@gmail.com>2017-12-06 15:16:12 -0500
commit5ac4f4d2563e7f9c5ffaecce4be4b9e2c5b0c081 (patch)
tree17f6f1d7bf4c03ea46ca36d115f78cf2a8314054
parentb852ef2660dac36e348865b455fab7fbcc0d2a7f (diff)
downloadrails-5ac4f4d2563e7f9c5ffaecce4be4b9e2c5b0c081.tar.gz
rails-5ac4f4d2563e7f9c5ffaecce4be4b9e2c5b0c081.tar.bz2
rails-5ac4f4d2563e7f9c5ffaecce4be4b9e2c5b0c081.zip
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
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb6
-rw-r--r--activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb18
2 files changed, 23 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index daece2bffd..3197b522b3 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -395,10 +395,11 @@ module ActiveRecord
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 @@ module ActiveRecord
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}"
diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
index 1f057fe5c6..14f4997d5b 100644
--- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
@@ -360,6 +360,24 @@ module ActiveRecord
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