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

gitlab_schema_info.rb « database « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 20d2b31a65ca9fcae3af85250b57baa5139bf886 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# frozen_string_literal: true

module Gitlab
  module Database
    GitlabSchemaInfoAllowCross = Struct.new(
      :specific_tables,
      keyword_init: true
    )

    GitlabSchemaInfo = Struct.new(
      :name,
      :description,
      :allow_cross_joins,
      :allow_cross_transactions,
      :allow_cross_foreign_keys,
      :file_path,
      keyword_init: true
    ) do
      def initialize(*)
        super
        self.name = name.to_sym
        self.allow_cross_joins = convert_array_to_hash(allow_cross_joins)
        self.allow_cross_transactions = convert_array_to_hash(allow_cross_transactions)
        self.allow_cross_foreign_keys = convert_array_to_hash(allow_cross_foreign_keys)
      end

      def self.load_file(yaml_file)
        content = YAML.load_file(yaml_file)
        new(**content.deep_symbolize_keys.merge(file_path: yaml_file))
      end

      def allow_cross_joins?(table_schemas, all_tables)
        allowed_schemas = allow_cross_joins || {}

        allowed_for?(allowed_schemas, table_schemas, all_tables)
      end

      def allow_cross_transactions?(table_schemas, all_tables)
        allowed_schemas = allow_cross_transactions || {}

        allowed_for?(allowed_schemas, table_schemas, all_tables)
      end

      def allow_cross_foreign_keys?(table_schemas, all_tables)
        allowed_schemas = allow_cross_foreign_keys || {}

        allowed_for?(allowed_schemas, table_schemas, all_tables)
      end

      private

      def allowed_for?(allowed_schemas, table_schemas, all_tables)
        denied_schemas = table_schemas - [name]
        denied_schemas -= allowed_schemas.keys
        return false unless denied_schemas.empty?

        all_tables.all? do |table|
          table_schema = ::Gitlab::Database::GitlabSchema.table_schema!(table)
          allowed_tables = allowed_schemas[table_schema]

          allowed_tables.nil? || allowed_tables.specific_tables.include?(table)
        end
      end

      # Convert from:
      # - schema_a
      # - schema_b:
      #     specific_tables:
      #     - table_b_of_schema_b
      #     - table_c_of_schema_b
      #
      # To:
      # { :schema_a => nil,
      #   :schema_b => { specific_tables : [:table_b_of_schema_b, :table_c_of_schema_b] }
      # }
      #
      def convert_array_to_hash(subject)
        result = {}

        subject&.each do |item|
          if item.is_a?(Hash)
            item.each do |key, value|
              result[key.to_sym] = GitlabSchemaInfoAllowCross.new(value || {})
            end
          else
            result[item.to_sym] = nil
          end
        end

        result.freeze
      end
    end
  end
end