class ROM::SQL::Schema::Inferrer

@api private

Constants

FALLBACK_SCHEMA

Public Instance Methods

call(schema, gateway) click to toggle source

@api private

Calls superclass method
# File lib/rom/sql/schema/inferrer.rb, line 35
def call(schema, gateway)
  if enabled?
    infer_from_database(gateway, schema, **super)
  else
    infer_from_attributes(gateway, schema, **super)
  end
rescue Sequel::Error => error
  on_error(schema.name, error)
  { **FALLBACK_SCHEMA, indexes: schema.indexes }
end
foreign_keys_from_attributes(attributes) click to toggle source

@api private

# File lib/rom/sql/schema/inferrer.rb, line 106
def foreign_keys_from_attributes(attributes)
  attributes.
    select(&:foreign_key?).
    map { |attr| SQL::ForeignKey.new([attr.unwrap], attr.target) }.
    to_set
end
foreign_keys_from_database(gateway, schema, attributes) click to toggle source

@api private

# File lib/rom/sql/schema/inferrer.rb, line 86
def foreign_keys_from_database(gateway, schema, attributes)
  dataset = schema.name.dataset

  gateway.connection.foreign_key_list(dataset).map { |definition|
    columns, table, key = definition.values_at(:columns, :table, :key)
    attrs = columns.map { |name| attributes[name] }

    SQL::ForeignKey.new(attrs, table, parent_keys: key)
  }.to_set
end
indexes_from_attributes(attributes) click to toggle source

@api private

# File lib/rom/sql/schema/inferrer.rb, line 98
def indexes_from_attributes(attributes)
  attributes.
    select(&:indexed?).
    map { |attr| SQL::Index.new([attr.unwrap]) }.
    to_set
end
indexes_from_database(gateway, schema, attributes) click to toggle source

@api private

# File lib/rom/sql/schema/inferrer.rb, line 70
def indexes_from_database(gateway, schema, attributes)
  if gateway.connection.respond_to?(:indexes)
    dataset = schema.name.dataset

    gateway.connection.indexes(dataset).map { |index_name, definition|
      columns, unique = definition.values_at(:columns, :unique)
      attrs = columns.map { |name| attributes[name] }

      SQL::Index.new(attrs, name: index_name, unique: unique)
    }.to_set
  else
    EMPTY_SET
  end
end
infer_from_attributes(_gateway, schema, attributes:, **rest) click to toggle source

@api private

# File lib/rom/sql/schema/inferrer.rb, line 59
def infer_from_attributes(_gateway, schema, attributes:, **rest)
  indexes = schema.indexes | indexes_from_attributes(attributes)
  foreign_keys = foreign_keys_from_attributes(attributes)

  { **rest,
    attributes: attributes.map { |attr| mark_indexed(attr, indexes) },
    foreign_keys: foreign_keys,
    indexes: indexes }
end
infer_from_database(gateway, schema, attributes:, **rest) click to toggle source

@api private

# File lib/rom/sql/schema/inferrer.rb, line 47
def infer_from_database(gateway, schema, attributes:, **rest)
  idx = attributes_index(attributes)
  indexes = indexes_from_database(gateway, schema, idx)
  foreign_keys = foreign_keys_from_database(gateway, schema, idx)

  { **rest,
    attributes: attributes.map { |attr| mark_fk(mark_indexed(attr, indexes), foreign_keys) },
    foreign_keys: foreign_keys,
    indexes: indexes }
end
suppress_errors() click to toggle source

@api private

# File lib/rom/sql/schema/inferrer.rb, line 114
def suppress_errors
  with(raise_on_error: false, silent: true)
end

Private Instance Methods

attributes_index(attributes) click to toggle source
# File lib/rom/sql/schema/inferrer.rb, line 120
def attributes_index(attributes)
  Hash.new { |idx, name| idx[name] = attributes.find { |attr| attr.name == name }.unwrap }
end
mark_fk(attribute, foreign_keys) click to toggle source

@private

# File lib/rom/sql/schema/inferrer.rb, line 134
def mark_fk(attribute, foreign_keys)
  if attribute.foreign_key?
    attribute
  else
    foreign_key = foreign_keys.find { |fk| fk.attributes.map(&:name) == [attribute.name] }

    if foreign_key.nil?
      attribute
    else
      attribute.meta(foreign_key: true, target: foreign_key.parent_table)
    end
  end
end
mark_indexed(attribute, indexes) click to toggle source

@private

# File lib/rom/sql/schema/inferrer.rb, line 125
def mark_indexed(attribute, indexes)
  if !attribute.indexed? && indexes.any? { |index| index.can_access?(attribute) }
    attribute.indexed
  else
    attribute
  end
end
on_error(dataset, e) click to toggle source

@api private

# File lib/rom/sql/schema/inferrer.rb, line 149
def on_error(dataset, e)
  if raise_on_error
    raise e
  elsif !silent
    warn "[#{dataset}] failed to infer schema. " \
         'Make sure tables exist before ROM container is set up. ' \
         'This may also happen when your migration tasks load ROM container, ' \
         'which is not needed for migrations as only the connection is required ' \
         "(#{e.message})"
  end
end