From 65872e846e491e923d38877d374936c9c7e81db2 Mon Sep 17 00:00:00 2001 From: Jim Jowdy Date: Tue, 26 Jan 2021 19:33:55 -0800 Subject: [PATCH] Fix retrieve_indexes_from_table when indexes is empty and base table does not exist. Some tables may have a table_name_prefix but no indexes. Previous versions of the code would strip the prefix and look for indexes on the resulting table which likely would not exist. This causes DB errors, at least in MySQL. So now check if the new table exists first before trying to show its indexes. --- lib/annotate/annotate_models.rb | 6 +++++- spec/lib/annotate/annotate_models_spec.rb | 23 +++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/annotate/annotate_models.rb b/lib/annotate/annotate_models.rb index be2a30cb..48810299 100644 --- a/lib/annotate/annotate_models.rb +++ b/lib/annotate/annotate_models.rb @@ -124,7 +124,11 @@ def retrieve_indexes_from_table(klass) # Try to search the table without prefix table_name_without_prefix = table_name.to_s.sub(klass.table_name_prefix, '') - klass.connection.indexes(table_name_without_prefix) + if klass.connection.table_exists?(table_name_without_prefix) + klass.connection.indexes(table_name_without_prefix) + else + [] + end end # Use the column information in an ActiveRecord class diff --git a/spec/lib/annotate/annotate_models_spec.rb b/spec/lib/annotate/annotate_models_spec.rb index 59cd8eb1..33b22017 100644 --- a/spec/lib/annotate/annotate_models_spec.rb +++ b/spec/lib/annotate/annotate_models_spec.rb @@ -53,7 +53,8 @@ def mock_connection(indexes = [], foreign_keys = [], check_constraints = []) foreign_keys: foreign_keys, check_constraints: check_constraints, supports_foreign_keys?: true, - supports_check_constraints?: true) + supports_check_constraints?: true, + table_exists?: true) end # rubocop:disable Metrics/ParameterLists @@ -538,7 +539,7 @@ def mock_column(name, type, options = {}) end end - context 'when one of indexes includes orderd index key' do + context 'when one of indexes includes ordered index key' do let :columns do [ mock_column("id", :integer), @@ -694,6 +695,24 @@ def mock_column(name, type, options = {}) it 'returns schema info without index information' do is_expected.to eq expected_result end + + # rubocop:disable RSpec/NestedGroups + context 'when the unprefixed table name does not exist' do + let :klass do + mock_class(:users, primary_key, columns, indexes, foreign_keys).tap do |mock_klass| + allow(mock_klass).to receive(:table_name_prefix).and_return('my_prefix_') + allow(mock_klass.connection).to receive(:table_exists?).with('users').and_return(false) + allow(mock_klass.connection).to receive(:indexes).with('users').and_raise('error fetching indexes on nonexistent table') + end + end + + it 'returns schema info without index information' do + is_expected.to eq expected_result + expect(klass).to have_received(:table_name_prefix).at_least(:once) + expect(klass.connection).to have_received(:table_exists?).with('users') + end + end + # rubocop:enable RSpec/NestedGroups end end