Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persistent2 custom primary keys are not supported #87

Open
albertov opened this issue Dec 16, 2014 · 8 comments
Open

Persistent2 custom primary keys are not supported #87

albertov opened this issue Dec 16, 2014 · 8 comments

Comments

@albertov
Copy link
Contributor

I'm trying to upgrade an existing application to latest Persistent2 and custom primary keys do not seem to be supported. My model definition is

Frontcover
    number Int
    publish UTCTime
    unpublish UTCTime
    created UTCTime
    modified UTCTime
    Primary number
    deriving Show Typeable

selecting/inserting Frontcover rows via Persistent2 works as expected, however, when trying to use the Frontcover entity in an Esqueleto query a runtime error is raised since a frontcover.id spurious columns is generated in the SQL.

The error is:

16/Dec/2014:19:17:34 +0100 [Error] InternalError "user error (Postgresql.withStmt': bad result status FatalError ((\"PGRES_FATAL_ERROR\",\"ERROR:  column frontcover.id does not exist\\nLINE 2: ...tcover\\\" ON \\\"article_frontcover\\\".\\\"frontcover_id\\\" = \\\"frontcove...\\n                                                             ^\\n\")))" @(CapitalMadrid-0.1.0.0:Foundation Foundation.hs:159:17)

An the Esqueleto query is:

    frontcoverQuery = 
      from $ \(fc `LeftOuterJoin` ar_fc
                  `LeftOuterJoin` ar
                  `LeftOuterJoin` cat
                  `LeftOuterJoin` usr
                  `LeftOuterJoin` ar_im
                  `LeftOuterJoin` im
                  `LeftOuterJoin` usr_im
                  `LeftOuterJoin` ar_tg) -> do
             on (ar?.ArticleId ==. ar_tg?.ArticleTagArticleId)
             on (usr?.UserImageId ==. just (usr_im?.ImageId))
             on (ar_im?.ArticleImImageId ==. im?.ImageId)
             on (ar_im?.ArticleImArticleId ==. ar?.ArticleId)
             on (ar?.ArticleAuthorId ==. just (usr?.UserUserId))
             on (ar?.ArticleCategoryId ==. just (cat?.CategoryId))
             on (ar_fc?.ArticleFrontcoverArticleId ==. ar?.ArticleId)
             on (ar_fc?.ArticleFrontcoverFrontcoverId ==. just (fc^.FrontcoverId))
             where_ $ fc^.FrontcoverId ==. fcId
             orderBy [asc (fc^.FrontcoverId), asc (ar?.ArticleId)]
             return (fc, ar, ar_fc, cat, usr, usr_im, im, ar_im, ar_tg)

Perhaps I'm missing something or doing something wrong?

@meteficha
Copy link
Member

@snoyberg, is @albertov the first one to try using custom primary keys on esqueleto?

I think esqueleto needs some work to support this use case :(.

@snoyberg
Copy link
Contributor

I haven't tried the new feature at all, I'm not actually very familiar with it. @gregwebs do you have any ideas on what changes to esqueleto might by necessary to add support?

@gregwebs
Copy link
Contributor

I have never looked at esqueleto source code. It is likely assuming an id field exists rather than getting the actual column name.

@meteficha
Copy link
Member

The assumptions are encoded on the Entity instance of the SqlSelect class. I'm not familiar with the new custom primary keys, but esqueleto isn't assuming anything about the name of the column, only that there is only one of them (e.g., (+1), idCol:). The EntityDef data type is still as undocumented as ever, so it's not obvious before looking at the backend&TH code what it should use instead of entityId, nor why this field still exists if it works just partially.

Does anyone want to take a stab at this?

@gregwebs
Copy link
Contributor

Thanks for the pointer to the esqueleto code.

entityId is there because EntityDef is not modeled with a sum type (I am not sure if changing to a sum type would work). This change to support primary keys was actually made before I every started making persistent 2 changes, but users did not know about it until it was publicized in the persistent 2 announcement.

The persistent code base checks the entityPrimary field before checking entityId. This can be seen (by searching for entityPrimary) in the persistent repo in persistent/Database/Persist/Sql/Orphan/{PersistStore,PersistUnique,PersistQuery}.hs

We should expose some of that functionality from persistent so that it does not need to be duplicated in esqueleto.

@albertov
Copy link
Contributor Author

I believe @gbwey took a stab at supporting composite primary keys (which I assume is a more general case of this concrete "custom pk" case) a couple of months ago here.

However, I've tried merging his fork and and linking against it but the problem remains :(

I'm still a bit overwhelmed with persistent/esqueleto's internals (I still consider myself a Haskell noob) but I think I might be able to give it a stab taking some inspiration from @gbwey's patch. Feel free to beat me to it though... :)

@albertov
Copy link
Contributor Author

I've just took a stab at it and it seems to work :). See pull requests above.

@albertov
Copy link
Contributor Author

Unfortunately I'm still getting the same error when compiling my app against the code from PR #88 (even though the unit tests I made pass !?). Perhaps its a stupid mistake on my part (like linking against old code, or whatever... I'm hungry) or maybe it is related to returning a tuple of entities instead of a single one, or related to the joins...

I'll investigate later when I have some rest and sugar in my blood.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants