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.

Public Instance Methods

dump_pg_auto_constraint_validations_cache() click to toggle source

Dump the in-memory cached metadata to the cache file.

    # File lib/sequel/plugins/pg_auto_constraint_validations.rb
134 def dump_pg_auto_constraint_validations_cache
135   raise Error, "No pg_auto_constraint_validations setup" unless file = @pg_auto_constraint_validations_cache_file
136   pg_auto_constraint_validations_cache = {}
137   @pg_auto_constraint_validations_cache.sort.each do |k, v|
138     pg_auto_constraint_validations_cache[k] = v
139   end
140   File.open(file, 'wb'){|f| f.write(Marshal.dump(pg_auto_constraint_validations_cache))}
141   nil
142 end
pg_auto_constraint_validation_override(constraint, columns, message) click to toggle source

Override the constraint validation columns and message for a given constraint

    # File lib/sequel/plugins/pg_auto_constraint_validations.rb
145 def pg_auto_constraint_validation_override(constraint, columns, message)
146   pgacv = Hash[@pg_auto_constraint_validations]
147   overrides = pgacv[:overrides] = Hash[pgacv[:overrides]]
148   overrides[constraint] = [Array(columns), message].freeze
149   overrides.freeze
150   @pg_auto_constraint_validations = pgacv.freeze
151   nil
152 end

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
163 def setup_pg_auto_constraint_validations
164   return unless @dataset
165 
166   case @dataset.first_source_table
167   when Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier
168    convert_errors = db.respond_to?(:error_info)
169   end
170 
171   unless convert_errors
172     # Might be a table returning function or subquery, skip handling those.
173     # Might have db not support error_info, skip handling that.
174     @pg_auto_constraint_validations = nil
175     return
176   end
177 
178   cache = @pg_auto_constraint_validations_cache
179   literal_table_name = dataset.literal(table_name)
180   unless cache && (metadata = cache[literal_table_name])
181     checks = {}
182     indexes = {}
183     foreign_keys = {}
184     referenced_by = {}
185 
186     db.check_constraints(table_name).each do |k, v|
187       checks[k] = v[:columns].dup.freeze unless v[:columns].empty?
188     end
189     db.indexes(table_name, :include_partial=>true).each do |k, v|
190       if v[:unique]
191         indexes[k] = v[:columns].dup.freeze
192       end
193     end
194     db.foreign_key_list(table_name, :schema=>false).each do |fk|
195       foreign_keys[fk[:name]] = fk[:columns].dup.freeze
196     end
197     db.foreign_key_list(table_name, :reverse=>true, :schema=>false).each do |fk|
198       referenced_by[[fk[:schema], fk[:table], fk[:name]].freeze] = fk[:key].dup.freeze
199     end
200 
201     schema, table = db[:pg_class].
202       join(:pg_namespace, :oid=>:relnamespace, db.send(:regclass_oid, table_name)=>:oid).
203       get([:nspname, :relname])
204 
205     metadata = {
206       :schema=>schema,
207       :table=>table,
208       :check=>checks,
209       :unique=>indexes,
210       :foreign_key=>foreign_keys,
211       :referenced_by=>referenced_by,
212       :overrides=>OPTS
213     }.freeze
214     metadata.each_value(&:freeze)
215 
216     if cache
217       cache[literal_table_name] = metadata
218     end
219   end
220 
221   @pg_auto_constraint_validations = metadata
222   nil
223 end