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     h = {}
139     v.each do |k, entry|
140       entry = Hash[entry.sort] if entry.is_a?(Hash)
141       h[k] = entry
142     end
143     pg_auto_constraint_validations_cache[k] = h
144   end
145   File.open(file, 'wb'){|f| f.write(Marshal.dump(pg_auto_constraint_validations_cache))}
146   nil
147 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
150 def pg_auto_constraint_validation_override(constraint, columns, message)
151   pgacv = Hash[@pg_auto_constraint_validations]
152   overrides = pgacv[:overrides] = Hash[pgacv[:overrides]]
153   overrides[constraint] = [Array(columns), message].freeze
154   overrides.freeze
155   @pg_auto_constraint_validations = pgacv.freeze
156   nil
157 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
168 def setup_pg_auto_constraint_validations
169   return unless @dataset
170 
171   case @dataset.first_source_table
172   when Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier
173    convert_errors = db.respond_to?(:error_info)
174   end
175 
176   unless convert_errors
177     # Might be a table returning function or subquery, skip handling those.
178     # Might have db not support error_info, skip handling that.
179     @pg_auto_constraint_validations = nil
180     return
181   end
182 
183   cache = @pg_auto_constraint_validations_cache
184   literal_table_name = dataset.literal(table_name)
185   unless cache && (metadata = cache[literal_table_name])
186     checks = {}
187     indexes = {}
188     foreign_keys = {}
189     referenced_by = {}
190 
191     db.check_constraints(table_name).each do |k, v|
192       checks[k] = v[:columns].dup.freeze unless v[:columns].empty?
193     end
194     db.indexes(table_name, :include_partial=>true).each do |k, v|
195       if v[:unique]
196         indexes[k] = v[:columns].dup.freeze
197       end
198     end
199     db.foreign_key_list(table_name, :schema=>false).each do |fk|
200       foreign_keys[fk[:name]] = fk[:columns].dup.freeze
201     end
202     db.foreign_key_list(table_name, :reverse=>true, :schema=>false).each do |fk|
203       referenced_by[[fk[:schema], fk[:table], fk[:name]].freeze] = fk[:key].dup.freeze
204     end
205 
206     schema, table = db[:pg_class].
207       join(:pg_namespace, :oid=>:relnamespace, db.send(:regclass_oid, table_name)=>:oid).
208       get([:nspname, :relname])
209 
210     metadata = {
211       :schema=>schema,
212       :table=>table,
213       :check=>checks,
214       :unique=>indexes,
215       :foreign_key=>foreign_keys,
216       :referenced_by=>referenced_by,
217       :overrides=>OPTS
218     }.freeze
219     metadata.each_value(&:freeze)
220 
221     if cache
222       cache[literal_table_name] = metadata
223     end
224   end
225 
226   @pg_auto_constraint_validations = metadata
227   nil
228 end