Class: Gitlab::Database::Reflection
- Inherits:
-
Object
- Object
- Gitlab::Database::Reflection
- Defined in:
- lib/gitlab/database/reflection.rb
Overview
A class for reflecting upon a database and its settings, such as the adapter name, PostgreSQL version, and the presence of tables or columns.
Instance Attribute Summary collapse
-
#model ⇒ Object
readonly
Returns the value of attribute model.
Instance Method Summary collapse
- #adapter_name ⇒ Object
- #cached_column_exists?(column_name) ⇒ Boolean
- #cached_table_exists? ⇒ Boolean
- #config ⇒ Object
- #database_name ⇒ Object
- #database_version ⇒ Object
-
#db_read_only? ⇒ Boolean
Check whether the underlying database is in read-only mode.
- #db_read_write? ⇒ Boolean
- #exists? ⇒ Boolean
- #flavor ⇒ Object
- #human_adapter_name ⇒ Object
-
#initialize(model) ⇒ Reflection
constructor
A new instance of Reflection.
- #postgresql? ⇒ Boolean
- #postgresql_minimum_supported_version? ⇒ Boolean
- #system_id ⇒ Object
- #username ⇒ Object
- #version ⇒ Object
Constructor Details
#initialize(model) ⇒ Reflection
Returns a new instance of Reflection.
10 11 12 13 |
# File 'lib/gitlab/database/reflection.rb', line 10 def initialize(model) @model = model @version = nil end |
Instance Attribute Details
#model ⇒ Object (readonly)
Returns the value of attribute model.
8 9 10 |
# File 'lib/gitlab/database/reflection.rb', line 8 def model @model end |
Instance Method Details
#adapter_name ⇒ Object
36 37 38 |
# File 'lib/gitlab/database/reflection.rb', line 36 def adapter_name config[:adapter] end |
#cached_column_exists?(column_name) ⇒ Boolean
79 80 81 82 83 |
# File 'lib/gitlab/database/reflection.rb', line 79 def cached_column_exists?(column_name) connection .schema_cache.columns_hash(model.table_name) .has_key?(column_name.to_s) end |
#cached_table_exists? ⇒ Boolean
85 86 87 |
# File 'lib/gitlab/database/reflection.rb', line 85 def cached_table_exists? exists? && connection.schema_cache.data_source_exists?(model.table_name) end |
#config ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/gitlab/database/reflection.rb', line 15 def config # The result of this method must not be cached, as other methods may use # it after making configuration changes and expect those changes to be # present. For example, `disable_prepared_statements` expects the # configuration settings to always be up to date. # # See the following for more information: # # - https://gitlab.com/gitlab-org/release/retrospectives/-/issues/39 # - https://gitlab.com/gitlab-com/gl-infra/production/-/issues/5238 model.connection_db_config.configuration_hash.with_indifferent_access end |
#database_name ⇒ Object
32 33 34 |
# File 'lib/gitlab/database/reflection.rb', line 32 def database_name config[:database] end |
#database_version ⇒ Object
71 72 73 |
# File 'lib/gitlab/database/reflection.rb', line 71 def database_version connection.execute("SELECT VERSION()").first['version'] end |
#db_read_only? ⇒ Boolean
Check whether the underlying database is in read-only mode
53 54 55 56 57 58 59 60 61 |
# File 'lib/gitlab/database/reflection.rb', line 53 def db_read_only? pg_is_in_recovery = connection .execute('SELECT pg_is_in_recovery()') .first .fetch('pg_is_in_recovery') Gitlab::Utils.to_boolean(pg_is_in_recovery) end |
#db_read_write? ⇒ Boolean
63 64 65 |
# File 'lib/gitlab/database/reflection.rb', line 63 def db_read_write? !db_read_only? end |
#exists? ⇒ Boolean
89 90 91 92 93 94 95 96 97 98 |
# File 'lib/gitlab/database/reflection.rb', line 89 def exists? # We can't _just_ check if `connection` raises an error, as it will # point to a `ConnectionProxy`, and obtaining those doesn't involve any # database queries. So instead we obtain the database version, which is # cached after the first call. connection.schema_cache.database_version true rescue StandardError false end |
#flavor ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/gitlab/database/reflection.rb', line 108 def flavor { # Based on https://aws.amazon.com/premiumsupport/knowledge-center/aurora-version-number/ 'Amazon Aurora PostgreSQL' => { statement: 'SELECT AURORA_VERSION()', error: /PG::UndefinedFunction/ }, # Based on https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts.General.FeatureSupport.Extensions, # this is also available for both Aurora and RDS, so we need to check for the former first. 'PostgreSQL on Amazon RDS' => { statement: 'SHOW rds.extensions', error: /PG::UndefinedObject/ }, # Based on https://cloud.google.com/sql/docs/postgres/flags#postgres-c this should be specific # to Cloud SQL for PostgreSQL 'Cloud SQL for PostgreSQL' => { statement: 'SHOW cloudsql.iam_authentication', error: /PG::UndefinedObject/ }, # Based on # - https://docs.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-extensions # - https://docs.microsoft.com/en-us/azure/postgresql/concepts-extensions # this should be available only for Azure Database for PostgreSQL - Flexible Server. 'Azure Database for PostgreSQL - Flexible Server' => { statement: 'SHOW azure.extensions', error: /PG::UndefinedObject/ }, # Based on # - https://docs.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-servers # - https://docs.microsoft.com/en-us/azure/postgresql/concepts-servers#managing-your-server # this database is present on both Flexible and Single server, so we should check the former first. 'Azure Database for PostgreSQL - Single Server' => { statement: "SELECT datname FROM pg_database WHERE datname = 'azure_maintenance'" }, # Based on # - https://cloud.google.com/sql/docs/postgres/flags # running a query to detect flag names that begin with 'alloydb 'AlloyDB for PostgreSQL' => { statement: "SELECT name FROM pg_settings WHERE name LIKE 'alloydb%'" } }.each do |flavor, conditions| return flavor if connection.execute(conditions[:statement]).to_a.present? rescue ActiveRecord::StatementInvalid => e raise if conditions[:error] && !e..match?(conditions[:error]) end nil end |
#human_adapter_name ⇒ Object
40 41 42 43 44 45 46 |
# File 'lib/gitlab/database/reflection.rb', line 40 def human_adapter_name if postgresql? 'PostgreSQL' else 'Unknown' end end |
#postgresql? ⇒ Boolean
48 49 50 |
# File 'lib/gitlab/database/reflection.rb', line 48 def postgresql? adapter_name.casecmp('postgresql') == 0 end |
#postgresql_minimum_supported_version? ⇒ Boolean
75 76 77 |
# File 'lib/gitlab/database/reflection.rb', line 75 def postgresql_minimum_supported_version? version.to_f >= MINIMUM_POSTGRES_VERSION end |
#system_id ⇒ Object
100 101 102 103 104 105 106 |
# File 'lib/gitlab/database/reflection.rb', line 100 def system_id row = connection .execute('SELECT system_identifier FROM pg_control_system()') .first row['system_identifier'] end |
#username ⇒ Object
28 29 30 |
# File 'lib/gitlab/database/reflection.rb', line 28 def username config[:username] || ENV['USER'] end |
#version ⇒ Object
67 68 69 |
# File 'lib/gitlab/database/reflection.rb', line 67 def version @version ||= database_version.match(/\A(?:PostgreSQL |)([^\s]+).*\z/)[1] end |