CakePHP - check for foreign key integrity on dataload - postgresql

I currently have a system which required regular data imports. The db is Postgresql.
What I want to do is validate if a foreign key does not exist on a dataload.
For example
Customer belongs to Title and the 'titles' table contains
( id : name )
1 : Mr
2 : Mrs
3 : Miss
If during the dataload I pass in say 22 as a title_id, postgres throws a foreign key constraint violation which throws a php warning. Does anyone know of a way to catch this rather me having to write custom validation rules?
Thanks
Leo

If using PDO, you can set the error mode to throw exceptions, like such:
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
You can then catch the exception and do whatever you please with it.

Related

.net core handle PostreSQL db exceptions

I have a .net core web api. Db is PostreSQL. I have a simple POST request that create an entity with two fields:
public class ClientDto{
public string Name {get;set;}
public int ClientId{get;set;}
}
ClientId - FK foreign key to table Clients.
Some client (Postman for exapmle) execute request, but in data model send ClientId that not exists in db.
I have global exeption handler and there I handle db exception, but exception object don't include separated information.
I would like to show to user beautiful message something like "Client with id = 1 not exists".
What the best practis to handle db exceptions?
May be before save object in db I need check if client with id = 1 exists in db? But it is an additional query.
May be before save object in db I need check if client with id = 1 exists in db? But it is an additional query.
I'd do this.
If your client doesn't give you good information in its exception then your probably better to do the additional query. If you're querying on an indexed field (which i'd expect given you are using a foreign key) then it will be a very quick query.
Exception throwing and catching is fairly expensive anyway and i'd probably be happy enough with the extra call.

Changing primary key generation with ManyToManyMapping

I am trying to find a work-around for the EclipseLink bug bugs.eclipse.org/bugs/show_bug.cgi?id=344448.
The issue is that EclipseLink chooses a primary key made of entity ID + hashmap value ID for each entry of the HashMap. I would like to modify to have the primary key of entity ID + hashmap key ID instead. This is not only an issue with the primary key constraint but also with the SQL statements generated by EclipseLink, eg delete, update, etc...
So... I saw there is a way to customise this behaviour using a Customiser and by grabbing the ManyToManyMapping of the hashmap field and modifying whatever is needed. I can't find much documentation on this so I am sort of trying out things... but so far no success.
public class ConfigureValuesFilter implements DescriptorCustomizer {
public void customize(ClassDescriptor descriptor) throws Exception {
ManyToManyMapping mapping = (ManyToManyMapping) descriptor
.getMappingForAttributeName("values");
// various attempts
}
I tried setting the primary key with mapping.setTargetRelationKeyFieldName ("value_KEY"); and the setTargetKeyFieldNames (why does it need both?) but this resulted in an array index out of bound error with the table (from the key) I want to use not available in the descriptor, see below.
Exception Description: The table [CASEVALUE] is not present in this descriptor.
Descriptor: RelationalDescriptor(testdb.EULADocument --> [DatabaseTable(EULADOCUMENT)])
Then I tried changing the delete query statement with setDeleteSQLString, but I am stuck on how to pass the parameter values
mapping.setDeleteSQLString("DELETE FROM LICENSE_EULADOCUMENT WHERE ((values_KEY = #VALUES_KEY) AND (License_ID = #LICENSE_ID))");
says it could not find the VALUES_KEY so sets it to NULL...
What is the recommended way to modify the behaviour?

Hibernate persisting incorrect values

I have some Hibernate code running against a Postgres 9.5 DB, which looks like roughly like below (anonymized) -
Integer myEntityId = myEntity.getId();
getCurrentSession().evict(myEntity);
myEntity.setId(null);
MyEntity clonedMyEntity = (MyEntity)getCurrentSession().merge(myEntity);
myEntity.setMyBooleanField(false);
getCurrentSession().save(myEntity);
I have an entity myEntity with a large number of fields. I want to create a duplicate of the record with only 1 field value changed. To achieve this, I evict the entity from session, set Primary Key to null, merge it back to session, set the field I want to change, and then save the entity to DB. However, this code (which was working correctly for some time), is not working now. It sees incorrect value for the boolean field I am trying to modify - as a result violating some database constraints. Please help me fix this or suggest a better way to achieve what I am trying.
The error was happening not on adding this record but on add of another record to an audit table, triggered by the addition of this record. A coworker suggested me to use Eclipse Breakpoint view and use the add breakpoint option there and select the ConstraintViolationException class - this helped me to see the error for which trigger was failing and why and accordingly modify the data to suit the database constraint.

Semantic exceptions from Hibernate when SQL hits constraints

I'm using Hibernate 5.2 with Postgre 9.5.
My DB schema has several constraints. Is there any "easy" possibility to expose constraint name to end user? Imagine I have unique constraint
ALTER TABLE JobTable
ADD CONSTRAINT JobTableJobStatusEnum
CHECK (jobStatus IN ('JobSubmitted', 'JobRunning', 'JobFailed', 'JobKilled', 'JobSucceeded'));
I want to re-throw something like
ConstraintViolationException("Can't execute operation. Your query breaks JobTableJobStatusEnum")
Yeah, It won't make any sense to business users, but other developers would understand the problem. I can grab constraint def from DB and put it into exception message also.
Basically you have constraints information in exception - stacktrace.
If you need to wrap original exception and add something custom (it's not so custom it's just change exception message), you can catch ConstraintViolationException (or exception and check that it's caused by ConstraintViolationException with apache commons-lang ExceptionUtils util)
catch(ConstraintViolationException e){
Strign message = e.getCause().getMessage();
.....
work with message
String detailMessage = String.format("Can't execute operation. Your query breaks %" , message);
throw new ConstraintViolationException(detailMessage , e);
}
For mysql (for Postgre should be something similar) it looks like
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:
Duplicate entry 'testemail#gmail.com' for key
'UK_n7ihswpy07ci568w34q0oi8he'
If you know format message for ConstraintViolation in your db , you can get constraint name from exception message method.

EF CodeFirst handling database exceptions while saving changes

Since EF doesn't support unique key contraints, it seems that we need to catch exception during the Save method, and display error message to user.
The problems with this approach are:
how do we know which record threw an exception
how do we know what kind of problem threw an exception (ex I could have two unique constraints on same record, so I need to tell the user which one is broken)
DBMS is SqlServer 2008.
How to resolve these problems?
If you allow that a user can enter values that must be unique in the database you should validate this input before you save the changes:
if (context.Customers.Any(c => c.SomeUniqueProperty == userInput))
// return to user with a message to change the input value
else
context.SaveChanges();
This isn't only the case for values with unique constraints in the database but also for entering foreign key values that must refer to existing target records or primary key values if the primary key isn't autogenerated in the database. EF doesn't help you in the latter situation either because a context doesn't know the content of the whole database table but only about the entities that are currently attached to the context. It is true that EF will forbid to attach two objects with the same primary key but allows two objects with the same unique key constraint. But this doesn't guard you completely against primary key constraint violations when you save changes to the database.
In the unlikely case that between the Any check and SaveChanges another user has entered a record with the same value, I would consider the occuring exception as not possible to handle and just tell the user "An expected error occurred, please try again...". If the user tries again the Any check happens again and he will get the more useful message to change the input value from the code above.
The exception returned for such unique key constraint or primary key constraint violations is a general DbUpdateException and one of the inner exceptions will be a SqlException that contains as one of its properties a SQL Server error code. Any other details can be found only in the exception message "Violation of UNIQUE KEY constraint IX_SomeUniqueProperty_Index..." or similar. If you expect that the user can understand and react accordingly to this information you could display it. Otherwise you could log this message for an administrator or developer to check for possible bugs or other problems.