module Sequel::Plugins::PgAutoConstraintValidations::ClassMethods

Attributes

pg_auto_constraint_validations[R]

Hash of metadata checked when an instance attempts to convert a constraint violation into a validation failure.

pg_auto_constraint_validations_messages[R]

Hash of error messages keyed by constraint type symbol to use in the generated validation failures.

Private Instance Methods

setup_pg_auto_constraint_validations() click to toggle source

Get the list of constraints, unique indexes, foreign keys in the current table, and keys in the current table referenced by foreign keys in other tables. Store this information so that if a constraint violation occurs, all necessary metadata is already available in the model, so a query is not required at runtime. This is both for performance and because in general after the constraint violation failure you will be inside a failed transaction and not able to execute queries.

# File lib/sequel/plugins/pg_auto_constraint_validations.rb, line 92
def setup_pg_auto_constraint_validations
  return unless @dataset

  case @dataset.first_source_table
  when Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier
   convert_errors = db.respond_to?(:error_info)
  end

  unless convert_errors
    # Might be a table returning function or subquery, skip handling those.
    # Might have db not support error_info, skip handling that.
    @pg_auto_constraint_validations = nil
    return
  end

  checks = {}
  indexes = {}
  foreign_keys = {}
  referenced_by = {}

  db.check_constraints(table_name).each do |k, v|
    checks[k] = v[:columns].dup.freeze
  end
  db.indexes(table_name, :include_partial=>true).each do |k, v|
    if v[:unique]
      indexes[k] = v[:columns].dup.freeze
    end
  end
  db.foreign_key_list(table_name, :schema=>false).each do |fk|
    foreign_keys[fk[:name]] = fk[:columns].dup.freeze
  end
  db.foreign_key_list(table_name, :reverse=>true, :schema=>false).each do |fk|
    referenced_by[[fk[:schema], fk[:table], fk[:name]].freeze] = fk[:key].dup.freeze
  end

  schema, table = db[:pg_class].
    join(:pg_namespace, :oid=>:relnamespace, db.send(:regclass_oid, table_name)=>:oid).
    get([:nspname, :relname])

  (@pg_auto_constraint_validations = {
    :schema=>schema,
    :table=>table,
    :check=>checks,
    :unique=>indexes,
    :foreign_key=>foreign_keys,
    :referenced_by=>referenced_by
  }.freeze).each_value(&:freeze)
end