updateAge :: MonadIO m => ReaderT SqlBackend m ()
updateAge = updateWhere [UserName ==. "SPJ" ] [UserAge =. 45]
Similar to updateWhere which is shown in the above example you can use other functions present in the module Database.Persist.Class. Note that the first parameter of updateWhere is [Filter val] and second parameter is [Update val]. By comparing this with the type of ==. and =., you can see that they match up in the above usage.
The above query when applied on dataset-1, will produce this:
Convenience function for getting a free PersistField instance
from a type with JSON instances. The JSON parser used will accept JSON
values other that object and arrays. So, if your instance serializes the
data to a JSON string, this will still work.
This is a specialization of tabulateEntityA, which allows you to
construct an Entity by providing an Applicative action for each
field instead of a regular function.
The type of record can usually be infered from the types of the provided filters
and select options. In the previous two examples, though, you'll notice that the
select options are polymorphic, applying to any record type. In order to help
type inference in such situations, or simply as an enhancement to readability,
you might find type application useful, illustrated below.
With Asc and Desc, we can provide the field we want to sort on. We can
provide multiple sort orders - later ones are used to sort records that are
equal on the first field.
Get all records matching the given criterion in the specified order.
Returns also the identifiers.
WARNING: This function returns a ConduitM, which suggests that it streams
the results. It does not stream results on most backends. If you need
streaming, see persistent-pagination for a means of chunking results based
on indexed ranges.
Check whether there are any conflicts for unique keys with this entity and
existing entities in the database.
Returns Nothing if the entity would stay unique, and could thus safely be updated.
on a conflict returns the conflicting key
This is similar to checkUnique, except it's useful for updating - when the
particular entity already exists, it would normally conflict with itself.
This variant ignores those conflicts
A modification of getBy, which takes the PersistEntity itself instead
of a Unique record. Returns a record matching one of the unique keys. This
function makes the most sense on entities with a single Unique
constructor.
Insert a value, checking for conflicts with any unique constraints. If a
duplicate exists in the database, it is returned as Left. Otherwise, the
new 'Key is returned as Right.
onlySimonConst :: MonadIO m => ReaderT SqlBackend m (Unique User)
onlySimonConst = onlyUnique $ User "Simon" 999
mSimonConst <- onlySimonConst
mSimonConst would be Simon's uniqueness constraint. Note that
onlyUnique doesn't work if there're more than two constraints. It will
fail with a type error instead.
Attempt to replace the record of the given key with the given new record.
First query the unique fields to make sure the replacement maintains
uniqueness constraints.
Return Nothing if the replacement was made.
If uniqueness is violated, return a Just with the Unique violation
Retrieve the list of FieldDef that makes up the fields of the entity.
This does not return the fields for an Id column or an implicit id. It
will return the key columns if you used the Primary syntax for defining the
primary key.
This does not return fields that are marked SafeToRemove or MigrationOnly
- so it only returns fields that are represented in the Haskell type. If you
need those fields, use getEntityFieldsDatabase.
This returns all of the FieldDef defined for the EntityDef, including
those fields that are marked as MigrationOnly (and therefore only present
in the database) or SafeToRemove (and a migration will drop the column if
it exists in the database).
For all the fields that are present on the Haskell-type, see
getEntityFields.
Note that as of this writing the span covers the entire file or quasiquote
where the item is defined due to parsing limitations. This may be changed in
a future release to be more accurate.
Retrieve the list of UniqueDef from an EntityDef. As of version 2.14,
this will also include the primary key on the entity, if one is defined. If
you do not want the primary key, see getEntityUniquesNoPrimaryKey.
Retrieve the list of UniqueDef from an EntityDef. This does not include
a Primary key, if one is defined. A future version of persistent will
include a Primary key among the Unique constructors for the Entity.
Automatically creates a valid PersistField instance for any datatype
that has valid ToJSON and FromJSON instances. For a datatype T it
generates instances similar to these:
instance PersistField T where
toPersistValue = PersistByteString . L.toStrict . encode
fromPersistValue = (left T.pack) . eitherDecodeStrict' <=< fromPersistValue
instance PersistFieldSql T where
sqlType _ = SqlString
Splice in a list of all EntityDef in scope. This is useful when running
mkPersist to ensure that all entity definitions are available for setting
foreign keys, and for performing migrations with all entities available.
mkPersist has the type MkPersistSettings -> [EntityDef] -> DecsQ. So, to
account for entities defined elsewhere, you'll mappend $(discoverEntities).
Likewise, to run migrations with all entity instances in scope, you'd write:
migrateAll = migrateModels $(discoverEntities)
Note that there is some odd behavior with Template Haskell and splicing
groups. If you call discoverEntities in the same module that defines
PersistEntity instances, you need to ensure they are in different top-level
binding groups. You can write $(pure []) at the top level to do this.
-- Foo and Bar both export an instance of PersistEntity
import Foo
import Bar
-- Since Foo and Bar are both imported, discoverEntities can find them here.
mkPersistWith sqlSettings $(discoverEntities) [persistLowerCase|
User
name Text
age Int
|]
-- onlyFooBar is defined in the same 'top level group' as the above generated
-- instance for User, so it isn't present in this list.
onlyFooBar :: [EntityDef]
onlyFooBar = $(discoverEntities)
-- We can manually create a new binding group with this, which splices an
-- empty list of declarations in.
$(pure [])
-- fooBarUser is able to see the User instance.
fooBarUser :: [EntityDef]
fooBarUser = $(discoverEntities)
The function mkMigrate currently implements exactly this behavior now. If
you're splitting up the entity definitions into separate files, then it is
better to use the entity definition list and the concatenate all the models
together into a big list to call with migrateModels.
module Foo where
share [mkPersist s, mkEntityDefList "fooModels"] ...
module Bar where
share [mkPersist s, mkEntityDefList "barModels"] ...
module Migration where
import Foo
import Bar
migrateAll = migrateModels (fooModels <> barModels)
Creates a declaration for the [EntityDef] from the persistent
schema. This is necessary because the Persistent QuasiQuoter is unable
to know the correct type of ID fields, and assumes that they are all
Int64.
Provide this in the list you give to share, much like mkMigrate.
Creates a single function to perform all migrations for the entities
defined here. One thing to be aware of is dependencies: if you have entities
with foreign references, make sure to place those definitions after the
entities they reference.
In persistent-2.13.0.0, this was changed to *ignore* the input entity def
list, and instead defer to mkEntityDefList to get the correct entities.
This avoids problems where the QuasiQuoter is unable to know what the right
reference types are. This sets mkPersist to be the "single source of truth"
for entity definitions.
This function should be used if you are only defining a single block of
Persistent models for the entire application. If you intend on defining
multiple blocks in different fiels, see mkPersistWith which allows you
to provide existing entity definitions so foreign key references work.
Like mkPersist, but allows you to provide a [EntityDef]
representing the predefined entities. This function will include those
EntityDef when looking for foreign key references.
You should use this if you intend on defining Persistent models in
multiple files.
Suppose we define a table Foo which has no dependencies.
Same as persistFileWith, but uses several external files instead of
one. Splitting your Persistent definitions into multiple modules can
potentially dramatically speed up compile times.
The recommended file extension is .persistentmodels.
Examples
Split your Persistent definitions into multiple files (models1, models2),
then create a new module for each new file and run mkPersist there:
Tip: To get the same import behavior as if you were declaring all your models in
one file, import your new files as Name into another file, then export module Name.
This approach may be used in the future to reduce memory usage during compilation,
but so far we've only seen mild reductions.
Most functions require a full [EntityDef], which can be provided
using $(discoverEntities) for all entites in scope, or defining
mkEntityDefList to define a list of entities from the given block.
Returns a NonEmpty list of FieldDef that correspond with the key
columns for an EntityDef including those fields that are marked as
MigrationOnly (and therefore only present in the database) or
SafeToRemove (and a migration will drop the column if it exists in the
database).
Parse raw field attributes into structured form. Any unrecognized
attributes will be preserved, identically as they are encountered,
as FieldAttrOther values.
A backwards-compatible alias for those that don't care about distinguishing between read and write queries.
It signifies the assumption that, by default, a backend can write as well as read.
A backwards-compatible alias for those that don't care about distinguishing between read and write queries.
It signifies the assumption that, by default, a backend can write as well as read.
A backwards-compatible alias for those that don't care about distinguishing between read and write queries.
It signifies the assumption that, by default, a backend can write as well as read.
Represents a value containing all the configuration options for a specific
backend. This abstraction makes it easier to write code that can easily swap
backends.
Datatype that represents an entity, with both its Key and
its Haskell record representation.
When using a SQL-based backend (such as SQLite or
PostgreSQL), an Entity may take any number of columns
depending on how many fields it has. In order to reconstruct
your entity on the Haskell side, persistent needs all of
your entity columns and in the right order. Note that you
don't need to worry about this when using persistent's API
since everything is handled correctly behind the scenes.
However, if you want to issue a raw SQL command that returns
an Entity, then you have to be careful with the column
order. While you could use SELECT Entity.* WHERE ... and
that would work most of the time, there are times when the
order of the columns on your database is different from the
order that persistent expects (for example, if you add a new
field in the middle of you entity definition and then use the
migration code -- persistent will expect the column to be in
the middle, but your DBMS will put it as the last column).
So, instead of using a query like the one above, you may use
rawSql (from the
Database.Persist.Sql module) with its /entity
selection placeholder/ (a double question mark ??). Using
rawSql the query above must be written as SELECT ?? WHERE
... Then rawSql will replace ?? with the list of all
columns that we need from your entity in the right order. If
your query returns two entities (i.e. (Entity backend a,
Entity backend b)), then you must you use SELECT ??, ??
WHERE ..., and so on.
An EntityField is parameterised by the Haskell record it belongs to
and the additional type of that field.
As of persistent-2.11.0.0, it's possible to use the OverloadedLabels
language extension to refer to EntityField values polymorphically. See
the documentation on SymbolToField for more information.
Instances1IsLabel
SymbolToFieldsymrectyp => IsLabelsym (EntityFieldrectyp)Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistEntity
This instance delegates to SymbolToField to provide
OverloadedLabels support to the EntityField type.
Filters which are available for select, updateWhere and
deleteWhere. Each filter constructor specifies the field being
filtered on, the type of comparison applied (equals, not equals, etc)
and the argument for the comparison.
Persistent users use combinators to create these.
Note that it's important to be careful about the PersistFilter that
you are using, if you use this directly. For example, using the InPersistFilter requires that you have an array- or list-shaped
EntityField. It is possible to construct values using this that will
create malformed runtime values.
Persistent serialized Haskell records to the database.
A Database Entity (A row in SQL, a document in MongoDB, etc)
corresponds to a Key plus a Haskell record.
For every Haskell record type stored in the database there is a
corresponding PersistEntity instance. An instance of PersistEntity
contains meta-data for the record. PersistEntity also helps abstract
over different record types. That way the same query interface can return
a PersistEntity, with each query returning different types of Haskell
records.
Some advanced type system capabilities are used to make this process
type-safe. Persistent users usually don't need to understand the class
associated data and functions.
An EntityField is parameterised by the Haskell record it belongs to
and the additional type of that field.
As of persistent-2.11.0.0, it's possible to use the OverloadedLabels
language extension to refer to EntityField values polymorphically. See
the documentation on SymbolToField for more information.
This function allows you to build an Entity a by specifying an
action that returns a value for the field in the callback function.
Let's look at an example.
parseFromEnvironmentVariables :: IO (Entity User)
parseFromEnvironmentVariables =
tabulateEntityA $ \userField ->
case userField of
UserName ->
getEnv USER_NAME
UserAge -> do
ageVar <- getEnv USER_AGE
case readMaybe ageVar of
Just age ->
pure age
Nothing ->
error $ "Failed to parse Age from: " <> ageVar
UserAddressId -> do
addressVar <- getEnv USER_ADDRESS_ID
pure $ AddressKey addressVar
Like tabulateEntityA, but works with any Apply f. This works
because all entities have at least one field, and so we can tabulate
things into semigroup-like shapes instead.
Extract a Key record from a record value. Currently, this is
only defined for entities using the Primary syntax for
natural/composite keys. In a future version of persistent which
incorporates the ID directly into the entity, this will always be Just.
A type class which is used to witness that a type is safe to insert into
the database without providing a primary key.
The TemplateHaskell function mkPersist will generate instances of this
class for any entity that it works on. If the entity has a default primary
key, then it provides a regular instance. If the entity has a Primary
natural key, then this works fine. But if the entity has an Id column with
no default=, then this does a TypeError and forces the user to use
insertKey.
Instances2SafeToInsert
TypeError (EntityErrorMessagea) => SafeToInsert (Entitya)Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistEntity
TypeError (FunctionErrorMessageab) => SafeToInsert (a -> b)Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistEntity
This type class is used with the OverloadedLabels extension to
provide a more convenient means of using the EntityField type.
EntityField definitions are prefixed with the type name to avoid
ambiguity, but this ambiguity can result in verbose code.
If you have a table User with a name Text field, then the
corresponding EntityField is UserName. With this, we can write
#name :: EntityField User Text.
What's more fun is that the type is more general: it's actually
#name
:: (SymbolToField "name" rec typ)
=> EntityField rec typ
Which means it is *polymorphic* over the actual record. This allows you
to write code that can be generic over the tables, provided they have
the right fields.
Prior to persistent-2.11.0, we provided an instance of
PersistField for the Natural type. This was in error, because
Natural represents an infinite value, and databases don't have
reasonable types for this.
The instance for Natural used the Int64 underlying type, which will
cause underflow and overflow errors. This type has the exact same code
in the instances, and will work seamlessly.
A more appropriate type for this is the Word series of types from
Data.Word. These have a bounded size, are guaranteed to be
non-negative, and are quite efficient for the database to store.
This type uses the SqlInt64 version, which will exhibit overflow and
underflow behavior. Additionally, it permits negative values in the
database, which isn't ideal.
In this example, we create a PersistField instance for a newtype following the "Smart Constructor" pattern.
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import qualified Data.Text as T
import qualified Data.Char as C
-- | An American Social Security Number
newtype SSN = SSN Text
deriving (Eq, Show, PersistFieldSql)
mkSSN :: Text -> EitherText SSN
mkSSN t = if (T.length t == 9) && (T.all C.isDigit t)
then Right $ SSN t
else Left $ "Invalid SSN: " <> t
instance PersistField SSN where
toPersistValue (SSN t) = PersistText t
fromPersistValue (PersistText t) = mkSSN t
-- Handle cases where the database does not give us PersistText
fromPersistValue x = Left $ "File.hs: When trying to deserialize an SSN: expected PersistText, received: " <> T.pack (show x)
Tips:
This file contain dozens of PersistField instances you can look at for examples.
TypeError ((((('Text"The instance of PersistField for the Natural type was removed." ':$$: 'Text"Please see the documentation for OverflowNatural if you want to ") ':$$: 'Text"continue using the old behavior or want to see documentation on ") ':$$: 'Text"why the instance was removed.") ':$$: 'Text"") ':$$: 'Text"This error instance will be removed in a future release.") => PersistFieldNaturalDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldHtmlDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldByteStringDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldInt16Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldInt32Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldInt64Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldInt8Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldRationalDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldBoolDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldDoubleDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldIntDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldWordDefined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldWord16Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldWord32Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldWord64Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
PersistFieldWord8Defined in persistent-2.18.1.0 · Database.Persist.Class.PersistField
Get all records matching the given criterion in the specified order.
Returns also the identifiers.
NOTE: This function returns an Acquire and a ConduitM, which implies
that it streams from the database. It does not. Please use selectList
to simplify the code. If you want streaming behavior, consider
persistent-pagination which efficiently chunks a query into ranges, or
investigate a backend-specific streaming solution.
This class witnesses that two backend are compatible, and that you can
convert from the sub backend into the sup backend. This is similar
to the HasPersistBackend and IsPersistBackend classes, but where you
don't want to fix the type associated with the PersistEntityBackend of
a record.
This works for SqlReadBackend because of the instance BackendCompatibleSqlBackendSqlReadBackend, without needing to go through the BaseBackend type family.
Likewise, functions that are currently hardcoded to use SqlBackend can be generalized:
Class which allows the plucking of a BaseBackend backend from some larger type.
For example,
instance HasPersistBackend (SqlReadBackend, Int) where
type BaseBackend (SqlReadBackend, Int) = SqlBackend
persistBackend = unSqlReadBackend . fst
Class which witnesses that backend is essentially the same as BaseBackend backend.
That is, they're isomorphic and backend is just some wrapper over BaseBackend backend.
Replace the record in the database with the given
key. Note that the result is undefined if such record does
not exist, so you must use insertKey or repsert in
these cases.
ToBackendKey converts a PersistEntityKey into a BackendKey
This can be used by each backend to convert between a Key and a plain
Haskell type. For Sql, that is done with toSqlKey and fromSqlKey.
By default, a PersistEntity uses the default BackendKey for its Key
and is an instance of ToBackendKey
A Key that instead uses a custom type will not be an instance of
ToBackendKey.
This class is used to ensure that functions requring at least one
unique key are not called with records that have 0 unique keys. The
quasiquoter automatically writes working instances for appropriate
entities, and generates TypeError instances for records that have
0 unique keys.
StypetypeMultipleUniqueKeysErrorty = ((('Text"The entity " ':<>: 'ShowTypety) ':<>: 'Text" has multiple unique keys.") ':$$: ('Text"The function you are trying to call requires only a single " ':<>: 'Text"unique key.")) ':$$: (('Text"There is probably a variant of the function with 'By' " ':<>: 'Text"appended that will allow you to select a unique key ") ':<>: 'Text"for the operation.")
This is an error message. It is used when an entity has multiple
unique keys, and the function expects a single unique key.
StypetypeNoUniqueKeysErrorty = (('Text"The entity " ':<>: 'ShowTypety) ':<>: 'Text" does not have any unique keys.") ':$$: ('Text"The function you are trying to call requires a unique key " ':<>: 'Text"to be defined on the entity.")
This class is used to ensure that upsert is only called on records
that have a single Unique key. The quasiquoter automatically generates
working instances for appropriate records, and generates TypeError
instances for records that have 0 or multiple unique keys.
Queries against Unique keys (other than the id Key).
Please read the general Persistent documentation to learn how to create
Unique keys.
Using this with an Entity without a Unique key leads to undefined
behavior. A few of these functions require a singleUnique, so using
an Entity with multiple Uniques is also undefined. In these cases
persistent's goal is to throw an exception as soon as possible, but
persistent is still transitioning to that.
SQL backends automatically create uniqueness constraints, but for MongoDB
you must manually place a unique index on a field to have a uniqueness
constraint.
Some functions in this module (insertUnique, insertBy, and
replaceUnique) first query the unique indexes to check for
conflicts. You could instead optimistically attempt to perform the
operation (e.g. replace instead of replaceUnique). However,
there is some fragility to trying to catch the correct exception and
determing the column of failure;
an exception will automatically abort the current SQL transaction.
Update based on a uniqueness constraint or insert:
insert the new record if it does not exist;
If the record exists (matched via it's uniqueness constraint), then update the existing record with the parameters which is passed on as list to the function.
Next, what if the schema has two uniqueness constraints?
Let's check it out using schema-2:
mSpjEnt <- upsertSpj [UserAge +=. 15]
This fails with a compile-time type error alerting us to the fact
that this record has multiple unique keys, and suggests that we look for
upsertBy to select the unique key we want.
upsertBySpjName :: MonadIO m => User -> [Update User] -> ReaderT SqlBackend m (Entity User)
upsertBySpjName record updates = upsertBy (UniqueUserName "SPJ") record updates
mSpjEnt <- upsertBySpjName (Person "X" 999) [PersonAge += .15]
upsertBySimonAge :: MonadIO m => User -> [Update User] -> ReaderT SqlBackend m (Entity User)
upsertBySimonAge record updates = upsertBy (UniqueUserName "SPJ") record updates
mPhilipEnt <- upsertBySimonAge (User "X" 999) [UserName =. "Philip"]
+----+-----------------+-----+
| id | name | age |
+----+-----------------+-----+
| 1 | SPJ | 40 |
+----+-----------------+-----+
| 2 | Simon -> Philip | 41 |
+----+-----------------+-----+
upsertByUnknownName :: MonadIO m => User -> [Update User] -> ReaderT SqlBackend m (Entity User)
upsertByUnknownName record updates = upsertBy (UniqueUserName "Unknown") record updates
mXEnt <- upsertByUnknownName (User "X" 999) [UserAge +=. 15]
A specification for how the implied ID columns are created.
By default, persistent will give each table a default column named id
(customizable by PersistSettings), and the column type will be whatever
you'd expect from BackendKey yourBackendType. For The SqlBackend type,
this is an auto incrementing integer primary key.
You might want to give a different example. A common use case in postgresql
is to use the UUID type, and automatically generate them using a SQL
function.
Previously, you'd need to add a custom Id annotation for each model.
User
Id UUID default="uuid_generate_v1mc()"
name Text
Dog
Id UUID default="uuid_generate_v1mc()"
name Text
user UserId
Now, you can simply create an ImplicitIdDef that corresponds to this
declaration.
newtype UUID = UUID ByteString
instance PersistField UUID where
toPersistValue (UUID bs) =
PersistLiteral_Escaped bs
fromPersistValue pv =
case pv of
PersistLiteral_ Escaped bs ->
Right (UUID bs)
_ ->
Left "nope"
instance PersistFieldSql UUID where
sqlType _ = SqlOtherUUID
With this instance at the ready, we can now create our implicit definition:
The DbSpecific constructor corresponds to the legacy
PersistDbSpecific constructor. We need to keep this around because
old databases may have serialized JSON representations that
reference this. We don't want to break the ability of a database to
load rows.
Instances4Eq, Ord, Read, Show
EqLiteralTypeDefined in persistent-2.18.1.0 · Database.Persist.PersistValue
OrdLiteralTypeDefined in persistent-2.18.1.0 · Database.Persist.PersistValue
ReadLiteralTypeDefined in persistent-2.18.1.0 · Database.Persist.PersistValue
ShowLiteralTypeDefined in persistent-2.18.1.0 · Database.Persist.PersistValue
This constructor is used to specify some raw literal value for the
backend. The LiteralType value specifies how the value should be
escaped. This can be used to make special, custom types avaialable
in the back end.
Deprecated. Deprecated since 2.11 because of inconsistent escaping behavior across backends. The Postgres backend escapes these values, while the MySQL backend does not. If you are using this, please switch to PersistLiteral_ and provide a relevant LiteralType for your conversion.
This pattern synonym used to be a data constructor for the
PersistValue type. It was changed to be a pattern so that JSON-encoded
database values could be parsed into their corresponding values. You
should not use this, and instead prefer to pattern match on
PersistLiteral_ directly.
If you use this, it will overlap a patern match on the 'PersistLiteral_,
PersistLiteral, and PersistLiteralEscaped patterns. If you need to
disambiguate between these constructors, pattern match on
PersistLiteral_ directly.
This pattern synonym used to be a data constructor on PersistValue,
but was changed into a catch-all pattern synonym to allow backwards
compatiblity with database types. See the documentation on
PersistDbSpecific for more details.
This pattern synonym used to be a data constructor on PersistValue,
but was changed into a catch-all pattern synonym to allow backwards
compatiblity with database types. See the documentation on
PersistDbSpecific for more details.
Settings that can be passed to the mkPersist (mps) function to control what code is generated.
This is (just) the data type definition, so you will most likely want to use and adapt concrete values
like sqlSettings.
Deprecated. The mpsGeneric function adds a considerable amount of overhead and complexity to the library without bringing significant benefit. We would like to remove it. If you require this feature, please comment on the linked GitHub issue, and we'll either keep it around, or we can figure out a nicer way to solve your problem.Github: https://github.com/yesodweb/persistent/issues/1204
Create generic types that can be used with multiple backends. Good for
reusable code, but makes error messages harder to understand. Default:
False.
A Checkmark should be used as a field type whenever a
uniqueness constraint should guarantee that a certain kind of
record may appear at most once, but other kinds of records may
appear any number of times.
NOTE: You need to mark any Checkmark fields as nullable
(see the following example).
For example, suppose there's a Location entity that
represents where a user has lived:
Location
user UserId
name Text
current Checkmark nullable
UniqueLocation user current
The UniqueLocation constraint allows any number of
InactiveLocations to be current. However, there may be
at most one currentLocation per user (i.e., either zero
or one per user).
This data type works because of the way that SQL treats
NULLable fields within uniqueness constraints. The SQL
standard says that NULL values should be considered
different, so we represent Inactive as SQL NULL, thus
allowing any number of Inactive records. On the other hand,
we represent Active as TRUE, so the uniqueness constraint
will disallow more than one Active record.
Note: There may be DBMSs that do not respect the SQL
standard's treatment of NULL values on uniqueness
constraints, please check if this data type works before
relying on it.
The SQL BOOLEAN type is used because it's the smallest data
type available. Note that we never use FALSE, just TRUE
and NULL. Provides the same behavior Maybe () would if
() was a valid PersistField.
An EntityDef represents the information that persistent knows
about an Entity. It uses this information to generate the Haskell
datatype, the SQL migrations, and other relevant conversions.
Instances5Eq, Ord, Read, Show, Lift
EqEntityDefDefined in persistent-2.18.1.0 · Database.Persist.Types.Base
OrdEntityDefDefined in persistent-2.18.1.0 · Database.Persist.Types.Base
ReadEntityDefDefined in persistent-2.18.1.0 · Database.Persist.Types.Base
ShowEntityDefDefined in persistent-2.18.1.0 · Database.Persist.Types.Base
LiftEntityDefDefined in persistent-2.18.1.0 · Database.Persist.Types.Base
This indicates that the column is nullable, but should not have
a Maybe type. For this to work out, you need to ensure that the
PersistField instance for the type in question can support
a PersistNull value.
data What = NoWhat | Hello Text
instance PersistField What where
fromPersistValue PersistNull =
pure NoWhat
fromPersistValue pv =
Hello $ fromPersistValue pv
instance PersistFieldSql What where
sqlType _ = SqlString
User
what What nullable
This tag means that the column will not be present on the Haskell code,
but will not be removed from the database. Useful to deprecate fields in
phases.
You should set the column to be nullable in the database. Otherwise,
inserts won't have values.
A SafeToRemove attribute is not present on the Haskell datatype, and
the backend migrations should attempt to drop the column without
triggering any unsafe migration warnings.
Useful after you've used MigrationOnly to remove a column from the
database in phases.
This attribute indicates that we should not create a foreign key
reference from a column. By default, persistent will try and create a
foreign key reference for a column if it can determine that the type of
the column is a Key entity or an EntityId and the Entity's name
was present in mkPersist.
This is useful if you want to use the explicit foreign key syntax.
Post
title Text
Comment
postId PostId noreference
Foreign Post fk_comment_post postId
This is set to specify precisely the database table the column refers
to.
Post
title Text
Comment
postId PostId references="post"
You should not need this - persistent should be capable of correctly
determining the target table's name. If you do need this, please file an
issue describing why.
This datatype describes how a foreign reference field cascades deletes
or updates.
This type is used in both parsing the model definitions and performing
migrations. A Nothing in either of the field values means that the
user has not specified a CascadeAction. An unspecified CascadeAction
is defaulted to Restrict when doing migrations.
A FieldDef represents the inormation that persistent knows about
a field of a datatype. This includes information used to parse the field
out of the database and what the field corresponds to.
The name of the field. Note that this does not corresponds to the
record labels generated for the particular entity - record labels
are generated with the type name prefixed to the field, so
a FieldDef that contains a FieldNameHS "name" for a type
User will have a record field userName.
Defines how operations on the field cascade on to the referenced
tables. This doesn't have any meaning if the fieldReference is set
to NoReference or SelfReference. The cascade option here should
be the same as the one obtained in the fieldReference.
A SQL data type. Naming attempts to reflect the underlying Haskell
datatypes, eg SqlString instead of SqlVarchar. Different SQL databases may
have different translations for these types.
The reason why a field is nullable is very important. A
field that is nullable because of a Maybe tag will have its
type changed from A to Maybe A. OTOH, a field that is
nullable because of a nullable tag will remain with the same
type.