module Sequel::Plugins::PgAutoConstraintValidations::InstanceMethods

Private Instance Methods

_insert_raw(ds) click to toggle source

Convert PostgreSQL constraint errors when inserting.

Calls superclass method
    # File lib/sequel/plugins/pg_auto_constraint_validations.rb
331 def _insert_raw(ds)
332   check_pg_constraint_error(ds){super}
333 end
_insert_select_raw(ds) click to toggle source

Convert PostgreSQL constraint errors when inserting.

Calls superclass method
    # File lib/sequel/plugins/pg_auto_constraint_validations.rb
336 def _insert_select_raw(ds)
337   check_pg_constraint_error(ds){super}
338 end
_update_without_checking(_) click to toggle source

Convert PostgreSQL constraint errors when updating.

Calls superclass method
    # File lib/sequel/plugins/pg_auto_constraint_validations.rb
341 def _update_without_checking(_)
342   check_pg_constraint_error(_update_dataset){super}
343 end
add_pg_constraint_validation_error(column, message) click to toggle source

If there is a single column instead of an array of columns, add the error for the column, otherwise add the error for the array of columns.

    # File lib/sequel/plugins/pg_auto_constraint_validations.rb
325 def add_pg_constraint_validation_error(column, message)
326   column = column.first if column.length == 1 
327   errors.add(column, message)
328 end
check_pg_constraint_error(ds) { || ... } click to toggle source

Yield to the given block, and if a Sequel::ConstraintViolation is raised, try to convert it to a Sequel::ValidationFailed error using the PostgreSQL error metadata.

    # File lib/sequel/plugins/pg_auto_constraint_validations.rb
226 def check_pg_constraint_error(ds)
227   yield
228 rescue Sequel::ConstraintViolation => e
229   begin
230     unless cv_info = model.pg_auto_constraint_validations
231       # Necessary metadata does not exist, just reraise the exception.
232       raise e
233     end
234 
235     info = ds.db.error_info(e)
236     m = ds.method(:output_identifier)
237     schema = info[:schema]
238     table = info[:table]
239 
240     if constraint = info[:constraint]
241       constraint = m.call(constraint)
242 
243       columns, message = cv_info[:overrides][constraint]
244       if columns
245         override = true
246         add_pg_constraint_validation_error(columns, message)
247       end
248     end
249 
250     messages = model.pg_auto_constraint_validations_messages
251 
252     unless override
253       case e
254       when Sequel::NotNullConstraintViolation
255         if column = info[:column]
256           add_pg_constraint_validation_error([m.call(column)], messages[:not_null])
257         end
258       when Sequel::CheckConstraintViolation
259         if columns = cv_info[:check][constraint]
260           add_pg_constraint_validation_error(columns, messages[:check])
261         end
262       when Sequel::UniqueConstraintViolation
263         if columns = cv_info[:unique][constraint]
264           add_pg_constraint_validation_error(columns, messages[:unique])
265         end
266       when Sequel::ForeignKeyConstraintViolation
267         message_primary = info[:message_primary]
268         if message_primary.start_with?('update')
269           # This constraint violation is different from the others, because the constraint
270           # referenced is a constraint for a different table, not for this table.  This
271           # happens when another table references the current table, and the referenced
272           # column in the current update is modified such that referential integrity
273           # would be broken.  Use the reverse foreign key information to figure out
274           # which column is affected in that case.
275           skip_schema_table_check = true
276           if columns = cv_info[:referenced_by][[m.call(schema), m.call(table), constraint]]
277             add_pg_constraint_validation_error(columns, messages[:referenced_by])
278           end
279         elsif message_primary.start_with?('insert')
280           if columns = cv_info[:foreign_key][constraint]
281             add_pg_constraint_validation_error(columns, messages[:foreign_key])
282           end
283         end
284       end
285     end
286   rescue
287     # If there is an error trying to conver the constraint violation
288     # into a validation failure, it's best to just raise the constraint
289     # violation.  This can make debugging the above block of code more
290     # difficult.
291     raise e
292   else
293     unless skip_schema_table_check
294       # The constraint violation could be caused by a trigger modifying
295       # a different table.  Check that the error schema and table
296       # match the model's schema and table, or clear the validation error
297       # that was set above.
298       if schema != cv_info[:schema] || table != cv_info[:table]
299         errors.clear
300       end
301     end
302 
303     if errors.empty?
304       # If we weren't able to parse the constraint violation metadata and
305       # convert it to an appropriate validation failure, or the schema/table
306       # didn't match, then raise the constraint violation.
307       raise e
308     end
309 
310     # Integrate with error_splitter plugin to split any multi-column errors
311     # and add them as separate single column errors
312     if respond_to?(:split_validation_errors, true)
313       split_validation_errors(errors)
314     end
315 
316     vf = ValidationFailed.new(self)
317     vf.set_backtrace(e.backtrace)
318     vf.wrapped_exception = e
319     raise vf
320   end
321 end