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
272 def _insert_raw(ds)
273   check_pg_constraint_error(ds){super}
274 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
277 def _insert_select_raw(ds)
278   check_pg_constraint_error(ds){super}
279 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
282 def _update_without_checking(_)
283   check_pg_constraint_error(_update_dataset){super}
284 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
266 def add_pg_constraint_validation_error(column, message)
267   column = column.first if column.length == 1 
268   errors.add(column, message)
269 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
167 def check_pg_constraint_error(ds)
168   yield
169 rescue Sequel::ConstraintViolation => e
170   begin
171     unless cv_info = model.pg_auto_constraint_validations
172       # Necessary metadata does not exist, just reraise the exception.
173       raise e
174     end
175 
176     info = ds.db.error_info(e)
177     m = ds.method(:output_identifier)
178     schema = info[:schema]
179     table = info[:table]
180 
181     if constraint = info[:constraint]
182       constraint = m.call(constraint)
183 
184       columns, message = cv_info[:overrides][constraint]
185       if columns
186         override = true
187         add_pg_constraint_validation_error(columns, message)
188       end
189     end
190 
191     messages = model.pg_auto_constraint_validations_messages
192 
193     unless override
194       case e
195       when Sequel::NotNullConstraintViolation
196         if column = info[:column]
197           add_pg_constraint_validation_error([m.call(column)], messages[:not_null])
198         end
199       when Sequel::CheckConstraintViolation
200         if columns = cv_info[:check][constraint]
201           add_pg_constraint_validation_error(columns, messages[:check])
202         end
203       when Sequel::UniqueConstraintViolation
204         if columns = cv_info[:unique][constraint]
205           add_pg_constraint_validation_error(columns, messages[:unique])
206         end
207       when Sequel::ForeignKeyConstraintViolation
208         message_primary = info[:message_primary]
209         if message_primary.start_with?('update')
210           # This constraint violation is different from the others, because the constraint
211           # referenced is a constraint for a different table, not for this table.  This
212           # happens when another table references the current table, and the referenced
213           # column in the current update is modified such that referential integrity
214           # would be broken.  Use the reverse foreign key information to figure out
215           # which column is affected in that case.
216           skip_schema_table_check = true
217           if columns = cv_info[:referenced_by][[m.call(schema), m.call(table), constraint]]
218             add_pg_constraint_validation_error(columns, messages[:referenced_by])
219           end
220         elsif message_primary.start_with?('insert')
221           if columns = cv_info[:foreign_key][constraint]
222             add_pg_constraint_validation_error(columns, messages[:foreign_key])
223           end
224         end
225       end
226     end
227   rescue
228     # If there is an error trying to conver the constraint violation
229     # into a validation failure, it's best to just raise the constraint
230     # violation.  This can make debugging the above block of code more
231     # difficult.
232     raise e
233   else
234     unless skip_schema_table_check
235       # The constraint violation could be caused by a trigger modifying
236       # a different table.  Check that the error schema and table
237       # match the model's schema and table, or clear the validation error
238       # that was set above.
239       if schema != cv_info[:schema] || table != cv_info[:table]
240         errors.clear
241       end
242     end
243 
244     if errors.empty?
245       # If we weren't able to parse the constraint violation metadata and
246       # convert it to an appropriate validation failure, or the schema/table
247       # didn't match, then raise the constraint violation.
248       raise e
249     end
250 
251     # Integrate with error_splitter plugin to split any multi-column errors
252     # and add them as separate single column errors
253     if respond_to?(:split_validation_errors, true)
254       split_validation_errors(errors)
255     end
256 
257     vf = ValidationFailed.new(self)
258     vf.set_backtrace(e.backtrace)
259     vf.wrapped_exception = e
260     raise vf
261   end
262 end