From 5ac4f4d2563e7f9c5ffaecce4be4b9e2c5b0c081 Mon Sep 17 00:00:00 2001 From: Ashley Ellis Pierce Date: Mon, 4 Dec 2017 16:44:33 -0500 Subject: 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 --- .../lib/active_record/connection_adapters/sqlite3_adapter.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'activerecord/lib') 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}" -- cgit v1.2.3