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