Search code examples
grailsgrails-orm

grails/gorm multi column unique constraint violation


I've included my domains below. I'm trying to specify a unique constraint on a column that would make the column unique based on the value of another column, and unique within the parent domain.

public enum PostStatus {
    PUBLISHED,
    PENDING_REVIEW,
    DRAFT,
    TRASH
}

public enum PostType {
    INTRO,
    FUTURE,
    FAMILY
}


class Post {


    String content
    PostType postType
    PostStatus postStatus
    Date dateCreated
    Date lastUpdated
    static belongsTo = [basicProfile:BasicProfile]

    static constraints = {
        content(blank:true, nullable:true, maxSize:5000)
        postType(blank:false, nullable:false)
        postStatus(blank:false, nullable:false, unique:'postType') //status must be unique within each postType, and within the parent.
    }
    static mapping = {
        content sqlType:'text'
    }
}

class Profile {
    static hasMany = [
            post:Post
    ]
}

Right now the postStatus is unique within the postType, but it applies the unique constraint to the Post table. So the table allows one postStatus per postType and then a unique constraint violation occurs. What I need is one unique postStatus per postType for each Profile.

post table insert example: good record #1: profile id: 1 post_status: DRAFT post_type: INTRO

good record #2: profile id: 1 post_status: PUBLISHED post_type: INTRO

good record #3: profile id: 1 post_status: DRAFT post_type: FUTURE

bad record #4, violates unique constraint with record 1 even though it's for a different profile id. profile id: 2 post_status: DRAFT post_type: INTRO

The Post belongTo a Profile, so how would I define the constraint to make it unique per Profile? Essentially I'm trying to get at a compound unique key:

profile.id + postType + postStatus


Solution

  • Have you tried the last example described at http://grails.org/doc/latest/ref/Constraints/unique.html ?

    e.g: postStatus(blank:false, nullable:false, unique:['postType', 'basicProfile'])