grails-data-mapping icon indicating copy to clipboard operation
grails-data-mapping copied to clipboard

Unique constraint is not multiple data source aware

Open hamza3202 opened this issue 8 years ago • 13 comments

Hi

As i understand, the unique constraint should only ensure uniqueness in one datasource but in case of multiple datasource it is checking for uniqueness across all the datasources.

github.com/hamza3202/grails-unique-constraint-bug is a sample project. Just run it and open localhost:8080/abc/index and you should see the error. I am on grails 3.2.2 java 1.8

hamza3202 avatar Feb 16 '17 14:02 hamza3202

Is there supposed to be a sample attached?

graemerocher avatar Feb 16 '17 14:02 graemerocher

Sorry. Attached now.

hamza3202 avatar Feb 16 '17 14:02 hamza3202

It isn't that it is applied across all datasource. The issue is that unique only operates against the default datasource.

Currently there is no easy fix for this, a workaround would be to use the validator constraint to define a validator that queries the correct datasource

graemerocher avatar Feb 17 '17 10:02 graemerocher

how can a validator identify the datasource?

hamza3202 avatar Feb 17 '17 10:02 hamza3202

By scoping the query that looks up the existing instance i.e. something like:

static constraints = {
    temp validator: { val, obj, errors ->
        def existing = Abc.second.findByTemp(temp)
        if(existing) {
                errors.rejectValue("temp","abc.temp.invalidValue")
        }
    }
}

graemerocher avatar Feb 17 '17 10:02 graemerocher

Actually in the validator we need to somehow identify if the record is being saved in default datasource or second datasource and then check if the value exists in that datasource. Your solution only insures uniqueness in one datasource

hamza3202 avatar Feb 17 '17 10:02 hamza3202

well that is a different requirement all together and will definitely need a custom validator :)

graemerocher avatar Feb 17 '17 11:02 graemerocher

Isn't that what the unique constraint should do by default? ensure uniqueness across one datasource only? As in column temp should be unique in datasource a and it should be unique in data source b too but not combined? So that we can have the same record in datasource a and datasource b?

hamza3202 avatar Feb 17 '17 11:02 hamza3202

Right yes I see what you are saying, never the less there is no way to do what you are trying to achieve right now with the current constraint mechanism and you will have to write logic in a service or controller that performs the check manually.

graemerocher avatar Feb 17 '17 11:02 graemerocher

Also it would be a lot simpler to implement a custom validator which ensures uniqueness across datasource if someone needs it. So the default should handle this case that i mentioned above

hamza3202 avatar Feb 17 '17 11:02 hamza3202

Like I said the fix is not simple, as we would need to change GORM significantly to pass through the state necessary to the validation infrastructure, but of course pull requests are always welcome

graemerocher avatar Feb 17 '17 11:02 graemerocher

I have found another application specific work around for my case but i am sure i will definitely need this in the future with other projects.

hamza3202 avatar Feb 17 '17 11:02 hamza3202

Hi @graemerocher when you get back to this, it will be great if you could allow some option to allow unique constraint across multiple datasources as well because I have ended up needing it too in the same project

hamza3202 avatar Mar 08 '17 18:03 hamza3202