summaryrefslogtreecommitdiff
path: root/lib/gitlab/database/partitioning/single_numeric_list_partition.rb
blob: fd99062974cc7d9021dc367cb8b29d19ca5b7049 (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
# frozen_string_literal: true

module Gitlab
  module Database
    module Partitioning
      class SingleNumericListPartition
        include Comparable

        def self.from_sql(table, partition_name, definition)
          # A list partition can support multiple values, but we only support a single number
          matches = definition.match(/FOR VALUES IN \('?(?<value>\d+)'?\)/)

          raise ArgumentError, 'Unknown partition definition' unless matches

          value = Integer(matches[:value])

          new(table, value, partition_name: partition_name)
        end

        attr_reader :table, :value

        def initialize(table, value, partition_name: nil)
          @table = table
          @value = value
          @partition_name = partition_name
        end

        def partition_name
          @partition_name || "#{table}_#{value}"
        end

        def data_size
          execute("SELECT pg_table_size(#{quote(full_partition_name)})").first['pg_table_size']
        end

        def to_sql
          <<~SQL
            CREATE TABLE IF NOT EXISTS #{fully_qualified_partition}
            PARTITION OF #{quote_table_name(table)}
            FOR VALUES IN (#{quote(value)})
          SQL
        end

        def to_detach_sql
          <<~SQL
            ALTER TABLE #{quote_table_name(table)}
            DETACH PARTITION #{fully_qualified_partition}
          SQL
        end

        def ==(other)
          table == other.table &&
            partition_name == other.partition_name &&
            value == other.value
        end
        alias_method :eql?, :==

        def hash
          [table, partition_name, value].hash
        end

        def <=>(other)
          return if table != other.table

          value <=> other.value
        end

        private

        delegate :execute, :quote, :quote_table_name, to: :conn, private: true

        def full_partition_name
          "%s.%s" % [Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA, partition_name]
        end

        def fully_qualified_partition
          quote_table_name(full_partition_name)
        end

        def conn
          @conn ||= Gitlab::Database::SharedModel.connection
        end
      end
    end
  end
end