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
333 def _insert_raw(ds)
334   check_pg_constraint_error(ds){super}
335 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
338 def _insert_select_raw(ds)
339   check_pg_constraint_error(ds){super}
340 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
343 def _update_without_checking(_)
344   check_pg_constraint_error(_update_dataset){super}
345 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
327 def add_pg_constraint_validation_error(column, message)
328   column = column.first if column.length == 1 
329   errors.add(column, message)
330 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       # :nocov:
254       case e
255       # :nocov:
256       when Sequel::NotNullConstraintViolation
257         if column = info[:column]
258           add_pg_constraint_validation_error([m.call(column)], messages[:not_null])
259         end
260       when Sequel::CheckConstraintViolation
261         if columns = cv_info[:check][constraint]
262           add_pg_constraint_validation_error(columns, messages[:check])
263         end
264       when Sequel::UniqueConstraintViolation
265         if columns = cv_info[:unique][constraint]
266           add_pg_constraint_validation_error(columns, messages[:unique])
267         end
268       when Sequel::ForeignKeyConstraintViolation
269         message_primary = info[:message_primary]
270         if message_primary.start_with?('update')
271           # This constraint violation is different from the others, because the constraint
272           # referenced is a constraint for a different table, not for this table.  This
273           # happens when another table references the current table, and the referenced
274           # column in the current update is modified such that referential integrity
275           # would be broken.  Use the reverse foreign key information to figure out
276           # which column is affected in that case.
277           skip_schema_table_check = true
278           if columns = cv_info[:referenced_by][[m.call(schema), m.call(table), constraint]]
279             add_pg_constraint_validation_error(columns, messages[:referenced_by])
280           end
281         elsif message_primary.start_with?('insert')
282           if columns = cv_info[:foreign_key][constraint]
283             add_pg_constraint_validation_error(columns, messages[:foreign_key])
284           end
285         end
286       end
287     end
288   rescue
289     # If there is an error trying to conver the constraint violation
290     # into a validation failure, it's best to just raise the constraint
291     # violation.  This can make debugging the above block of code more
292     # difficult.
293     raise e
294   else
295     unless skip_schema_table_check
296       # The constraint violation could be caused by a trigger modifying
297       # a different table.  Check that the error schema and table
298       # match the model's schema and table, or clear the validation error
299       # that was set above.
300       if schema != cv_info[:schema] || table != cv_info[:table]
301         errors.clear
302       end
303     end
304 
305     if errors.empty?
306       # If we weren't able to parse the constraint violation metadata and
307       # convert it to an appropriate validation failure, or the schema/table
308       # didn't match, then raise the constraint violation.
309       raise e
310     end
311 
312     # Integrate with error_splitter plugin to split any multi-column errors
313     # and add them as separate single column errors
314     if respond_to?(:split_validation_errors, true)
315       split_validation_errors(errors)
316     end
317 
318     vf = ValidationFailed.new(self)
319     vf.set_backtrace(e.backtrace)
320     vf.wrapped_exception = e
321     raise vf
322   end
323 end