!Uc'      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~None>@AHV persistentRepresents a value containing all the configuration options for a specific backend. This abstraction makes it easier to write code that can easily swap backends. persistent Load the config settings from a -, most likely taken from a YAML config file. persistent:Modify the config settings based on environment variables. persistent@Create a new connection pool based on the given config settings. persistent;Run a database action by taking a connection from the pool. None 2>@AHVM' persistentA 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.& persistentAlways uses UTC timezone( persistenta backend-specific name) persistentTA raw value which can be stored in any backend and can be marshalled to and from a  PersistField.6 persistent'Intended especially for MongoDB backend7 persistent:Intended especially for PostgreSQL backend for text arrays8 persistentUsing 8 allows you to use types specific to a particular backend For example, below is a simple example of the PostGIS geography type: data Geo = Geo ByteString instance PersistField Geo where toPersistValue (Geo t) = PersistDbSpecific t fromPersistValue (PersistDbSpecific t) = Right $ Geo $ Data.ByteString.concat ["'", t, "'"] fromPersistValue _ = Left "Geo values must be converted from PersistDbSpecific" instance PersistFieldSql Geo where sqlType _ = SqlOther "GEOGRAPHY(POINT,4326)" toPoint :: Double -> Double -> Geo toPoint lat lon = Geo $ Data.ByteString.concat ["'POINT(", ps $ lon, " ", ps $ lat, ")'"] where ps = Data.Text.pack . show PIf Foo has a geography field, we can then perform insertions like the following: insert $ Foo (toPoint 44 44) : persistentGeneric ExceptionI persistent>Used instead of FieldDef to generate a smaller amount of codeT persistent|An EmbedFieldDef is the same as a FieldDef But it is only used for embeddedFields so it only has data needed for embeddingX persistentW< can create a cycle (issue #311) when a cycle is detected, W will be Nothing and X will be JustY persistentAn EmbedEntityDef is the same as an EntityDef But it is only used for fieldReference so it only has data needed for embedding] persistentpThere are 3 kinds of references 1) composite (to fields that exist in the record) 2) single field 3) embedded_ persistentA ForeignRef has a late binding to the EntityDef it references via HaskellName and has the Haskell type of the foreign key in the form of FieldTypeb persistentcA SelfReference stops an immediate cycle which causes non-termination at compile-time (issue #311).c persistentA c 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.e persistentThe 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 c that contains a u "name" for a type User will have a record field userName.f persistent_The name of the field in the database. For SQL databases, this corresponds to the column name.g persistent!The type of the field in Haskell.h persistent(The type of the field in a SQL database.i persistent:User annotations for a field. These are provided with the ! operator.j persistent If this is \, then the Haskell datatype will have a strict record field. The default value for this is .l  persistentOptional comments for a FieldQ. There is not currently a way to attach comments to a field in the quasiquoter.n persistentOptional module and name.y persistentAn y! 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.{ persistent1The name of the entity as Haskell understands it.| persistent;The name of the database table corresponding to the entity.} persistent'The entity's primary key or identifier.~ persistentThe  persistent+ entity syntax allows you to add arbitrary qs to an entity using the !5 operator. Those attributes are stored in this list. persistentThe fields for this entity. Note that the ID field will not be present in this list. To get all of the fields for an entity, use . persistent+The Uniqueness constraints for this entity. persistentFThe foreign key relationships that this entity has to other entities. persistent>A list of type classes that have been derived for this entity. persistentAWhether or not this entity represents a sum type in the database.  persistent Optional comments on the entity. persistentThe 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 A0. OTOH, a field that is nullable because of a nullable% tag will remain with the same type. persistentA  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 Location0 entity that represents where a user has lived: mLocation user UserId name Text current Checkmark nullable UniqueLocation user current The UniqueLocation" constraint allows any number of  Locations to be current&. However, there may be at most one current Location/ per user (i.e., either zero or one per user).9This data type works because of the way that SQL treats NULLHable fields within uniqueness constraints. The SQL standard says that NULL9 values should be considered different, so we represent  as SQL NULL, thus allowing any number of , records. On the other hand, we represent  as TRUE<, so the uniqueness constraint will disallow more than one  record.Note:I 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 BOOLEANV 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. persistent@When used on a uniqueness constraint, there may be at most one  record. persistentBWhen used on a uniqueness constraint, there may be any number of  records.  ('&%$#"! )876543210/.-,+*9?>=<;:@AHGFEDCBIJKMLNOSRQPTUXWVYZ\[]b`_^acdljihgkefmponqrstuvwxyz~|{} None =>?@AEHVX persistentUThis class teaches Persistent how to take a custom type and marshal it to and from a )), allowing it to be stored in a database.ExamplesSimple Newtype You can use newtype: to add more type safety/readability to a basis type like . In these cases, just derive  and PersistFieldSql: U{-# LANGUAGE GeneralizedNewtypeDeriving #-} newtype HashedPassword = HashedPassword  deriving (Eq, Show, , PersistFieldSql) Smart Constructor NewtypeIn this example, we create a B instance for a newtype following the "Smart Constructor" pattern. ={-# LANGUAGE GeneralizedNewtypeDeriving #-} import qualified  Data.Text as T import qualified  Data.CharA as C -- | An American Social Security Number newtype SSN = SSN 1 deriving (Eq, Show, PersistFieldSql) mkSSN ::  ->  A SSN mkSSN t = if (T.length t == 9) && (T.all C.isDigit t) then  $ SSN t else " $ "Invalid SSN: " <> t instance  SSN where  (SSN t) = * t  (*R t) = mkSSN t -- Handle cases where the database does not give us PersistText  x = e $ "File.hs: When trying to deserialize an SSN: expected PersistText, received: " <> T.pack (show x) Tips:This file contain dozens of ( instances you can look at for examples.Typically custom % instances will only accept a single ) constructor in . Internal $ instances accept a wide variety of )Gs to accomodate e.g. storing booleans as integers, booleans or strings.NIf you're making a custom instance and using a SQL database, you'll also need PersistFieldSql, to specify the type of the database column. persistent FIXME Add documentation to that. persistent Haskell type persistentOriginal bytestring persistentInteger result persistentExtra bytestring persistent Error message persistent Haskell type persistentOriginal bytestring persistent Error message persistent6Haskell type, should match Haskell name exactly, e.g. Int64 persistentODatabase type(s), should appear different from Haskell name, e.g. "integer" or INT, not Int. persistentIncorrect value persistent Error message persistent6Haskell type, should match Haskell name exactly, e.g. Int64 persistentReceived value persistent Error message None&'17>@AHSVX! persistent2Datatype that represents an entity, with both its ( and its Haskell record representation.CWhen using a SQL-based backend (such as SQLite or PostgreSQL), an  may take any number of columns depending on how many fields it has. In order to reconstruct your entity on the Haskell side,  persistentu 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.AHowever, if you want to issue a raw SQL command that returns an K, 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  persistentz 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   (from the Database.Persist.GenericSqlJ 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.  persistentBValue to filter with. Highly dependant on the type of filter used. persistent 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.1Persistent users use combinators to create these.1Note that it's important to be careful about the G that you are using, if you use this directly. For example, using the  2 requires that you have an array- or list-shaped [. It is possible to construct values using this that will create malformed runtime values. persistent3convenient for internal use, not needed for the API persistentQuery options.$Persistent users use these directly. persistentUpdating a database entity.1Persistent users use combinators to create these. persistentCPersistent serialized Haskell records to the database. A Database > (A row in SQL, a document in MongoDB, etc) corresponds to a  plus a Haskell record.OFor every Haskell record type stored in the database there is a corresponding  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 @, 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. persistent:Persistent allows multiple different backends (databases). persistentzBy default, a backend will automatically generate the key Instead you can specify a Primary key made up of unique values. persistentAn ] is parameterised by the Haskell record it belongs to and the additional type of that field. persistentUnique keys besides the . persistentA lower-level key operation. persistentA lower-level key operation. persistent!A meta-operation to retrieve the  . persistent Retrieve the y meta-data for the record. persistentReturn meta-data for a given . persistent8A meta-operation to get the database fields of a record. persistentLA lower-level operation to convert from database values to a Haskell record. persistent%A meta operation to retrieve all the  keys. persistentA lower level operation. persistentA lower level operation. persistentUse a  as a lens. persistent$Textual representation of the record persistent1Get list of values corresponding to given entity. persistent Predefined toJSON!. The resulting JSON looks like "{"key": 1, "value": {"name": ...}}.The typical usage is: Finstance ToJSON (Entity User) where toJSON = keyValueEntityToJSON  persistent Predefined  parseJSON. The input JSON looks like "{"key": 1, "value": {"name": ...}}.The typical usage is: Minstance FromJSON (Entity User) where parseJSON = keyValueEntityFromJSON  persistent Predefined toJSON!. The resulting JSON looks like {"id": 1, "name": ...}.The typical usage is: @instance ToJSON (Entity User) where toJSON = entityIdToJSON  persistent Predefined  parseJSON. The input JSON looks like {"id": 1, "name": ...}.The typical usage is: Ginstance FromJSON (Entity User) where parseJSON = entityIdFromJSON  persistentYRealistically this is only going to be used for MongoDB, so lets use MongoDB conventions persistent(Convenience function for getting a free + instance from a type with JSON instances."Example usage in combination with : sinstance PersistField MyData where fromPersistValue = fromPersistValueJSON toPersistValue = toPersistValueJSON  persistent(Convenience function for getting a free  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."Example usage in combination with : sinstance PersistField MyData where fromPersistValue = fromPersistValueJSON toPersistValue = toPersistValueJSON  persistent(Convenience function for getting a free  instance from a type with an  instance. The function derivePersistFieldn from the persistent-template package should generally be preferred. However, if you want to ensure that an ORDER BYf clause that uses your field will order rows by the data constructor order, this is a better choice."Example usage in combination with : data SeverityLevel = Low | Medium | Critical | High deriving (Enum, Bounded) instance PersistField SeverityLevel where fromPersistValue = fromPersistValueEnum toPersistValue = toPersistValueEnum  persistent(Convenience function for getting a free  instance from a type with an * instance. This function also requires a - instance to improve the reporting of errors."Example usage in combination with : data SeverityLevel = Low | Medium | Critical | High deriving (Enum, Bounded) instance PersistField SeverityLevel where fromPersistValue = fromPersistValueEnum toPersistValue = toPersistValueEnum 7None>@AHV   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]a^_`bcdfekghijlmnopqrstuvwxyz}{|~yz~|{}xuvwrstqmponcdljihgkef]b`_^aYZ\[TUXWVNOSRQPJKMLI@AHGFEDCB9?>=<;:)876543210/.-,+*('&%$#"!   None %>@AHV'  persistentfields in other entity persistentvA line. We don't care about spaces in the middle of the line. Also, we don't care about the ammount of indentation. persistentA token used by the parser. persistentSpaces n are n consecutive spaces. persistent Token tok is token tok already unquoted. persistent5Whether fields are by default strict. Default value: True. persistent*The name of the id column. Default value: idF The name of the id column can also be changed on a per-model basis Dhttps://github.com/yesodweb/persistent/wiki/Persistent-entity-syntax persistent?Parses a quasi-quoted syntax into a list of entity definitions. persistentTokenize a string. persistentVA string of tokens is empty when it has only spaces. There can't be two consecutive , so this takes O(1) time. persistentERemove leading spaces and remove spaces in the middle of the tokens. persistent5Divide lines into blocks and make entity definitions. persistentConstruct an entity definition. persistentname persistententity attributes persistentindented lines None ,>@AHV persistentkCreate a new record in the database, returning an automatically created key (in SQL an auto-increment id). Example usageUsing  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, let's insert a new user John. _insertJohn :: MonadIO m => ReaderT SqlBackend m (Key User) insertJohn = insert $ User "John" 30 johnId <- insertJohn The above query when applied on  #dataset-persist-store-1 dataset-1, will produce this: +-----+------+-----+ |id |name |age | +-----+------+-----+ |1 |SPJ |40 | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ |3 |John |30 | +-----+------+-----+ persistentSame as , but doesn't return a Key. Example usagewith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, `insertJohn :: MonadIO m => ReaderT SqlBackend m (Key User) insertJohn = insert_ $ User "John" 30 The above query when applied on  #dataset-persist-store-1 dataset-1, will produce this: +-----+------+-----+ |id |name |age | +-----+------+-----+ |1 |SPJ |40 | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ |3 |John |30 | +-----+------+-----+ persistent9Create multiple records in the database and return their s.If you don't need the inserted s, use .fThe MongoDB and PostgreSQL backends insert all records and retrieve their keys in one database query.GThe SQLite and MySQL backends use the slow, default implementation of  mapM insert. Example usagewith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, insertUsers :: MonadIO m => ReaderT SqlBackend m [Key User] insertUsers = insertMany [User "John" 30, User "Nick" 32, User "Jane" 20] userIds <- insertUsers The above query when applied on  #dataset-persist-store-1 dataset-1, will produce this: +-----+------+-----+ |id |name |age | +-----+------+-----+ |1 |SPJ |40 | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ |3 |John |30 | +-----+------+-----+ |4 |Nick |32 | +-----+------+-----+ |5 |Jane |20 | +-----+------+-----+ persistentSame as , but doesn't return any s.]The MongoDB, PostgreSQL, SQLite and MySQL backends insert all records in one database query. Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, insertUsers_ :: MonadIO m => ReaderT SqlBackend m () insertUsers_ = insertMany_ [User "John" 30, User "Nick" 32, User "Jane" 20] The above query when applied on  #dataset-persist-store-1 dataset-1, will produce this: +-----+------+-----+ |id |name |age | +-----+------+-----+ |1 |SPJ |40 | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ |3 |John |30 | +-----+------+-----+ |4 |Nick |32 | +-----+------+-----+ |5 |Jane |20 | +-----+------+-----+ persistentSame as , but takes an  instead of just a record.PUseful when migrating data from one entity to another and want to preserve ids.]The MongoDB, PostgreSQL, SQLite and MySQL backends insert all records in one database query. Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, }insertUserEntityMany :: MonadIO m => ReaderT SqlBackend m () insertUserEntityMany = insertEntityMany [SnakeEntity, EvaEntity] The above query when applied on  #dataset-persist-store-1 dataset-1, will produce this: +-----+------+-----+ |id |name |age | +-----+------+-----+ |1 |SPJ |40 | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ |3 |Snake |38 | +-----+------+-----+ |4 |Eva |38 | +-----+------+-----+ persistent8Create a new record in the database using the given key. Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, winsertAliceKey :: MonadIO m => Key User -> ReaderT SqlBackend m () insertAliceKey key = insertKey key $ User "Alice" 20 JinsertAliceKey $ UserKey {unUserKey = SqlBackendKey {unSqlBackendKey = 3}} The above query when applied on  #dataset-persist-store-1 dataset-1, will produce this: +-----+------+-----+ |id |name |age | +-----+------+-----+ |1 |SPJ |40 | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ |3 |Alice |20 | +-----+------+-----+ persistent;Put the record in the database with the given key. Unlike T, if a record with the given key does not exist then a new record will be inserted. Example usageWe try to explain upsertBy using  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1.First, we insert Philip to  #dataset-persist-store-1 dataset-1. einsertPhilip :: MonadIO m => ReaderT SqlBackend m (Key User) insertPhilip = insert $ User "Philip" 42 philipId <- insertPhilipThis query will produce: +-----+------+-----+ |id |name |age | +-----+------+-----+ |1 |SPJ |40 | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ |3 |Philip|42 | +-----+------+-----+ wrepsertHaskell :: MonadIO m => Key record -> ReaderT SqlBackend m () repsertHaskell id = repsert id $ User "Haskell" 81 repsertHaskell philipId;This query will replace Philip's record with Haskell's one: :+-----+-----------------+--------+ |id |name |age | +-----+-----------------+--------+ |1 |SPJ |40 | +-----+-----------------+--------+ |2 |Simon |41 | +-----+-----------------+--------+ |3 |Philip -> Haskell|42 -> 81| +-----+-----------------+--------+3 inserts the given record if the key doesn't exist. nrepsertXToUnknown :: MonadIO m => ReaderT SqlBackend m () repsertXToUnknown = repsert unknownId $ User "X" 999)For example, applying the above query to  #dataset-persist-store-1 dataset-1 will produce this: +-----+------+-----+ |id |name |age | +-----+------+-----+ |1 |SPJ |40 | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ |3 |X |999 | +-----+------+-----+ persistent$Put many entities into the database.Batch version of  for SQL backends.PUseful when migrating data from one entity to another and want to preserve ids. Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, repsertManyUsers :: MonadIO m =>ReaderT SqlBackend m () repsertManyusers = repsertMany [(simonId, User "Philip" 20), (unknownId999, User "Mr. X" 999)] The above query when applied on  #dataset-persist-store-1 dataset-1, will produce this: :+-----+----------------+---------+ |id |name |age | +-----+----------------+---------+ |1 |SPJ |40 | +-----+----------------+---------+ |2 |Simon -> Philip |41 -> 20 | +-----+----------------+---------+ |999 |Mr. X |999 | +-----+----------------+---------+ persistentReplace 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  or  in these cases. Example usageWith  #schema-persist-store-1schema-1 schama-1 and  #dataset-persist-store-1 dataset-1, creplaceSpj :: MonadIO m => User -> ReaderT SqlBackend m () replaceSpj record = replace spjId record The above query when applied on  #dataset-persist-store-1 dataset-1, will produce this: +-----+------+-----+ |id |name |age | +-----+------+-----+ |1 |Mike |45 | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ persistentODelete a specific record by identifier. Does nothing if record does not exist. Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, JdeleteSpj :: MonadIO m => ReaderT SqlBackend m () deleteSpj = delete spjId The above query when applied on  #dataset-persist-store-1 dataset-1, will produce this: h+-----+------+-----+ |id |name |age | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ persistent.Update individual fields on a specific record. Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, kupdateSpj :: MonadIO m => [Update User] -> ReaderT SqlBackend m () updateSpj updates = update spjId updates updateSpj [UserAge +=. 100] The above query when applied on  #dataset-persist-store-1 dataset-1, will produce this: +-----+------+-----+ |id |name |age | +-----+------+-----+ |1 |SPJ |140 | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ persistentaUpdate individual fields on a specific record, and retrieve the updated value from the database._Note that this function will throw an exception if the given key is not found in the database. Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, vupdateGetSpj :: MonadIO m => [Update User] -> ReaderT SqlBackend m User updateGetSpj updates = updateGet spjId updates %spj <- updateGetSpj [UserAge +=. 100] The above query when applied on  #dataset-persist-store-1 dataset-1, will produce this: +-----+------+-----+ |id |name |age | +-----+------+-----+ |1 |SPJ |140 | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ persistent)Get a record by identifier, if available. Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, KgetSpj :: MonadIO m => ReaderT SqlBackend m (Maybe User) getSpj = get spjId mspj <- getSpj The above query when applied on  #dataset-persist-store-1 dataset-1, will get this: J+------+-----+ | name | age | +------+-----+ | SPJ | 40 | +------+-----+ persistent?Get many records by their respective identifiers, if available. Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1: ^getUsers :: MonadIO m => ReaderT SqlBackend m (Map (Key User) User) getUsers = getMany allkeys musers <- getUsers The above query when applied on  #dataset-persist-store-1 dataset-1, will get these records: +----+-------+-----+ | id | name | age | +----+-------+-----+ | 1 | SPJ | 40 | +----+-------+-----+ | 2 | Simon | 41 | +----+-------+-----+ persistent converts a   into a 8 This can be used by each backend to convert between a 7 and a plain Haskell type. For Sql, that is done with toSqlKey and  fromSqlKey.By default, a  uses the default 0 for its Key and is an instance of ToBackendKeyA = that instead uses a custom type will not be an instance of . persistent-A convenient alias for common type signatures persistentYThis 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  and H classes, but where you don't want to fix the type associated with the  of a record.)Generally speaking, where you might have:  foo :: (  record , PeristEntityBackend record ~  backend ,  IsSqlBackend backend ) this can be replaced with:  foo :: (  record, ,  record ~ backend ,   SqlBackend backend ) This works for SqlReadBackend because of the  instance   SqlBackend SqlReadBackend$, without needing to go through the  type family.8Likewise, functions that are currently hardcoded to use  SqlBackend can be generalized: -- before: asdf ::   SqlBackend) m () asdf = pure () -- after: asdf' :: @ SqlBackend backend => ReaderT backend m () asdf' = withReaderT  asdf  persistentClass 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. persistentThis function is how we actually construct and tag a backend as having read or write capabilities. It should be used carefully and only when actually constructing a backendY. Careless use allows us to accidentally run a write query against a read-only database. persistent%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  persistentSame as v, but for a non-null (not Maybe) foreign key. Unsafe unless your database is enforcing that the foreign key is valid. Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, OgetJustSpj :: MonadIO m => ReaderT SqlBackend m User getJustSpj = getJust spjId spj <- getJust spjId The above query when applied on  #dataset-persist-store-1 dataset-1, will get this record: c+----+------+-----+ | id | name | age | +----+------+-----+ | 1 | SPJ | 40 | +----+------+-----+ [getJustUnknown :: MonadIO m => ReaderT SqlBackend m User getJustUnknown = getJust unknownIdmrx <- getJustUnknownThis just throws an error. persistentSame as , but returns an  instead of just the record. Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, jgetJustEntitySpj :: MonadIO m => ReaderT SqlBackend m (Entity User) getJustEntitySpj = getJustEntity spjId spjEnt <- getJustEntitySpj The above query when applied on  #dataset-persist-store-1 dataset-1, will get this entity: c+----+------+-----+ | id | name | age | +----+------+-----+ | 1 | SPJ | 40 | +----+------+-----+ persistentICurry this to make a convenience function that loads an associated model. foreign = belongsTo foreignId persistentSame as  , but uses getJust# and therefore is similarly unsafe. persistentLike insert, but returns the complete Entity. Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, }insertHaskellEntity :: MonadIO m => ReaderT SqlBackend m (Entity User) insertHaskellEntity = insertEntity $ User "Haskell" 81 !haskellEnt <- insertHaskellEntity The above query when applied on  #dataset-persist-store-1 dataset-1, will produce this: +----+---------+-----+ | id | name | age | +----+---------+-----+ | 1 | SPJ | 40 | +----+---------+-----+ | 2 | Simon | 41 | +----+---------+-----+ | 3 | Haskell | 81 | +----+---------+-----+ persistentLike get, but returns the complete Entity. Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, fgetSpjEntity :: MonadIO m => ReaderT SqlBackend m (Maybe (Entity User)) getSpjEntity = getEntity spjId mSpjEnt <- getSpjEntity The above query when applied on  #dataset-persist-store-1 dataset-1, will get this entity: c+----+------+-----+ | id | name | age | +----+------+-----+ | 1 | SPJ | 40 | +----+------+-----+ persistentLike ( but just returns the record instead of . Example usageWith  #schema-persist-store-1schema-1 and  #dataset-persist-store-1 dataset-1, kinsertDaveRecord :: MonadIO m => ReaderT SqlBackend m User insertDaveRecord = insertRecord $ User "Dave" 50 dave <- insertDaveRecord The above query when applied on  #dataset-persist-store-1 dataset-1, will produce this: +-----+------+-----+ |id |name |age | +-----+------+-----+ |1 |SPJ |40 | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ |3 |Dave |50 | +-----+------+-----+%None .>@AHUVX  persistentThis 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  TypeError0 instances for records that have 0 unique keys.  persistent|This is an error message. It is used when an entity has multiple unique keys, and the function expects a single unique key.  persistent@This is an error message. It is used when writing instances of ' for an entity that has no unique keys.  persistent"This class is used to ensure that / is only called on records that have a single h key. The quasiquoter automatically generates working instances for appropriate records, and generates  TypeError< instances for records that have 0 or multiple unique keys. persistentSome functions in this module (,  , and ) first query the unique indexes to check for conflicts. You could instead optimistically attempt to perform the operation (e.g.  instead of  ). However,gthere is some fragility to trying to catch the correct exception and determing the column of failure;Ban exception will automatically abort the current SQL transaction. persistentKDelete a specific record by unique key. Does nothing if no record matches. Example usageWith  #schema-persist-unique-1schema-1 and  #dataset-persist-unique-1 dataset-1, gdeleteBySpjName :: MonadIO m => ReaderT SqlBackend m () deleteBySpjName = deleteBy UniqueUserName "SPJ" The above query when applied on  #dataset-persist-unique-1 dataset-1, will produce this: h+-----+------+-----+ |id |name |age | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ persistentLike , but returns J when the record couldn't be inserted because of a uniqueness constraint. Example usageWith  #schema-persist-unique-1schema-1 and  #dataset-persist-unique-1 dataset-1-, we try to insert the following two records: QlinusId <- insertUnique $ User "Linus" 48 spjId <- insertUnique $ User "SPJ" 90 +-----+------+-----+ |id |name |age | +-----+------+-----+ |1 |SPJ |40 | +-----+------+-----+ |2 |Simon |41 | +-----+------+-----+ |3 |Linus |48 | +-----+------+-----+Linus's record was inserted to  #dataset-persist-unique-1 dataset-11, while SPJ wasn't because SPJ already exists in  #dataset-persist-unique-1 dataset-1. persistent2Update 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. Example usageFirst, we try to explain  using  #schema-persist-unique-1schema-1 and  #dataset-persist-unique-1 dataset-1. upsertSpj :: MonadIO m => [Update User] -> ReaderT SqlBackend m (Maybe (Entity User)) upsertSpj updates = upsert (User "SPJ" 999) upadtes %mSpjEnt <- upsertSpj [UserAge +=. 15] The above query when applied on  #dataset-persist-unique-1 dataset-1, will produce this: +-----+-----+--------+ |id |name |age | +-----+-----+--------+ |1 |SPJ |40 -> 55| +-----+-----+--------+ |2 |Simon|41 | +-----+-----+--------+ upsertX :: MonadIO m => [Update User] -> ReaderT SqlBackend m (Maybe (Entity User)) upsertX updates = upsert (User "X" 999) updates !mXEnt <- upsertX [UserAge +=. 15] The above query when applied on  #dataset-persist-unique-1 dataset-1, will produce this: +-----+-----+--------+ |id |name |age | +-----+-----+--------+ |1 |SPJ |40 | +-----+-----+--------+ |2 |Simon|41 | +-----+-----+--------+ |3 |X |999 | +-----+-----+--------+SNext, what if the schema has two uniqueness constraints? Let's check it out using  #schema-persist-unique-2schema-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  " to select the unique key we want.  persistent8Update based on a given uniqueness constraint or insert:+insert the new record if it does not exist;Hupdate the existing record that matches the given uniqueness constraint. Example usageWe try to explain   using  #schema-persist-unique-2schema-2 and  #dataset-persist-unique-1 dataset-1. 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]The above query will alter  #dataset-persist-unique-1 dataset-1 to: +-----+-----+--------+ |id |name |age | +-----+-----+--------+ |1 |SPJ |40 -> 55| +-----+-----+--------+ |2 |Simon|41 | +-----+-----+--------+ upsertBySimonAge :: MonadIO m => User -> [Update User] -> ReaderT SqlBackend m (Entity User) upsertBySimonAge record updates = upsertBy (UniqueUserName "SPJ") record updates DmPhilipEnt <- upsertBySimonAge (User "X" 999) [UserName =. "Philip"]The above query will alter  #dataset-persist-unique-1 dataset-1 to: +----+-----------------+-----+ | 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]This query will alter  #dataset-persist-unique-1 dataset-1 to: +-----+-----+-----+ |id |name |age | +-----+-----+-----+ |1 |SPJ |40 | +-----+-----+-----+ |2 |Simon|41 | +-----+-----+-----+ |3 |X |999 | +-----+-----+-----+  persistentPut many records into dbHinsert new records that do not exist (or violate any unique constraints)9replace existing records (matching any unique constraint)  persistentQueries against  keys (other than the id ).IPlease read the general Persistent documentation to learn how to create  keys.qUsing this with an Entity without a Unique key leads to undefined behavior. A few of these functions require a single $, so using an Entity with multiple s 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.  persistentFGet a record by unique key, if available. Returns also the identifier. Example usageWith  #schema-persist-unique-1schema-1 and  #dataset-persist-unique-1 dataset-1: tgetBySpjName :: MonadIO m => ReaderT SqlBackend m (Maybe (Entity User)) getBySpjName = getBy $ UniqueUserName "SPJ" mSpjEnt <- getBySpjName The above query when applied on  #dataset-persist-unique-1 dataset-1, will get this entity: c+----+------+-----+ | id | name | age | +----+------+-----+ | 1 | SPJ | 40 | +----+------+-----+  persistentGiven a proxy for a  record, this returns the sole N for that entity.  persistent4Given a proxy for a record that has an instance of , this returns a  list of the Ns for that entity.  persistentInsert a value, checking for conflicts with any unique constraints. If a duplicate exists in the database, it is returned as *. Otherwise, the new 'Key is returned as . Example usageWith  #schema-persist-unique-2schema-2 and  #dataset-persist-unique-1 dataset-1", we have following lines of code: |l1 <- insertBy $ User "SPJ" 20 l2 <- insertBy $ User "XXX" 41 l3 <- insertBy $ User "SPJ" 40 r1 <- insertBy $ User "XXX" 100First three lines return p because there're duplicates in given record's uniqueness constraints. While the last line returns a new key as . persistentLike , but returns J when the record couldn't be inserted because of a uniqueness constraint. Example usageWe use  #schema-persist-unique-2schema-2 and  #dataset-persist-unique-1 dataset-1 here. insertUniqueSpjEntity :: MonadIO m => ReaderT SqlBackend m (Maybe (Entity User)) insertUniqueSpjEntity = insertUniqueEntity $ User "SPJ" 50  mSpjEnt <- insertUniqueSpjEntityThe above query results  as SPJ already exists. insertUniqueAlexaEntity :: MonadIO m => ReaderT SqlBackend m (Maybe (Entity User)) insertUniqueAlexaEntity = insertUniqueEntity $ User "Alexa" 3 "mAlexaEnt <- insertUniqueSpjEntity]Because there's no such unique keywords of the given record, the above query when applied on  #dataset-persist-unique-1 dataset-1, will produce this: +----+-------+-----+ | id | name | age | +----+-------+-----+ | 1 | SPJ | 40 | +----+-------+-----+ | 2 | Simon | 41 | +----+-------+-----+ | 3 | Alexa | 3 | +----+-------+-----+ persistent*Return the single unique key for a record. Example usageWe use shcema-1 and  #dataset-persist-unique-1 dataset-1 here. ponlySimonConst :: MonadIO m => ReaderT SqlBackend m (Unique User) onlySimonConst = onlyUnique $ User "Simon" 999 mSimonConst <- onlySimonConst mSimonConst4 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. persistentA modification of  , which takes the  itself instead of a # record. Returns a record matching oneS of the unique keys. This function makes the most sense on entities with a single  constructor. Example usageWith  #schema-persist-unique-1schema-1 and  #dataset-persist-unique-1 dataset-1,lgetBySpjValue :: MonadIO m => ReaderT SqlBackend m (Maybe (Entity User)) getBySpjValue = getByValue $ User SPJ 999 mSpjEnt <- getBySpjValue The above query when applied on  #dataset-persist-unique-1 dataset-1, will get this record: c+----+------+-----+ | id | name | age | +----+------+-----+ | 1 | SPJ | 40 | +----+------+-----+  persistentuRetrieve a record from the database using the given unique keys. It will attempt to find a matching record for each : in the list, and returns the first one that has a match.Returns M if you provide an empty list ('[]') or if no value matches in the database. persistentAttempt 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 C if the replacement was made. If uniqueness is violated, return a  with the  violation persistentnCheck whether there are any conflicts for unique keys with this entity and existing entities in the database.Returns m if the entity would be unique, and could thus safely be inserted. on a conflict returns the conflicting key Example usageWe use  #schema-persist-unique-1schema-1 and  #dataset-persist-unique-1 dataset-1 here.This would be : *mAlanConst <- checkUnique $ User "Alan" 70While this would be  because SPJ already exists: (mSpjConst <- checkUnique $ User "SPJ" 60 persistentThe slow but generic   implemetation for any  B. * Lookup corresponding entities (if any) for each record using & * For pre-existing records, issue a B for each old key and new record * For new records, issue a bulk  persistent This function returns a list of ) that correspond to the 7 keys on that record. This is useful for comparing two record+s for equality only on the basis of their  keys. persistentnew record to insert persistent/updates to perform if the record already exists persistent.the record in the database after the operation  persistent uniqueness constraint to find by persistentnew record to insert persistent/updates to perform if the record already exists persistent.the record in the database after the operation  persistent4A list of the records you want to insert or replace.     None>@AHV  persistent0Backends supporting conditional write operations persistentDUpdate individual fields on any record matching the given criterion. persistent0Delete all records matching the given criterion. persistent0Backends supporting conditional read operations. persistentcGet all records matching the given criterion in the specified order. Returns also the identifiers. persistent,Get just the first record for the criterion. persistentGet the .s of all records matching the given criterion. persistent;The total number of records fulfilling the given criterion. persistentcGet all records matching the given criterion in the specified order. Returns also the identifiers. persistentGet the .s of all records matching the given criterion. persistentCall ! but return the result as a list. persistentCall ! but return the result as a list. None>@AHV persistentFor combinations of backends and entities that support cascade-deletion. Cascade-deletion  means that entries that depend on other entries to be deleted will be deleted as well.  persistent3Perform cascade-deletion of single database entry.! persistent5Cascade-deletion of entries satisfying given filters. !None ,>@AHV" persistentA 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.# persistentA 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.$ persistentA 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.k      !"#$k"$     # !None ,2>@AHSVX% persistent$A backend which is a wrapper around  SqlBackend.& persistentLike  SqlPersistTM but compatible with any SQL backend which can handle read and write queries.' persistentLike  SqlPersistTC but compatible with any SQL backend which can handle read queries.( persistent^A constraint synonym which witnesses that a backend is SQL and can run read and write queries.) persistentTA constraint synonym which witnesses that a backend is SQL and can run read queries.* persistent5An SQL backend which can handle read or write queries%The constructor was exposed in 2.10.0- persistent1An SQL backend which can only handle read queries&The constructor was exposed in 2.10.0.3 persistentBtable name, column names, id name, either 1 or 2 statements to run4 persistentpSQL for inserting many rows and returning their primary keys, for backends that support this functioanlity. If -, rows will be inserted one-at-a-time using 3.5 persistentOSome databases support performing UPSERT _and_ RETURN entity in a single call.This field when set will be used to generate the UPSERT+RETURN sql given * an entity definition * updates to be run on unique key(s) collision When left as , we find the unique key from entity def before * trying to fetch an entity by said key * perform an update when result found, else issue an insert * return new entity from db6 persistentoSome databases support performing bulk UPSERT, specifically "insert or replace many records" in a single call.This field when set, given * an entity definition * number of records to be inserted should produce a PUT MANY sql with placeholders for records When left as , we default to using defaultPutMany.B persistentsSome databases (probably only Sqlite) have a limit on how many question-mark parameters may be used in a statementC  persistentSome databases support performing bulk an atomic+bulk INSERT where constraint conflicting entities can replace existing entities.This field when set, given * an entity definition * number of records to be inserted should produce a INSERT sql with placeholders for primary+record fields When left as , we default to using defaultRepsertMany.D persistentPlease refer to the documentation for the database in question for a full overview of the semantics of the varying isloation levelsU persistentWUseful for running a write query against an untagged backend with unknown capabilities.V persistentSUseful for running a read query against a backend with read and write capabilities.W persistentLUseful for running a read query against a backend with unknown capabilities.8%&'()*+,-./01=23456789:;<>?@ABCDEFGHIJKLMNOPQRSTUVW8-./*+,WVUSOPQRIJKLMNDEFGHT01=23456789:;<>?@ABC)('&%None>@AHV!ic persistentA single column (see rawSql). Any  PersistField may be used here, including )% (which does not do any processing).g persistentA g+ is a four level monad stack consisting of: []0 representing a log of errors in the migrations. hV representing a list of migrations to run, along with whether or not they are safe. 0 , aka the k% transformer for database interop. for arbitrary IO.B%&'()*+,-./01=23456789:;<>?@ABCIJKLMNOPQRSUVWcdefghijklmnopqrstuvwNone>@AHV#y persistent0Create the list of columns for the given entity.xyNone >@AEHVXz persistentAssign a field a value. Example usage pupdateAge :: MonadIO m => ReaderT SqlBackend m () updateAge = updateWhere [UserName ==. "SPJ" ] [UserAge =. 45]  Similar to W 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  is [ val] and second parameter is [* val]. By comparing this with the type of  and z4, you can see that they match up in the above usage. The above query when applied on  #dataset dataset-1, will produce this: +-----+-----+--------+ |id |name |age | +-----+-----+--------+ |1 |SPJ |40 -> 45| +-----+-----+--------+ |2 |Simon|41 | +-----+-----+--------+{ persistentAssign a field by addition (+=). Example usage jaddAge :: MonadIO m => ReaderT SqlBackend m () addAge = updateWhere [UserName ==. "SPJ" ] [UserAge +=. 1]  The above query when applied on  #dataset dataset-1, will produce this: +-----+-----+---------+ |id |name |age | +-----+-----+---------+ |1 |SPJ |40 -> 41 | +-----+-----+---------+ |2 |Simon|41 | +-----+-----+---------+| persistentAssign a field by subtraction (-=). Example usage tsubtractAge :: MonadIO m => ReaderT SqlBackend m () subtractAge = updateWhere [UserName ==. "SPJ" ] [UserAge -=. 1]  The above query when applied on  #dataset dataset-1, will produce this: +-----+-----+---------+ |id |name |age | +-----+-----+---------+ |1 |SPJ |40 -> 39 | +-----+-----+---------+ |2 |Simon|41 | +-----+-----+---------+} persistent"Assign a field by multiplication (*=). Example usage tmultiplyAge :: MonadIO m => ReaderT SqlBackend m () multiplyAge = updateWhere [UserName ==. "SPJ" ] [UserAge *=. 2]  The above query when applied on  #dataset dataset-1, will produce this: +-----+-----+--------+ |id |name |age | +-----+-----+--------+ |1 |SPJ |40 -> 80| +-----+-----+--------+ |2 |Simon|41 | +-----+-----+--------+~ persistentAssign a field by division (/=). Example usage pdivideAge :: MonadIO m => ReaderT SqlBackend m () divideAge = updateWhere [UserName ==. "SPJ" ] [UserAge /=. 2]  The above query when applied on  #dataset dataset-1, will produce this: +-----+-----+---------+ |id |name |age | +-----+-----+---------+ |1 |SPJ |40 -> 20 | +-----+-----+---------+ |2 |Simon|41 | +-----+-----+---------+ persistentCheck for equality. Example usage mselectSPJ :: MonadIO m => ReaderT SqlBackend m [Entity User] selectSPJ = selectList [UserName ==. "SPJ" ] []  The above query when applied on  #dataset dataset-1, will produce this: c+-----+-----+-----+ |id |name |age | +-----+-----+-----+ |1 |SPJ |40 | +-----+-----+-----+ persistentNon-equality check. Example usage qselectSimon :: MonadIO m => ReaderT SqlBackend m [Entity User] selectSimon = selectList [UserName !=. "SPJ" ] []  The above query when applied on  #dataset dataset-1, will produce this: c+-----+-----+-----+ |id |name |age | +-----+-----+-----+ |2 |Simon|41 | +-----+-----+-----+ persistentLess-than check. Example usage pselectLessAge :: MonadIO m => ReaderT SqlBackend m [Entity User] selectLessAge = selectList [UserAge <. 41 ] []  The above query when applied on  #dataset dataset-1, will produce this: c+-----+-----+-----+ |id |name |age | +-----+-----+-----+ |1 |SPJ |40 | +-----+-----+-----+ persistentLess-than or equal check. Example usage {selectLessEqualAge :: MonadIO m => ReaderT SqlBackend m [Entity User] selectLessEqualAge = selectList [UserAge <=. 40 ] []  The above query when applied on  #dataset dataset-1, will produce this: c+-----+-----+-----+ |id |name |age | +-----+-----+-----+ |1 |SPJ |40 | +-----+-----+-----+ persistentGreater-than check. Example usage vselectGreaterAge :: MonadIO m => ReaderT SqlBackend m [Entity User] selectGreaterAge = selectList [UserAge >. 40 ] []  The above query when applied on  #dataset dataset-1, will produce this: c+-----+-----+-----+ |id |name |age | +-----+-----+-----+ |2 |Simon|41 | +-----+-----+-----+ persistentGreater-than or equal check. Example usage selectGreaterEqualAge :: MonadIO m => ReaderT SqlBackend m [Entity User] selectGreaterEqualAge = selectList [UserAge >=. 41 ] []  The above query when applied on  #dataset dataset-1, will produce this: c+-----+-----+-----+ |id |name |age | +-----+-----+-----+ |2 |Simon|41 | +-----+-----+-----+ persistent Check if value is in given list. Example usage rselectUsers :: MonadIO m => ReaderT SqlBackend m [Entity User] selectUsers = selectList [UserAge <-. [40, 41]] []  The above query when applied on  #dataset dataset-1, will produce this: +-----+-----+-----+ |id |name |age | +-----+-----+-----+ |1 |SPJ |40 | +-----+-----+-----+ |2 |Simon|41 | +-----+-----+-----+ jselectSPJ :: MonadIO m => ReaderT SqlBackend m [Entity User] selectSPJ = selectList [UserAge <-. [40]] []  The above query when applied on  #dataset dataset-1, will produce this: c+-----+-----+-----+ |id |name |age | +-----+-----+-----+ |1 |SPJ |40 | +-----+-----+-----+ persistent$Check if value is not in given list. Example usage oselectSimon :: MonadIO m => ReaderT SqlBackend m [Entity User] selectSimon = selectList [UserAge /<-. [40]] []  The above query when applied on  #dataset dataset-1, will produce this: c+-----+-----+-----+ |id |name |age | +-----+-----+-----+ |2 |Simon|41 | +-----+-----+-----+ persistent,The OR of two lists of filters. For example: selectList ([ PersonAge >. 25 , PersonAge <. 30 ] ||. [ PersonIncome >. 15000 , PersonIncome <. 25000 ]) []>will filter records where a person's age is between 25 and 30 or1 a person's income is between (15000 and 25000).If you are looking for an (&&.) operator to do (A AND B AND (C OR D)) you can use the (++)! operator instead as there is no (&&.). For example: selectList ([ PersonAge >. 25 , PersonAge <. 30 ] ++ ([PersonCategory ==. 1] ||. [PersonCategory ==. 5])) []>will filter records where a person's age is between 25 and 30 and' (person's category is either 1 or 5). persistentConvert list of )Vs into textual representation of JSON object. This is a type-constrained synonym for . persistentqConvert map (list of tuples) into textual representation of JSON object. This is a type-constrained synonym for . persistent+A more general way to convert instances of  type class to strict text . persistentFIXME What's this exactly?*   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]a^_`bcdfekghijlmnopqrstuvwxyz}{|~      !"#$z{|}~z{|}~z3{3|3}3~3444444443None>@AHV persistent Gets the c for an .None=>?@AHVX\ persistentRTells Persistent what database column type should be used to store a Haskell type.ExamplesSimple Boolean Alternative 7data Switch = On | Off deriving (Show, Eq) instance  Switch where  s = case s of On -> / True Off -> / False  (/ b) = if b then  On else  Off z x = Left $ "File.hs: When trying to deserialize a Switch: expected PersistBool, received: " <> T.pack (show x) instance  Switch where  _ = # Non-Standard Database Types@If your database supports non-standard types, such as Postgres' uuid, you can use ( to use them: ,import qualified Data.UUID as UUID instance  UUID where  = 8 . toASCIIBytes  (8/ uuid) = case fromASCIIBytes uuid of  -> ` $ "Model/CustomTypes.hs: Failed to deserialize a UUID; received: " <> T.pack (show uuid)  uuid' ->  uuid'  x = Left $ "File.hs: When trying to deserialize a UUID: expected PersistDbSpecific, received: "-- > <> T.pack (show x) instance  UUID where  _ = ( "uuid" User Created Database TypesHSimilarly, some databases support creating custom types, e.g. Postgres'  Dhttps://www.postgresql.org/docs/current/static/sql-createdomain.htmlDOMAIN and  Ahttps://www.postgresql.org/docs/current/static/datatype-enum.htmlENUM features. You can use ( to specify a custom type: >CREATE DOMAIN ssn AS text CHECK ( value ~ '^[0-9]{9}$');  instance PersistFieldSQL SSN where  _ = ( "ssn"  cCREATE TYPE rainbow_color AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet');  instance PersistFieldSQL RainbowColor where  _ = ( "rainbow_color"  persistent1Class for data types that may be retrived from a rawSql query. persistentONumber of columns that this data type needs and the list of substitutions for SELECT placeholders ??. persistent>A string telling the user why the column count is what it is. persistent1Transform a row of the result into the data type.  persistent  persistent  persistent  persistent  persistent  persistent  persistent  persistent  persistent  persistent  persistent  persistent  persistentNone>@AHV persistentExecute a raw SQL statement persistentKExecute a raw SQL statement and return the number of rows it has modified. persistentlExecute a raw SQL statement and return its results as a list. If you do not expect a return value, use of  is recommended.If you're using s$ (which is quite likely), then you must; use entity selection placeholders (double question mark, ?? ). These ?? placeholders are then replaced for the names of the columns that we need for your entities. You'll receive an error if you don't use the placeholders. Please see the s documentation for more details.0You may put value placeholders (question marks, ?) in your SQL query. These placeholders are then replaced by the values you pass on the second parameter, already correctly escaped. You may want to use 2 to help you constructing the placeholder values.]Since you're giving a raw SQL statement, you don't get any guarantees regarding safety. If  is not able to parse the results of your query back, then an exception is raised. However, most common problems are mitigated by using the entity selection placeholder ??>, and you shouldn't see any error at all if you're not using c.Some example of  based on this schema: share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase| Person name String age Int Maybe deriving Show BlogPost title String authorId PersonId deriving Show |] #Examples based on the above schema: getPerson :: MonadIO m => ReaderT SqlBackend m [Entity Person] getPerson = rawSql "select ?? from person where name=?" [PersistText "john"] getAge :: MonadIO m => ReaderT SqlBackend m [Single Int] getAge = rawSql "select person.age from person where name=?" [PersistText "john"] getAgeName :: MonadIO m => ReaderT SqlBackend m [(Single Int, Single Text)] getAgeName = rawSql "select person.age, person.name from person where name=?" [PersistText "john"] getPersonBlog :: MonadIO m => ReaderT SqlBackend m [(Entity Person, Entity BlogPost)] getPersonBlog = rawSql "select ??,?? from person,blog_post where person.id = blog_post.author_id" [] KMinimal working program for PostgreSQL backend based on the above concepts: -{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} import Control.Monad.IO.Class (liftIO) import Control.Monad.Logger (runStderrLoggingT) import Database.Persist import Control.Monad.Reader import Data.Text import Database.Persist.Sql import Database.Persist.Postgresql import Database.Persist.TH share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase| Person name String age Int Maybe deriving Show |] conn = "host=localhost dbname=new_db user=postgres password=postgres port=5432" getPerson :: MonadIO m => ReaderT SqlBackend m [Entity Person] getPerson = rawSql "select ?? from person where name=?" [PersistText "sibi"] liftSqlPersistMPool y x = liftIO (runSqlPersistMPool y x) main :: IO () main = runStderrLoggingT $ withPostgresqlPool conn 10 $ liftSqlPersistMPool $ do runMigration migrateAll xs <- getPerson liftIO (print xs)  persistent*SQL statement, possibly with placeholders. persistent Values to fill the placeholders. persistent*SQL statement, possibly with placeholders. persistent Values to fill the placeholders. persistent*SQL statement, possibly with placeholders. persistent Values to fill the placeholders. None >@AHVXB persistentbGet a connection from the pool, run the given action, and then return the connection to the pool.Note: This function previously timed out after 2 seconds, but this behavior was buggy and caused more problems than it solved. Since version 2.1.2, it performs no timeout checks.  persistentLike -, but supports specifying an isolation level.  persistentLike  h, but times out the operation if resource allocation does not complete within the given timeout period.  persistentLike -, but supports specifying an isolation level. persistentyCreate a connection and run sql queries within it. This function automatically closes the connection on it's completion. Example usage 6{-# LANGUAGE GADTs #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies#-} {-# LANGUAGE TemplateHaskell#-} {-# LANGUAGE QuasiQuotes#-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} import Control.Monad.IO.Class (liftIO) import Control.Monad.Logger import Conduit import Database.Persist import Database.Sqlite import Database.Persist.Sqlite import Database.Persist.TH share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase| Person name String age Int Maybe deriving Show |] openConnection :: LogFunc -> IO SqlBackend openConnection logfn = do conn <- open "/home/sibi/test.db" wrapConnection conn logfn main :: IO () main = do runNoLoggingT $ runResourceT $ withSqlConn openConnection (\backend -> flip runSqlConn backend $ do runMigration migrateAll insert_ $ Person "John doe" $ Just 35 insert_ $ Person "Divya" $ Just 36 (pers :: [Entity Person]) <- selectList [] [] liftIO $ print pers return () )%On executing it, you get this output: Migrating: CREATE TABLE "person"("id" INTEGER PRIMARY KEY,"name" VARCHAR NOT NULL,"age" INTEGER NULL) [Entity {entityKey = PersonKey {unPersonKey = SqlBackendKey {unSqlBackendKey = 1}}, entityVal = Person {personName = "John doe", personAge = Just 35}},Entity {entityKey = PersonKey {unPersonKey = SqlBackendKey {unSqlBackendKey = 2}}, entityVal = Person {personName = "Hema", personAge = Just 36}}]  persistentTimeout period in microseconds persistentcreate a new connection persistentconnection count  None >@AEHMVX# persistent[get the SQL string for the table that a PeristEntity represents Useful for raw SQL queries`Your backend may provide a more convenient tableName function which does not operate in a Monad persistent>useful for a backend to implement tableName by adding escaping persistent[get the SQL string for the field that an EntityField represents Useful for raw SQL queries`Your backend may provide a more convenient fieldName function which does not operate in a Monad persistent>useful for a backend to implement fieldName by adding escapingNone>@AHV$LNone >@AEHVX_*\ persistentSame as *, but returns the number of rows affected. persistentSame as *, but returns the number of rows affected. persistentBGenerates sql for limit and offset for postgres, sqlite and mysql.  persistentinclude table name? persistentinclude WHERE? persistentinclude table name? persistentinclude the table nameNone>@AHVPm persistentGiven a gr, this parses it and returns either a list of errors associated with the migration or a list of migrations to do. persistentLike ,, but instead of returning the value in an  value, it calls  on the error values. persistentPrints a migration. persistent Convert a g to a list of  values corresponding to their i statements. persistentReturn all of the i4 values associated with the given migration. Calls + if there's a parse error on any migration. persistentkRuns a migration. If the migration fails to parse or if any of the migrations are unsafe, then this calls  to halt the program.  persistentSame as s, but does not report the individual migrations on stderr. Instead it returns a list of the executed SQL commands.+This is a safer/more robust alternative to b, but may be less silent for some persistent implementations, most notably persistent-postgresql persistentSame as V, but returns a list of the SQL commands executed instead of printing them to stderr.2This function silences the migration by remapping . As a result, it is not thread-safe and can clobber output from other parts of the program. This implementation method was chosen to also silence postgresql migration output on stderr, but is not recommended! persistentRun the given migration against the database. If the migration fails to parse, or there are any unsafe migrations, then this will error at runtime. This returns a list of the migrations that were executed. persistentLike P, but this will perform the unsafe database migrations instead of erroring out.  persistentSame as V, but returns a list of the SQL commands executed instead of printing them to stderr. persistentQSort the alter DB statements so tables are created before constraints are added. persistent1Given a list of old entity definitions and a new y in val, this creates a g9 to update the old list of definitions with the new one.  persistentReport a single error in a g.  persistentReport multiple errors in a g.  persistent&Add a migration to the migration plan.  persistentAdd a h (aka a [(, )]) to the migration plan. persistent is silent? persistentYIs the migration safe to run? (eg a non-destructive and idempotent update on the schema) persistentA 7 value representing the command to run on the database.None>@AHVZS persistent~Commit the current transaction and begin a new one. This is used when a transaction commit is required within the context of L (which brackets its provided action with a transaction begin/commit pair).  persistentVCommit the current transaction and begin a new one with the specified isolation level. persistentiRoll back the current transaction and begin a new one. This rolls back to the state of the last call to  or the enclosing  call.  persistentYRoll back the current transaction and begin a new one with the specified isolation level.   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]a^_`bcdfekghijlmnopqrstuvwxyz}{|~      !"#$%&'()*+,-./01=23456789:;<>?@ABCDEFGHIJKLMNOPQRSUVWcdefghijklmnopqrstuvwxyz{|}~Յcdefghijklmnopqrstuvw01=23456789:;<>?@ABC-./*+,IJKLMNSOPQRWVU)('&%DEFGHyx ! " # $ % & ' ( ) ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Z [ \ ] ^ _ ` a b c c d e f f g h i j k k l m n o o p q r s t u v w x x y z { | } ~                                     6         (            !"#$%&'()*+,-./0123345567789:;<=>?@ABCDEFGHIJKLMNOOPQRSTUVWXYZ[\]^_`abcdefghhijklmnopqrsstuvwxyz{|}~               !"#$%&'()*+(persistent-2.10.4-46xgHsOpj143FNGNwCZRVZDatabase.Persist.ClassDatabase.Persist.TypesDatabase.PersistDatabase.Persist.Quasi#Database.Persist.Sql.Types.InternalDatabase.Persist.SqlDatabase.Persist.Sql.Util$Database.Persist.Class.PersistConfigDatabase.Persist.Types.Base#Database.Persist.Class.PersistField$Database.Persist.Class.PersistEntityDatabase.Persist.GenericSqlrawSql#Database.Persist.Class.PersistStore$Database.Persist.Class.PersistUnique#Database.Persist.Class.PersistQuery$Database.Persist.Class.DeleteCascadeDatabase.Persist.Sql.TypesDatabase.Persist.Sql.InternalDatabase.Persist.Sql.ClassDatabase.Persist.Sql.RawDatabase.Persist.Sql.Run(Database.Persist.Sql.Orphan.PersistStore)Database.Persist.Sql.Orphan.PersistUnique(Database.Persist.Sql.Orphan.PersistQueryDatabase.Persist.Sql.Migration PersistConfigPersistConfigBackendPersistConfigPool loadConfigapplyEnvcreatePoolConfigrunPool PersistUpdateAssignAddSubtractMultiplyDivideBackendSpecificUpdateOnlyUniqueExceptionUpdateException KeyNotFound UpsertError PersistFilterEqNeGtLtGeLeInNotInBackendSpecificFilterSqlType SqlStringSqlInt32SqlInt64SqlReal SqlNumericSqlBoolSqlDaySqlTime SqlDayTimeSqlBlobSqlOther PersistValue PersistTextPersistByteString PersistInt64 PersistDoublePersistRational PersistBool PersistDayPersistTimeOfDayPersistUTCTime PersistNull PersistList PersistMapPersistObjectId PersistArrayPersistDbSpecificPersistException PersistErrorPersistMarshalErrorPersistInvalidFieldPersistForeignConstraintUnmetPersistMongoDBErrorPersistMongoDBUnsupported ForeignDefforeignRefTableHaskellforeignRefTableDBNameforeignConstraintNameHaskellforeignConstraintNameDBName foreignFields foreignAttrsforeignNullableForeignFieldDef CompositeDefcompositeFieldscompositeAttrs UniqueDef uniqueHaskell uniqueDBName uniqueFields uniqueAttrs EmbedFieldDef emFieldDB emFieldEmbed emFieldCycleEmbedEntityDefembeddedHaskellembeddedFields ReferenceDef NoReference ForeignRefEmbedRef CompositeRef SelfReferenceFieldDef fieldHaskellfieldDB fieldType fieldSqlType fieldAttrs fieldStrictfieldReference fieldComments FieldType FTTypeConFTAppFTListAttrDBNameunDBName HaskellName unHaskellName ExtraLine EntityDef entityHaskellentityDBentityId entityAttrs entityFields entityUniquesentityForeigns entityDerives entityExtra entitySumentityComments WhyNullable ByMaybeAttrByNullableAttr IsNullableNullable NotNullable CheckmarkActiveInactive entityPrimaryentityKeyFieldskeyAndEntityFieldstoEmbedEntityDeffromPersistValueTextSomePersistField PersistFieldtoPersistValuefromPersistValue getPersistMapEntity entityKey entityVal FilterValue FilterValues UnsafeValueFilter FilterAndFilterOr BackendFilter filterField filterValue filterFilter SelectOptAscDescOffsetByLimitToUpdate BackendUpdate updateField updateValue updateUpdate PersistEntityPersistEntityBackendKey EntityFieldUnique keyToValues keyFromValuespersistIdField entityDefpersistFieldDeftoPersistFieldsfromPersistValuespersistUniqueKeyspersistUniqueToFieldNamespersistUniqueToValues fieldLens entityValueskeyValueEntityToJSONkeyValueEntityFromJSONentityIdToJSONentityIdFromJSONtoPersistValueJSONfromPersistValueJSONPersistSettings psToDBNamepsStrictFieldspsIdNameupperCaseSettingslowerCaseSettingsparsenullable$fShowParseState $fShowToken $fEqTokenPersistStoreWriteinsertinsert_ insertMany insertMany_insertEntityMany insertKeyrepsert repsertManyreplacedeleteupdate updateGetPersistStoreReadgetgetMany PersistCore BackendKey ToBackendKey toBackendKeyfromBackendKeyPersistRecordBackendBackendCompatibleprojectBackendIsPersistBackendmkPersistBackendHasPersistBackend BaseBackendpersistBackend liftPersistgetJust getJustEntity belongsTo belongsToJust insertEntity getEntity insertRecordAtLeastOneUniqueKeyrequireUniquesPMultipleUniqueKeysErrorNoUniqueKeysErrorOnlyOneUniqueKey onlyUniquePPersistUniqueWritedeleteBy insertUniqueupsertupsertByputManyPersistUniqueReadgetByinsertByinsertUniqueEntity onlyUnique getByValue replaceUnique checkUniquePersistQueryWrite updateWhere deleteWherePersistQueryReadselectSourceRes selectFirst selectKeysRescount selectSource selectKeys selectListselectKeysList DeleteCascade deleteCascadedeleteCascadeWhere PersistStore PersistQuery PersistUnique IsSqlBackend SqlWriteTSqlReadTSqlBackendCanWriteSqlBackendCanReadSqlWriteBackendunSqlWriteBackendSqlReadBackendunSqlReadBackend SqlBackend connPrepare connInsertSqlconnInsertManySql connUpsertSqlconnPutManySql connStmtMap connCloseconnMigrateSql connBegin connCommit connRollbackconnEscapeName connNoLimit connRDBMSconnLimitOffset connLogFunc connMaxParamsconnRepsertManySqlIsolationLevelReadUncommitted ReadCommittedRepeatableRead Serializable Statement stmtFinalize stmtReset stmtExecute stmtQueryInsertSqlResult ISRSingle ISRInsertGet ISRManyKeysLogFuncmakeIsolationLevelStatementwriteToUnknown readToWrite readToUnknown$fIsPersistBackendSqlBackend$fHasPersistBackendSqlBackend $fIsPersistBackendSqlReadBackend!$fHasPersistBackendSqlReadBackend!$fIsPersistBackendSqlWriteBackend"$fHasPersistBackendSqlWriteBackend$fShowIsolationLevel$fEqIsolationLevel$fEnumIsolationLevel$fOrdIsolationLevel$fBoundedIsolationLevelSingleunSingleConnectionPool MigrationCautiousMigrationSql SqlPersistM SqlPersistTPersistentSqlExceptionStatementAlreadyFinalizedCouldn'tGetSQLConnectionColumncNamecNullcSqlTypecDefaultcDefaultConstraintNamecMaxLen cReferencedefaultAttribute mkColumns=.+=.-=.*=./=.==.!=.<.<=.>.>=.<-./<-.||. listToJSON mapToJSON toJsonTextlimitOffsetOrderentityColumnNameskeyAndEntityColumnNamesentityColumnCounthasCompositeKey dbIdColumnsdbIdColumnsEsc dbColumnsparseEntityValues isIdFieldupdateFieldDefupdatePersistValuecommaSeparated mkUpdateText mkUpdateText' parenWrappedPersistFieldSqlsqlTypeRawSql rawSqlColsrawSqlColCountReasonrawSqlProcessRowrawQuery rawQueryRes rawExecuterawExecuteCount getStmtConn runSqlPoolrunSqlPoolWithIsolation runSqlConnrunSqlConnWithIsolationrunSqlPersistMrunSqlPersistMPoolliftSqlPersistMPool withSqlPool createSqlPool askLogFunc withSqlConnclose'SqlWriteBackendKeyunSqlWriteBackendKeySqlReadBackendKeyunSqlReadBackendKey SqlBackendKeyunSqlBackendKey withRawQuerytoSqlKey fromSqlKey getTableName tableDBName getFieldName fieldDBNamedeleteWhereCountupdateWhereCountdecorateSQLWithLimitOffsetparseMigrationparseMigration'printMigration showMigration getMigration runMigrationrunMigrationQuietrunMigrationSilentrunMigrationUnsaferunMigrationUnsafeQuietmigrate reportError reportErrors addMigration addMigrationstransactionSavetransactionSaveWithIsolationtransactionUndotransactionUndoWithIsolation$aeson-1.4.5.0-9WciqreC8Dh4Ox91K72izuData.Aeson.Types.InternalValueghc-prim GHC.TypesTruebytestring-0.10.8.2Data.ByteString.Internal ByteString text-1.2.3.1Data.Text.InternalTextbase Data.EitherEitherRightLeftextraInputError intParseErrorfromPersistValueErrorfromPersistValueParseError recordNameidFieldtoPersistValueEnumGHC.EnumEnumfromPersistValueEnumBounded_unboundFieldsLineTokenSpacestokenizeempty removeSpaces parseLines mkEntityDeftransformers-0.5.5.0Control.Monad.Trans.ReaderReaderT GHC.MaybeNothingonlyOneUniqueDefatLeastOneUniqueDefGHC.BaseNonEmptygetByValueUniquesJustdefaultPutManypersistUniqueKeyValuesControl.Monad.Trans.Writer.LazyWriterTIOData.Aeson.Types.ToJSONToJSONfrom9to9from10to10from11to11from12to12$fRawSql(,,,,,,,,,,,)$fRawSql(,,,,,,,,,,)$fRawSql(,,,,,,,,,)$fRawSql(,,,,,,,,) $fRawSqlMaybegetStmtwithResourceTimeout,resource-pool-0.2.3.2-6gg8Kz4Ftsq8Ou95h5FFTw Data.Pool withResourcefilterClauseHelper filterClause orderClauseGHC.ErrerrorGHC.IO.Handle.FDstderr runMigration'sortMigrationsBool