-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Type-safe, multi-backend data serialization. -- -- Hackage documentation generation is not reliable. For up to date -- documentation, please see: -- http://www.stackage.org/package/persistent. @package persistent @version 2.10.5.4 module Database.Persist.Types -- | 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 -- Inactive Locations to be current. However, -- there may be at most one current Location 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. data Checkmark -- | When used on a uniqueness constraint, there may be at most one -- Active record. Active :: Checkmark -- | When used on a uniqueness constraint, there may be any number of -- Inactive records. Inactive :: Checkmark data IsNullable Nullable :: !WhyNullable -> IsNullable NotNullable :: IsNullable -- | 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. data WhyNullable ByMaybeAttr :: WhyNullable ByNullableAttr :: WhyNullable -- | 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. data EntityDef EntityDef :: !HaskellName -> !DBName -> !FieldDef -> ![Attr] -> ![FieldDef] -> ![UniqueDef] -> ![ForeignDef] -> ![Text] -> !Map Text [ExtraLine] -> !Bool -> !Maybe Text -> EntityDef -- | The name of the entity as Haskell understands it. [entityHaskell] :: EntityDef -> !HaskellName -- | The name of the database table corresponding to the entity. [entityDB] :: EntityDef -> !DBName -- | The entity's primary key or identifier. [entityId] :: EntityDef -> !FieldDef -- | The persistent entity syntax allows you to add arbitrary -- Attrs to an entity using the ! operator. Those -- attributes are stored in this list. [entityAttrs] :: EntityDef -> ![Attr] -- | The 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 -- keyAndEntityFields. [entityFields] :: EntityDef -> ![FieldDef] -- | The Uniqueness constraints for this entity. [entityUniques] :: EntityDef -> ![UniqueDef] -- | The foreign key relationships that this entity has to other entities. [entityForeigns] :: EntityDef -> ![ForeignDef] -- | A list of type classes that have been derived for this entity. [entityDerives] :: EntityDef -> ![Text] [entityExtra] :: EntityDef -> !Map Text [ExtraLine] -- | Whether or not this entity represents a sum type in the database. [entitySum] :: EntityDef -> !Bool -- | Optional comments on the entity. [entityComments] :: EntityDef -> !Maybe Text entityPrimary :: EntityDef -> Maybe CompositeDef entityKeyFields :: EntityDef -> [FieldDef] keyAndEntityFields :: EntityDef -> [FieldDef] type ExtraLine = [Text] newtype HaskellName HaskellName :: Text -> HaskellName [unHaskellName] :: HaskellName -> Text newtype DBName DBName :: Text -> DBName [unDBName] :: DBName -> Text type Attr = Text data FieldType -- | Optional module and name. FTTypeCon :: Maybe Text -> Text -> FieldType FTApp :: FieldType -> FieldType -> FieldType FTList :: FieldType -> FieldType -- | 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. data FieldDef FieldDef :: !HaskellName -> !DBName -> !FieldType -> !SqlType -> ![Attr] -> !Bool -> !ReferenceDef -> !Maybe Text -> FieldDef -- | 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 HaskellName "name" for -- a type User will have a record field userName. [fieldHaskell] :: FieldDef -> !HaskellName -- | The name of the field in the database. For SQL databases, this -- corresponds to the column name. [fieldDB] :: FieldDef -> !DBName -- | The type of the field in Haskell. [fieldType] :: FieldDef -> !FieldType -- | The type of the field in a SQL database. [fieldSqlType] :: FieldDef -> !SqlType -- | User annotations for a field. These are provided with the ! -- operator. [fieldAttrs] :: FieldDef -> ![Attr] -- | If this is True, then the Haskell datatype will have a strict -- record field. The default value for this is True. [fieldStrict] :: FieldDef -> !Bool [fieldReference] :: FieldDef -> !ReferenceDef -- | Optional comments for a Field. There is not currently a way -- to attach comments to a field in the quasiquoter. [fieldComments] :: FieldDef -> !Maybe Text -- | There are 3 kinds of references 1) composite (to fields that exist in -- the record) 2) single field 3) embedded data ReferenceDef NoReference :: ReferenceDef -- | A 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 -- FieldType ForeignRef :: !HaskellName -> !FieldType -> ReferenceDef EmbedRef :: EmbedEntityDef -> ReferenceDef CompositeRef :: CompositeDef -> ReferenceDef -- | A SelfReference stops an immediate cycle which causes non-termination -- at compile-time (issue #311). SelfReference :: ReferenceDef -- | An EmbedEntityDef is the same as an EntityDef But it is only used for -- fieldReference so it only has data needed for embedding data EmbedEntityDef EmbedEntityDef :: !HaskellName -> ![EmbedFieldDef] -> EmbedEntityDef [embeddedHaskell] :: EmbedEntityDef -> !HaskellName [embeddedFields] :: EmbedEntityDef -> ![EmbedFieldDef] -- | An EmbedFieldDef is the same as a FieldDef But it is only used for -- embeddedFields so it only has data needed for embedding data EmbedFieldDef EmbedFieldDef :: !DBName -> Maybe EmbedEntityDef -> Maybe HaskellName -> EmbedFieldDef [emFieldDB] :: EmbedFieldDef -> !DBName [emFieldEmbed] :: EmbedFieldDef -> Maybe EmbedEntityDef -- | emFieldEmbed can create a cycle (issue #311) when a cycle is -- detected, emFieldEmbed will be Nothing and emFieldCycle -- will be Just [emFieldCycle] :: EmbedFieldDef -> Maybe HaskellName toEmbedEntityDef :: EntityDef -> EmbedEntityDef data UniqueDef UniqueDef :: !HaskellName -> !DBName -> ![(HaskellName, DBName)] -> ![Attr] -> UniqueDef [uniqueHaskell] :: UniqueDef -> !HaskellName [uniqueDBName] :: UniqueDef -> !DBName [uniqueFields] :: UniqueDef -> ![(HaskellName, DBName)] [uniqueAttrs] :: UniqueDef -> ![Attr] data CompositeDef CompositeDef :: ![FieldDef] -> ![Attr] -> CompositeDef [compositeFields] :: CompositeDef -> ![FieldDef] [compositeAttrs] :: CompositeDef -> ![Attr] -- | Used instead of FieldDef to generate a smaller amount of code type ForeignFieldDef = (HaskellName, DBName) data ForeignDef ForeignDef :: !HaskellName -> !DBName -> !HaskellName -> !DBName -> ![(ForeignFieldDef, ForeignFieldDef)] -> ![Attr] -> Bool -> ForeignDef [foreignRefTableHaskell] :: ForeignDef -> !HaskellName [foreignRefTableDBName] :: ForeignDef -> !DBName [foreignConstraintNameHaskell] :: ForeignDef -> !HaskellName [foreignConstraintNameDBName] :: ForeignDef -> !DBName [foreignFields] :: ForeignDef -> ![(ForeignFieldDef, ForeignFieldDef)] [foreignAttrs] :: ForeignDef -> ![Attr] [foreignNullable] :: ForeignDef -> Bool data PersistException -- | Generic Exception PersistError :: Text -> PersistException PersistMarshalError :: Text -> PersistException PersistInvalidField :: Text -> PersistException PersistForeignConstraintUnmet :: Text -> PersistException PersistMongoDBError :: Text -> PersistException PersistMongoDBUnsupported :: Text -> PersistException -- | A raw value which can be stored in any backend and can be marshalled -- to and from a PersistField. data PersistValue PersistText :: Text -> PersistValue PersistByteString :: ByteString -> PersistValue PersistInt64 :: Int64 -> PersistValue PersistDouble :: Double -> PersistValue PersistRational :: Rational -> PersistValue PersistBool :: Bool -> PersistValue PersistDay :: Day -> PersistValue PersistTimeOfDay :: TimeOfDay -> PersistValue PersistUTCTime :: UTCTime -> PersistValue PersistNull :: PersistValue PersistList :: [PersistValue] -> PersistValue PersistMap :: [(Text, PersistValue)] -> PersistValue -- | Intended especially for MongoDB backend PersistObjectId :: ByteString -> PersistValue -- | Intended especially for PostgreSQL backend for text arrays PersistArray :: [PersistValue] -> PersistValue -- | Using PersistDbSpecific 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
--   
-- -- If Foo has a geography field, we can then perform insertions like the -- following: -- --
--   insert $ Foo (toPoint 44 44)
--   
PersistDbSpecific :: ByteString -> PersistValue fromPersistValueText :: PersistValue -> Either Text Text -- | 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. data SqlType SqlString :: SqlType SqlInt32 :: SqlType SqlInt64 :: SqlType SqlReal :: SqlType SqlNumeric :: Word32 -> Word32 -> SqlType SqlBool :: SqlType SqlDay :: SqlType SqlTime :: SqlType -- | Always uses UTC timezone SqlDayTime :: SqlType SqlBlob :: SqlType -- | a backend-specific name SqlOther :: Text -> SqlType data PersistFilter Eq :: PersistFilter Ne :: PersistFilter Gt :: PersistFilter Lt :: PersistFilter Ge :: PersistFilter Le :: PersistFilter In :: PersistFilter NotIn :: PersistFilter BackendSpecificFilter :: Text -> PersistFilter data UpdateException KeyNotFound :: String -> UpdateException UpsertError :: String -> UpdateException data OnlyUniqueException OnlyUniqueException :: String -> OnlyUniqueException data PersistUpdate Assign :: PersistUpdate Add :: PersistUpdate Subtract :: PersistUpdate Multiply :: PersistUpdate Divide :: PersistUpdate BackendSpecificUpdate :: Text -> PersistUpdate data SomePersistField SomePersistField :: a -> SomePersistField -- | Updating a database entity. -- -- Persistent users use combinators to create these. data Update record Update :: EntityField record typ -> typ -> PersistUpdate -> Update record [updateField] :: Update record -> EntityField record typ [updateValue] :: Update record -> typ [updateUpdate] :: Update record -> PersistUpdate BackendUpdate :: BackendSpecificUpdate (PersistEntityBackend record) record -> Update record type family BackendSpecificUpdate backend record -- | Query options. -- -- Persistent users use these directly. data SelectOpt record Asc :: EntityField record typ -> SelectOpt record Desc :: EntityField record typ -> SelectOpt record OffsetBy :: Int -> SelectOpt record LimitTo :: Int -> SelectOpt record -- | 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 -- In PersistFilter requires that you have an array- or -- list-shaped EntityField. It is possible to construct values -- using this that will create malformed runtime values. data Filter record Filter :: EntityField record typ -> FilterValue typ -> PersistFilter -> Filter record [filterField] :: Filter record -> EntityField record typ [filterValue] :: Filter record -> FilterValue typ [filterFilter] :: Filter record -> PersistFilter -- | convenient for internal use, not needed for the API FilterAnd :: [Filter record] -> Filter record FilterOr :: [Filter record] -> Filter record BackendFilter :: BackendSpecificFilter (PersistEntityBackend record) record -> Filter record -- | Value to filter with. Highly dependant on the type of filter used. data FilterValue typ [FilterValue] :: typ -> FilterValue typ [FilterValues] :: [typ] -> FilterValue typ [UnsafeValue] :: forall a typ. PersistField a => a -> FilterValue typ type family BackendSpecificFilter backend record -- | By default, a backend will automatically generate the key Instead you -- can specify a Primary key made up of unique values. data family Key record -- | 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.GenericSql 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. data Entity record Entity :: Key record -> record -> Entity record [entityKey] :: Entity record -> Key record [entityVal] :: Entity record -> record -- | This module defines the Persistent entity syntax used in the -- quasiquoter to generate persistent entities. -- -- The basic structure of the syntax looks like this: -- --
--   TableName
--       fieldName      FieldType
--       otherField     String
--       nullableField  Int       Maybe
--   
-- -- You start an entity definition with the table name, in this case, -- TableName. It's followed by a list of fields on the entity, -- which have the basic form fieldName FieldType. You can -- indicate that a field is nullable with Maybe at the end of the -- type. -- -- persistent automatically generates an ID column for you, if -- you don't specify one, so the above table definition corresponds to -- the following SQL: -- --
--   CREATE TABLE table_name (
--       id                SERIAL PRIMARY KEY,
--       field_name        field_type NOT NULL,
--       other_field       varchar    NOT NULL,
--       nullable_field    int NULL
--   );
--   
-- -- Note that the exact SQL that is generated can be customized using the -- PersistSettings that are passed to the parse function. -- -- It generates a Haskell datatype with the following form: -- --
--   data TableName = TableName
--       { tableNameFieldName :: FieldType
--       , tableNameOtherField :: String
--       , tableNameNullableField :: Maybe Int
--       }
--   
-- -- As with the SQL generated, the specifics of this are customizable. See -- the persistent-template package for details. -- --

Deriving

-- -- You can add a deriving clause to a table, and the generated Haskell -- type will have a deriving clause with that. Unlike normal Haskell -- syntax, you don't need parentheses or commas to separate the classes, -- and you can even have multiple deriving clauses. -- --
--   User
--       name String
--       age  Int
--       deriving Eq Show
--       deriving Ord
--   
-- --

Unique Keys

-- -- You can define a uniqueness key on a table with the following format: -- --
--   User
--      name String
--      age  Int
--   
--      UniqueUserName name
--   
-- -- This will put a unique index on the user table and the -- name field. -- --

Setting defaults

-- -- You can use a default=${sql expression} clause to set a -- default for a field. The thing following the `=` is interpreted as SQL -- that will be put directly into the table definition. -- --
--   User
--       name    Text
--       admin   Bool default=false
--   
-- -- This creates a SQL definition like this: -- --
--   CREATE TABLE user (
--     id      SERIAL PRIMARY KEY,
--     name    VARCHAR NOT NULL,
--     admin   BOOL DEFAULT=false
--   );
--   
-- -- A restriction here is that you still need to provide a value when -- performing an insert, because the generated Haskell type has -- the form: -- --
--   data User = User
--       { userName :: Text
--       , userAdmin :: Bool
--       }
--   
-- -- You can work around this by using a 'Maybe Bool' and supplying -- Nothing by default. -- --

Custom ID column

-- -- If you don't want to use the default ID column type of Int64, -- you can set a custom type with an Id field. This -- User has a Text ID. -- --
--   User
--       Id   Text
--       name Text
--       age  Int
--   
-- -- If you do this, it's a good idea to set a default for the ID. -- Otherwise, you will need to use insertKey instead of -- insert when performing inserts. -- --
--   insertKey (UserKey "Hello world!") (User Bob 32)
--   
-- -- If you attempt to do insert (User Bob 32), -- then you will receive a runtime error because the SQL database doesn't -- know how to make an ID for you anymore. So instead just use a default -- expression, like this: -- --
--   User
--       Id      Text default=generate_user_id()
--       name    Text
--       age     Int
--   
-- --

Custom Primary Keys

-- -- Sometimes you don't want to have an ID column, and you want a -- different sort of primary key. This is a table that stores unique -- email addresses, and the email is the primary key. We store the first -- and second part (eg first@second) separately. -- --
--   Email
--       firstPart   Text
--       secondPart  Text
--   
--       Primary firstPart secondPart
--   
-- -- This creates a table with the following form: -- --
--   CREATE TABLE email (
--       first_part  varchar,
--       second_part varchar,
--   
--       PRIMARY KEY (first_part, second_part)
--   
-- -- You can specify 1 or more columns in the primary key. -- --

Overriding SQL

-- -- You can use a sql=custom annotation to provide some -- customization on the entity and field. For example, you might prefer -- to name a table differently than what persistent will do by -- default. You may also prefer to name a field differently. -- --
--   User sql=big_user_table
--       fullName    String sql=name
--       age         Int
--   
-- -- This will alter the generated SQL to be: -- --
--   CREATE TABEL big_user_table (
--       id      SERIAL PRIMARY KEY,
--       name    VARCHAR,
--       age     INT
--   );
--   
-- --

Attributes

-- -- The QuasiQuoter allows you to provide arbitrary attributes to an -- entity or field. This can be used to extend the code in ways that the -- library hasn't anticipated. If you use this feature, we'd definitely -- appreciate hearing about it and potentially supporting your use case -- directly! -- --
--   User !funny
--       field   String  !sad
--       good    Dog     !sogood
--   
-- -- We can see the attributes using the entityAttrs field and the -- fieldAttrs field. -- --
--   userAttrs = do
--       let userDefinition = entityDef (Proxy :: Proxy User)
--       let userAttributes = entityAttrs userDefinition
--       let fieldAttributes = map fieldAttrs (entityFields userDefinition)
--       print userAttributes
--   -- ["funny"]
--       print fieldAttributes
--   -- [["sad"],["sogood"]]
--   
-- --

Documentation Comments

-- -- The quasiquoter supports ordinary comments with -- and -- #. Since persistent-2.10.5.1, it also supports -- documentation comments. The grammar for documentation comments is -- similar to Haskell's Haddock syntax, with a few restrictions: -- --
    --
  1. Only the -- | form is allowed.
  2. --
  3. You must put a space before and after the | pipe -- character.
  4. --
  5. The comment must be indented at the same level as the entity or -- field it documents.
  6. --
-- -- An example of the field documentation is: -- --
--   -- | I am a doc comment for a User. Users are important
--   -- | to the application, and should be treasured.
--   User
--       -- | Users have names. Call them by names.
--       name String
--       -- | A user can be old, or young, and we care about
--       -- | this for some reason.
--       age Int
--   
-- -- The documentation is present on the entityComments field on the -- EntityDef for the entity: -- --
--   >>> let userDefinition = entityDef (Proxy :: Proxy User)
--   >>> entityComments userDefinition
--   "I am a doc comment for a User. Users are importantnto the application, and should be treasured.n"
--   
-- -- Likewise, the field documentation is present in the -- fieldComments field on the FieldDef present in the -- EntityDef: -- --
--   >>> let userFields = entityFields userDefinition
--   >>> let comments = map fieldComments userFields
--   >>> mapM_ putStrLn comments
--   "Users have names. Call them by names."
--   "A user can be old, or young, and we care aboutnthis for some reason."
--   
-- -- Unfortunately, we can't use this to create Haddocks for you, because -- Template Haskell does not support Haddock yet. -- persistent backends *can* use this to generate SQL -- COMMENTs, which are useful for a database perspective, and -- you can use the @persistent-documentation@ library to render a -- Markdown document of the entity definitions. module Database.Persist.Quasi -- | Parses a quasi-quoted syntax into a list of entity definitions. parse :: PersistSettings -> Text -> [EntityDef] data PersistSettings PersistSettings :: !Text -> Text -> !Bool -> !Text -> PersistSettings [psToDBName] :: PersistSettings -> !Text -> Text -- | Whether fields are by default strict. Default value: True. [psStrictFields] :: PersistSettings -> !Bool -- | The name of the id column. Default value: id The name of the -- id column can also be changed on a per-model basis -- https://github.com/yesodweb/persistent/wiki/Persistent-entity-syntax [psIdName] :: PersistSettings -> !Text upperCaseSettings :: PersistSettings lowerCaseSettings :: PersistSettings nullable :: [Text] -> IsNullable instance GHC.Show.Show a => GHC.Show.Show (Database.Persist.Quasi.ParseState a) instance GHC.Classes.Eq Database.Persist.Quasi.Token instance GHC.Show.Show Database.Persist.Quasi.Token instance GHC.Show.Show Database.Persist.Quasi.LinesWithComments instance GHC.Classes.Eq Database.Persist.Quasi.LinesWithComments instance GHC.Show.Show (f Data.Text.Internal.Text) => GHC.Show.Show (Database.Persist.Quasi.Line' f) instance GHC.Classes.Eq (f Data.Text.Internal.Text) => GHC.Classes.Eq (Database.Persist.Quasi.Line' f) module Database.Persist.Class -- | ToBackendKey converts a PersistEntity Key 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. class (PersistEntity record, PersistEntityBackend record ~ backend, PersistCore backend) => ToBackendKey backend record toBackendKey :: ToBackendKey backend record => Key record -> BackendKey backend fromBackendKey :: ToBackendKey backend record => BackendKey backend -> Key record class PersistCore backend where { data family BackendKey backend; } -- | 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. type PersistStore a = PersistStoreWrite a class (Show (BackendKey backend), Read (BackendKey backend), Eq (BackendKey backend), Ord (BackendKey backend), PersistCore backend, PersistField (BackendKey backend), ToJSON (BackendKey backend), FromJSON (BackendKey backend)) => PersistStoreRead backend -- | Get a record by identifier, if available. -- --

Example usage

-- -- With schema-1 and dataset-1, -- --
--   getSpj :: MonadIO m => ReaderT SqlBackend m (Maybe User)
--   getSpj = get spjId
--   
-- --
--   mspj <- getSpj
--   
-- -- The above query when applied on dataset-1, will get this: -- --
--   +------+-----+
--   | name | age |
--   +------+-----+
--   | SPJ  |  40 |
--   +------+-----+
--   
get :: (PersistStoreRead backend, MonadIO m, PersistRecordBackend record backend) => Key record -> ReaderT backend m (Maybe record) -- | Get many records by their respective identifiers, if available. -- --

Example usage

-- -- With schema-1 and dataset-1: -- --
--   getUsers :: MonadIO m => ReaderT SqlBackend m (Map (Key User) User)
--   getUsers = getMany allkeys
--   
-- --
--   musers <- getUsers
--   
-- -- The above query when applied on dataset-1, will get these -- records: -- --
--   +----+-------+-----+
--   | id | name  | age |
--   +----+-------+-----+
--   |  1 | SPJ   |  40 |
--   +----+-------+-----+
--   |  2 | Simon |  41 |
--   +----+-------+-----+
--   
getMany :: (PersistStoreRead backend, MonadIO m, PersistRecordBackend record backend) => [Key record] -> ReaderT backend m (Map (Key record) record) class (Show (BackendKey backend), Read (BackendKey backend), Eq (BackendKey backend), Ord (BackendKey backend), PersistStoreRead backend, PersistField (BackendKey backend), ToJSON (BackendKey backend), FromJSON (BackendKey backend)) => PersistStoreWrite backend -- | Create a new record in the database, returning an automatically -- created key (in SQL an auto-increment id). -- --

Example usage

-- -- Using schema-1 and 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-1, will produce this: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |1    |SPJ   |40   |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   |3    |John  |30   |
--   +-----+------+-----+
--   
insert :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m (Key record) -- | Same as insert, but doesn't return a Key. -- --

Example usage

-- -- with schema-1 and dataset-1, -- --
--   insertJohn :: MonadIO m => ReaderT SqlBackend m (Key User)
--   insertJohn = insert_ $ User "John" 30
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |1    |SPJ   |40   |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   |3    |John  |30   |
--   +-----+------+-----+
--   
insert_ :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m () -- | Create multiple records in the database and return their Keys. -- -- If you don't need the inserted Keys, use insertMany_. -- -- The MongoDB and PostgreSQL backends insert all records and retrieve -- their keys in one database query. -- -- The SQLite and MySQL backends use the slow, default implementation of -- mapM insert. -- --

Example usage

-- -- with schema-1 and 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-1, will produce this: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |1    |SPJ   |40   |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   |3    |John  |30   |
--   +-----+------+-----+
--   |4    |Nick  |32   |
--   +-----+------+-----+
--   |5    |Jane  |20   |
--   +-----+------+-----+
--   
insertMany :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m [Key record] -- | Same as insertMany, but doesn't return any Keys. -- -- The MongoDB, PostgreSQL, SQLite and MySQL backends insert all records -- in one database query. -- --

Example usage

-- -- With schema-1 and 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-1, will produce this: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |1    |SPJ   |40   |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   |3    |John  |30   |
--   +-----+------+-----+
--   |4    |Nick  |32   |
--   +-----+------+-----+
--   |5    |Jane  |20   |
--   +-----+------+-----+
--   
insertMany_ :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m () -- | Same as insertMany_, but takes an Entity instead of just -- a record. -- -- Useful 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 usage

-- -- With schema-1 and dataset-1, -- --
--   insertUserEntityMany :: MonadIO m => ReaderT SqlBackend m ()
--   insertUserEntityMany = insertEntityMany [SnakeEntity, EvaEntity]
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |1    |SPJ   |40   |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   |3    |Snake |38   |
--   +-----+------+-----+
--   |4    |Eva   |38   |
--   +-----+------+-----+
--   
insertEntityMany :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [Entity record] -> ReaderT backend m () -- | Create a new record in the database using the given key. -- --

Example usage

-- -- With schema-1 and dataset-1, -- --
--   insertAliceKey :: MonadIO m => Key User -> ReaderT SqlBackend m ()
--   insertAliceKey key = insertKey key $ User "Alice" 20
--   
-- --
--   insertAliceKey $ UserKey {unUserKey = SqlBackendKey {unSqlBackendKey = 3}}
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |1    |SPJ   |40   |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   |3    |Alice |20   |
--   +-----+------+-----+
--   
insertKey :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m () -- | Put the record in the database with the given key. Unlike -- replace, if a record with the given key does not exist then a -- new record will be inserted. -- --

Example usage

-- -- We try to explain upsertBy using schema-1 and -- dataset-1. -- -- First, we insert Philip to dataset-1. -- --
--   insertPhilip :: MonadIO m => ReaderT SqlBackend m (Key User)
--   insertPhilip = insert $ User "Philip" 42
--   
-- --
--   philipId <- insertPhilip
--   
-- -- This query will produce: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |1    |SPJ   |40   |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   |3    |Philip|42   |
--   +-----+------+-----+
--   
-- --
--   repsertHaskell :: 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|
--   +-----+-----------------+--------+
--   
-- -- repsert inserts the given record if the key doesn't exist. -- --
--   repsertXToUnknown :: MonadIO m => ReaderT SqlBackend m ()
--   repsertXToUnknown = repsert unknownId $ User "X" 999
--   
-- -- For example, applying the above query to dataset-1 will produce -- this: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |1    |SPJ   |40   |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   |3    |X     |999  |
--   +-----+------+-----+
--   
repsert :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m () -- | Put many entities into the database. -- -- Batch version of repsert for SQL backends. -- -- Useful when migrating data from one entity to another and want to -- preserve ids. -- --

Example usage

-- -- With schema-1 and 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-1, will produce this: -- --
--   +-----+----------------+---------+
--   |id   |name            |age      |
--   +-----+----------------+---------+
--   |1    |SPJ             |40       |
--   +-----+----------------+---------+
--   |2    |Simon -> Philip |41 -> 20 |
--   +-----+----------------+---------+
--   |999  |Mr. X           |999      |
--   +-----+----------------+---------+
--   
repsertMany :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [(Key record, record)] -> ReaderT backend m () -- | 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. -- --

Example usage

-- -- With schema-1 schama-1 and dataset-1, -- --
--   replaceSpj :: MonadIO m => User -> ReaderT SqlBackend m ()
--   replaceSpj record = replace spjId record
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |1    |Mike  |45   |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   
replace :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> record -> ReaderT backend m () -- | Delete a specific record by identifier. Does nothing if record does -- not exist. -- --

Example usage

-- -- With schema-1 and dataset-1, -- --
--   deleteSpj :: MonadIO m => ReaderT SqlBackend m ()
--   deleteSpj = delete spjId
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   
delete :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> ReaderT backend m () -- | Update individual fields on a specific record. -- --

Example usage

-- -- With schema-1 and dataset-1, -- --
--   updateSpj :: MonadIO m => [Update User] -> ReaderT SqlBackend m ()
--   updateSpj updates = update spjId updates
--   
-- --
--   updateSpj [UserAge +=. 100]
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |1    |SPJ   |140  |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   
update :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> [Update record] -> ReaderT backend m () -- | Update 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 usage

-- -- With schema-1 and dataset-1, -- --
--   updateGetSpj :: MonadIO m => [Update User] -> ReaderT SqlBackend m User
--   updateGetSpj updates = updateGet spjId updates
--   
-- --
--   spj <- updateGetSpj [UserAge +=. 100]
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |1    |SPJ   |140  |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   
updateGet :: (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> [Update record] -> ReaderT backend m record -- | A convenient alias for common type signatures type PersistRecordBackend record backend = (PersistEntity record, PersistEntityBackend record ~ BaseBackend backend) -- | Same as get, but for a non-null (not Maybe) foreign key. Unsafe -- unless your database is enforcing that the foreign key is valid. -- --

Example usage

-- -- With schema-1 and dataset-1, -- --
--   getJustSpj :: MonadIO m => ReaderT SqlBackend m User
--   getJustSpj = getJust spjId
--   
-- --
--   spj <- getJust spjId
--   
-- -- The above query when applied on dataset-1, will get this -- record: -- --
--   +----+------+-----+
--   | id | name | age |
--   +----+------+-----+
--   |  1 | SPJ  |  40 |
--   +----+------+-----+
--   
-- --
--   getJustUnknown :: MonadIO m => ReaderT SqlBackend m User
--   getJustUnknown = getJust unknownId
--   
-- -- mrx <- getJustUnknown -- -- This just throws an error. getJust :: (PersistStoreRead backend, PersistRecordBackend record backend, MonadIO m) => Key record -> ReaderT backend m record -- | Same as getJust, but returns an Entity instead of just -- the record. -- --

Example usage

-- -- With schema-1 and dataset-1, -- --
--   getJustEntitySpj :: MonadIO m => ReaderT SqlBackend m (Entity User)
--   getJustEntitySpj = getJustEntity spjId
--   
-- --
--   spjEnt <- getJustEntitySpj
--   
-- -- The above query when applied on dataset-1, will get this -- entity: -- --
--   +----+------+-----+
--   | id | name | age |
--   +----+------+-----+
--   |  1 | SPJ  |  40 |
--   +----+------+-----+
--   
getJustEntity :: (PersistEntityBackend record ~ BaseBackend backend, MonadIO m, PersistEntity record, PersistStoreRead backend) => Key record -> ReaderT backend m (Entity record) -- | Like get, but returns the complete Entity. -- --

Example usage

-- -- With schema-1 and dataset-1, -- --
--   getSpjEntity :: MonadIO m => ReaderT SqlBackend m (Maybe (Entity User))
--   getSpjEntity = getEntity spjId
--   
-- --
--   mSpjEnt <- getSpjEntity
--   
-- -- The above query when applied on dataset-1, will get this -- entity: -- --
--   +----+------+-----+
--   | id | name | age |
--   +----+------+-----+
--   |  1 | SPJ  |  40 |
--   +----+------+-----+
--   
getEntity :: (PersistStoreRead backend, PersistRecordBackend e backend, MonadIO m) => Key e -> ReaderT backend m (Maybe (Entity e)) -- | Curry this to make a convenience function that loads an associated -- model. -- --
--   foreign = belongsTo foreignId
--   
belongsTo :: (PersistStoreRead backend, PersistEntity ent1, PersistRecordBackend ent2 backend, MonadIO m) => (ent1 -> Maybe (Key ent2)) -> ent1 -> ReaderT backend m (Maybe ent2) -- | Same as belongsTo, but uses getJust and therefore is -- similarly unsafe. belongsToJust :: (PersistStoreRead backend, PersistEntity ent1, PersistRecordBackend ent2 backend, MonadIO m) => (ent1 -> Key ent2) -> ent1 -> ReaderT backend m ent2 -- | Like insert, but returns the complete Entity. -- --

Example usage

-- -- With schema-1 and dataset-1, -- --
--   insertHaskellEntity :: MonadIO m => ReaderT SqlBackend m (Entity User)
--   insertHaskellEntity = insertEntity $ User "Haskell" 81
--   
-- --
--   haskellEnt <- insertHaskellEntity
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +----+---------+-----+
--   | id |  name   | age |
--   +----+---------+-----+
--   |  1 | SPJ     |  40 |
--   +----+---------+-----+
--   |  2 | Simon   |  41 |
--   +----+---------+-----+
--   |  3 | Haskell |  81 |
--   +----+---------+-----+
--   
insertEntity :: (PersistStoreWrite backend, PersistRecordBackend e backend, MonadIO m) => e -> ReaderT backend m (Entity e) -- | Like insertEntity but just returns the record instead of -- Entity. -- --

Example usage

-- -- With schema-1 and dataset-1, -- --
--   insertDaveRecord :: MonadIO m => ReaderT SqlBackend m User
--   insertDaveRecord = insertRecord $ User "Dave" 50
--   
-- --
--   dave <- insertDaveRecord
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |1    |SPJ   |40   |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   |3    |Dave  |50   |
--   +-----+------+-----+
--   
insertRecord :: (PersistEntityBackend record ~ BaseBackend backend, PersistEntity record, MonadIO m, PersistStoreWrite backend) => record -> ReaderT backend m record -- | 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. type PersistUnique a = PersistUniqueWrite a -- | 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 single -- Unique, 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. class (PersistCore backend, PersistStoreRead backend) => PersistUniqueRead backend -- | Get a record by unique key, if available. Returns also the identifier. -- --

Example usage

-- -- With schema-1 and dataset-1: -- --
--   getBySpjName :: MonadIO m  => ReaderT SqlBackend m (Maybe (Entity User))
--   getBySpjName = getBy $ UniqueUserName "SPJ"
--   
-- --
--   mSpjEnt <- getBySpjName
--   
-- -- The above query when applied on dataset-1, will get this -- entity: -- --
--   +----+------+-----+
--   | id | name | age |
--   +----+------+-----+
--   |  1 | SPJ  |  40 |
--   +----+------+-----+
--   
getBy :: (PersistUniqueRead backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> ReaderT backend m (Maybe (Entity record)) -- | 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, -- -- class (PersistUniqueRead backend, PersistStoreWrite backend) => PersistUniqueWrite backend -- | Delete a specific record by unique key. Does nothing if no record -- matches. -- --

Example usage

-- -- With schema-1 and dataset-1, -- --
--   deleteBySpjName :: MonadIO m => ReaderT SqlBackend m ()
--   deleteBySpjName = deleteBy UniqueUserName "SPJ"
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+------+-----+
--   |id   |name  |age  |
--   +-----+------+-----+
--   |2    |Simon |41   |
--   +-----+------+-----+
--   
deleteBy :: (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> ReaderT backend m () -- | Like insert, but returns Nothing when the record -- couldn't be inserted because of a uniqueness constraint. -- --

Example usage

-- -- With schema-1 and dataset-1, we try to insert the -- following two records: -- --
--   linusId <- 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-1, while SPJ wasn't -- because SPJ already exists in dataset-1. insertUnique :: (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => record -> ReaderT backend m (Maybe (Key record)) -- | Update based on a uniqueness constraint or insert: -- -- -- --

Example usage

-- -- First, we try to explain upsert using schema-1 and -- 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-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-1, will produce this: -- --
--   +-----+-----+--------+
--   |id   |name |age     |
--   +-----+-----+--------+
--   |1    |SPJ  |40      |
--   +-----+-----+--------+
--   |2    |Simon|41      |
--   +-----+-----+--------+
--   |3    |X    |999     |
--   +-----+-----+--------+
--   
-- -- 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. upsert :: (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> [Update record] -> ReaderT backend m (Entity record) -- | Update based on a given uniqueness constraint or insert: -- -- -- --

Example usage

-- -- We try to explain upsertBy using schema-2 and -- 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-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
--   
-- --
--   mPhilipEnt <- upsertBySimonAge (User "X" 999) [UserName =. "Philip"]
--   
-- -- The above query will alter 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-1 to: -- --
--   +-----+-----+-----+
--   |id   |name |age  |
--   +-----+-----+-----+
--   |1    |SPJ  |40   |
--   +-----+-----+-----+
--   |2    |Simon|41   |
--   +-----+-----+-----+
--   |3    |X    |999  |
--   +-----+-----+-----+
--   
upsertBy :: (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> record -> [Update record] -> ReaderT backend m (Entity record) -- | Put many records into db -- -- putMany :: (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m () -- | 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. class PersistEntity record => OnlyOneUniqueKey record onlyUniqueP :: OnlyOneUniqueKey record => record -> Unique record -- | 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. class PersistEntity record => AtLeastOneUniqueKey record requireUniquesP :: AtLeastOneUniqueKey record => record -> NonEmpty (Unique record) -- | This is an error message. It is used when writing instances of -- OnlyOneUniqueKey for an entity that has no unique keys. type NoUniqueKeysError ty = 'Text "The entity " :<>: 'ShowType ty :<>: '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 is an error message. It is used when an entity has multiple -- unique keys, and the function expects a single unique key. type MultipleUniqueKeysError ty = 'Text "The entity " :<>: 'ShowType ty :<>: '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." -- | 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. -- --

Example usage

-- -- With schema-1 and dataset-1, -- -- getBySpjValue :: MonadIO m => ReaderT SqlBackend m (Maybe (Entity -- User)) getBySpjValue = getByValue $ User SPJ 999 -- --
--   mSpjEnt <- getBySpjValue
--   
-- -- The above query when applied on dataset-1, will get this -- record: -- --
--   +----+------+-----+
--   | id | name | age |
--   +----+------+-----+
--   |  1 | SPJ  |  40 |
--   +----+------+-----+
--   
getByValue :: forall record m backend. (MonadIO m, PersistUniqueRead backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record) => record -> ReaderT backend m (Maybe (Entity record)) -- | 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. -- --

Example usage

-- -- With schema-2 and 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" 100
--   
-- -- First three lines return Left because there're duplicates in -- given record's uniqueness constraints. While the last line returns a -- new key as Right. insertBy :: (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record) => record -> ReaderT backend m (Either (Entity record) (Key record)) -- | Like insertEntity, but returns Nothing when the record -- couldn't be inserted because of a uniqueness constraint. -- --

Example usage

-- -- We use schema-2 and dataset-1 here. -- --
--   insertUniqueSpjEntity :: MonadIO m => ReaderT SqlBackend m (Maybe (Entity User))
--   insertUniqueSpjEntity = insertUniqueEntity $ User "SPJ" 50
--   
-- --
--   mSpjEnt <- insertUniqueSpjEntity
--   
-- -- The above query results Nothing 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-1, will produce this: -- --
--   +----+-------+-----+
--   | id | name  | age |
--   +----+-------+-----+
--   |  1 | SPJ   |  40 |
--   +----+-------+-----+
--   |  2 | Simon |  41 |
--   +----+-------+-----+
--   |  3 | Alexa |   3 |
--   +----+-------+-----+
--   
insertUniqueEntity :: (MonadIO m, PersistRecordBackend record backend, PersistUniqueWrite backend) => record -> ReaderT backend m (Maybe (Entity record)) -- | 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 replaceUnique :: (MonadIO m, Eq (Unique record), PersistRecordBackend record backend, PersistUniqueWrite backend) => Key record -> record -> ReaderT backend m (Maybe (Unique record)) -- | Check whether there are any conflicts for unique keys with this entity -- and existing entities in the database. -- -- Returns Nothing if the entity would be unique, and could thus -- safely be inserted. on a conflict returns the conflicting key -- --

Example usage

-- -- We use schema-1 and dataset-1 here. -- -- This would be Nothing: -- --
--   mAlanConst <- checkUnique $ User "Alan" 70
--   
-- -- While this would be Just because SPJ already exists: -- --
--   mSpjConst <- checkUnique $ User "SPJ" 60
--   
checkUnique :: (MonadIO m, PersistRecordBackend record backend, PersistUniqueRead backend) => record -> ReaderT backend m (Maybe (Unique record)) -- | Return the single unique key for a record. -- --

Example usage

-- -- We use shcema-1 and dataset-1 here. -- --
--   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. onlyUnique :: (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> ReaderT backend m (Unique record) -- | 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. type PersistQuery a = PersistQueryWrite a -- | Backends supporting conditional read operations. class (PersistCore backend, PersistStoreRead backend) => PersistQueryRead backend -- | Get all records matching the given criterion in the specified order. -- Returns also the identifiers. selectSourceRes :: (PersistQueryRead backend, PersistRecordBackend record backend, MonadIO m1, MonadIO m2) => [Filter record] -> [SelectOpt record] -> ReaderT backend m1 (Acquire (ConduitM () (Entity record) m2 ())) -- | Get just the first record for the criterion. selectFirst :: (PersistQueryRead backend, MonadIO m, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> ReaderT backend m (Maybe (Entity record)) -- | Get the Keys of all records matching the given criterion. selectKeysRes :: (PersistQueryRead backend, MonadIO m1, MonadIO m2, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> ReaderT backend m1 (Acquire (ConduitM () (Key record) m2 ())) -- | The total number of records fulfilling the given criterion. count :: (PersistQueryRead backend, MonadIO m, PersistRecordBackend record backend) => [Filter record] -> ReaderT backend m Int -- | Backends supporting conditional write operations class (PersistQueryRead backend, PersistStoreWrite backend) => PersistQueryWrite backend -- | Update individual fields on any record matching the given criterion. updateWhere :: (PersistQueryWrite backend, MonadIO m, PersistRecordBackend record backend) => [Filter record] -> [Update record] -> ReaderT backend m () -- | Delete all records matching the given criterion. deleteWhere :: (PersistQueryWrite backend, MonadIO m, PersistRecordBackend record backend) => [Filter record] -> ReaderT backend m () -- | Get all records matching the given criterion in the specified order. -- Returns also the identifiers. selectSource :: (PersistQueryRead backend, MonadResource m, PersistRecordBackend record backend, MonadReader backend m) => [Filter record] -> [SelectOpt record] -> ConduitM () (Entity record) m () -- | Get the Keys of all records matching the given criterion. selectKeys :: (PersistQueryRead backend, MonadResource m, PersistRecordBackend record backend, MonadReader backend m) => [Filter record] -> [SelectOpt record] -> ConduitM () (Key record) m () -- | Call selectSource but return the result as a list. selectList :: (MonadIO m, PersistQueryRead backend, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> ReaderT backend m [Entity record] -- | Call selectKeys but return the result as a list. selectKeysList :: (MonadIO m, PersistQueryRead backend, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> ReaderT backend m [Key record] -- | For 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. class (PersistStoreWrite backend, PersistEntity record, BaseBackend backend ~ PersistEntityBackend record) => DeleteCascade record backend -- | Perform cascade-deletion of single database entry. deleteCascade :: (DeleteCascade record backend, MonadIO m) => Key record -> ReaderT backend m () -- | Cascade-deletion of entries satisfying given filters. deleteCascadeWhere :: (MonadIO m, DeleteCascade record backend, PersistQueryWrite backend) => [Filter record] -> ReaderT backend m () -- | 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. class (PersistField (Key record), ToJSON (Key record), FromJSON (Key record), Show (Key record), Read (Key record), Eq (Key record), Ord (Key record)) => PersistEntity record where { -- | Persistent allows multiple different backends (databases). type family PersistEntityBackend record; -- | By default, a backend will automatically generate the key Instead you -- can specify a Primary key made up of unique values. data family Key record; -- | An EntityField is parameterised by the Haskell record it -- belongs to and the additional type of that field. data family EntityField record :: * -> *; -- | Unique keys besides the Key. data family Unique record; } -- | A lower-level key operation. keyToValues :: PersistEntity record => Key record -> [PersistValue] -- | A lower-level key operation. keyFromValues :: PersistEntity record => [PersistValue] -> Either Text (Key record) -- | A meta-operation to retrieve the Key EntityField. persistIdField :: PersistEntity record => EntityField record (Key record) -- | Retrieve the EntityDef meta-data for the record. entityDef :: (PersistEntity record, Monad m) => m record -> EntityDef -- | Return meta-data for a given EntityField. persistFieldDef :: PersistEntity record => EntityField record typ -> FieldDef -- | A meta-operation to get the database fields of a record. toPersistFields :: PersistEntity record => record -> [SomePersistField] -- | A lower-level operation to convert from database values to a Haskell -- record. fromPersistValues :: PersistEntity record => [PersistValue] -> Either Text record -- | A meta operation to retrieve all the Unique keys. persistUniqueKeys :: PersistEntity record => record -> [Unique record] -- | A lower level operation. persistUniqueToFieldNames :: PersistEntity record => Unique record -> [(HaskellName, DBName)] -- | A lower level operation. persistUniqueToValues :: PersistEntity record => Unique record -> [PersistValue] -- | Use a PersistField as a lens. fieldLens :: PersistEntity record => EntityField record field -> forall f. Functor f => (field -> f field) -> Entity record -> f (Entity record) -- | This class teaches Persistent how to take a custom type and marshal it -- to and from a PersistValue, allowing it to be stored in a -- database. -- --

Examples

-- --
Simple Newtype
-- -- You can use newtype to add more type safety/readability to a -- basis type like ByteString. In these cases, just derive -- PersistField and PersistFieldSql: -- --
--   {-# LANGUAGE GeneralizedNewtypeDeriving #-}
--   
--   newtype HashedPassword = HashedPassword ByteString
--     deriving (Eq, Show, PersistField, PersistFieldSql)
--   
-- --
Smart Constructor Newtype
-- -- 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 -> Either Text 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: -- -- class PersistField a toPersistValue :: PersistField a => a -> PersistValue fromPersistValue :: PersistField a => PersistValue -> Either Text a -- | 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. class PersistConfig c where { type family PersistConfigBackend c :: (* -> *) -> * -> *; type family PersistConfigPool c; } -- | Load the config settings from a Value, most likely taken from a -- YAML config file. loadConfig :: PersistConfig c => Value -> Parser c -- | Modify the config settings based on environment variables. applyEnv :: PersistConfig c => c -> IO c -- | Create a new connection pool based on the given config settings. createPoolConfig :: PersistConfig c => c -> IO (PersistConfigPool c) -- | Run a database action by taking a connection from the pool. runPool :: (PersistConfig c, MonadUnliftIO m) => c -> PersistConfigBackend c m a -> PersistConfigPool c -> m a -- | Get list of values corresponding to given entity. entityValues :: PersistEntity record => Entity record -> [PersistValue] -- | 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 HasPersistBackend backend where { type family BaseBackend backend; } persistBackend :: HasPersistBackend backend => backend -> BaseBackend backend -- | 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. class (HasPersistBackend backend) => IsPersistBackend backend liftPersist :: (MonadIO m, MonadReader backend m) => ReaderT backend IO b -> m b -- | 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. -- -- Generally speaking, where you might have: -- --
--   foo ::
--     ( PersistEntity record
--     , PeristEntityBackend record ~ BaseBackend backend
--     , IsSqlBackend backend
--     )
--   
-- -- this can be replaced with: -- --
--   foo ::
--     ( PersistEntity record,
--     , PersistEntityBackend record ~ backend
--     , BackendCompatible SqlBackend backend
--     )
--   
-- -- This works for SqlReadBackend because of the instance -- BackendCompatible SqlBackend -- SqlReadBackend, without needing to go through the -- BaseBackend type family. -- -- Likewise, functions that are currently hardcoded to use -- SqlBackend can be generalized: -- --
--   -- before:
--   asdf :: ReaderT SqlBackend m ()
--   asdf = pure ()
--   
--   -- after:
--   asdf' :: BackendCompatible SqlBackend backend => ReaderT backend m ()
--   asdf' = withReaderT projectBackend asdf
--   
class BackendCompatible sup sub projectBackend :: BackendCompatible sup sub => sub -> sup -- | Predefined toJSON. The resulting JSON looks like {"key": -- 1, "value": {"name": ...}}. -- -- The typical usage is: -- --
--   instance ToJSON (Entity User) where
--       toJSON = keyValueEntityToJSON
--   
keyValueEntityToJSON :: (PersistEntity record, ToJSON record) => Entity record -> Value -- | Predefined parseJSON. The input JSON looks like {"key": -- 1, "value": {"name": ...}}. -- -- The typical usage is: -- --
--   instance FromJSON (Entity User) where
--       parseJSON = keyValueEntityFromJSON
--   
keyValueEntityFromJSON :: (PersistEntity record, FromJSON record) => Value -> Parser (Entity record) -- | Predefined toJSON. The resulting JSON looks like {"id": -- 1, "name": ...}. -- -- The typical usage is: -- --
--   instance ToJSON (Entity User) where
--       toJSON = entityIdToJSON
--   
entityIdToJSON :: (PersistEntity record, ToJSON record) => Entity record -> Value -- | Predefined parseJSON. The input JSON looks like {"id": 1, -- "name": ...}. -- -- The typical usage is: -- --
--   instance FromJSON (Entity User) where
--       parseJSON = entityIdFromJSON
--   
entityIdFromJSON :: (PersistEntity record, FromJSON record) => Value -> Parser (Entity record) -- | Convenience function for getting a free PersistField instance -- from a type with JSON instances. -- -- Example usage in combination with fromPersistValueJSON: -- --
--   instance PersistField MyData where
--     fromPersistValue = fromPersistValueJSON
--     toPersistValue = toPersistValueJSON
--   
toPersistValueJSON :: ToJSON a => a -> PersistValue -- | 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. -- -- Example usage in combination with toPersistValueJSON: -- --
--   instance PersistField MyData where
--     fromPersistValue = fromPersistValueJSON
--     toPersistValue = toPersistValueJSON
--   
fromPersistValueJSON :: FromJSON a => PersistValue -> Either Text a module Database.Persist.Sql.Types.Internal -- | 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 HasPersistBackend backend where { type family BaseBackend backend; } persistBackend :: HasPersistBackend backend => backend -> BaseBackend backend -- | 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. class (HasPersistBackend backend) => IsPersistBackend backend -- | This 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 backend. Careless use allows us to -- accidentally run a write query against a read-only database. mkPersistBackend :: IsPersistBackend backend => BaseBackend backend -> backend -- | An SQL backend which can only handle read queries -- -- The constructor was exposed in 2.10.0. newtype SqlReadBackend SqlReadBackend :: SqlBackend -> SqlReadBackend [unSqlReadBackend] :: SqlReadBackend -> SqlBackend -- | An SQL backend which can handle read or write queries -- -- The constructor was exposed in 2.10.0 newtype SqlWriteBackend SqlWriteBackend :: SqlBackend -> SqlWriteBackend [unSqlWriteBackend] :: SqlWriteBackend -> SqlBackend -- | Useful for running a read query against a backend with unknown -- capabilities. readToUnknown :: Monad m => ReaderT SqlReadBackend m a -> ReaderT SqlBackend m a -- | Useful for running a read query against a backend with read and write -- capabilities. readToWrite :: Monad m => ReaderT SqlReadBackend m a -> ReaderT SqlWriteBackend m a -- | Useful for running a write query against an untagged backend with -- unknown capabilities. writeToUnknown :: Monad m => ReaderT SqlWriteBackend m a -> ReaderT SqlBackend m a type LogFunc = Loc -> LogSource -> LogLevel -> LogStr -> IO () data InsertSqlResult ISRSingle :: Text -> InsertSqlResult ISRInsertGet :: Text -> Text -> InsertSqlResult ISRManyKeys :: Text -> [PersistValue] -> InsertSqlResult data Statement Statement :: IO () -> IO () -> ([PersistValue] -> IO Int64) -> (forall m. MonadIO m => [PersistValue] -> Acquire (ConduitM () [PersistValue] m ())) -> Statement [stmtFinalize] :: Statement -> IO () [stmtReset] :: Statement -> IO () [stmtExecute] :: Statement -> [PersistValue] -> IO Int64 [stmtQuery] :: Statement -> forall m. MonadIO m => [PersistValue] -> Acquire (ConduitM () [PersistValue] m ()) -- | Please refer to the documentation for the database in question for a -- full overview of the semantics of the varying isloation levels data IsolationLevel ReadUncommitted :: IsolationLevel ReadCommitted :: IsolationLevel RepeatableRead :: IsolationLevel Serializable :: IsolationLevel makeIsolationLevelStatement :: (Monoid s, IsString s) => IsolationLevel -> s data SqlBackend SqlBackend :: (Text -> IO Statement) -> (EntityDef -> [PersistValue] -> InsertSqlResult) -> Maybe (EntityDef -> [[PersistValue]] -> InsertSqlResult) -> Maybe (EntityDef -> NonEmpty UniqueDef -> Text -> Text) -> Maybe (EntityDef -> Int -> Text) -> IORef (Map Text Statement) -> IO () -> ([EntityDef] -> (Text -> IO Statement) -> EntityDef -> IO (Either [Text] [(Bool, Text)])) -> ((Text -> IO Statement) -> Maybe IsolationLevel -> IO ()) -> ((Text -> IO Statement) -> IO ()) -> ((Text -> IO Statement) -> IO ()) -> (DBName -> Text) -> Text -> Text -> ((Int, Int) -> Bool -> Text -> Text) -> LogFunc -> Maybe Int -> Maybe (EntityDef -> Int -> Text) -> SqlBackend [connPrepare] :: SqlBackend -> Text -> IO Statement -- | table name, column names, id name, either 1 or 2 statements to run [connInsertSql] :: SqlBackend -> EntityDef -> [PersistValue] -> InsertSqlResult -- | SQL for inserting many rows and returning their primary keys, for -- backends that support this functioanlity. If Nothing, rows will -- be inserted one-at-a-time using connInsertSql. [connInsertManySql] :: SqlBackend -> Maybe (EntityDef -> [[PersistValue]] -> InsertSqlResult) -- | Some 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 Nothing, 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 db [connUpsertSql] :: SqlBackend -> Maybe (EntityDef -> NonEmpty UniqueDef -> Text -> Text) -- | Some 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 Nothing, we default to using -- defaultPutMany. [connPutManySql] :: SqlBackend -> Maybe (EntityDef -> Int -> Text) [connStmtMap] :: SqlBackend -> IORef (Map Text Statement) [connClose] :: SqlBackend -> IO () [connMigrateSql] :: SqlBackend -> [EntityDef] -> (Text -> IO Statement) -> EntityDef -> IO (Either [Text] [(Bool, Text)]) [connBegin] :: SqlBackend -> (Text -> IO Statement) -> Maybe IsolationLevel -> IO () [connCommit] :: SqlBackend -> (Text -> IO Statement) -> IO () [connRollback] :: SqlBackend -> (Text -> IO Statement) -> IO () [connEscapeName] :: SqlBackend -> DBName -> Text [connNoLimit] :: SqlBackend -> Text [connRDBMS] :: SqlBackend -> Text [connLimitOffset] :: SqlBackend -> (Int, Int) -> Bool -> Text -> Text [connLogFunc] :: SqlBackend -> LogFunc -- | Some databases (probably only Sqlite) have a limit on how many -- question-mark parameters may be used in a statement [connMaxParams] :: SqlBackend -> Maybe Int -- | Some 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 Nothing, we default to using -- defaultRepsertMany. [connRepsertManySql] :: SqlBackend -> Maybe (EntityDef -> Int -> Text) -- | A constraint synonym which witnesses that a backend is SQL and can run -- read queries. type SqlBackendCanRead backend = (BackendCompatible SqlBackend backend, PersistQueryRead backend, PersistStoreRead backend, PersistUniqueRead backend) -- | A constraint synonym which witnesses that a backend is SQL and can run -- read and write queries. type SqlBackendCanWrite backend = (SqlBackendCanRead backend, PersistQueryWrite backend, PersistStoreWrite backend, PersistUniqueWrite backend) -- | Like SqlPersistT but compatible with any SQL backend which -- can handle read queries. type SqlReadT m a = forall backend. (SqlBackendCanRead backend) => ReaderT backend m a -- | Like SqlPersistT but compatible with any SQL backend which -- can handle read and write queries. type SqlWriteT m a = forall backend. (SqlBackendCanWrite backend) => ReaderT backend m a -- | A backend which is a wrapper around SqlBackend. type IsSqlBackend backend = (IsPersistBackend backend, BaseBackend backend ~ SqlBackend) instance GHC.Enum.Bounded Database.Persist.Sql.Types.Internal.IsolationLevel instance GHC.Classes.Ord Database.Persist.Sql.Types.Internal.IsolationLevel instance GHC.Enum.Enum Database.Persist.Sql.Types.Internal.IsolationLevel instance GHC.Classes.Eq Database.Persist.Sql.Types.Internal.IsolationLevel instance GHC.Show.Show Database.Persist.Sql.Types.Internal.IsolationLevel instance Database.Persist.Class.PersistStore.HasPersistBackend Database.Persist.Sql.Types.Internal.SqlWriteBackend instance Database.Persist.Class.PersistStore.IsPersistBackend Database.Persist.Sql.Types.Internal.SqlWriteBackend instance Database.Persist.Class.PersistStore.HasPersistBackend Database.Persist.Sql.Types.Internal.SqlReadBackend instance Database.Persist.Class.PersistStore.IsPersistBackend Database.Persist.Sql.Types.Internal.SqlReadBackend instance Database.Persist.Class.PersistStore.HasPersistBackend Database.Persist.Sql.Types.Internal.SqlBackend instance Database.Persist.Class.PersistStore.IsPersistBackend Database.Persist.Sql.Types.Internal.SqlBackend module Database.Persist -- | Assign a field a value. -- --

Example usage

-- --
--   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: -- --
--   +-----+-----+--------+
--   |id   |name |age     |
--   +-----+-----+--------+
--   |1    |SPJ  |40 -> 45|
--   +-----+-----+--------+
--   |2    |Simon|41      |
--   +-----+-----+--------+
--   
(=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Update v infixr 3 =. -- | Assign a field by addition (+=). -- --

Example usage

-- --
--   addAge :: MonadIO m => ReaderT SqlBackend m ()
--   addAge = updateWhere [UserName ==. "SPJ" ] [UserAge +=. 1]
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+-----+---------+
--   |id   |name |age      |
--   +-----+-----+---------+
--   |1    |SPJ  |40 -> 41 |
--   +-----+-----+---------+
--   |2    |Simon|41       |
--   +-----+-----+---------+
--   
(+=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Update v infixr 3 +=. -- | Assign a field by subtraction (-=). -- --

Example usage

-- --
--   subtractAge :: MonadIO m => ReaderT SqlBackend m ()
--   subtractAge = updateWhere [UserName ==. "SPJ" ] [UserAge -=. 1]
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+-----+---------+
--   |id   |name |age      |
--   +-----+-----+---------+
--   |1    |SPJ  |40 -> 39 |
--   +-----+-----+---------+
--   |2    |Simon|41       |
--   +-----+-----+---------+
--   
(-=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Update v infixr 3 -=. -- | Assign a field by multiplication (*=). -- --

Example usage

-- --
--   multiplyAge :: MonadIO m => ReaderT SqlBackend m ()
--   multiplyAge = updateWhere [UserName ==. "SPJ" ] [UserAge *=. 2]
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+-----+--------+
--   |id   |name |age     |
--   +-----+-----+--------+
--   |1    |SPJ  |40 -> 80|
--   +-----+-----+--------+
--   |2    |Simon|41      |
--   +-----+-----+--------+
--   
(*=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Update v infixr 3 *=. -- | Assign a field by division (/=). -- --

Example usage

-- --
--   divideAge :: MonadIO m => ReaderT SqlBackend m ()
--   divideAge = updateWhere [UserName ==. "SPJ" ] [UserAge /=. 2]
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+-----+---------+
--   |id   |name |age      |
--   +-----+-----+---------+
--   |1    |SPJ  |40 -> 20 |
--   +-----+-----+---------+
--   |2    |Simon|41       |
--   +-----+-----+---------+
--   
(/=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Update v infixr 3 /=. -- | Check for equality. -- --

Example usage

-- --
--   selectSPJ :: MonadIO m => ReaderT SqlBackend m [Entity User]
--   selectSPJ = selectList [UserName ==. "SPJ" ] []
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+-----+-----+
--   |id   |name |age  |
--   +-----+-----+-----+
--   |1    |SPJ  |40   |
--   +-----+-----+-----+
--   
(==.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Filter v infix 4 ==. -- | Non-equality check. -- --

Example usage

-- --
--   selectSimon :: MonadIO m => ReaderT SqlBackend m [Entity User]
--   selectSimon = selectList [UserName !=. "SPJ" ] []
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+-----+-----+
--   |id   |name |age  |
--   +-----+-----+-----+
--   |2    |Simon|41   |
--   +-----+-----+-----+
--   
(!=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Filter v infix 4 !=. -- | Less-than check. -- --

Example usage

-- --
--   selectLessAge :: MonadIO m => ReaderT SqlBackend m [Entity User]
--   selectLessAge = selectList [UserAge <. 41 ] []
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+-----+-----+
--   |id   |name |age  |
--   +-----+-----+-----+
--   |1    |SPJ  |40   |
--   +-----+-----+-----+
--   
(<.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Filter v infix 4 <. -- | Greater-than check. -- --

Example usage

-- --
--   selectGreaterAge :: MonadIO m => ReaderT SqlBackend m [Entity User]
--   selectGreaterAge = selectList [UserAge >. 40 ] []
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+-----+-----+
--   |id   |name |age  |
--   +-----+-----+-----+
--   |2    |Simon|41   |
--   +-----+-----+-----+
--   
(>.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Filter v infix 4 >. -- | Less-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-1, will produce this: -- --
--   +-----+-----+-----+
--   |id   |name |age  |
--   +-----+-----+-----+
--   |1    |SPJ  |40   |
--   +-----+-----+-----+
--   
(<=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Filter v infix 4 <=. -- | Greater-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-1, will produce this: -- --
--   +-----+-----+-----+
--   |id   |name |age  |
--   +-----+-----+-----+
--   |2    |Simon|41   |
--   +-----+-----+-----+
--   
(>=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Filter v infix 4 >=. -- | Check if value is in given list. -- --

Example usage

-- --
--   selectUsers :: MonadIO m => ReaderT SqlBackend m [Entity User]
--   selectUsers = selectList [UserAge <-. [40, 41]] []
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+-----+-----+
--   |id   |name |age  |
--   +-----+-----+-----+
--   |1    |SPJ  |40   |
--   +-----+-----+-----+
--   |2    |Simon|41   |
--   +-----+-----+-----+
--   
-- --
--   selectSPJ :: MonadIO m => ReaderT SqlBackend m [Entity User]
--   selectSPJ = selectList [UserAge <-. [40]] []
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+-----+-----+
--   |id   |name |age  |
--   +-----+-----+-----+
--   |1    |SPJ  |40   |
--   +-----+-----+-----+
--   
(<-.) :: forall v typ. PersistField typ => EntityField v typ -> [typ] -> Filter v infix 4 <-. -- | Check if value is not in given list. -- --

Example usage

-- --
--   selectSimon :: MonadIO m => ReaderT SqlBackend m [Entity User]
--   selectSimon = selectList [UserAge /<-. [40]] []
--   
-- -- The above query when applied on dataset-1, will produce this: -- --
--   +-----+-----+-----+
--   |id   |name |age  |
--   +-----+-----+-----+
--   |2    |Simon|41   |
--   +-----+-----+-----+
--   
(/<-.) :: forall v typ. PersistField typ => EntityField v typ -> [typ] -> Filter v infix 4 /<-. -- | 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 -- or 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). (||.) :: forall v. [Filter v] -> [Filter v] -> [Filter v] infixl 3 ||. -- | Convert list of PersistValues into textual representation of -- JSON object. This is a type-constrained synonym for toJsonText. listToJSON :: [PersistValue] -> Text -- | Convert map (list of tuples) into textual representation of JSON -- object. This is a type-constrained synonym for toJsonText. mapToJSON :: [(Text, PersistValue)] -> Text -- | A more general way to convert instances of ToJSON type class to -- strict text Text. toJsonText :: ToJSON j => j -> Text -- | FIXME Add documentation to that. getPersistMap :: PersistValue -> Either Text [(Text, PersistValue)] -- | FIXME What's this exactly? limitOffsetOrder :: PersistEntity val => [SelectOpt val] -> (Int, Int, [SelectOpt val]) module Database.Persist.Sql.Util parseEntityValues :: PersistEntity record => EntityDef -> [PersistValue] -> Either Text (Entity record) entityColumnNames :: EntityDef -> SqlBackend -> [Sql] keyAndEntityColumnNames :: EntityDef -> SqlBackend -> [Sql] entityColumnCount :: EntityDef -> Int isIdField :: PersistEntity record => EntityField record typ -> Bool hasCompositeKey :: EntityDef -> Bool dbIdColumns :: SqlBackend -> EntityDef -> [Text] dbIdColumnsEsc :: (DBName -> Text) -> EntityDef -> [Text] dbColumns :: SqlBackend -> EntityDef -> [Text] -- | Gets the FieldDef for an Update. updateFieldDef :: PersistEntity v => Update v -> FieldDef updatePersistValue :: Update v -> PersistValue mkUpdateText :: PersistEntity record => SqlBackend -> Update record -> Text mkUpdateText' :: PersistEntity record => (DBName -> Text) -> (Text -> Text) -> Update record -> Text commaSeparated :: [Text] -> Text parenWrapped :: Text -> Text module Database.Persist.Sql -- | A single column (see rawSql). Any PersistField may -- be used here, including PersistValue (which does not do any -- processing). newtype Single a Single :: a -> Single a [unSingle] :: Single a -> a type ConnectionPool = Pool SqlBackend -- | A Migration is a four level monad stack consisting of: -- -- type Migration = WriterT [Text] (WriterT CautiousMigration (ReaderT SqlBackend IO)) () type CautiousMigration = [(Bool, Sql)] type Sql = Text type SqlPersistM = SqlPersistT (NoLoggingT (ResourceT IO)) type SqlPersistT = ReaderT SqlBackend data PersistentSqlException StatementAlreadyFinalized :: Text -> PersistentSqlException Couldn'tGetSQLConnection :: PersistentSqlException data Column Column :: !DBName -> !Bool -> !SqlType -> !Maybe Text -> !Maybe DBName -> !Maybe Integer -> !Maybe (DBName, DBName) -> Column [cName] :: Column -> !DBName [cNull] :: Column -> !Bool [cSqlType] :: Column -> !SqlType [cDefault] :: Column -> !Maybe Text [cDefaultConstraintName] :: Column -> !Maybe DBName [cMaxLen] :: Column -> !Maybe Integer [cReference] :: Column -> !Maybe (DBName, DBName) data SqlBackend SqlBackend :: (Text -> IO Statement) -> (EntityDef -> [PersistValue] -> InsertSqlResult) -> Maybe (EntityDef -> [[PersistValue]] -> InsertSqlResult) -> Maybe (EntityDef -> NonEmpty UniqueDef -> Text -> Text) -> Maybe (EntityDef -> Int -> Text) -> IORef (Map Text Statement) -> IO () -> ([EntityDef] -> (Text -> IO Statement) -> EntityDef -> IO (Either [Text] [(Bool, Text)])) -> ((Text -> IO Statement) -> Maybe IsolationLevel -> IO ()) -> ((Text -> IO Statement) -> IO ()) -> ((Text -> IO Statement) -> IO ()) -> (DBName -> Text) -> Text -> Text -> ((Int, Int) -> Bool -> Text -> Text) -> LogFunc -> Maybe Int -> Maybe (EntityDef -> Int -> Text) -> SqlBackend [connPrepare] :: SqlBackend -> Text -> IO Statement -- | table name, column names, id name, either 1 or 2 statements to run [connInsertSql] :: SqlBackend -> EntityDef -> [PersistValue] -> InsertSqlResult -- | SQL for inserting many rows and returning their primary keys, for -- backends that support this functioanlity. If Nothing, rows will -- be inserted one-at-a-time using connInsertSql. [connInsertManySql] :: SqlBackend -> Maybe (EntityDef -> [[PersistValue]] -> InsertSqlResult) -- | Some 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 Nothing, 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 db [connUpsertSql] :: SqlBackend -> Maybe (EntityDef -> NonEmpty UniqueDef -> Text -> Text) -- | Some 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 Nothing, we default to using -- defaultPutMany. [connPutManySql] :: SqlBackend -> Maybe (EntityDef -> Int -> Text) [connStmtMap] :: SqlBackend -> IORef (Map Text Statement) [connClose] :: SqlBackend -> IO () [connMigrateSql] :: SqlBackend -> [EntityDef] -> (Text -> IO Statement) -> EntityDef -> IO (Either [Text] [(Bool, Text)]) [connBegin] :: SqlBackend -> (Text -> IO Statement) -> Maybe IsolationLevel -> IO () [connCommit] :: SqlBackend -> (Text -> IO Statement) -> IO () [connRollback] :: SqlBackend -> (Text -> IO Statement) -> IO () [connEscapeName] :: SqlBackend -> DBName -> Text [connNoLimit] :: SqlBackend -> Text [connRDBMS] :: SqlBackend -> Text [connLimitOffset] :: SqlBackend -> (Int, Int) -> Bool -> Text -> Text [connLogFunc] :: SqlBackend -> LogFunc -- | Some databases (probably only Sqlite) have a limit on how many -- question-mark parameters may be used in a statement [connMaxParams] :: SqlBackend -> Maybe Int -- | Some 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 Nothing, we default to using -- defaultRepsertMany. [connRepsertManySql] :: SqlBackend -> Maybe (EntityDef -> Int -> Text) -- | An SQL backend which can only handle read queries -- -- The constructor was exposed in 2.10.0. newtype SqlReadBackend SqlReadBackend :: SqlBackend -> SqlReadBackend [unSqlReadBackend] :: SqlReadBackend -> SqlBackend -- | An SQL backend which can handle read or write queries -- -- The constructor was exposed in 2.10.0 newtype SqlWriteBackend SqlWriteBackend :: SqlBackend -> SqlWriteBackend [unSqlWriteBackend] :: SqlWriteBackend -> SqlBackend data Statement Statement :: IO () -> IO () -> ([PersistValue] -> IO Int64) -> (forall m. MonadIO m => [PersistValue] -> Acquire (ConduitM () [PersistValue] m ())) -> Statement [stmtFinalize] :: Statement -> IO () [stmtReset] :: Statement -> IO () [stmtExecute] :: Statement -> [PersistValue] -> IO Int64 [stmtQuery] :: Statement -> forall m. MonadIO m => [PersistValue] -> Acquire (ConduitM () [PersistValue] m ()) type LogFunc = Loc -> LogSource -> LogLevel -> LogStr -> IO () data InsertSqlResult ISRSingle :: Text -> InsertSqlResult ISRInsertGet :: Text -> Text -> InsertSqlResult ISRManyKeys :: Text -> [PersistValue] -> InsertSqlResult -- | Useful for running a read query against a backend with unknown -- capabilities. readToUnknown :: Monad m => ReaderT SqlReadBackend m a -> ReaderT SqlBackend m a -- | Useful for running a read query against a backend with read and write -- capabilities. readToWrite :: Monad m => ReaderT SqlReadBackend m a -> ReaderT SqlWriteBackend m a -- | Useful for running a write query against an untagged backend with -- unknown capabilities. writeToUnknown :: Monad m => ReaderT SqlWriteBackend m a -> ReaderT SqlBackend m a -- | A constraint synonym which witnesses that a backend is SQL and can run -- read queries. type SqlBackendCanRead backend = (BackendCompatible SqlBackend backend, PersistQueryRead backend, PersistStoreRead backend, PersistUniqueRead backend) -- | A constraint synonym which witnesses that a backend is SQL and can run -- read and write queries. type SqlBackendCanWrite backend = (SqlBackendCanRead backend, PersistQueryWrite backend, PersistStoreWrite backend, PersistUniqueWrite backend) -- | Like SqlPersistT but compatible with any SQL backend which -- can handle read queries. type SqlReadT m a = forall backend. (SqlBackendCanRead backend) => ReaderT backend m a -- | Like SqlPersistT but compatible with any SQL backend which -- can handle read and write queries. type SqlWriteT m a = forall backend. (SqlBackendCanWrite backend) => ReaderT backend m a -- | A backend which is a wrapper around SqlBackend. type IsSqlBackend backend = (IsPersistBackend backend, BaseBackend backend ~ SqlBackend) -- | Class for data types that may be retrived from a rawSql -- query. class RawSql a -- | Number of columns that this data type needs and the list of -- substitutions for SELECT placeholders ??. rawSqlCols :: RawSql a => (DBName -> Text) -> a -> (Int, [Text]) -- | A string telling the user why the column count is what it is. rawSqlColCountReason :: RawSql a => a -> String -- | Transform a row of the result into the data type. rawSqlProcessRow :: RawSql a => [PersistValue] -> Either Text a -- | Tells Persistent what database column type should be used to store a -- Haskell type. -- --

Examples

-- --
Simple Boolean Alternative
-- --
--   data Switch = On | Off
--     deriving (Show, Eq)
--   
--   instance PersistField Switch where
--     toPersistValue s = case s of
--       On -> PersistBool True
--       Off -> PersistBool False
--     fromPersistValue (PersistBool b) = if b then Right On else Right Off
--     fromPersistValue x = Left $ "File.hs: When trying to deserialize a Switch: expected PersistBool, received: " <> T.pack (show x)
--   
--   instance PersistFieldSql Switch where
--     sqlType _ = SqlBool
--   
-- --
Non-Standard Database Types
-- -- If your database supports non-standard types, such as Postgres' -- uuid, you can use SqlOther to use them: -- --
--   import qualified Data.UUID as UUID
--   instance PersistField UUID where
--     toPersistValue = PersistDbSpecific . toASCIIBytes
--     fromPersistValue (PersistDbSpecific uuid) =
--       case fromASCIIBytes uuid of
--         Nothing -> Left $ "Model/CustomTypes.hs: Failed to deserialize a UUID; received: " <> T.pack (show uuid)
--         Just uuid' -> Right uuid'
--     fromPersistValue x = Left $ "File.hs: When trying to deserialize a UUID: expected PersistDbSpecific, received: "-- >  <> T.pack (show x)
--   
--   instance PersistFieldSql UUID where
--     sqlType _ = SqlOther "uuid"
--   
-- --
User Created Database Types
-- -- Similarly, some databases support creating custom types, e.g. -- Postgres' DOMAIN and ENUM features. You can use -- SqlOther to specify a custom type: -- --
--   CREATE DOMAIN ssn AS text
--         CHECK ( value ~ '^[0-9]{9}$');
--   
-- --
--   instance PersistFieldSQL SSN where
--     sqlType _ = SqlOther "ssn"
--   
-- --
--   CREATE TYPE rainbow_color AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet');
--   
-- --
--   instance PersistFieldSQL RainbowColor where
--     sqlType _ = SqlOther "rainbow_color"
--   
class PersistField a => PersistFieldSql a sqlType :: PersistFieldSql a => Proxy a -> SqlType -- | This newtype wrapper is useful when selecting an entity out of the -- database and you want to provide a prefix to the table being selected. -- -- Consider this raw SQL query: -- --
--   SELECT ??
--   FROM my_long_table_name AS mltn
--   INNER JOIN other_table AS ot
--      ON mltn.some_col = ot.other_col
--   WHERE ...
--   
-- -- We don't want to refer to my_long_table_name every time, so -- we create an alias. If we want to select it, we have to tell the raw -- SQL quasi-quoter that we expect the entity to be prefixed with some -- other name. -- -- We can give the above query a type with this, like: -- --
--   getStuff :: SqlPersistM [EntityWithPrefix "mltn" MyLongTableName]
--   getStuff = rawSql queryText []
--   
-- -- The EntityWithPrefix bit is a boilerplate newtype wrapper, so -- you can remove it with unPrefix, like this: -- --
--   getStuff :: SqlPersistM [Entity MyLongTableName]
--   getStuff = unPrefix @"mltn" <$> rawSql queryText []
--   
-- -- The symbol is a "type application" and requires the -- TypeApplications@ language extension. newtype EntityWithPrefix (prefix :: Symbol) record EntityWithPrefix :: Entity record -> EntityWithPrefix (prefix :: Symbol) record [unEntityWithPrefix] :: EntityWithPrefix (prefix :: Symbol) record -> Entity record -- | A helper function to tell GHC what the EntityWithPrefix prefix -- should be. This allows you to use a type application to specify the -- prefix, instead of specifying the etype on the result. -- -- As an example, here's code that uses this: -- --
--   myQuery :: SqlPersistM [Entity Person]
--   myQuery = map (unPrefix @"p") $ rawSql query []
--     where
--       query = "SELECT ?? FROM person AS p"
--   
unPrefix :: forall prefix record. EntityWithPrefix prefix record -> Entity record -- | The returned Acquire gets a connection from the pool, but does -- NOT start a new transaction. Used to implement -- acquireSqlConnFromPool and -- acquireSqlConnFromPoolWithIsolation, this is useful for -- performing actions on a connection that cannot be done within a -- transaction, such as VACUUM in Sqlite. -- | Deprecated: The Pool ~> Acquire functions are unpredictable and -- may result in resource leaks with asynchronous exceptions. They will -- be removed in 2.12. If you need them, please file an issue and we'll -- try to help get you sorted. See issue #1199 on GitHub for the -- debugging log. unsafeAcquireSqlConnFromPool :: forall backend m. (MonadReader (Pool backend) m, BackendCompatible SqlBackend backend) => m (Acquire backend) -- | The returned Acquire gets a connection from the pool, starts a -- new transaction and gives access to the prepared connection. -- -- When the acquired connection is released the transaction is committed -- and the connection returned to the pool. -- -- Upon an exception the transaction is rolled back and the connection -- destroyed. -- -- This is equivalent to runSqlPool but does not incur the -- MonadUnliftIO constraint, meaning it can be used within, for -- example, a Conduit pipeline. -- | Deprecated: The Pool ~> Acquire functions are unpredictable and -- may result in resource leaks with asynchronous exceptions. They will -- be removed in 2.12. If you need them, please file an issue and we'll -- try to help get you sorted. See issue #1199 on GitHub for the -- debugging log. acquireSqlConnFromPool :: (MonadReader (Pool backend) m, BackendCompatible SqlBackend backend) => m (Acquire backend) -- | Like acquireSqlConnFromPool, but lets you specify an explicit -- isolation level. -- | Deprecated: The Pool ~> Acquire functions are unpredictable and -- may result in resource leaks with asynchronous exceptions. They will -- be removed in 2.12. If you need them, please file an issue and we'll -- try to help get you sorted. See issue #1199 on GitHub for the -- debugging log. acquireSqlConnFromPoolWithIsolation :: (MonadReader (Pool backend) m, BackendCompatible SqlBackend backend) => IsolationLevel -> m (Acquire backend) -- | Get 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. runSqlPool :: (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> m a -- | Like runSqlPool, but supports specifying an isolation level. runSqlPoolWithIsolation :: (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> IsolationLevel -> m a -- | Starts a new transaction on the connection. When the acquired -- connection is released the transaction is committed and the connection -- returned to the pool. -- -- Upon an exception the transaction is rolled back and the connection -- destroyed. -- -- This is equivalent to 'runSqlConn but does not incur the -- MonadUnliftIO constraint, meaning it can be used within, for -- example, a Conduit pipeline. acquireSqlConn :: (MonadReader backend m, BackendCompatible SqlBackend backend) => m (Acquire backend) -- | Like acquireSqlConn, but lets you specify an explicit isolation -- level. acquireSqlConnWithIsolation :: (MonadReader backend m, BackendCompatible SqlBackend backend) => IsolationLevel -> m (Acquire backend) runSqlConn :: (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> backend -> m a -- | Like runSqlConn, but supports specifying an isolation level. runSqlConnWithIsolation :: (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> backend -> IsolationLevel -> m a runSqlPersistM :: BackendCompatible SqlBackend backend => ReaderT backend (NoLoggingT (ResourceT IO)) a -> backend -> IO a runSqlPersistMPool :: BackendCompatible SqlBackend backend => ReaderT backend (NoLoggingT (ResourceT IO)) a -> Pool backend -> IO a liftSqlPersistMPool :: (MonadIO m, BackendCompatible SqlBackend backend) => ReaderT backend (NoLoggingT (ResourceT IO)) a -> Pool backend -> m a withSqlPool :: (MonadLogger m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> (Pool backend -> m a) -> m a createSqlPool :: forall m backend. (MonadLogger m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> m (Pool backend) askLogFunc :: forall m. (MonadUnliftIO m, MonadLogger m) => m LogFunc -- | Create a connection and run sql queries within it. This function -- automatically closes the connection on it's completion. -- --

Example usage

-- --
--   {-# 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}}]
--   
withSqlConn :: (MonadUnliftIO m, MonadLogger m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> (backend -> m a) -> m a close' :: BackendCompatible SqlBackend backend => backend -> IO () -- | Given a Migration, this parses it and returns either a list of -- errors associated with the migration or a list of migrations to do. parseMigration :: MonadIO m => Migration -> ReaderT SqlBackend m (Either [Text] CautiousMigration) -- | Like parseMigration, but instead of returning the value in an -- Either value, it calls error on the error values. parseMigration' :: MonadIO m => Migration -> ReaderT SqlBackend m CautiousMigration -- | Prints a migration. printMigration :: MonadIO m => Migration -> ReaderT SqlBackend m () -- | Convert a Migration to a list of Text values -- corresponding to their Sql statements. showMigration :: MonadIO m => Migration -> ReaderT SqlBackend m [Text] -- | Return all of the Sql values associated with the given -- migration. Calls error if there's a parse error on any -- migration. getMigration :: MonadIO m => Migration -> ReaderT SqlBackend m [Sql] -- | Runs a migration. If the migration fails to parse or if any of the -- migrations are unsafe, then this calls error to halt the -- program. runMigration :: MonadIO m => Migration -> ReaderT SqlBackend m () -- | Same as runMigration, 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 runMigrationSilent, -- but may be less silent for some persistent implementations, most -- notably persistent-postgresql runMigrationQuiet :: MonadIO m => Migration -> ReaderT SqlBackend m [Text] -- | Same as runMigration, but returns a list of the SQL commands -- executed instead of printing them to stderr. -- -- This function silences the migration by remapping stderr. 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! runMigrationSilent :: MonadUnliftIO m => Migration -> ReaderT SqlBackend m [Text] -- | Like runMigration, but this will perform the unsafe database -- migrations instead of erroring out. runMigrationUnsafe :: MonadIO m => Migration -> ReaderT SqlBackend m () -- | Same as runMigrationUnsafe, but returns a list of the SQL -- commands executed instead of printing them to stderr. runMigrationUnsafeQuiet :: MonadIO m => Migration -> ReaderT SqlBackend m [Text] -- | Given a list of old entity definitions and a new EntityDef in -- val, this creates a Migration to update the old list -- of definitions with the new one. migrate :: [EntityDef] -> EntityDef -> Migration -- | Report multiple errors in a Migration. reportErrors :: [Text] -> Migration -- | Report a single error in a Migration. reportError :: Text -> Migration -- | Add a CautiousMigration (aka a [(Bool, -- Text)]) to the migration plan. addMigrations :: CautiousMigration -> Migration -- | Add a migration to the migration plan. addMigration :: Bool -> Sql -> Migration withRawQuery :: MonadIO m => Text -> [PersistValue] -> ConduitM [PersistValue] Void IO a -> ReaderT SqlBackend m a data family BackendKey backend toSqlKey :: ToBackendKey SqlBackend record => Int64 -> Key record fromSqlKey :: ToBackendKey SqlBackend record => Key record -> Int64 -- | 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 getFieldName :: forall record typ m backend. (PersistEntity record, PersistEntityBackend record ~ SqlBackend, BackendCompatible SqlBackend backend, Monad m) => EntityField record typ -> ReaderT backend m Text -- | 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 getTableName :: forall record m backend. (PersistEntity record, BackendCompatible SqlBackend backend, Monad m) => record -> ReaderT backend m Text -- | useful for a backend to implement tableName by adding escaping tableDBName :: PersistEntity record => record -> DBName -- | useful for a backend to implement fieldName by adding escaping fieldDBName :: forall record typ. PersistEntity record => EntityField record typ -> DBName rawQuery :: (MonadResource m, MonadReader env m, BackendCompatible SqlBackend env) => Text -> [PersistValue] -> ConduitM () [PersistValue] m () rawQueryRes :: (MonadIO m1, MonadIO m2, BackendCompatible SqlBackend env) => Text -> [PersistValue] -> ReaderT env m1 (Acquire (ConduitM () [PersistValue] m2 ())) -- | Execute a raw SQL statement rawExecute :: (MonadIO m, BackendCompatible SqlBackend backend) => Text -> [PersistValue] -> ReaderT backend m () -- | Execute a raw SQL statement and return the number of rows it has -- modified. rawExecuteCount :: (MonadIO m, BackendCompatible SqlBackend backend) => Text -> [PersistValue] -> ReaderT backend m Int64 -- | Execute a raw SQL statement and return its results as a list. If you -- do not expect a return value, use of rawExecute is recommended. -- -- If you're using Entitys (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 -- Entitys documentation for more details. -- -- You 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 toPersistValue to help you constructing the placeholder -- values. -- -- Since you're giving a raw SQL statement, you don't get any guarantees -- regarding safety. If rawSql 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 Single. -- -- Some example of rawSql 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" []
--   
-- -- Minimal 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)
--   
rawSql :: (RawSql a, MonadIO m, BackendCompatible SqlBackend backend) => Text -> [PersistValue] -> ReaderT backend m [a] -- | Same as deleteWhere, but returns the number of rows affected. deleteWhereCount :: (PersistEntity val, MonadIO m, PersistEntityBackend val ~ SqlBackend, BackendCompatible SqlBackend backend) => [Filter val] -> ReaderT backend m Int64 -- | Same as updateWhere, but returns the number of rows affected. updateWhereCount :: (PersistEntity val, MonadIO m, SqlBackend ~ PersistEntityBackend val, BackendCompatible SqlBackend backend) => [Filter val] -> [Update val] -> ReaderT backend m Int64 -- | Commit the current transaction and begin a new one. This is used when -- a transaction commit is required within the context of -- runSqlConn (which brackets its provided action with a -- transaction begin/commit pair). transactionSave :: MonadIO m => ReaderT SqlBackend m () -- | Commit the current transaction and begin a new one with the specified -- isolation level. transactionSaveWithIsolation :: MonadIO m => IsolationLevel -> ReaderT SqlBackend m () -- | Roll back the current transaction and begin a new one. This rolls back -- to the state of the last call to transactionSave or the -- enclosing runSqlConn call. transactionUndo :: MonadIO m => ReaderT SqlBackend m () -- | Roll back the current transaction and begin a new one with the -- specified isolation level. transactionUndoWithIsolation :: MonadIO m => IsolationLevel -> ReaderT SqlBackend m () -- | Please refer to the documentation for the database in question for a -- full overview of the semantics of the varying isloation levels data IsolationLevel ReadUncommitted :: IsolationLevel ReadCommitted :: IsolationLevel RepeatableRead :: IsolationLevel Serializable :: IsolationLevel getStmtConn :: SqlBackend -> Text -> IO Statement -- | Create the list of columns for the given entity. mkColumns :: [EntityDef] -> EntityDef -> ([Column], [UniqueDef], [ForeignDef]) defaultAttribute :: [Attr] -> Maybe Text -- | Generates sql for limit and offset for postgres, sqlite and mysql. decorateSQLWithLimitOffset :: Text -> (Int, Int) -> Bool -> Text -> Text