Module: PartitionGardener::HashRouting

Defined in:
lib/partition_gardener/hash_routing.rb

Class Method Summary collapse

Class Method Details

.collect_bucket_counts(config) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/partition_gardener/hash_routing.rb', line 5

def collect_bucket_counts(config)
  table_name = config[:table_name]
  modulus = config.fetch(:hash_modulus, Strategy::HashBranches::DEFAULT_MODULUS)
  bucket_counts = Hash.new(0)

  Connection.attached_partitions(table_name).each do |partition|
    next if partition.default

    remainder = remainder_from_partition(partition, table_name)
    next if remainder.nil?

    bucket_counts[remainder] += Connection.count_rows_in_partition_table(partition.name)
  end

  default_name = Naming.default_partition_name(table_name)
  if Connection.partition_exists?(default_name) && Connection.partition_attached?(table_name, default_name)
    counts_in_default(default_name, config[:partition_key_column], modulus).each do |remainder, count|
      bucket_counts[remainder] += count
    end
  end

  bucket_counts
end

.counts_in_default(partition_name, partition_key_column, modulus) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/partition_gardener/hash_routing.rb', line 40

def counts_in_default(partition_name, partition_key_column, modulus)
  connection = Connection.connection
  column = connection.quote_column_name(partition_key_column)
  remainder_sql = remainder_sql_expression(column, modulus, connection)

  sql = <<~SQL
    SELECT #{remainder_sql} AS remainder,
           COUNT(*)::int AS row_count
    FROM #{Connection.quoted_table(partition_name)}
    GROUP BY 1
  SQL

  connection.execute(sql).each_with_object({}) do |row, counts|
    counts[row["remainder"].to_i] = row["row_count"].to_i
  end
end

.integer_column?(quoted_column) ⇒ Boolean

Returns:

  • (Boolean)


65
66
67
68
# File 'lib/partition_gardener/hash_routing.rb', line 65

def integer_column?(quoted_column)
  normalized = quoted_column.delete('"').downcase
  normalized == "id" || normalized.end_with?("_id")
end

.remainder_from_partition(partition, table_name) ⇒ Object



29
30
31
32
33
34
35
36
37
38
# File 'lib/partition_gardener/hash_routing.rb', line 29

def remainder_from_partition(partition, table_name)
  if partition.range_start.is_a?(Hash) && partition.range_start.key?(:remainder)
    return partition.range_start[:remainder]
  end

  match = partition.name.match(/^#{Regexp.escape(table_name)}_[ha]_(\d+)$/)
  return match[1].to_i if match

  nil
end

.remainder_sql_expression(quoted_column, modulus, connection) ⇒ Object



57
58
59
60
61
62
63
# File 'lib/partition_gardener/hash_routing.rb', line 57

def remainder_sql_expression(quoted_column, modulus, connection)
  if integer_column?(quoted_column)
    "mod(abs(hashint8extended(#{quoted_column}::bigint, 0)), #{modulus})"
  else
    "mod(abs(hashtextextended(#{quoted_column}::text, 0)), #{modulus})"
  end
end