Skip to content

Commit

Permalink
Clear schema cache when a table is created/dropped/renamed
Browse files Browse the repository at this point in the history
Otherwise `Model.table_exists?` returns the staled cache result.
  • Loading branch information
kamipo committed Jun 13, 2019
1 parent 0ad238f commit 5cab344
Show file tree
Hide file tree
Showing 6 changed files with 18 additions and 4 deletions.
Expand Up @@ -310,6 +310,8 @@ def create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **o

if force
drop_table(table_name, force: force, if_exists: true)
else
schema_cache.clear_data_source_cache!(table_name.to_s)
end

result = execute schema_creation.accept td
Expand Down Expand Up @@ -499,6 +501,7 @@ def rename_table(table_name, new_name)
# it can be helpful to provide these in a migration's +change+ method so it can be reverted.
# In that case, +options+ and the block will be used by #create_table.
def drop_table(table_name, options = {})
schema_cache.clear_data_source_cache!(table_name.to_s)
execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}"
end

Expand Down
Expand Up @@ -289,6 +289,8 @@ def change_table_comment(table_name, comment_or_changes) # :nodoc:
# Example:
# rename_table('octopuses', 'octopi')
def rename_table(table_name, new_name)
schema_cache.clear_data_source_cache!(table_name.to_s)
schema_cache.clear_data_source_cache!(new_name.to_s)
execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
rename_table_indexes(table_name, new_name)
end
Expand All @@ -309,6 +311,7 @@ def rename_table(table_name, new_name)
# it can be helpful to provide these in a migration's +change+ method so it can be reverted.
# In that case, +options+ and the block will be used by create_table.
def drop_table(table_name, options = {})
schema_cache.clear_data_source_cache!(table_name.to_s)
execute "DROP#{' TEMPORARY' if options[:temporary]} TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
end

Expand Down
Expand Up @@ -55,6 +55,7 @@ def drop_database(name) #:nodoc:
end

def drop_table(table_name, options = {}) # :nodoc:
schema_cache.clear_data_source_cache!(table_name.to_s)
execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
end

Expand Down Expand Up @@ -376,6 +377,8 @@ def primary_keys(table_name) # :nodoc:
# rename_table('octopuses', 'octopi')
def rename_table(table_name, new_name)
clear_cache!
schema_cache.clear_data_source_cache!(table_name.to_s)
schema_cache.clear_data_source_cache!(new_name.to_s)
execute "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
pk, seq = pk_and_sequence_for(new_name)
if pk
Expand Down
Expand Up @@ -218,6 +218,8 @@ def remove_index(table_name, options = {}) #:nodoc:
# Example:
# rename_table('octopuses', 'octopi')
def rename_table(table_name, new_name)
schema_cache.clear_data_source_cache!(table_name.to_s)
schema_cache.clear_data_source_cache!(new_name.to_s)
exec_query "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
rename_table_indexes(table_name, new_name)
end
Expand Down
5 changes: 4 additions & 1 deletion activerecord/test/cases/migration_test.rb
Expand Up @@ -190,6 +190,7 @@ def test_add_table_with_decimals

assert_not_predicate BigNumber, :table_exists?
GiveMeBigNumbers.up
assert_predicate BigNumber, :table_exists?
BigNumber.reset_column_information

assert BigNumber.create(
Expand Down Expand Up @@ -482,6 +483,7 @@ def test_rename_table_with_prefix_and_suffix
Thing.reset_table_name
Thing.reset_sequence_name
WeNeedThings.up
assert_predicate Thing, :table_exists?
Thing.reset_column_information

assert Thing.create("content" => "hello world")
Expand All @@ -502,8 +504,9 @@ def test_add_drop_table_with_prefix_and_suffix
ActiveRecord::Base.table_name_suffix = "_suffix"
Reminder.reset_table_name
Reminder.reset_sequence_name
Reminder.reset_column_information
WeNeedReminders.up
assert_predicate Reminder, :table_exists?
Reminder.reset_column_information
assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
assert_equal "hello world", Reminder.first.content

Expand Down
6 changes: 3 additions & 3 deletions activerecord/test/cases/migrator_test.rb
Expand Up @@ -429,10 +429,10 @@ def test_migrator_db_has_no_schema_migrations_table
_, migrator = migrator_class(3)
migrator = migrator.new("valid")

ActiveRecord::Base.connection.drop_table "schema_migrations", if_exists: true
assert_not ActiveRecord::Base.connection.table_exists?("schema_migrations")
ActiveRecord::SchemaMigration.drop_table
assert_not_predicate ActiveRecord::SchemaMigration, :table_exists?
migrator.migrate(1)
assert ActiveRecord::Base.connection.table_exists?("schema_migrations")
assert_predicate ActiveRecord::SchemaMigration, :table_exists?
end

def test_migrator_forward
Expand Down

0 comments on commit 5cab344

Please sign in to comment.