Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/database/gitlab_schema.rb')
-rw-r--r--lib/gitlab/database/gitlab_schema.rb85
1 files changed, 41 insertions, 44 deletions
diff --git a/lib/gitlab/database/gitlab_schema.rb b/lib/gitlab/database/gitlab_schema.rb
index 4394c089b22..9b58284b389 100644
--- a/lib/gitlab/database/gitlab_schema.rb
+++ b/lib/gitlab/database/gitlab_schema.rb
@@ -3,13 +3,15 @@
# This module gathers information about table to schema mapping
# to understand table affinity
#
-# Each table / view needs to have assigned gitlab_schema. Names supported today:
+# Each table / view needs to have assigned gitlab_schema. For example:
#
# - gitlab_shared - defines a set of tables that are found on all databases (data accessed is dependent on connection)
# - gitlab_main / gitlab_ci - defines a set of tables that can only exist on a given application database
# - gitlab_geo - defines a set of tables that can only exist on the geo database
# - gitlab_internal - defines all internal tables of Rails and PostgreSQL
#
+# All supported GitLab schemas can be viewed in `db/gitlab_schemas/` and `ee/db/gitlab_schemas/`
+#
# Tables for the purpose of tests should be prefixed with `_test_my_table_name`
module Gitlab
@@ -17,8 +19,6 @@ module Gitlab
module GitlabSchema
UnknownSchemaError = Class.new(StandardError)
- DICTIONARY_PATH = 'db/docs/'
-
def self.table_schemas!(tables)
tables.map { |table| table_schema!(table) }.to_set
end
@@ -67,44 +67,50 @@ module Gitlab
# All `pg_` tables are marked as `internal`
return :gitlab_internal if table_name.start_with?('pg_')
-
- # Sometimes the name of an index can be interpreted as a table's name.
- # For eg, if we execute "ALTER INDEX my_index..", my_index is interpreted as a table name.
- # In such cases, we should return the schema of the database table actually
- # holding that index.
- index_name = table_name
- derive_schema_from_index(index_name)
end
# rubocop:enable Metrics/CyclomaticComplexity
- def self.dictionary_path_globs
- [Rails.root.join(DICTIONARY_PATH, '*.yml')]
+ def self.table_schema!(name)
+ # rubocop:disable Gitlab/DocUrl
+ self.table_schema(name) || raise(
+ UnknownSchemaError,
+ "Could not find gitlab schema for table #{name}: Any new or deleted tables must be added to the database dictionary " \
+ "See https://docs.gitlab.com/ee/development/database/database_dictionary.html"
+ )
+ # rubocop:enable Gitlab/DocUrl
end
- def self.view_path_globs
- [Rails.root.join(DICTIONARY_PATH, 'views', '*.yml')]
+ private_class_method def self.cross_access_allowed?(type, table_schemas)
+ table_schemas.any? do |schema|
+ extra_schemas = table_schemas - [schema]
+ extra_schemas -= Gitlab::Database.all_gitlab_schemas[schema]&.public_send(type) || [] # rubocop:disable GitlabSecurity/PublicSend
+ extra_schemas.empty?
+ end
end
- def self.deleted_views_path_globs
- [Rails.root.join(DICTIONARY_PATH, 'deleted_views', '*.yml')]
+ def self.cross_joins_allowed?(table_schemas)
+ table_schemas.empty? || self.cross_access_allowed?(:allow_cross_joins, table_schemas)
end
- def self.deleted_tables_path_globs
- [Rails.root.join(DICTIONARY_PATH, 'deleted_tables', '*.yml')]
+ def self.cross_transactions_allowed?(table_schemas)
+ table_schemas.empty? || self.cross_access_allowed?(:allow_cross_transactions, table_schemas)
end
- def self.views_and_tables_to_schema
- @views_and_tables_to_schema ||= self.tables_to_schema.merge(self.views_to_schema)
+ def self.cross_foreign_key_allowed?(table_schemas)
+ self.cross_access_allowed?(:allow_cross_foreign_keys, table_schemas)
end
- def self.table_schema!(name)
- # rubocop:disable Gitlab/DocUrl
- self.table_schema(name) || raise(
- UnknownSchemaError,
- "Could not find gitlab schema for table #{name}: Any new or deleted tables must be added to the database dictionary " \
- "See https://docs.gitlab.com/ee/development/database/database_dictionary.html"
- )
- # rubocop:enable Gitlab/DocUrl
+ def self.dictionary_paths
+ Gitlab::Database.all_database_connections
+ .values.map(&:db_docs_dir).uniq
+ end
+
+ def self.dictionary_path_globs(scope)
+ self.dictionary_paths.map { |path| Rails.root.join(path, scope, '*.yml') }
+ end
+
+ def self.views_and_tables_to_schema
+ @views_and_tables_to_schema ||= self.tables_to_schema.merge(self.views_to_schema)
end
def self.deleted_views_and_tables_to_schema
@@ -112,36 +118,27 @@ module Gitlab
end
def self.deleted_tables_to_schema
- @deleted_tables_to_schema ||= self.build_dictionary(self.deleted_tables_path_globs)
+ @deleted_tables_to_schema ||= self.build_dictionary('deleted_tables').to_h
end
def self.deleted_views_to_schema
- @deleted_views_to_schema ||= self.build_dictionary(self.deleted_views_path_globs)
+ @deleted_views_to_schema ||= self.build_dictionary('deleted_views').to_h
end
def self.tables_to_schema
- @tables_to_schema ||= self.build_dictionary(self.dictionary_path_globs)
+ @tables_to_schema ||= self.build_dictionary('').to_h
end
def self.views_to_schema
- @views_to_schema ||= self.build_dictionary(self.view_path_globs)
+ @views_to_schema ||= self.build_dictionary('views').to_h
end
def self.schema_names
@schema_names ||= self.views_and_tables_to_schema.values.to_set
end
- private_class_method def self.derive_schema_from_index(index_name)
- index = Gitlab::Database::PostgresIndex.find_by(name: index_name,
- schema: ApplicationRecord.connection.current_schema)
-
- return unless index
-
- table_schema(index.tablename)
- end
-
- private_class_method def self.build_dictionary(path_globs)
- Dir.glob(path_globs).each_with_object({}) do |file_path, dic|
+ def self.build_dictionary(scope)
+ Dir.glob(dictionary_path_globs(scope)).map do |file_path|
data = YAML.load_file(file_path)
key_name = data['table_name'] || data['view_name']
@@ -156,7 +153,7 @@ module Gitlab
end
# rubocop:enable Gitlab/DocUrl
- dic[key_name] = data['gitlab_schema'].to_sym
+ [key_name, data['gitlab_schema'].to_sym]
end
end
end