I would like to be able to define a Haskell type that can be contained in multiple database fields.
This has two example use cases:
Inlining Records
Suppose I have a datatype like
data Tax = Tax { location :: Text, amount :: Integer }
I want to include this on a record. I can manually use a schema like:
Purchase1
subtotal Integer
taxLocation Text
taxAmount Integer
and then define an intermediary data model
data Purchase2 = Purchase2
{ purchaseSubtotal :: Integer
, purchaseTax :: Tax
}
and relevant conversion functions.
However, I'd prefer to write something like:
Purchase3
subtotal Integer
tax (Inline Tax)
which would "expand" to a schema like Purchase1 defined above. The Inline type can be used to distinguish inlining the columns vs a composite type (which Postgres supports, and possible other databases).
"One Of" sum types
Suppose I write a data type like
data Choice
= A Int
| B
| C Char
| D
And I want to include this model in a field. One option is to "inline" the constructors as nullable value fields, and then use a CHECK constraint to ensure that exactly one value is present.
So a schema like:
User
name Text
choice (OneOf Choice)
could expand out to:
CREATE TABLE user (
id SERIAL PRIMARY KEY,
choice_a INT,
choice_b BOOL,
choice_c CHAR,
choice_d BOOL,
CHECK (
( choice_a IS NOT NULL AND choice_b IS NULL AND choice_c IS NULL AND choice_d IS NULL)
OR
( etc etc etc )
)
Then parsing code can safely assume that exactly one is present and provide the right constructor. This is an automated way of doing "absorption" on sub-tables, where it would be error prone to do so in app code.
As far as I can tell, this would require modifying the PersistField and PersistFieldSql definitions to be able to talk about a variable amount of columns. I'm not sure the best way to approach that would be.
I would like to be able to define a Haskell type that can be contained in multiple database fields.
This has two example use cases:
Inlining Records
Suppose I have a datatype like
I want to include this on a record. I can manually use a schema like:
and then define an intermediary data model
and relevant conversion functions.
However, I'd prefer to write something like:
which would "expand" to a schema like
Purchase1defined above. TheInlinetype can be used to distinguish inlining the columns vs a composite type (which Postgres supports, and possible other databases)."One Of" sum types
Suppose I write a data type like
And I want to include this model in a field. One option is to "inline" the constructors as nullable value fields, and then use a
CHECKconstraint to ensure that exactly one value is present.So a schema like:
could expand out to:
Then parsing code can safely assume that exactly one is present and provide the right constructor. This is an automated way of doing "absorption" on sub-tables, where it would be error prone to do so in app code.
As far as I can tell, this would require modifying the
PersistFieldandPersistFieldSqldefinitions to be able to talk about a variable amount of columns. I'm not sure the best way to approach that would be.