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