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