Skip to content

Cannot create complex circular relationships between tables and datatypes #147

@ghost

Description

The title here is a bit misleading, but the basic idea is that complex mutually-dependent tables and datatypes are not currently possible.

An example:

Foo
    name Text
Bar
    name Text
    parent Parent

This schema will work fine if Parent is declared before the splice occurs. However, we run into a problem if we want the following:

data Parent = ParentFoo FooId | ParentBar BarId
    deriving (Show, Read, Eq)

This datatype depends on the datatypes introduced by mkPersist, but mkPersist also depends on those datatypes. The natural (for an experienced programmer, anyway) approach is to include the declaration of Parent in the splice:

$(concat <$> sequence [ [d| data Parent = ParentFoo $(conT $ mkName "FooId")
                                        | ParentBar $(conT $ mkName "BarId")
                        |]
                      , derivePersistField "Parent"
                      , mkPersist ps $(persistFileWith lowerCaseSettings modelFile)
                      ])

This approach still has a problem though! Because persistFileWith returns the SqlType unadorned in the FieldDef, the compiler attempts to splice in the Parent datatype in the inner splice, which naturally fails.

This two-stage problem has been seen before, as is evidenced by the code in getSqlType in Database.Persist.TH, which has to work around the issue.

Better, I think, would be to return a lifted Exp, changing the type of the EntityDef spliced in by persistFileWith (and other functions that produce EntityDefs) from EntityDef SqlType to EntityDef SqlTypeExp, as this will allow the splicing of the SqlType to be delayed until the outer splice, where the new datatype is visible and able to be compiled mutually with the rest of the database schema.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions