Module: PartitionGardener::Predicate

Defined in:
lib/partition_gardener/predicate.rb

Constant Summary collapse

COLUMN_PATTERN =
/\A[a-z_][a-z0-9_]*\z/i
OPERATORS =
%w[eq ne is_null is_not_null].freeze

Class Method Summary collapse

Class Method Details

.list_branch_entries(branches, discriminator_column: nil, connection: nil) ⇒ Object



60
61
62
63
64
65
66
67
68
# File 'lib/partition_gardener/predicate.rb', line 60

def list_branch_entries(branches, discriminator_column: nil, connection: nil)
  normalize_branches!(branches, discriminator_column: discriminator_column, connection: connection).map do |branch|
    {
      name: branch.fetch(:name),
      value: branch.fetch(:value),
      where_condition: branch.fetch(:where_condition)
    }
  end
end

.normalize_branch!(branch, discriminator_column: nil, connection: nil) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/partition_gardener/predicate.rb', line 31

def normalize_branch!(branch, discriminator_column: nil, connection: nil)
  entry = branch.transform_keys(&:to_sym)
  entry = entry.dup

  if entry[:predicate]
    entry[:where_condition] = render(entry[:predicate], connection: connection)
    entry.delete(:predicate)
  elsif entry[:where_condition]
    entry[:where_condition] = entry[:where_condition].to_s
  elsif (column = entry[:discriminator_column] || discriminator_column) && entry.key?(:value)
    entry[:where_condition] = render(
      {column: column, operator: "eq", value: entry[:value]},
      connection: connection
    )
  else
    name = entry[:name] || "?"
    raise ArgumentError,
      "branch #{name.inspect} needs predicate, where_condition, or value with discriminator_column"
  end

  entry
end

.normalize_branches!(branches, discriminator_column: nil, connection: nil) ⇒ Object



54
55
56
57
58
# File 'lib/partition_gardener/predicate.rb', line 54

def normalize_branches!(branches, discriminator_column: nil, connection: nil)
  branches.map do |branch|
    normalize_branch!(branch, discriminator_column: discriminator_column, connection: connection)
  end
end

.render(predicate, connection: nil) ⇒ Object



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

def render(predicate, connection: nil)
  connection ||= Connection.connection
  predicate = predicate.transform_keys(&:to_sym)
  column = predicate.fetch(:column)
  operator = predicate.fetch(:operator).to_s

  validate_column!(column)
  validate_operator!(operator)

  quoted_column = connection.quote_column_name(column)

  case operator
  when "eq"
    "#{quoted_column} = #{connection.quote(predicate.fetch(:value))}"
  when "ne"
    "#{quoted_column} <> #{connection.quote(predicate.fetch(:value))}"
  when "is_null"
    "#{quoted_column} IS NULL"
  when "is_not_null"
    "#{quoted_column} IS NOT NULL"
  end
end

.validate_column!(column) ⇒ Object

Raises:

  • (ArgumentError)


70
71
72
73
74
75
# File 'lib/partition_gardener/predicate.rb', line 70

def validate_column!(column)
  name = column.to_s
  return if COLUMN_PATTERN.match?(name)

  raise ArgumentError, "predicate column must be a simple identifier, got #{name.inspect}"
end

.validate_operator!(operator) ⇒ Object

Raises:

  • (ArgumentError)


77
78
79
80
81
# File 'lib/partition_gardener/predicate.rb', line 77

def validate_operator!(operator)
  return if OPERATORS.include?(operator)

  raise ArgumentError, "unsupported predicate operator: #{operator.inspect} (allowed: #{OPERATORS.join(", ")})"
end