summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/database/postgresql_adapter/type_map_cache_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/lib/gitlab/database/postgresql_adapter/type_map_cache_spec.rb')
-rw-r--r--spec/lib/gitlab/database/postgresql_adapter/type_map_cache_spec.rb68
1 files changed, 68 insertions, 0 deletions
diff --git a/spec/lib/gitlab/database/postgresql_adapter/type_map_cache_spec.rb b/spec/lib/gitlab/database/postgresql_adapter/type_map_cache_spec.rb
new file mode 100644
index 00000000000..e9c512f94bb
--- /dev/null
+++ b/spec/lib/gitlab/database/postgresql_adapter/type_map_cache_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::PostgresqlAdapter::TypeMapCache do
+ let(:db_config) { ActiveRecord::Base.configurations.configs_for(env_name: 'test', name: 'primary').configuration_hash }
+ let(:adapter_class) { ActiveRecord::ConnectionAdapters::PostgreSQLAdapter }
+
+ before do
+ adapter_class.type_map_cache.clear
+ end
+
+ describe '#initialize_type_map' do
+ it 'caches loading of types in memory' do
+ recorder_without_cache = ActiveRecord::QueryRecorder.new(skip_schema_queries: false) { initialize_connection.disconnect! }
+ expect(recorder_without_cache.log).to include(a_string_matching(/FROM pg_type/)).twice
+
+ recorder_with_cache = ActiveRecord::QueryRecorder.new(skip_schema_queries: false) { initialize_connection.disconnect! }
+
+ expect(recorder_with_cache.count).to be < recorder_without_cache.count
+
+ # There's still one pg_type query left here because `#add_pg_decoders` executes another pg_type query
+ # in https://github.com/rails/rails/blob/v6.1.3.2/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L912.
+ # This query is much cheaper because it only returns very few records.
+ expect(recorder_with_cache.log).to include(a_string_matching(/FROM pg_type/)).once
+ end
+
+ it 'only reuses the cache if the connection parameters are exactly the same' do
+ initialize_connection.disconnect!
+
+ other_config = db_config.dup
+ other_config[:connect_timeout] = db_config[:connect_timeout].to_i + 10
+
+ recorder = ActiveRecord::QueryRecorder.new(skip_schema_queries: false) { initialize_connection(other_config).disconnect! }
+
+ expect(recorder.log).to include(a_string_matching(/FROM pg_type/)).twice
+ end
+ end
+
+ describe '#reload_type_map' do
+ it 'clears the cache and executes the type map query again' do
+ initialize_connection.disconnect!
+
+ connection = initialize_connection
+ recorder = ActiveRecord::QueryRecorder.new(skip_schema_queries: false) { connection.reload_type_map }
+
+ expect(recorder.log).to include(a_string_matching(/FROM pg_type/)).once
+ end
+ end
+
+ # Based on https://github.com/rails/rails/blob/v6.1.3.2/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L36-L41
+ def initialize_connection(config = db_config)
+ conn_params = config.symbolize_keys.compact
+
+ conn_params[:user] = conn_params.delete(:username) if conn_params[:username]
+ conn_params[:dbname] = conn_params.delete(:database) if conn_params[:database]
+
+ valid_conn_param_keys = PG::Connection.conndefaults_hash.keys + [:requiressl]
+ conn_params.slice!(*valid_conn_param_keys)
+
+ adapter_class.new(
+ adapter_class.new_client(conn_params),
+ ActiveRecord::Base.logger,
+ conn_params,
+ config
+ )
+ end
+end