-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Persistent based event sourcing. -- -- Event source library for persistent databases. @package persistent-eventsource @version 0.2.0 -- | Classy shim around Database.Esqueleto.Legacy -- -- In the style of Database.Persist.Monad, this exposes a -- "classy" (typeclass-using) API for Esqueleto functions, allowing them -- to be used with MonadSqlQuery constraints rather than a -- ReaderT SqlBackend concrete type. -- -- The goal of this module is to be a drop-in replacement for -- Database.Esqueleto.Legacy. module Database.Esqueleto.Monad.Legacy -- | Classy version of select select :: (MonadSqlQuery m, SqlSelect a r) => SqlQuery a -> m [r] -- | Classy version of selectOne selectOne :: (MonadSqlQuery m, SqlSelect a r) => SqlQuery a -> m (Maybe r) -- | Classy version of delete delete :: MonadSqlQuery m => SqlQuery () -> m () -- | Classy version of update update :: (MonadSqlQuery m, PersistEntity val, BackendCompatible SqlBackend (PersistEntityBackend val)) => (SqlExpr (Entity val) -> SqlQuery ()) -> m () renderQuerySelect :: (MonadSqlQuery m, SqlSelect a r) => SqlQuery a -> m (Text, [PersistValue]) -- | The lifted version of deleteWhere deleteWhere :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [Filter record] -> m () -- | The lifted version of get get :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => Key record -> m (Maybe record) -- | The lifted version of getBy getBy :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => Unique record -> m (Maybe (Entity record)) -- | The lifted version of getEntity getEntity :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => Key record -> m (Maybe (Entity record)) -- | The lifted version of getMany getMany :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [Key record] -> m (Map (Key record) record) -- | The lifted version of insert insert :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => record -> m (Key record) -- | The lifted version of insert_ insert_ :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => record -> m () -- | The lifted version of insertKey insertKey :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => Key record -> record -> m () -- | The lifted version of insertMany_ insertMany_ :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [record] -> m () -- | The lifted version of insertEntityMany insertEntityMany :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [Entity record] -> m () -- | The lifted version of selectFirst selectFirst :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [Filter record] -> [SelectOpt record] -> m (Maybe (Entity record)) -- | The lifted version of updateWhere updateWhere :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [Filter record] -> [Update record] -> m () -- | Avoid N+1 queries and join entities into a map structure. -- -- This function is useful to call on the result of a single -- JOIN. For example, suppose you have this query: -- --
--   getFoosAndNestedBarsFromParent
--       :: ParentId
--       -> SqlPersistT IO [(Entity Foo, Maybe (Entity Bar))]
--   getFoosAndNestedBarsFromParent parentId =
--       select $ do
--           (foo :& bar) <- from $
--               table Foo
--               `LeftOuterJoin`
--               table Bar
--                   `on` do
--                       \(foo :& bar) ->
--                           foo ^. FooId ==. bar ?. BarFooId
--           where_ $
--               foo ^. FooParentId ==. val parentId
--           pure (foo, bar)
--   
-- -- This is a natural result type for SQL - a list of tuples. However, -- it's not what we usually want in Haskell - each Foo in the -- list will be represented multiple times, once for each Bar. -- -- We can write fmap associateJoin and it will -- translate it into a Map that is keyed on the Key of -- the left Entity, and the value is a tuple of the entity's value -- as well as the list of each coresponding entity. -- --
--   getFoosAndNestedBarsFromParentHaskellese
--       :: ParentId
--       -> SqlPersistT (Map (Key Foo) (Foo, [Maybe (Entity Bar)]))
--   getFoosAndNestedBarsFromParentHaskellese parentId =
--       fmap associateJoin $ getFoosdAndNestedBarsFromParent parentId
--   
-- -- What if you have multiple joins? -- -- Let's use associateJoin with a *two* join query. -- --
--   userPostComments
--       :: SqlQuery (SqlExpr (Entity User, Entity Post, Entity Comment))
--   userPostsComment = do
--       (u :& p :& c) <- from $
--           table User
--           `InnerJoin`
--           table Post
--               on do
--                   \(u :& p) ->
--                       u ^. UserId ==. p ^. PostUserId
--           `InnerJoin`
--           table @Comment
--               `on` do
--                   \(_ :& p :& c) ->
--                       p ^. PostId ==. c ^. CommentPostId
--       pure (u, p, c)
--   
-- -- This query returns a User, with all of the users Posts, and then all -- of the Comments on that post. -- -- First, we *nest* the tuple. -- --
--   nest :: (a, b, c) -> (a, (b, c))
--   nest (a, b, c) = (a, (b, c))
--   
-- -- This makes the return of the query conform to the input expected from -- associateJoin. -- --
--   nestedUserPostComments
--       :: SqlPersistT IO [(Entity User, (Entity Post, Entity Comment))]
--   nestedUserPostComments =
--       fmap nest $ select userPostsComments
--   
-- -- Now, we can call associateJoin on it. -- --
--   associateUsers
--       :: [(Entity User, (Entity Post, Entity Comment))]
--       -> Map UserId (User, [(Entity Post, Entity Comment)])
--   associateUsers =
--       associateJoin
--   
-- -- Next, we'll use the Functor instances for Map and -- tuple to call associateJoin on the [(Entity Post, Entity -- Comment)]. -- --
--   associatePostsAndComments
--       :: Map UserId (User, [(Entity Post, Entity Comment)])
--       -> Map UserId (User, Map PostId (Post, [Entity Comment]))
--   associatePostsAndComments =
--       fmap (fmap associateJoin)
--   
-- -- For more reading on this topic, see this Foxhound Systems blog -- post. associateJoin :: forall e1 e0. Ord (Key e0) => [(Entity e0, e1)] -> Map (Key e0) (e0, [e1]) -- | Synonym for delete that does not clash with -- esqueleto's delete. deleteKey :: forall backend val (m :: Type -> Type). (PersistStore backend, BaseBackend backend ~ PersistEntityBackend val, MonadIO m, PersistEntity val) => Key val -> ReaderT backend m () -- | valJ is like val but for something that is already a -- Value. The use case it was written for was, given a -- Value lift the Key for that Value into the -- query expression in a type safe way. However, the implementation is -- more generic than that so we call it valJ. -- -- Its important to note that the input entity and the output entity are -- constrained to be the same by the type signature on the function -- (https://github.com/prowdsponsor/esqueleto/pull/69). valJ :: PersistField (Key entity) => Value (Key entity) -> SqlExpr (Value (Key entity)) -- | valkey i = val . toSqlKey -- (https://github.com/prowdsponsor/esqueleto/issues/9). valkey :: (ToBackendKey SqlBackend entity, PersistField (Key entity)) => Int64 -> SqlExpr (Value (Key entity)) -- | Insert a PersistField for every selected value, return the -- count afterward insertSelectCount :: forall (m :: Type -> Type) a backend. (MonadIO m, PersistEntity a, SqlBackendCanWrite backend) => SqlQuery (SqlExpr (Insertion a)) -> ReaderT backend m Int64 -- | Insert a PersistField for every selected value. insertSelect :: forall (m :: Type -> Type) a backend. (MonadIO m, PersistEntity a, SqlBackendCanWrite backend) => SqlQuery (SqlExpr (Insertion a)) -> ReaderT backend m () -- | Renders a SqlQuery into a Text value along with the -- list of PersistValues that would be supplied to the database -- for ? placeholders. renderQueryInsertInto :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m) => SqlQuery a -> ReaderT backend m (Text, [PersistValue]) -- | Renders a SqlQuery into a Text value along with the -- list of PersistValues that would be supplied to the database -- for ? placeholders. renderQueryUpdate :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m) => SqlQuery a -> ReaderT backend m (Text, [PersistValue]) -- | Renders a SqlQuery into a Text value along with the -- list of PersistValues that would be supplied to the database -- for ? placeholders. renderQueryDelete :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m) => SqlQuery a -> ReaderT backend m (Text, [PersistValue]) -- | Renders a SqlQuery into a Text value along with the -- list of PersistValues that would be supplied to the database -- for ? placeholders. -- -- You must ensure that the Mode you pass to this function -- corresponds with the actual SqlQuery. If you pass a query that -- uses incompatible features (like an INSERT statement with a -- SELECT mode) then you'll get a weird result. renderQueryToText :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m) => Mode -> SqlQuery a -> ReaderT backend m (Text, [PersistValue]) -- | Same as update, but returns the number of rows affected. updateCount :: forall (m :: Type -> Type) val backend. (MonadIO m, PersistEntity val, BackendCompatible SqlBackend (PersistEntityBackend val), SqlBackendCanWrite backend) => (SqlExpr (Entity val) -> SqlQuery ()) -> ReaderT backend m Int64 -- | Same as delete, but returns the number of rows affected. deleteCount :: forall (m :: Type -> Type) backend. (MonadIO m, SqlBackendCanWrite backend) => SqlQuery () -> ReaderT backend m Int64 -- | Execute an esqueleto SELECT query inside -- persistent's SqlPersistT monad and return a -- Source of rows. selectSource :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, IsPersistBackend backend, PersistQueryRead backend, PersistStoreRead backend, PersistUniqueRead backend, MonadResource m) => SqlQuery a -> ConduitT () r (ReaderT backend m) () -- | FROM clause: bring entities into scope. -- -- Note that this function will be replaced by the one in -- Database.Esqueleto.Experimental in version 4.0.0.0 of the -- library. The Experimental module has a dramatically improved -- means for introducing tables and entities that provides more power and -- less potential for runtime errors. -- -- This function internally uses two type classes in order to provide -- some flexibility of how you may call it. Internally we refer to these -- type classes as the two different magics. -- -- The innermost magic allows you to use from with the following -- types: -- -- -- -- The outermost magic allows you to use from on any tuples of -- types supported by innermost magic (and also tuples of tuples, and so -- on), up to 8-tuples. -- -- Note that using from for the same entity twice does work and -- corresponds to a self-join. You don't even need to use two different -- calls to from, you may use a JOIN or a tuple. -- -- The following are valid examples of uses of from (the types -- of the arguments of the lambda are inside square brackets): -- --
--   from $ \person -> ...
--   from $ \(person, blogPost) -> ...
--   from $ \(p `LeftOuterJoin` mb) -> ...
--   from $ \(p1 `InnerJoin` f `InnerJoin` p2) -> ...
--   from $ \((p1 `InnerJoin` f) `InnerJoin` p2) -> ...
--   
-- -- The types of the arguments to the lambdas above are, respectively: -- --
--   person
--     :: ( Esqueleto query expr backend
--        , PersistEntity Person
--        , PersistEntityBackend Person ~ backend
--        ) => expr (Entity Person)
--   (person, blogPost)
--     :: (...) => (expr (Entity Person), expr (Entity BlogPost))
--   (p `LeftOuterJoin` mb)
--     :: (...) => InnerJoin (expr (Entity Person)) (expr (Maybe (Entity BlogPost)))
--   (p1 `InnerJoin` f `InnerJoin` p2)
--     :: (...) => InnerJoin
--                   (InnerJoin (expr (Entity Person))
--                              (expr (Entity Follow)))
--                   (expr (Entity Person))
--   (p1 `InnerJoin` (f `InnerJoin` p2)) ::
--     :: (...) => InnerJoin
--                   (expr (Entity Person))
--                   (InnerJoin (expr (Entity Follow))
--                              (expr (Entity Person)))
--   
-- -- Note that some backends may not support all kinds of JOINs. from :: From a => (a -> SqlQuery b) -> SqlQuery b -- | Syntax sugar for case_. else_ :: expr a -> expr a -- | Syntax sugar for case_. then_ :: () -- | Syntax sugar for case_. when_ :: expr (Value Bool) -> () -> expr a -> (expr (Value Bool), expr a) -- | Convert an entity's key into another entity's. -- -- This function is to be used when you change an entity's Id to -- be that of another entity. For example: -- --
--   Bar
--     barNum Int
--   Foo
--     bar BarId
--     fooNum Int
--     Primary bar
--   
-- -- In this example, Bar is said to be the BaseEnt(ity), and Foo the -- child. To model this in Esqueleto, declare: -- --
--   instance ToBaseId Foo where
--     type BaseEnt Foo = Bar
--     toBaseIdWitness barId = FooKey barId
--   
-- -- Now you're able to write queries such as: -- --
--   select $
--   from $ (bar `InnerJoin` foo) -> do
--   on (toBaseId (foo ^. FooId) ==. bar ^. BarId)
--   return (bar, foo)
--   
-- -- Note: this function may be unsafe to use in conditions not like the -- one of the example above. toBaseId :: ToBaseId ent => SqlExpr (Value (Key ent)) -> SqlExpr (Value (Key (BaseEnt ent))) -- | CASE statement. For example: -- --
--   select $
--   return $
--   case_
--      [ when_
--          (exists $
--          from $ \p -> do
--          where_ (p ^. PersonName ==. val "Mike"))
--        then_
--          (sub_select $
--          from $ \v -> do
--          let sub =
--                  from $ \c -> do
--                  where_ (c ^. PersonName ==. val "Mike")
--                  return (c ^. PersonFavNum)
--          where_ (v ^. PersonFavNum >. sub_select sub)
--          return $ count (v ^. PersonName) +. val (1 :: Int)) ]
--      (else_ $ val (-1))
--   
-- -- This query is a bit complicated, but basically it checks if a person -- named "Mike" exists, and if that person does, run the -- subquery to find out how many people have a ranking (by Fav Num) -- higher than "Mike". -- -- NOTE: There are a few things to be aware about this statement. -- -- case_ :: PersistField a => [(SqlExpr (Value Bool), SqlExpr (Value a))] -> SqlExpr (Value a) -> SqlExpr (Value a) -- | Apply extra SqlExpr Value arguments to a PersistField -- constructor (<&>) :: SqlExpr (Insertion (a -> b)) -> SqlExpr (Value a) -> SqlExpr (Insertion b) -- | Apply a PersistField constructor to SqlExpr Value -- arguments. (<#) :: (a -> b) -> SqlExpr (Value a) -> SqlExpr (Insertion b) (/=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 /=. (*=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 *=. (-=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 -=. (+=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 +=. (=.) :: (PersistEntity val, PersistField typ) => EntityField val typ -> SqlExpr (Value typ) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 =. -- | SET clause used on UPDATEs. Note that while it's not -- a type error to use this function on a SELECT, it will most -- certainly result in a runtime error. set :: PersistEntity val => SqlExpr (Entity val) -> [SqlExpr (Entity val) -> SqlExpr Update] -> SqlQuery () -- | NOT EXISTS operator. notExists :: SqlQuery () -> SqlExpr (Value Bool) -- | EXISTS operator. For example: -- --
--   select $
--   from $ \person -> do
--   where_ $ exists $
--            from $ \post -> do
--            where_ (post ^. BlogPostAuthorId ==. person ^. PersonId)
--   return person
--   
exists :: SqlQuery () -> SqlExpr (Value Bool) -- | NOT IN operator. notIn :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (ValueList typ) -> SqlExpr (Value Bool) -- | IN operator. For example if you want to select all -- Persons by a list of IDs: -- --
--   SELECT *
--   FROM Person
--   WHERE Person.id IN (?)
--   
-- -- In esqueleto, we may write the same query above as: -- --
--   select $
--   from $ \person -> do
--   where_ $ person ^. PersonId `in_` valList personIds
--   return person
--   
-- -- Where personIds is of type [Key Person]. in_ :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (ValueList typ) -> SqlExpr (Value Bool) -- | Same as just but for ValueList. Most of the time you -- won't need it, though, because you can use just from inside -- subList_select or Just from inside valList. justList :: SqlExpr (ValueList typ) -> SqlExpr (ValueList (Maybe typ)) -- | Lift a list of constant value from Haskell-land to the query. valList :: PersistField typ => [typ] -> SqlExpr (ValueList typ) -- | Execute a subquery SELECT in an SqlExpression. Returns a list -- of values. subList_select :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (ValueList a) -- | Cast a string type into Text. This function is very useful if -- you want to use newtypes, or if you want to apply functions -- such as like to strings of different types. -- -- Safety: This is a slightly unsafe function, especially if you -- have defined your own instances of SqlString. Also, since -- Maybe is an instance of SqlString, it's possible to turn -- a nullable value into a non-nullable one. Avoid using this function if -- possible. castString :: (SqlString s, SqlString r) => SqlExpr (Value s) -> SqlExpr (Value r) -- | The || string concatenation operator (named after Haskell's -- ++ in order to avoid naming clash with ||.). Supported -- by SQLite and PostgreSQL. (++.) :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value s) infixr 5 ++. -- | The CONCAT function with a variable number of parameters. -- Supported by MySQL and PostgreSQL. concat_ :: SqlString s => [SqlExpr (Value s)] -> SqlExpr (Value s) -- | The string %. May be useful while using like -- and concatenation (concat_ or ++., depending on your -- database). Note that you always have to type the parenthesis, for -- example: -- --
--   name `like` (%) ++. val "John" ++. (%)
--   
(%) :: SqlString s => SqlExpr (Value s) -- | ILIKE operator (case-insensitive LIKE). -- -- Supported by PostgreSQL only. ilike :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool) infixr 2 `ilike` -- | LIKE operator. like :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool) infixr 2 `like` -- | RIGHT function. @since 3.3.0 right_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s) -- | LEFT function. @since 3.3.0 left_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s) -- | LENGTH function. @since 3.3.0 length_ :: (SqlString s, Num a) => SqlExpr (Value s) -> SqlExpr (Value a) -- | LTRIM function. @since 3.3.0 ltrim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | RTRIM function. @since 3.3.0 rtrim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | TRIM function. @since 3.3.0 trim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | UPPER function. @since 3.3.0 upper_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | LOWER function. lower_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | Like coalesce, but takes a non-nullable SqlExpression placed -- at the end of the SqlExpression list, which guarantees a non-NULL -- result. coalesceDefault :: PersistField a => [SqlExpr (Value (Maybe a))] -> SqlExpr (Value a) -> SqlExpr (Value a) -- | COALESCE function. Evaluates the arguments in order and -- returns the value of the first non-NULL SqlExpression, or NULL -- (Nothing) otherwise. Some RDBMSs (such as SQLite) require at least two -- arguments; please refer to the appropriate documentation. coalesce :: PersistField a => [SqlExpr (Value (Maybe a))] -> SqlExpr (Value (Maybe a)) -- | Same as castNum, but for nullable values. castNumM :: (Num a, Num b) => SqlExpr (Value (Maybe a)) -> SqlExpr (Value (Maybe b)) -- | Allow a number of one type to be used as one of another type via an -- implicit cast. An explicit cast is not made, this function changes -- only the types on the Haskell side. -- -- Caveat: Trying to use castNum from Double to -- Int will not result in an integer, the original fractional -- number will still be used! Use round_, ceiling_ or -- floor_ instead. -- -- Safety: This operation is mostly safe due to the Num -- constraint between the types and the fact that RDBMSs usually allow -- numbers of different types to be used interchangeably. However, there -- may still be issues with the query not being accepted by the RDBMS or -- persistent not being able to parse it. castNum :: (Num a, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) avg_ :: (PersistField a, PersistField b) => SqlExpr (Value a) -> SqlExpr (Value (Maybe b)) max_ :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value (Maybe a)) min_ :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value (Maybe a)) sum_ :: (PersistField a, PersistField b) => SqlExpr (Value a) -> SqlExpr (Value (Maybe b)) floor_ :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) ceiling_ :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) round_ :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) random_ :: (PersistField a, Num a) => SqlExpr (Value a) -- | BETWEEN. -- -- @since: 3.1.0 between :: PersistField a => SqlExpr (Value a) -> (SqlExpr (Value a), SqlExpr (Value a)) -> SqlExpr (Value Bool) (*.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 7 *. (/.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 7 /. (-.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 6 -. (+.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 6 +. (||.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool) infixr 2 ||. (&&.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool) infixr 3 &&. (!=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 !=. (<.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 <. (<=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 <=. (>.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 >. (>=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 >=. (==.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 ==. not_ :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -- | COUNT(DISTINCT x). countDistinct :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a) -- | COUNT. count :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a) -- | COUNT(*) value. countRows :: Num a => SqlExpr (Value a) -- | Join nested Maybes in a Value into one. This is useful -- when calling aggregate functions on nullable fields. joinV :: SqlExpr (Value (Maybe (Maybe typ))) -> SqlExpr (Value (Maybe typ)) -- | NULL value. nothing :: SqlExpr (Value (Maybe typ)) -- | Analogous to Just, promotes a value of type typ into -- one of type Maybe typ. It should hold that val . -- Just === just . val. just :: SqlExpr (Value typ) -> SqlExpr (Value (Maybe typ)) -- | IS NULL comparison. -- -- For IS NOT NULL, you can negate this with not_, as in -- not_ (isNothing (person ^. PersonAge)) -- -- Warning: Persistent and Esqueleto have different behavior for != -- Nothing: -- -- TODO: table -- -- In SQL, = NULL and != NULL return NULL instead of -- true or false. For this reason, you very likely do not want to use -- !=. Nothing in Esqueleto. You may find these -- hlint rules helpful to enforce this: -- --
--   - error: {lhs: v Database.Esqueleto.==. Database.Esqueleto.nothing, rhs: Database.Esqueleto.isNothing v, name: Use Esqueleto's isNothing}
--   - error: {lhs: v Database.Esqueleto.==. Database.Esqueleto.val Nothing, rhs: Database.Esqueleto.isNothing v, name: Use Esqueleto's isNothing}
--   - error: {lhs: v Database.Esqueleto.!=. Database.Esqueleto.nothing, rhs: not_ (Database.Esqueleto.isNothing v), name: Use Esqueleto's not isNothing}
--   - error: {lhs: v Database.Esqueleto.!=. Database.Esqueleto.val Nothing, rhs: not_ (Database.Esqueleto.isNothing v), name: Use Esqueleto's not isNothing}
--   
isNothing :: PersistField typ => SqlExpr (Value (Maybe typ)) -> SqlExpr (Value Bool) -- | Lift a constant value from Haskell-land to the query. val :: PersistField typ => typ -> SqlExpr (Value typ) -- | Project a field of an entity that may be null. (?.) :: (PersistEntity val, PersistField typ) => SqlExpr (Maybe (Entity val)) -> EntityField val typ -> SqlExpr (Value (Maybe typ)) -- | Project an SqlExpression that may be null, guarding against null -- cases. withNonNull :: PersistField typ => SqlExpr (Value (Maybe typ)) -> (SqlExpr (Value typ) -> SqlQuery a) -> SqlQuery a -- | Project a field of an entity. (^.) :: forall typ val. (PersistEntity val, PersistField typ) => SqlExpr (Entity val) -> EntityField val typ -> SqlExpr (Value typ) infixl 9 ^. -- | Execute a subquery SELECT in a SqlExpr. This function -- is unsafe, because it can throw runtime exceptions in two cases: -- --
    --
  1. If the query passed has 0 result rows, then it will return a -- NULL value. The persistent parsing operations will -- fail on an unexpected NULL.
  2. --
  3. If the query passed returns more than one row, then the SQL engine -- will fail with an error like "More than one row returned by a subquery -- used as an expression".
  4. --
-- -- This function is safe if you guarantee that exactly one row will be -- returned, or if the result already has a Maybe type for some -- reason. -- -- For variants with the safety encoded already, see subSelect and -- subSelectMaybe. For the most common safe use of this, see -- subSelectCount. subSelectUnsafe :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value a) -- | Performs a sub-select using the given foreign key on the entity. This -- is useful to extract values that are known to be present by the -- database schema. -- -- As an example, consider the following persistent definition: -- --
--   User
--     profile ProfileId
--   
--   Profile
--     name    Text
--   
-- -- The following query will return the name of the user. -- --
--   getUserWithName =
--       select $
--       from $ user ->
--       pure (user, subSelectForeign user UserProfile (^. ProfileName)
--   
subSelectForeign :: (BackendCompatible SqlBackend (PersistEntityBackend val1), PersistEntity val1, PersistEntity val2, PersistField a) => SqlExpr (Entity val2) -> EntityField val2 (Key val1) -> (SqlExpr (Entity val1) -> SqlExpr (Value a)) -> SqlExpr (Value a) -- | Execute a subquery SELECT in a SqlExpr that returns a -- list. This is an alias for subList_select and is provided for -- symmetry with the other safe subselect functions. subSelectList :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (ValueList a) -- | Performs a COUNT of the given query in a subSelect -- manner. This is always guaranteed to return a result value, and is -- completely safe. subSelectCount :: (Num a, PersistField a) => SqlQuery ignored -> SqlExpr (Value a) -- | Execute a subquery SELECT in a SqlExpr. This function -- is a shorthand for the common joinV . subSelect -- idiom, where you are calling subSelect on an expression that -- would be Maybe already. -- -- As an example, you would use this function when calling sum_ or -- max_, which have Maybe in the result type (for a 0 row -- query). subSelectMaybe :: PersistField a => SqlQuery (SqlExpr (Value (Maybe a))) -> SqlExpr (Value (Maybe a)) -- | Execute a subquery SELECT in a SqlExpr. The query -- passed to this function will only return a single result - it has a -- LIMIT 1 passed in to the query to make it safe, and the -- return type is Maybe to indicate that the subquery might result -- in 0 rows. -- -- If you find yourself writing joinV . subSelect, -- then consider using subSelectMaybe. -- -- If you're performing a countRows, then you can use -- subSelectCount which is safe. -- -- If you know that the subquery will always return exactly one row (eg a -- foreign key constraint guarantees that you'll get exactly one row), -- then consider subSelectUnsafe, along with a comment explaining -- why it is safe. subSelect :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value (Maybe a)) -- | Execute a subquery SELECT in an SqlExpression. Returns a -- simple value so should be used only when the SELECT query is -- guaranteed to return just one row. -- -- Deprecated in 3.2.0. sub_select :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value a) -- | Add a locking clause to the query. Please read LockingKind -- documentation and your RDBMS manual. -- -- If multiple calls to locking are made on the same query, the -- last one is used. locking :: LockingKind -> SqlQuery () -- | HAVING. having :: SqlExpr (Value Bool) -> SqlQuery () -- | ORDER BY random() clause. rand :: SqlExpr OrderBy -- | A convenience function that calls both distinctOn and -- orderBy. In other words, -- --
--   distinctOnOrderBy [asc foo, desc bar, desc quux] $ do
--     ...
--   
-- -- is the same as: -- --
--   distinctOn [don foo, don  bar, don  quux] $ do
--     orderBy  [asc foo, desc bar, desc quux]
--     ...
--   
distinctOnOrderBy :: [SqlExpr OrderBy] -> SqlQuery a -> SqlQuery a -- | Erase an SqlExpression's type so that it's suitable to be used by -- distinctOn. don :: SqlExpr (Value a) -> SqlExpr DistinctOn -- | DISTINCT ON. Change the current SELECT into -- SELECT DISTINCT ON (SqlExpressions). For example: -- --
--   select $
--     from \foo ->
--     distinctOn [don (foo ^. FooName), don (foo ^. FooState)] $ do
--     ...
--   
-- -- You can also chain different calls to distinctOn. The above is -- equivalent to: -- --
--   select $
--     from \foo ->
--     distinctOn [don (foo ^. FooName)] $
--     distinctOn [don (foo ^. FooState)] $ do
--     ...
--   
-- -- Each call to distinctOn adds more SqlExpressions. Calls to -- distinctOn override any calls to distinct. -- -- Note that PostgreSQL requires the SqlExpressions on DISTINCT -- ON to be the first ones to appear on a ORDER BY. This is -- not managed automatically by esqueleto, keeping its spirit of trying -- to be close to raw SQL. -- -- Supported by PostgreSQL only. distinctOn :: [SqlExpr DistinctOn] -> SqlQuery a -> SqlQuery a -- | DISTINCT. Change the current SELECT into SELECT -- DISTINCT. For example: -- --
--   select $ distinct $
--     from \foo -> do
--     ...
--   
-- -- Note that this also has the same effect: -- --
--   select $
--     from \foo -> do
--     distinct (return ())
--     ...
--   
distinct :: SqlQuery a -> SqlQuery a -- | OFFSET. Usually used with limit. offset :: Int64 -> SqlQuery () -- | LIMIT. Limit the number of returned rows. limit :: Int64 -> SqlQuery () -- | Descending order of this field or SqlExpression. desc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy -- | Ascending order of this field or SqlExpression. asc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy -- | ORDER BY clause. See also asc and desc. -- -- Multiple calls to orderBy get concatenated on the final query, -- including distinctOnOrderBy. orderBy :: [SqlExpr OrderBy] -> SqlQuery () -- | GROUP BY clause. You can enclose multiple columns in a tuple. -- --
--   select $ from \(foo `InnerJoin` bar) -> do
--     on (foo ^. FooBarId ==. bar ^. BarId)
--     groupBy (bar ^. BarId, bar ^. BarName)
--     return (bar ^. BarId, bar ^. BarName, countRows)
--   
-- -- With groupBy you can sort by aggregate functions, like so (we used -- let to restrict the more general countRows to -- SqlSqlExpr (Value Int) to avoid ambiguity---the second use of -- countRows has its type restricted by the :: Int -- below): -- --
--   r <- select $ from \(foo `InnerJoin` bar) -> do
--     on (foo ^. FooBarId ==. bar ^. BarId)
--     groupBy $ bar ^. BarName
--     let countRows' = countRows
--     orderBy [asc countRows']
--     return (bar ^. BarName, countRows')
--   forM_ r $ \(Value name, Value count) -> do
--     print name
--     print (count :: Int)
--   
-- --

Need more columns?

-- -- The ToSomeValues class is defined for SqlExpr and tuples -- of SqlExprs. We only have definitions for up to 8 elements in a -- tuple right now, so it's possible that you may need to have more than -- 8 elements. -- -- For example, consider a query with a groupBy call like this: -- --
--   groupBy (e0, e1, e2, e3, e4, e5, e6, e7)
--   
-- -- This is the biggest you can get with a single tuple. However, you can -- easily nest the tuples to add more: -- --
--   groupBy ((e0, e1, e2, e3, e4, e5, e6, e7), e8, e9)
--   
groupBy :: ToSomeValues a => a -> SqlQuery () -- | An ON clause, useful to describe how two tables are related. -- Cross joins and tuple-joins do not need an on clause, but -- InnerJoin and the various outer joins do. -- -- Database.Esqueleto.Experimental in version 4.0.0.0 of the -- library. The Experimental module has a dramatically improved -- means for introducing tables and entities that provides more power and -- less potential for runtime errors. -- -- If you don't include an on clause (or include too many!) then a -- runtime exception will be thrown. -- -- As an example, consider this simple join: -- --
--   select $
--   from $ \(foo `InnerJoin` bar) -> do
--     on (foo ^. FooId ==. bar ^. BarFooId)
--     ...
--   
-- -- We need to specify the clause for joining the two columns together. If -- we had this: -- --
--   select $
--   from $ \(foo `CrossJoin` bar) -> do
--     ...
--   
-- -- Then we can safely omit the on clause, because the cross join -- will make pairs of all records possible. -- -- You can do multiple on clauses in a query. This query joins -- three tables, and has two on clauses: -- --
--   select $
--   from $ \(foo `InnerJoin` bar `InnerJoin` baz) -> do
--     on (baz ^. BazId ==. bar ^. BarBazId)
--     on (foo ^. FooId ==. bar ^. BarFooId)
--     ...
--   
-- -- Old versions of esqueleto required that you provide the on -- clauses in reverse order. This restriction has been lifted - you can -- now provide on clauses in any order, and the SQL should work -- itself out. The above query is now totally equivalent to this: -- --
--   select $
--   from $ \(foo `InnerJoin` bar `InnerJoin` baz) -> do
--     on (foo ^. FooId ==. bar ^. BarFooId)
--     on (baz ^. BazId ==. bar ^. BarBazId)
--     ...
--   
on :: SqlExpr (Value Bool) -> SqlQuery () -- | WHERE clause: restrict the query's result. where_ :: SqlExpr (Value Bool) -> SqlQuery () -- | A single value (as opposed to a whole entity). You may use -- (^.) or (?.) to get a Value -- from an Entity. newtype Value a Value :: a -> Value a [unValue] :: Value a -> a -- | A list of single values. There's a limited set of functions able to -- work with this data type (such as subList_select, -- valList, in_ and exists). newtype ValueList a ValueList :: a -> ValueList a -- | Data type that represents an INNER JOIN (see -- LeftOuterJoin for an example). data InnerJoin a b InnerJoin :: a -> b -> InnerJoin a b infixl 2 `InnerJoin` infixl 2 `InnerJoin` -- | Data type that represents a CROSS JOIN (see -- LeftOuterJoin for an example). data CrossJoin a b CrossJoin :: a -> b -> CrossJoin a b infixl 2 `CrossJoin` infixl 2 `CrossJoin` -- | Data type that represents a LEFT OUTER JOIN. For example, -- --
--   select $
--   from $ \(person `LeftOuterJoin` pet) ->
--     ...
--   
-- -- is translated into -- --
--   SELECT ...
--   FROM Person LEFT OUTER JOIN Pet
--   ...
--   
-- -- See also: from. data LeftOuterJoin a b LeftOuterJoin :: a -> b -> LeftOuterJoin a b infixl 2 `LeftOuterJoin` infixl 2 `LeftOuterJoin` -- | Data type that represents a RIGHT OUTER JOIN (see -- LeftOuterJoin for an example). data RightOuterJoin a b RightOuterJoin :: a -> b -> RightOuterJoin a b infixl 2 `RightOuterJoin` infixl 2 `RightOuterJoin` -- | Data type that represents a FULL OUTER JOIN (see -- LeftOuterJoin for an example). data FullOuterJoin a b FullOuterJoin :: a -> b -> FullOuterJoin a b infixl 2 `FullOuterJoin` infixl 2 `FullOuterJoin` -- | (Internal) A kind of JOIN. data JoinKind -- |
--   INNER JOIN
--   
InnerJoinKind :: JoinKind -- |
--   CROSS JOIN
--   
CrossJoinKind :: JoinKind -- |
--   LEFT OUTER JOIN
--   
LeftOuterJoinKind :: JoinKind -- |
--   RIGHT OUTER JOIN
--   
RightOuterJoinKind :: JoinKind -- |
--   FULL OUTER JOIN
--   
FullOuterJoinKind :: JoinKind -- | Exception thrown whenever on is used to create an ON -- clause but no matching JOIN is found. data OnClauseWithoutMatchingJoinException OnClauseWithoutMatchingJoinException :: String -> OnClauseWithoutMatchingJoinException -- | Phantom type used by orderBy, asc and desc. data OrderBy -- | Phantom type used by distinctOn and don. data DistinctOn -- | Different kinds of locking clauses supported by locking. -- -- Note that each RDBMS has different locking support. The constructors -- of this datatype specify only the syntax of the locking -- mechanism, not its semantics. For example, even though both -- MySQL and PostgreSQL support ForUpdate, there are no guarantees -- that they will behave the same. data LockingKind -- | FOR UPDATE syntax. Supported by MySQL, Oracle and PostgreSQL. ForUpdate :: LockingKind -- | FOR UPDATE SKIP LOCKED syntax. Supported by MySQL, Oracle and -- PostgreSQL. ForUpdateSkipLocked :: LockingKind -- | FOR SHARE syntax. Supported by PostgreSQL. ForShare :: LockingKind -- | LOCK IN SHARE MODE syntax. Supported by MySQL. LockInShareMode :: LockingKind -- | Phantom class of data types that are treated as strings by the RDBMS. -- It has no methods because it's only used to avoid type errors such as -- trying to concatenate integers. -- -- If you have a custom data type or newtype, feel free to make -- it an instance of this class. class PersistField a => SqlString a -- | e.g. type BaseEnt MyBase = MyChild type family BaseEnt ent -- | Class that enables one to use toBaseId to convert an entity's -- key on a query into another (cf. toBaseId). class ToBaseId ent where { -- | e.g. type BaseEnt MyBase = MyChild type family BaseEnt ent; } -- | Convert from the key of the BaseEnt(ity) to the key of the child -- entity. This function is not actually called, but that it typechecks -- proves this operation is safe. toBaseIdWitness :: ToBaseId ent => Key (BaseEnt ent) -> Key ent -- | (Internal) Class that implements the tuple from magic (see -- fromStart). class From a -- | SQL backend for esqueleto using SqlPersistT. data SqlQuery a -- | Constraint synonym for persistent entities whose backend is -- SqlBackend. type SqlEntity ent = (PersistEntity ent, PersistEntityBackend ent ~ SqlBackend) -- | An expression on the SQL backend. -- -- Raw expression: Contains a SqlExprMeta and a function for -- building the expr. It recieves a parameter telling it whether it is in -- a parenthesized context, and takes information about the SQL -- connection (mainly for escaping names) and returns both an string -- (Builder) and a list of values to be interpolated by the SQL -- backend. data SqlExpr 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 -> Type -> Type -> Type; 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 type family PersistConfigBackend c :: Type -> Type -> Type -> Type type family PersistConfigPool c -- | An ConstraintNameHS represents the Haskell-side name that -- persistent will use for a constraint. newtype ConstraintNameHS ConstraintNameHS :: Text -> ConstraintNameHS [unConstraintNameHS] :: ConstraintNameHS -> Text -- | A ConstraintNameDB represents the datastore-side name that -- persistent will use for a constraint. newtype ConstraintNameDB ConstraintNameDB :: Text -> ConstraintNameDB [unConstraintNameDB] :: ConstraintNameDB -> Text -- | An EntityNameDB represents the datastore-side name that -- persistent will use for an entity. newtype EntityNameDB EntityNameDB :: Text -> EntityNameDB [unEntityNameDB] :: EntityNameDB -> Text -- | An EntityNameHS represents the Haskell-side name that -- persistent will use for an entity. newtype EntityNameHS EntityNameHS :: Text -> EntityNameHS [unEntityNameHS] :: EntityNameHS -> Text -- | A FieldNameHS represents the Haskell-side name that -- persistent will use for a field. newtype FieldNameHS FieldNameHS :: Text -> FieldNameHS [unFieldNameHS] :: FieldNameHS -> Text -- | An EntityNameDB represents the datastore-side name that -- persistent will use for an entity. newtype FieldNameDB FieldNameDB :: Text -> FieldNameDB [unFieldNameDB] :: FieldNameDB -> Text -- | Convenience operations for working with '-NameDB' types. class DatabaseName a escapeWith :: DatabaseName a => (Text -> str) -> a -> str -- | A type that determines how a backend should handle the literal. data LiteralType -- | The accompanying value will be escaped before inserting into the -- database. This is the correct default choice to use. Escaped :: LiteralType -- | The accompanying value will not be escaped when inserting into the -- database. This is potentially dangerous - use this with care. Unescaped :: LiteralType -- | The DbSpecific constructor corresponds to the legacy -- PersistDbSpecific constructor. We need to keep this around -- because old databases may have serialized JSON representations that -- reference this. We don't want to break the ability of a database to -- load rows. DbSpecific :: LiteralType -- | 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 -- | This constructor is used to specify some raw literal value for the -- backend. The LiteralType value specifies how the value should -- be escaped. This can be used to make special, custom types avaialable -- in the back end. PersistLiteral_ :: LiteralType -> ByteString -> PersistValue -- | This pattern synonym used to be a data constructor on -- PersistValue, but was changed into a catch-all pattern synonym -- to allow backwards compatiblity with database types. See the -- documentation on PersistDbSpecific for more details. pattern PersistLiteral :: ByteString -> PersistValue -- | This pattern synonym used to be a data constructor for the -- PersistValue type. It was changed to be a pattern so that -- JSON-encoded database values could be parsed into their corresponding -- values. You should not use this, and instead prefer to pattern match -- on PersistLiteral_ directly. -- -- If you use this, it will overlap a patern match on the -- 'PersistLiteral_, PersistLiteral, and -- PersistLiteralEscaped patterns. If you need to disambiguate -- between these constructors, pattern match on PersistLiteral_ -- directly. pattern PersistDbSpecific :: ByteString -> PersistValue -- | This pattern synonym used to be a data constructor on -- PersistValue, but was changed into a catch-all pattern synonym -- to allow backwards compatiblity with database types. See the -- documentation on PersistDbSpecific for more details. pattern PersistLiteralEscaped :: ByteString -> PersistValue fromPersistValueText :: PersistValue -> Either Text Text -- | 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 -- | 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 :: !FieldNameHS -> !FieldNameDB -> !FieldType -> !SqlType -> ![FieldAttr] -> !Bool -> !ReferenceDef -> !FieldCascade -> !Maybe Text -> !Maybe Text -> !Bool -> 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 FieldNameHS "name" for -- a type User will have a record field userName. [fieldHaskell] :: FieldDef -> !FieldNameHS -- | The name of the field in the database. For SQL databases, this -- corresponds to the column name. [fieldDB] :: FieldDef -> !FieldNameDB -- | 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 -> ![FieldAttr] -- | 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 -- | Defines how operations on the field cascade on to the referenced -- tables. This doesn't have any meaning if the fieldReference is -- set to NoReference or SelfReference. The cascade option -- here should be the same as the one obtained in the -- fieldReference. [fieldCascade] :: FieldDef -> !FieldCascade -- | Optional comments for a Field. There is not currently a way -- to attach comments to a field in the quasiquoter. [fieldComments] :: FieldDef -> !Maybe Text -- | Whether or not the field is a GENERATED column, and -- additionally the expression to use for generation. [fieldGenerated] :: FieldDef -> !Maybe Text -- | True if the field is an implicit ID column. False -- otherwise. [fieldIsImplicitIdColumn] :: FieldDef -> !Bool data PersistUpdate Assign :: PersistUpdate Add :: PersistUpdate Subtract :: PersistUpdate Multiply :: PersistUpdate Divide :: PersistUpdate BackendSpecificUpdate :: Text -> PersistUpdate data UpdateException KeyNotFound :: String -> UpdateException UpsertError :: String -> UpdateException data PersistFilter Eq :: PersistFilter Ne :: PersistFilter Gt :: PersistFilter Lt :: PersistFilter Ge :: PersistFilter Le :: PersistFilter In :: PersistFilter NotIn :: PersistFilter -- | 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 PersistException -- | Generic Exception PersistError :: Text -> PersistException PersistMarshalError :: Text -> PersistException PersistInvalidField :: Text -> PersistException PersistForeignConstraintUnmet :: Text -> PersistException PersistMongoDBError :: Text -> PersistException PersistMongoDBUnsupported :: Text -> PersistException -- | An action that might happen on a deletion or update on a foreign key -- change. data CascadeAction Cascade :: CascadeAction Restrict :: CascadeAction SetNull :: CascadeAction SetDefault :: CascadeAction -- | This datatype describes how a foreign reference field cascades deletes -- or updates. -- -- This type is used in both parsing the model definitions and performing -- migrations. A Nothing in either of the field values means that -- the user has not specified a CascadeAction. An unspecified -- CascadeAction is defaulted to Restrict when doing -- migrations. data FieldCascade FieldCascade :: !Maybe CascadeAction -> !Maybe CascadeAction -> FieldCascade [fcOnUpdate] :: FieldCascade -> !Maybe CascadeAction [fcOnDelete] :: FieldCascade -> !Maybe CascadeAction data ForeignDef ForeignDef :: !EntityNameHS -> !EntityNameDB -> !ConstraintNameHS -> !ConstraintNameDB -> !FieldCascade -> ![(ForeignFieldDef, ForeignFieldDef)] -> ![Attr] -> Bool -> Bool -> ForeignDef [foreignRefTableHaskell] :: ForeignDef -> !EntityNameHS [foreignRefTableDBName] :: ForeignDef -> !EntityNameDB [foreignConstraintNameHaskell] :: ForeignDef -> !ConstraintNameHS [foreignConstraintNameDBName] :: ForeignDef -> !ConstraintNameDB -- | Determine how the field will cascade on updates and deletions. [foreignFieldCascade] :: ForeignDef -> !FieldCascade [foreignFields] :: ForeignDef -> ![(ForeignFieldDef, ForeignFieldDef)] [foreignAttrs] :: ForeignDef -> ![Attr] [foreignNullable] :: ForeignDef -> Bool -- | Determines if the reference is towards a Primary Key or not. [foreignToPrimary] :: ForeignDef -> Bool -- | Used instead of FieldDef to generate a smaller amount of code type ForeignFieldDef = (FieldNameHS, FieldNameDB) data CompositeDef CompositeDef :: !NonEmpty FieldDef -> ![Attr] -> CompositeDef [compositeFields] :: CompositeDef -> !NonEmpty FieldDef [compositeAttrs] :: CompositeDef -> ![Attr] -- | Type for storing the Uniqueness constraint in the Schema. Assume you -- have the following schema with a uniqueness constraint: -- --
--   Person
--     name String
--     age Int
--     UniqueAge age
--   
-- -- This will be represented as: -- --
--   UniqueDef
--       { uniqueHaskell = ConstraintNameHS (packPTH UniqueAge)
--       , uniqueDBName = ConstraintNameDB (packPTH "unique_age")
--       , uniqueFields = [(FieldNameHS (packPTH "age"), FieldNameDB (packPTH "age"))]
--       , uniqueAttrs = []
--       }
--   
data UniqueDef UniqueDef :: !ConstraintNameHS -> !ConstraintNameDB -> !NonEmpty (FieldNameHS, FieldNameDB) -> ![Attr] -> UniqueDef [uniqueHaskell] :: UniqueDef -> !ConstraintNameHS [uniqueDBName] :: UniqueDef -> !ConstraintNameDB [uniqueFields] :: UniqueDef -> !NonEmpty (FieldNameHS, FieldNameDB) [uniqueAttrs] :: UniqueDef -> ![Attr] -- | 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 :: FieldNameDB -> Maybe (Either SelfEmbed EntityNameHS) -> EmbedFieldDef [emFieldDB] :: EmbedFieldDef -> FieldNameDB [emFieldEmbed] :: EmbedFieldDef -> Maybe (Either SelfEmbed EntityNameHS) -- | 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 :: EntityNameHS -> [EmbedFieldDef] -> EmbedEntityDef [embeddedHaskell] :: EmbedEntityDef -> EntityNameHS [embeddedFields] :: EmbedEntityDef -> [EmbedFieldDef] -- | 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 -- name and has the Haskell type of the foreign key in the form of -- FieldType ForeignRef :: !EntityNameHS -> ReferenceDef EmbedRef :: EntityNameHS -> ReferenceDef CompositeRef :: CompositeDef -> ReferenceDef -- | A SelfReference stops an immediate cycle which causes non-termination -- at compile-time (issue #311). SelfReference :: ReferenceDef -- | A FieldType describes a field parsed from the QuasiQuoter and -- is used to determine the Haskell type in the generated code. -- -- name Text parses into FTTypeCon Nothing Text -- -- name T.Text parses into FTTypeCon (Just T -- Text) -- -- name (Jsonb User) parses into: -- --
--   FTApp (FTTypeCon Nothing Jsonb) (FTTypeCon Nothing User)
--   
data FieldType -- | Optional module and name. FTTypeCon :: Maybe Text -> Text -> FieldType FTTypePromoted :: Text -> FieldType FTApp :: FieldType -> FieldType -> FieldType FTList :: FieldType -> FieldType -- | Attributes that may be attached to fields that can affect migrations -- and serialization in backend-specific ways. -- -- While we endeavor to, we can't forsee all use cases for all backends, -- and so FieldAttr is extensible through its constructor -- FieldAttrOther. data FieldAttr -- | The Maybe keyword goes after the type. This indicates that the -- column is nullable, and the generated Haskell code will have a -- Maybe type for it. -- -- Example: -- --
--   User
--       name Text Maybe
--   
FieldAttrMaybe :: FieldAttr -- | This indicates that the column is nullable, but should not have a -- Maybe type. For this to work out, you need to ensure that the -- PersistField instance for the type in question can support a -- PersistNull value. -- --
--   data What = NoWhat | Hello Text
--   
--   instance PersistField What where
--       fromPersistValue PersistNull =
--           pure NoWhat
--       fromPersistValue pv =
--           Hello $ fromPersistValue pv
--   
--   instance PersistFieldSql What where
--       sqlType _ = SqlString
--   
--   User
--       what What nullable
--   
FieldAttrNullable :: FieldAttr -- | This tag means that the column will not be present on the Haskell -- code, but will not be removed from the database. Useful to deprecate -- fields in phases. -- -- You should set the column to be nullable in the database. Otherwise, -- inserts won't have values. -- --
--   User
--       oldName Text MigrationOnly
--       newName Text
--   
FieldAttrMigrationOnly :: FieldAttr -- | A SafeToRemove attribute is not present on the Haskell -- datatype, and the backend migrations should attempt to drop the column -- without triggering any unsafe migration warnings. -- -- Useful after you've used MigrationOnly to remove a column -- from the database in phases. -- --
--   User
--       oldName Text SafeToRemove
--       newName Text
--   
FieldAttrSafeToRemove :: FieldAttr -- | This attribute indicates that we should create a foreign key reference -- from a column. By default, persistent will try and create a -- foreign key reference for a column if it can determine that the type -- of the column is a Key entity or an -- EntityId and the Entity's name was present in -- mkPersist. -- -- This is useful if you want to use the explicit foreign key syntax. -- --
--   Post
--       title    Text
--   
--   Comment
--       postId   PostId      noreference
--       Foreign Post fk_comment_post postId
--   
FieldAttrNoreference :: FieldAttr -- | This is set to specify precisely the database table the column refers -- to. -- --
--   Post
--       title    Text
--   
--   Comment
--       postId   PostId references="post"
--   
-- -- You should not need this - persistent should be capable of -- correctly determining the target table's name. If you do need this, -- please file an issue describing why. FieldAttrReference :: Text -> FieldAttr -- | Specify a name for the constraint on the foreign key reference for -- this table. -- --
--   Post
--       title    Text
--   
--   Comment
--       postId   PostId constraint="my_cool_constraint_name"
--   
FieldAttrConstraint :: Text -> FieldAttr -- | Specify the default value for a column. -- --
--   User
--       createdAt    UTCTime     default="NOW()"
--   
-- -- Note that a default= attribute does not mean you can omit the -- value while inserting. FieldAttrDefault :: Text -> FieldAttr -- | Specify a custom SQL type for the column. Generally, you should define -- a custom datatype with a custom PersistFieldSql instance -- instead of using this. -- --
--   User
--       uuid     Text    sqltype=UUID
--   
FieldAttrSqltype :: Text -> FieldAttr -- | Set a maximum length for a column. Useful for VARCHAR and indexes. -- --
--   User
--       name     Text    maxlen=200
--   
--       UniqueName name
--   
FieldAttrMaxlen :: Integer -> FieldAttr -- | Specify the database name of the column. -- --
--   User
--       blarghle     Int     sql="b_l_a_r_g_h_l_e"
--   
-- -- Useful for performing phased migrations, where one column is renamed -- to another column over time. FieldAttrSql :: Text -> FieldAttr -- | A grab bag of random attributes that were unrecognized by the parser. FieldAttrOther :: Text -> FieldAttr type Attr = Text type ExtraLine = [Text] -- | The definition for the entity's primary key ID. data EntityIdDef -- | The entity has a single key column, and it is a surrogate key - that -- is, you can't go from rec -> Key rec. EntityIdField :: !FieldDef -> EntityIdDef -- | The entity has a natural key. This means you can write rec -> -- Key rec because all the key fields are present on the datatype. -- -- A natural key can have one or more columns. EntityIdNaturalKey :: !CompositeDef -> EntityIdDef -- | 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 -- | 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 data IsNullable Nullable :: !WhyNullable -> IsNullable NotNullable :: IsNullable -- | 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 fieldAttrsContainsNullable :: [FieldAttr] -> IsNullable -- | Return the [FieldDef] for the entity keys. entitiesPrimary :: EntityDef -> NonEmpty FieldDef entityPrimary :: EntityDef -> Maybe CompositeDef -- | Returns a NonEmpty list of FieldDef that correspond with -- the key columns for an EntityDef. keyAndEntityFields :: EntityDef -> NonEmpty FieldDef -- | Parse raw field attributes into structured form. Any unrecognized -- attributes will be preserved, identically as they are encountered, as -- FieldAttrOther values. parseFieldAttrs :: [Text] -> [FieldAttr] isFieldNotGenerated :: FieldDef -> Bool -- | Returns True if the FieldDef does not have a -- MigrationOnly or SafeToRemove flag from the -- QuasiQuoter. isHaskellField :: FieldDef -> Bool -- | A FieldCascade that does nothing. noCascade :: FieldCascade -- | Renders a FieldCascade value such that it can be used in SQL -- migrations. renderFieldCascade :: FieldCascade -> Text -- | Render a CascadeAction to Text such that it can be used -- in a SQL command. renderCascadeAction :: CascadeAction -> Text -- | A Statement is a representation of a database query that has -- been prepared and stored on the server side. data Statement Statement :: IO () -> IO () -> ([PersistValue] -> IO Int64) -> (forall (m :: Type -> Type). MonadIO m => [PersistValue] -> Acquire (ConduitM () [PersistValue] m ())) -> Statement [stmtFinalize] :: Statement -> IO () [stmtReset] :: Statement -> IO () [stmtExecute] :: Statement -> [PersistValue] -> IO Int64 [stmtQuery] :: Statement -> forall (m :: Type -> Type). MonadIO m => [PersistValue] -> Acquire (ConduitM () [PersistValue] m ()) data InsertSqlResult ISRSingle :: Text -> InsertSqlResult ISRInsertGet :: Text -> Text -> InsertSqlResult ISRManyKeys :: Text -> [PersistValue] -> InsertSqlResult type LogFunc = Loc -> LogSource -> LogLevel -> LogStr -> IO () -- | Replace the FieldDef FieldAttr with the new list. setFieldAttrs :: [FieldAttr] -> FieldDef -> FieldDef -- | Modify the list of field attributes. overFieldAttrs :: ([FieldAttr] -> [FieldAttr]) -> FieldDef -> FieldDef -- | Add an attribute to the list of field attributes. addFieldAttr :: FieldAttr -> FieldDef -> FieldDef -- | Check if the field definition is nullable isFieldNullable :: FieldDef -> IsNullable -- | Check if the field is `Maybe a` isFieldMaybe :: FieldDef -> Bool -- | Retrieve the list of UniqueDef from an EntityDef. This -- currently does not include a Primary key, if one is defined. -- A future version of persistent will include a -- Primary key among the Unique constructors for the -- Entity. getEntityUniques :: EntityDef -> [UniqueDef] -- | Retrieve the Haskell name of the given entity. getEntityHaskellName :: EntityDef -> EntityNameHS -- | Return the database name for the given entity. getEntityDBName :: EntityDef -> EntityNameDB getEntityExtra :: EntityDef -> Map Text [[Text]] setEntityDBName :: EntityNameDB -> EntityDef -> EntityDef getEntityComments :: EntityDef -> Maybe Text getEntityForeignDefs :: EntityDef -> [ForeignDef] -- | Retrieve the list of FieldDef that makes up the fields of the -- entity. -- -- This does not return the fields for an Id column or an -- implicit id. It will return the key columns if you used the -- Primary syntax for defining the primary key. -- -- This does not return fields that are marked SafeToRemove or -- MigrationOnly - so it only returns fields that are -- represented in the Haskell type. If you need those fields, use -- getEntityFieldsDatabase. getEntityFields :: EntityDef -> [FieldDef] -- | This returns all of the FieldDef defined for the -- EntityDef, including those fields that are marked as -- MigrationOnly (and therefore only present in the database) or -- SafeToRemove (and a migration will drop the column if it -- exists in the database). -- -- For all the fields that are present on the Haskell-type, see -- getEntityFields. getEntityFieldsDatabase :: EntityDef -> [FieldDef] isEntitySum :: EntityDef -> Bool getEntityId :: EntityDef -> EntityIdDef getEntityIdField :: EntityDef -> Maybe FieldDef -- | Set an entityId to be the given FieldDef. setEntityId :: FieldDef -> EntityDef -> EntityDef setEntityIdDef :: EntityIdDef -> EntityDef -> EntityDef getEntityKeyFields :: EntityDef -> NonEmpty FieldDef -- | Perform a mapping function over all of the entity fields, as -- determined by getEntityFieldsDatabase. overEntityFields :: ([FieldDef] -> [FieldDef]) -> EntityDef -> EntityDef data SomePersistField SomePersistField :: a -> SomePersistField -- | Prior to persistent-2.11.0, we provided an instance of -- PersistField for the Natural type. This was in error, -- because Natural represents an infinite value, and databases -- don't have reasonable types for this. -- -- The instance for Natural used the Int64 underlying type, -- which will cause underflow and overflow errors. This type has the -- exact same code in the instances, and will work seamlessly. -- -- A more appropriate type for this is the Word series of types -- from Data.Word. These have a bounded size, are guaranteed to be -- non-negative, and are quite efficient for the database to store. newtype OverflowNatural OverflowNatural :: Natural -> OverflowNatural [unOverflowNatural] :: OverflowNatural -> Natural -- | 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 -- | This type class is used with the OverloadedLabels extension -- to provide a more convenient means of using the EntityField -- type. EntityField definitions are prefixed with the type name -- to avoid ambiguity, but this ambiguity can result in verbose code. -- -- If you have a table User with a name Text field, -- then the corresponding EntityField is UserName. With -- this, we can write #name :: EntityField User Text. -- -- What's more fun is that the type is more general: it's actually -- #name :: (SymbolToField "name" rec typ) => EntityField rec -- typ -- -- Which means it is *polymorphic* over the actual record. This allows -- you to write code that can be generic over the tables, provided they -- have the right fields. class SymbolToField (sym :: Symbol) rec typ | sym rec -> typ symbolToField :: SymbolToField sym rec typ => EntityField rec typ -- | 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 -- | Value to filter with. Highly dependant on the type of filter used. data FilterValue typ [FilterValue] :: forall typ. typ -> FilterValue typ [FilterValues] :: forall typ. [typ] -> FilterValue typ [UnsafeValue] :: forall a typ. PersistField a => a -> FilterValue typ type family BackendSpecificUpdate backend record -- | 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. -- -- As of persistent-2.11.0.0, it's possible to use the -- OverloadedLabels language extension to refer to -- EntityField values polymorphically. See the documentation on -- SymbolToField for more information. data family EntityField record :: Type -> Type; -- | 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 => proxy 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 -> NonEmpty (FieldNameHS, FieldNameDB) -- | A lower level operation. persistUniqueToValues :: PersistEntity record => Unique record -> [PersistValue] -- | Use a PersistField as a lens. fieldLens :: PersistEntity record => EntityField record field -> forall (f :: Type -> Type). Functor f => (field -> f field) -> Entity record -> f (Entity record) -- | Extract a Key record from a record value. -- Currently, this is only defined for entities using the -- Primary syntax for natural/composite keys. In a future -- version of persistent which incorporates the ID directly into -- the entity, this will always be Just. keyFromRecordM :: PersistEntity record => Maybe (record -> Key record) -- | 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. -- -- As of persistent-2.11.0.0, it's possible to use the -- OverloadedLabels language extension to refer to -- EntityField values polymorphically. See the documentation on -- SymbolToField for more information. data family EntityField record :: Type -> Type -- | Unique keys besides the Key. data family Unique record -- | Get list of values corresponding to given entity. entityValues :: PersistEntity record => Entity record -> [PersistValue] -- | 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 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 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 :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m [Key record] -- | 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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> 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 :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> [Update record] -> ReaderT backend m record 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 class PersistCore backend where { data family BackendKey backend; } data family BackendKey backend -- | 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 -- | A convenient alias for common type signatures type PersistRecordBackend record backend = (PersistEntity record, PersistEntityBackend record ~ BaseBackend backend) -- | 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' = withCompatibleBackend asdf
--   
class BackendCompatible sup sub projectBackend :: BackendCompatible sup sub => sub -> sup -- | 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 -- | 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 type family BaseBackend backend -- | Run a query against a larger backend by plucking out BaseBackend -- backend -- -- This is a helper for reusing existing queries when expanding the -- backend type. withBaseBackend :: forall backend (m :: Type -> Type) a. HasPersistBackend backend => ReaderT (BaseBackend backend) m a -> ReaderT backend m a -- | Run a query against a compatible backend, by projecting the backend -- -- This is a helper for using queries which run against a specific -- backend type that your backend is compatible with. withCompatibleBackend :: forall sup sub (m :: Type -> Type) a. BackendCompatible sup sub => ReaderT sup m a -> ReaderT sub m a liftPersist :: (MonadIO m, MonadReader backend m) => ReaderT backend IO b -> m b -- | 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 :: forall record backend (m :: Type -> Type). (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 :: forall record backend (m :: Type -> Type). (PersistEntityBackend record ~ BaseBackend backend, MonadIO m, PersistEntity record, PersistStoreRead backend) => Key record -> ReaderT backend m (Entity record) -- | Curry this to make a convenience function that loads an associated -- model. -- --
--   foreign = belongsTo foreignId
--   
belongsTo :: forall ent1 ent2 backend (m :: Type -> Type). (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 :: forall ent1 ent2 backend (m :: Type -> Type). (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 :: forall e backend (m :: Type -> Type). (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 :: forall record backend (m :: Type -> Type). (PersistEntityBackend record ~ BaseBackend backend, PersistEntity record, MonadIO m, PersistStoreWrite backend) => record -> ReaderT backend m record -- | A SqlBackend represents a handle or connection to a database. -- It contains functions and values that allow databases to have more -- optimized implementations, as well as references that benefit -- performance and sharing. -- -- Instead of using the SqlBackend constructor directly, use the -- mkSqlBackend function. -- -- A SqlBackend is *not* thread-safe. You should not assume that a -- SqlBackend can be shared among threads and run concurrent -- queries. This *will* result in problems. Instead, you should create a -- Pool SqlBackend, known as a -- ConnectionPool, and pass that around in multi-threaded -- applications. -- -- To run actions in the persistent library, you should use the -- runSqlConn function. If you're using a multithreaded -- application, use the runSqlPool function. data SqlBackend -- | 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 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." -- | 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 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 -- | 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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> record -> [Update record] -> ReaderT backend m (Entity record) -- | Put many records into db -- -- putMany :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m () -- | 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 PersistStoreRead backend => PersistUniqueRead backend -- | Given a proxy for a PersistEntity record, this returns the sole -- UniqueDef for that entity. onlyOneUniqueDef :: (OnlyOneUniqueKey record, Monad proxy) => proxy record -> UniqueDef -- | 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 :: forall record backend (m :: Type -> Type). (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 :: forall record backend (m :: Type -> Type). (MonadIO m, PersistRecordBackend record backend, PersistUniqueWrite backend) => record -> ReaderT backend m (Maybe (Entity 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 :: forall record backend (m :: Type -> Type). (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> ReaderT backend m (Unique record) -- | 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 :: Type -> Type) backend. (MonadIO m, PersistUniqueRead backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record) => 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 :: forall record backend (m :: Type -> Type). (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 :: forall record backend (m :: Type -> Type). (MonadIO m, PersistRecordBackend record backend, PersistUniqueRead backend) => 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 stay unique, and could thus -- safely be updated. on a conflict returns the conflicting key -- -- This is similar to checkUnique, except it's useful for updating -- - when the particular entity already exists, it would normally -- conflict with itself. This variant ignores those conflicts -- --

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
--   
checkUniqueUpdateable :: forall record backend (m :: Type -> Type). (MonadIO m, PersistRecordBackend record backend, PersistUniqueRead backend) => Entity record -> ReaderT backend m (Maybe (Unique record)) -- | Backends supporting conditional write operations class (PersistQueryRead backend, PersistStoreWrite backend) => PersistQueryWrite backend -- | 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. -- -- NOTE: This function returns an Acquire and a ConduitM, -- which implies that it streams from the database. It does not. Please -- use selectList to simplify the code. If you want streaming -- behavior, consider persistent-pagination which efficiently -- chunks a query into ranges, or investigate a backend-specific -- streaming solution. selectSourceRes :: forall record (m1 :: Type -> Type) (m2 :: Type -> Type). (PersistQueryRead backend, PersistRecordBackend record backend, MonadIO m1, MonadIO m2) => [Filter record] -> [SelectOpt record] -> ReaderT backend m1 (Acquire (ConduitM () (Entity record) m2 ())) -- | Get the Keys of all records matching the given criterion. selectKeysRes :: forall (m1 :: Type -> Type) (m2 :: Type -> Type) record. (PersistQueryRead backend, MonadIO m1, MonadIO m2, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> ReaderT backend m1 (Acquire (ConduitM () (Key record) m2 ())) -- | Get the Keys of all records matching the given criterion. -- -- For an example, see selectList. selectKeys :: forall record backend (m :: Type -> Type). (PersistQueryRead backend, MonadResource m, PersistRecordBackend record backend, MonadReader backend m) => [Filter record] -> [SelectOpt record] -> ConduitM () (Key record) m () -- | 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 :: forall (m :: Type -> Type). (DeleteCascade record backend, MonadIO m) => Key record -> ReaderT backend m () -- | Cascade-deletion of entries satisfying given filters. deleteCascadeWhere :: forall record backend (m :: Type -> Type). (MonadIO m, DeleteCascade record backend, PersistQueryWrite backend) => [Filter record] -> ReaderT backend m () -- | 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 -- | 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 -- | A backend which is a wrapper around SqlBackend. type IsSqlBackend backend = (IsPersistBackend backend, BaseBackend backend ~ SqlBackend) -- | Like SqlPersistT but compatible with any SQL backend which -- can handle read and write queries. type SqlWriteT (m :: Type -> Type) a = forall backend. SqlBackendCanWrite backend => ReaderT backend m a -- | Like SqlPersistT but compatible with any SQL backend which -- can handle read queries. type SqlReadT (m :: Type -> Type) a = forall backend. SqlBackendCanRead backend => ReaderT backend m a -- | 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) -- | 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) -- | An SQL backend which can handle read or write queries -- -- The constructor was exposed in 2.10.0 newtype SqlWriteBackend SqlWriteBackend :: SqlBackend -> SqlWriteBackend [$sel:unSqlWriteBackend:SqlWriteBackend] :: SqlWriteBackend -> SqlBackend -- | An SQL backend which can only handle read queries -- -- The constructor was exposed in 2.10.0. newtype SqlReadBackend SqlReadBackend :: SqlBackend -> SqlReadBackend [$sel:unSqlReadBackend:SqlReadBackend] :: SqlReadBackend -> SqlBackend -- | Useful for running a write query against an untagged backend with -- unknown capabilities. writeToUnknown :: forall (m :: Type -> Type) a. Monad m => ReaderT SqlWriteBackend m a -> ReaderT SqlBackend m a -- | Useful for running a read query against a backend with read and write -- capabilities. readToWrite :: forall (m :: Type -> Type) a. Monad m => ReaderT SqlReadBackend m a -> ReaderT SqlWriteBackend m a -- | Useful for running a read query against a backend with unknown -- capabilities. readToUnknown :: forall (m :: Type -> Type) a. Monad m => ReaderT SqlReadBackend m a -> ReaderT SqlBackend m a -- | 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 -- | Values to configure a pool of database connections. See -- Data.Pool for details. data ConnectionPoolConfig ConnectionPoolConfig :: Int -> NominalDiffTime -> Int -> ConnectionPoolConfig -- | How many stripes to divide the pool into. See Data.Pool for -- details. Default: 1. [connectionPoolConfigStripes] :: ConnectionPoolConfig -> Int -- | How long connections can remain idle before being disposed of, in -- seconds. Default: 600 [connectionPoolConfigIdleTimeout] :: ConnectionPoolConfig -> NominalDiffTime -- | How many connections should be held in the connection pool. Default: -- 10 [connectionPoolConfigSize] :: ConnectionPoolConfig -> Int type ConnectionPool = Pool SqlBackend type SqlPersistM = SqlPersistT NoLoggingT ResourceT IO type SqlPersistT = ReaderT SqlBackend data PersistentSqlException StatementAlreadyFinalized :: Text -> PersistentSqlException Couldn'tGetSQLConnection :: PersistentSqlException -- | This value specifies how a field references another table. data ColumnReference ColumnReference :: !EntityNameDB -> !ConstraintNameDB -> !FieldCascade -> ColumnReference -- | The table name that the [crTableName] :: ColumnReference -> !EntityNameDB -- | The name of the foreign key constraint. [crConstraintName] :: ColumnReference -> !ConstraintNameDB -- | Whether or not updates/deletions to the referenced table cascade to -- this table. [crFieldCascade] :: ColumnReference -> !FieldCascade data Column Column :: !FieldNameDB -> !Bool -> !SqlType -> !Maybe Text -> !Maybe Text -> !Maybe ConstraintNameDB -> !Maybe Integer -> !Maybe ColumnReference -> Column [cName] :: Column -> !FieldNameDB [cNull] :: Column -> !Bool [cSqlType] :: Column -> !SqlType [cDefault] :: Column -> !Maybe Text [cGenerated] :: Column -> !Maybe Text [cDefaultConstraintName] :: Column -> !Maybe ConstraintNameDB [cMaxLen] :: Column -> !Maybe Integer [cReference] :: Column -> !Maybe ColumnReference -- | Initializes a ConnectionPoolConfig with default values. See the -- documentation of ConnectionPoolConfig for each field's default -- value. defaultConnectionPoolConfig :: ConnectionPoolConfig -- | Record of functions to override the default behavior in -- mkColumns. It is recommended you initialize this with -- emptyBackendSpecificOverrides and override the default values, -- so that as new fields are added, your code still compiles. -- -- For added safety, use the getBackendSpecific* and -- setBackendSpecific* functions, as a breaking change to the -- record field labels won't be reflected in a major version bump of the -- library. data BackendSpecificOverrides -- | If the override is defined, then this returns a function that accepts -- an entity name and field name and provides the ConstraintNameDB -- for the foreign key constraint. -- -- An abstract accessor for the BackendSpecificOverrides getBackendSpecificForeignKeyName :: BackendSpecificOverrides -> Maybe (EntityNameDB -> FieldNameDB -> ConstraintNameDB) -- | Set the backend's foreign key generation function to this value. setBackendSpecificForeignKeyName :: (EntityNameDB -> FieldNameDB -> ConstraintNameDB) -> BackendSpecificOverrides -> BackendSpecificOverrides -- | Creates an empty BackendSpecificOverrides (i.e. use the default -- behavior; no overrides) emptyBackendSpecificOverrides :: BackendSpecificOverrides defaultAttribute :: [FieldAttr] -> Maybe Text -- | Create the list of columns for the given entity. mkColumns :: [EntityDef] -> EntityDef -> BackendSpecificOverrides -> ([Column], [UniqueDef], [ForeignDef]) -- | A more general way to convert instances of ToJSON type class to -- strict text Text. toJsonText :: ToJSON j => j -> Text -- | 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 = PersistLiteralEncoded . toASCIIBytes
--     fromPersistValue (PersistLiteralEncoded 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 PersistLiteralEncoded, 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 -- | 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 => (Text -> 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 -- | 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 = fmap (unPrefix @"p") $ rawSql query []
--     where
--       query = "SELECT ?? FROM person AS p"
--   
unPrefix :: forall (prefix :: Symbol) record. EntityWithPrefix prefix record -> Entity record rawQuery :: forall (m :: Type -> Type) env. (MonadResource m, MonadReader env m, BackendCompatible SqlBackend env) => Text -> [PersistValue] -> ConduitM () [PersistValue] m () rawQueryRes :: forall (m1 :: Type -> Type) (m2 :: Type -> Type) env. (MonadIO m1, MonadIO m2, BackendCompatible SqlBackend env) => Text -> [PersistValue] -> ReaderT env m1 (Acquire (ConduitM () [PersistValue] m2 ())) -- | Execute a raw SQL statement rawExecute :: forall (m :: Type -> Type) backend. (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 :: forall (m :: Type -> Type) backend. (MonadIO m, BackendCompatible SqlBackend backend) => Text -> [PersistValue] -> ReaderT backend m Int64 getStmtConn :: SqlBackend -> Text -> IO Statement -- | 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 :: forall a (m :: Type -> Type) backend. (RawSql a, MonadIO m, BackendCompatible SqlBackend backend) => Text -> [PersistValue] -> ReaderT backend m [a] -- | Get a connection from the pool, run the given action, and then return -- the connection to the pool. -- -- This function performs the given action in a transaction. If an -- exception occurs during the action, then the transaction is rolled -- back. -- -- 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 :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> m a -- | Like runSqlPool, but supports specifying an isolation level. runSqlPoolWithIsolation :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> IsolationLevel -> m a -- | Like runSqlPool, but does not surround the action in a -- transaction. This action might leave your database in a weird state. runSqlPoolNoTransaction :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> Maybe IsolationLevel -> m a -- | This function is how runSqlPool and -- runSqlPoolNoTransaction are defined. In addition to the action -- to be performed and the Pool of conections to use, we give you -- the opportunity to provide three actions - initialize, afterwards, and -- onException. runSqlPoolWithHooks :: forall backend m a before after onException. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> Maybe IsolationLevel -> (backend -> m before) -> (backend -> m after) -> (backend -> SomeException -> m onException) -> m a -- | This function is how runSqlPoolWithHooks is defined. -- -- It's currently the most general function for using a SQL pool. runSqlPoolWithExtensibleHooks :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> Maybe IsolationLevel -> SqlPoolHooks m backend -> 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 :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> backend -> m a -- | Like runSqlConn, but supports specifying an isolation level. runSqlConnWithIsolation :: forall backend m a. (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 :: forall backend m a. (MonadIO m, BackendCompatible SqlBackend backend) => ReaderT backend (NoLoggingT (ResourceT IO)) a -> Pool backend -> m a withSqlPool :: forall backend m a. (MonadLoggerIO m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> (Pool backend -> m a) -> m a -- | Creates a pool of connections to a SQL database which can be used by -- the Pool backend -> m a function. After the function -- completes, the connections are destroyed. withSqlPoolWithConfig :: forall backend m a. (MonadLoggerIO m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> ConnectionPoolConfig -> (Pool backend -> m a) -> m a createSqlPool :: forall backend m. (MonadLoggerIO m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> m (Pool backend) -- | Creates a pool of connections to a SQL database. createSqlPoolWithConfig :: (MonadLoggerIO m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> ConnectionPoolConfig -> m (Pool backend) -- | 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 :: forall backend m a. (MonadUnliftIO m, MonadLoggerIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> (backend -> m a) -> m a close' :: BackendCompatible SqlBackend backend => backend -> IO () withRawQuery :: forall (m :: Type -> Type) a. MonadIO m => Text -> [PersistValue] -> ConduitM [PersistValue] Void IO a -> ReaderT SqlBackend m a toSqlKey :: ToBackendKey SqlBackend record => Int64 -> Key record fromSqlKey :: ToBackendKey SqlBackend record => Key record -> Int64 -- | 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 :: Type -> Type) 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 -> EntityNameDB -- | 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 :: Type -> Type) backend. (PersistEntity record, PersistEntityBackend record ~ SqlBackend, BackendCompatible SqlBackend backend, Monad m) => EntityField record typ -> ReaderT backend m Text -- | useful for a backend to implement fieldName by adding escaping fieldDBName :: PersistEntity record => EntityField record typ -> FieldNameDB -- | Used when determining how to prefix a column name in a WHERE -- clause. data FilterTablePrefix -- | Prefix the column with the table name. This is useful if the column -- name might be ambiguous. PrefixTableName :: FilterTablePrefix -- | Prefix the column name with the EXCLUDED keyword. This is -- used with the Postgresql backend when doing ON CONFLICT DO -- UPDATE clauses - see the documentation on upsertWhere -- and upsertManyWhere. PrefixExcluded :: FilterTablePrefix -- | Render a [Filter record] into a Text value -- suitable for inclusion into a SQL query. filterClause :: PersistEntity val => Maybe FilterTablePrefix -> SqlBackend -> [Filter val] -> Text -- | Render a [Filter record] into a Text value -- suitable for inclusion into a SQL query, as well as the -- [PersistValue] to properly fill in the ? -- place holders. filterClauseWithVals :: PersistEntity val => Maybe FilterTablePrefix -> SqlBackend -> [Filter val] -> (Text, [PersistValue]) -- | Render a [SelectOpt record] made up *only* of -- Asc and Desc constructors into a Text value -- suitable for inclusion into a SQL query. orderClause :: PersistEntity val => Maybe FilterTablePrefix -> SqlBackend -> [SelectOpt val] -> Text -- | Generates sql for limit and offset for postgres, sqlite and mysql. decorateSQLWithLimitOffset :: Text -> (Int, Int) -> Text -> Text -- | An exception indicating that Persistent refused to run some unsafe -- migrations. Contains a list of pairs where the Bool tracks whether the -- migration was unsafe (True means unsafe), and the Sql is the sql -- statement for the migration. newtype PersistUnsafeMigrationException PersistUnsafeMigrationException :: [(Bool, Sql)] -> PersistUnsafeMigrationException -- | A Migration is a four level monad stack consisting of: -- -- type Migration = WriterT [Text] WriterT CautiousMigration ReaderT SqlBackend IO () -- | A list of SQL operations, marked with a safety flag. If the -- Bool is True, then the operation is *unsafe* - it might -- be destructive, or otherwise not idempotent. If the Bool is -- False, then the operation is *safe*, and can be run repeatedly -- without issues. type CautiousMigration = [(Bool, Sql)] type Sql = Text -- | 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 :: forall (m :: Type -> Type). (HasCallStack, 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' :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m CautiousMigration -- | Prints a migration. printMigration :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m () -- | Convert a Migration to a list of Text values -- corresponding to their Sql statements. showMigration :: forall (m :: Type -> Type). (HasCallStack, 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 :: forall (m :: Type -> Type). (MonadIO m, HasCallStack) => Migration -> ReaderT SqlBackend m [Sql] -- | Runs a migration. If the migration fails to parse or if any of the -- migrations are unsafe, then this throws a -- PersistUnsafeMigrationException. runMigration :: forall (m :: Type -> Type). 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 :: forall (m :: Type -> Type). 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 :: forall (m :: Type -> Type). MonadUnliftIO m => Migration -> ReaderT SqlBackend m [Text] -- | Like runMigration, but this will perform the unsafe database -- migrations instead of erroring out. runMigrationUnsafe :: forall (m :: Type -> Type). 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 :: forall (m :: Type -> Type). (HasCallStack, 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 a single error in a Migration. reportError :: Text -> Migration -- | Report multiple errors in a Migration. reportErrors :: [Text] -> Migration -- | Add a migration to the migration plan. addMigration :: Bool -> Sql -> Migration -- | Add a CautiousMigration (aka a [(Bool, -- Text)]) to the migration plan. addMigrations :: CautiousMigration -> Migration -- | Run an action against the database during a migration. Can be useful -- for eg creating Postgres extensions: -- --
--   runSqlCommand $ rawExecute "CREATE EXTENSION IF NOT EXISTS "uuid-ossp";" []
--   
runSqlCommand :: SqlPersistT IO () -> Migration -- | 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 :: forall (m :: Type -> Type). MonadIO m => ReaderT SqlBackend m () -- | Commit the current transaction and begin a new one with the specified -- isolation level. transactionSaveWithIsolation :: forall (m :: Type -> Type). 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 :: forall (m :: Type -> Type). MonadIO m => ReaderT SqlBackend m () -- | Roll back the current transaction and begin a new one with the -- specified isolation level. transactionUndoWithIsolation :: forall (m :: Type -> Type). MonadIO m => IsolationLevel -> ReaderT SqlBackend m () -- | Classy shim around Database.Esqueleto.Experimental -- -- In the style of Database.Persist.Monad, this exposes a -- "classy" (typeclass-using) API for Esqueleto functions, allowing them -- to be used with MonadSqlQuery constraints rather than a -- ReaderT SqlBackend concrete type. -- -- The goal of this module is to be a drop-in replacement for -- Database.Esqueleto.Experimental. module Database.Esqueleto.Monad.Experimental -- | Avoid N+1 queries and join entities into a map structure. -- -- This function is useful to call on the result of a single -- JOIN. For example, suppose you have this query: -- --
--   getFoosAndNestedBarsFromParent
--       :: ParentId
--       -> SqlPersistT IO [(Entity Foo, Maybe (Entity Bar))]
--   getFoosAndNestedBarsFromParent parentId =
--       select $ do
--           (foo :& bar) <- from $
--               table Foo
--               `LeftOuterJoin`
--               table Bar
--                   `on` do
--                       \(foo :& bar) ->
--                           foo ^. FooId ==. bar ?. BarFooId
--           where_ $
--               foo ^. FooParentId ==. val parentId
--           pure (foo, bar)
--   
-- -- This is a natural result type for SQL - a list of tuples. However, -- it's not what we usually want in Haskell - each Foo in the -- list will be represented multiple times, once for each Bar. -- -- We can write fmap associateJoin and it will -- translate it into a Map that is keyed on the Key of -- the left Entity, and the value is a tuple of the entity's value -- as well as the list of each coresponding entity. -- --
--   getFoosAndNestedBarsFromParentHaskellese
--       :: ParentId
--       -> SqlPersistT (Map (Key Foo) (Foo, [Maybe (Entity Bar)]))
--   getFoosAndNestedBarsFromParentHaskellese parentId =
--       fmap associateJoin $ getFoosdAndNestedBarsFromParent parentId
--   
-- -- What if you have multiple joins? -- -- Let's use associateJoin with a *two* join query. -- --
--   userPostComments
--       :: SqlQuery (SqlExpr (Entity User, Entity Post, Entity Comment))
--   userPostsComment = do
--       (u :& p :& c) <- from $
--           table User
--           `InnerJoin`
--           table Post
--               on do
--                   \(u :& p) ->
--                       u ^. UserId ==. p ^. PostUserId
--           `InnerJoin`
--           table @Comment
--               `on` do
--                   \(_ :& p :& c) ->
--                       p ^. PostId ==. c ^. CommentPostId
--       pure (u, p, c)
--   
-- -- This query returns a User, with all of the users Posts, and then all -- of the Comments on that post. -- -- First, we *nest* the tuple. -- --
--   nest :: (a, b, c) -> (a, (b, c))
--   nest (a, b, c) = (a, (b, c))
--   
-- -- This makes the return of the query conform to the input expected from -- associateJoin. -- --
--   nestedUserPostComments
--       :: SqlPersistT IO [(Entity User, (Entity Post, Entity Comment))]
--   nestedUserPostComments =
--       fmap nest $ select userPostsComments
--   
-- -- Now, we can call associateJoin on it. -- --
--   associateUsers
--       :: [(Entity User, (Entity Post, Entity Comment))]
--       -> Map UserId (User, [(Entity Post, Entity Comment)])
--   associateUsers =
--       associateJoin
--   
-- -- Next, we'll use the Functor instances for Map and -- tuple to call associateJoin on the [(Entity Post, Entity -- Comment)]. -- --
--   associatePostsAndComments
--       :: Map UserId (User, [(Entity Post, Entity Comment)])
--       -> Map UserId (User, Map PostId (Post, [Entity Comment]))
--   associatePostsAndComments =
--       fmap (fmap associateJoin)
--   
-- -- For more reading on this topic, see this Foxhound Systems blog -- post. associateJoin :: forall e1 e0. Ord (Key e0) => [(Entity e0, e1)] -> Map (Key e0) (e0, [e1]) -- | Synonym for delete that does not clash with -- esqueleto's delete. deleteKey :: forall backend val (m :: Type -> Type). (PersistStore backend, BaseBackend backend ~ PersistEntityBackend val, MonadIO m, PersistEntity val) => Key val -> ReaderT backend m () -- | valJ is like val but for something that is already a -- Value. The use case it was written for was, given a -- Value lift the Key for that Value into the -- query expression in a type safe way. However, the implementation is -- more generic than that so we call it valJ. -- -- Its important to note that the input entity and the output entity are -- constrained to be the same by the type signature on the function -- (https://github.com/prowdsponsor/esqueleto/pull/69). valJ :: PersistField (Key entity) => Value (Key entity) -> SqlExpr (Value (Key entity)) -- | valkey i = val . toSqlKey -- (https://github.com/prowdsponsor/esqueleto/issues/9). valkey :: (ToBackendKey SqlBackend entity, PersistField (Key entity)) => Int64 -> SqlExpr (Value (Key entity)) -- | Insert a PersistField for every selected value, return the -- count afterward insertSelectCount :: forall (m :: Type -> Type) a backend. (MonadIO m, PersistEntity a, SqlBackendCanWrite backend) => SqlQuery (SqlExpr (Insertion a)) -> ReaderT backend m Int64 -- | Insert a PersistField for every selected value. insertSelect :: forall (m :: Type -> Type) a backend. (MonadIO m, PersistEntity a, SqlBackendCanWrite backend) => SqlQuery (SqlExpr (Insertion a)) -> ReaderT backend m () -- | Renders a SqlQuery into a Text value along with the -- list of PersistValues that would be supplied to the database -- for ? placeholders. renderQueryInsertInto :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m) => SqlQuery a -> ReaderT backend m (Text, [PersistValue]) -- | Renders a SqlQuery into a Text value along with the -- list of PersistValues that would be supplied to the database -- for ? placeholders. renderQueryUpdate :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m) => SqlQuery a -> ReaderT backend m (Text, [PersistValue]) -- | Renders a SqlQuery into a Text value along with the -- list of PersistValues that would be supplied to the database -- for ? placeholders. renderQueryDelete :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m) => SqlQuery a -> ReaderT backend m (Text, [PersistValue]) -- | Renders a SqlQuery into a Text value along with the -- list of PersistValues that would be supplied to the database -- for ? placeholders. -- -- You must ensure that the Mode you pass to this function -- corresponds with the actual SqlQuery. If you pass a query that -- uses incompatible features (like an INSERT statement with a -- SELECT mode) then you'll get a weird result. renderQueryToText :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m) => Mode -> SqlQuery a -> ReaderT backend m (Text, [PersistValue]) -- | Same as update, but returns the number of rows affected. updateCount :: forall (m :: Type -> Type) val backend. (MonadIO m, PersistEntity val, BackendCompatible SqlBackend (PersistEntityBackend val), SqlBackendCanWrite backend) => (SqlExpr (Entity val) -> SqlQuery ()) -> ReaderT backend m Int64 -- | Same as delete, but returns the number of rows affected. deleteCount :: forall (m :: Type -> Type) backend. (MonadIO m, SqlBackendCanWrite backend) => SqlQuery () -> ReaderT backend m Int64 -- | Execute an esqueleto SELECT query inside -- persistent's SqlPersistT monad and return a -- Source of rows. selectSource :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, IsPersistBackend backend, PersistQueryRead backend, PersistStoreRead backend, PersistUniqueRead backend, MonadResource m) => SqlQuery a -> ConduitT () r (ReaderT backend m) () -- | Syntax sugar for case_. else_ :: expr a -> expr a -- | Syntax sugar for case_. then_ :: () -- | Syntax sugar for case_. when_ :: expr (Value Bool) -> () -> expr a -> (expr (Value Bool), expr a) -- | Convert an entity's key into another entity's. -- -- This function is to be used when you change an entity's Id to -- be that of another entity. For example: -- --
--   Bar
--     barNum Int
--   Foo
--     bar BarId
--     fooNum Int
--     Primary bar
--   
-- -- In this example, Bar is said to be the BaseEnt(ity), and Foo the -- child. To model this in Esqueleto, declare: -- --
--   instance ToBaseId Foo where
--     type BaseEnt Foo = Bar
--     toBaseIdWitness barId = FooKey barId
--   
-- -- Now you're able to write queries such as: -- --
--   select $
--   from $ (bar `InnerJoin` foo) -> do
--   on (toBaseId (foo ^. FooId) ==. bar ^. BarId)
--   return (bar, foo)
--   
-- -- Note: this function may be unsafe to use in conditions not like the -- one of the example above. toBaseId :: ToBaseId ent => SqlExpr (Value (Key ent)) -> SqlExpr (Value (Key (BaseEnt ent))) -- | CASE statement. For example: -- --
--   select $
--   return $
--   case_
--      [ when_
--          (exists $
--          from $ \p -> do
--          where_ (p ^. PersonName ==. val "Mike"))
--        then_
--          (sub_select $
--          from $ \v -> do
--          let sub =
--                  from $ \c -> do
--                  where_ (c ^. PersonName ==. val "Mike")
--                  return (c ^. PersonFavNum)
--          where_ (v ^. PersonFavNum >. sub_select sub)
--          return $ count (v ^. PersonName) +. val (1 :: Int)) ]
--      (else_ $ val (-1))
--   
-- -- This query is a bit complicated, but basically it checks if a person -- named "Mike" exists, and if that person does, run the -- subquery to find out how many people have a ranking (by Fav Num) -- higher than "Mike". -- -- NOTE: There are a few things to be aware about this statement. -- -- case_ :: PersistField a => [(SqlExpr (Value Bool), SqlExpr (Value a))] -> SqlExpr (Value a) -> SqlExpr (Value a) -- | Apply extra SqlExpr Value arguments to a PersistField -- constructor (<&>) :: SqlExpr (Insertion (a -> b)) -> SqlExpr (Value a) -> SqlExpr (Insertion b) -- | Apply a PersistField constructor to SqlExpr Value -- arguments. (<#) :: (a -> b) -> SqlExpr (Value a) -> SqlExpr (Insertion b) (/=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 /=. (*=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 *=. (-=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 -=. (+=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 +=. (=.) :: (PersistEntity val, PersistField typ) => EntityField val typ -> SqlExpr (Value typ) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 =. -- | SET clause used on UPDATEs. Note that while it's not -- a type error to use this function on a SELECT, it will most -- certainly result in a runtime error. set :: PersistEntity val => SqlExpr (Entity val) -> [SqlExpr (Entity val) -> SqlExpr Update] -> SqlQuery () -- | NOT EXISTS operator. notExists :: SqlQuery () -> SqlExpr (Value Bool) -- | EXISTS operator. For example: -- --
--   select $
--   from $ \person -> do
--   where_ $ exists $
--            from $ \post -> do
--            where_ (post ^. BlogPostAuthorId ==. person ^. PersonId)
--   return person
--   
exists :: SqlQuery () -> SqlExpr (Value Bool) -- | NOT IN operator. notIn :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (ValueList typ) -> SqlExpr (Value Bool) -- | IN operator. For example if you want to select all -- Persons by a list of IDs: -- --
--   SELECT *
--   FROM Person
--   WHERE Person.id IN (?)
--   
-- -- In esqueleto, we may write the same query above as: -- --
--   select $
--   from $ \person -> do
--   where_ $ person ^. PersonId `in_` valList personIds
--   return person
--   
-- -- Where personIds is of type [Key Person]. in_ :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (ValueList typ) -> SqlExpr (Value Bool) -- | Same as just but for ValueList. Most of the time you -- won't need it, though, because you can use just from inside -- subList_select or Just from inside valList. justList :: SqlExpr (ValueList typ) -> SqlExpr (ValueList (Maybe typ)) -- | Lift a list of constant value from Haskell-land to the query. valList :: PersistField typ => [typ] -> SqlExpr (ValueList typ) -- | Execute a subquery SELECT in an SqlExpression. Returns a list -- of values. subList_select :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (ValueList a) -- | Cast a string type into Text. This function is very useful if -- you want to use newtypes, or if you want to apply functions -- such as like to strings of different types. -- -- Safety: This is a slightly unsafe function, especially if you -- have defined your own instances of SqlString. Also, since -- Maybe is an instance of SqlString, it's possible to turn -- a nullable value into a non-nullable one. Avoid using this function if -- possible. castString :: (SqlString s, SqlString r) => SqlExpr (Value s) -> SqlExpr (Value r) -- | The || string concatenation operator (named after Haskell's -- ++ in order to avoid naming clash with ||.). Supported -- by SQLite and PostgreSQL. (++.) :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value s) infixr 5 ++. -- | The CONCAT function with a variable number of parameters. -- Supported by MySQL and PostgreSQL. concat_ :: SqlString s => [SqlExpr (Value s)] -> SqlExpr (Value s) -- | The string %. May be useful while using like -- and concatenation (concat_ or ++., depending on your -- database). Note that you always have to type the parenthesis, for -- example: -- --
--   name `like` (%) ++. val "John" ++. (%)
--   
(%) :: SqlString s => SqlExpr (Value s) -- | ILIKE operator (case-insensitive LIKE). -- -- Supported by PostgreSQL only. ilike :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool) infixr 2 `ilike` -- | LIKE operator. like :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool) infixr 2 `like` -- | RIGHT function. @since 3.3.0 right_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s) -- | LEFT function. @since 3.3.0 left_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s) -- | LENGTH function. @since 3.3.0 length_ :: (SqlString s, Num a) => SqlExpr (Value s) -> SqlExpr (Value a) -- | LTRIM function. @since 3.3.0 ltrim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | RTRIM function. @since 3.3.0 rtrim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | TRIM function. @since 3.3.0 trim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | UPPER function. @since 3.3.0 upper_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | LOWER function. lower_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | Like coalesce, but takes a non-nullable SqlExpression placed -- at the end of the SqlExpression list, which guarantees a non-NULL -- result. coalesceDefault :: PersistField a => [SqlExpr (Value (Maybe a))] -> SqlExpr (Value a) -> SqlExpr (Value a) -- | COALESCE function. Evaluates the arguments in order and -- returns the value of the first non-NULL SqlExpression, or NULL -- (Nothing) otherwise. Some RDBMSs (such as SQLite) require at least two -- arguments; please refer to the appropriate documentation. coalesce :: PersistField a => [SqlExpr (Value (Maybe a))] -> SqlExpr (Value (Maybe a)) -- | Same as castNum, but for nullable values. castNumM :: (Num a, Num b) => SqlExpr (Value (Maybe a)) -> SqlExpr (Value (Maybe b)) -- | Allow a number of one type to be used as one of another type via an -- implicit cast. An explicit cast is not made, this function changes -- only the types on the Haskell side. -- -- Caveat: Trying to use castNum from Double to -- Int will not result in an integer, the original fractional -- number will still be used! Use round_, ceiling_ or -- floor_ instead. -- -- Safety: This operation is mostly safe due to the Num -- constraint between the types and the fact that RDBMSs usually allow -- numbers of different types to be used interchangeably. However, there -- may still be issues with the query not being accepted by the RDBMS or -- persistent not being able to parse it. castNum :: (Num a, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) avg_ :: (PersistField a, PersistField b) => SqlExpr (Value a) -> SqlExpr (Value (Maybe b)) max_ :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value (Maybe a)) min_ :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value (Maybe a)) sum_ :: (PersistField a, PersistField b) => SqlExpr (Value a) -> SqlExpr (Value (Maybe b)) floor_ :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) ceiling_ :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) round_ :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) random_ :: (PersistField a, Num a) => SqlExpr (Value a) -- | BETWEEN. -- -- @since: 3.1.0 between :: PersistField a => SqlExpr (Value a) -> (SqlExpr (Value a), SqlExpr (Value a)) -> SqlExpr (Value Bool) (*.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 7 *. (/.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 7 /. (-.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 6 -. (+.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 6 +. (||.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool) infixr 2 ||. (&&.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool) infixr 3 &&. (!=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 !=. (<.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 <. (<=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 <=. (>.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 >. (>=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 >=. (==.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 ==. not_ :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -- | COUNT(DISTINCT x). countDistinct :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a) -- | COUNT. count :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a) -- | COUNT(*) value. countRows :: Num a => SqlExpr (Value a) -- | Join nested Maybes in a Value into one. This is useful -- when calling aggregate functions on nullable fields. joinV :: SqlExpr (Value (Maybe (Maybe typ))) -> SqlExpr (Value (Maybe typ)) -- | NULL value. nothing :: SqlExpr (Value (Maybe typ)) -- | Analogous to Just, promotes a value of type typ into -- one of type Maybe typ. It should hold that val . -- Just === just . val. just :: SqlExpr (Value typ) -> SqlExpr (Value (Maybe typ)) -- | IS NULL comparison. -- -- For IS NOT NULL, you can negate this with not_, as in -- not_ (isNothing (person ^. PersonAge)) -- -- Warning: Persistent and Esqueleto have different behavior for != -- Nothing: -- -- TODO: table -- -- In SQL, = NULL and != NULL return NULL instead of -- true or false. For this reason, you very likely do not want to use -- !=. Nothing in Esqueleto. You may find these -- hlint rules helpful to enforce this: -- --
--   - error: {lhs: v Database.Esqueleto.==. Database.Esqueleto.nothing, rhs: Database.Esqueleto.isNothing v, name: Use Esqueleto's isNothing}
--   - error: {lhs: v Database.Esqueleto.==. Database.Esqueleto.val Nothing, rhs: Database.Esqueleto.isNothing v, name: Use Esqueleto's isNothing}
--   - error: {lhs: v Database.Esqueleto.!=. Database.Esqueleto.nothing, rhs: not_ (Database.Esqueleto.isNothing v), name: Use Esqueleto's not isNothing}
--   - error: {lhs: v Database.Esqueleto.!=. Database.Esqueleto.val Nothing, rhs: not_ (Database.Esqueleto.isNothing v), name: Use Esqueleto's not isNothing}
--   
isNothing :: PersistField typ => SqlExpr (Value (Maybe typ)) -> SqlExpr (Value Bool) -- | Lift a constant value from Haskell-land to the query. val :: PersistField typ => typ -> SqlExpr (Value typ) -- | Project a field of an entity that may be null. (?.) :: (PersistEntity val, PersistField typ) => SqlExpr (Maybe (Entity val)) -> EntityField val typ -> SqlExpr (Value (Maybe typ)) -- | Project an SqlExpression that may be null, guarding against null -- cases. withNonNull :: PersistField typ => SqlExpr (Value (Maybe typ)) -> (SqlExpr (Value typ) -> SqlQuery a) -> SqlQuery a -- | Project a field of an entity. (^.) :: forall typ val. (PersistEntity val, PersistField typ) => SqlExpr (Entity val) -> EntityField val typ -> SqlExpr (Value typ) infixl 9 ^. -- | Execute a subquery SELECT in a SqlExpr. This function -- is unsafe, because it can throw runtime exceptions in two cases: -- --
    --
  1. If the query passed has 0 result rows, then it will return a -- NULL value. The persistent parsing operations will -- fail on an unexpected NULL.
  2. --
  3. If the query passed returns more than one row, then the SQL engine -- will fail with an error like "More than one row returned by a subquery -- used as an expression".
  4. --
-- -- This function is safe if you guarantee that exactly one row will be -- returned, or if the result already has a Maybe type for some -- reason. -- -- For variants with the safety encoded already, see subSelect and -- subSelectMaybe. For the most common safe use of this, see -- subSelectCount. subSelectUnsafe :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value a) -- | Performs a sub-select using the given foreign key on the entity. This -- is useful to extract values that are known to be present by the -- database schema. -- -- As an example, consider the following persistent definition: -- --
--   User
--     profile ProfileId
--   
--   Profile
--     name    Text
--   
-- -- The following query will return the name of the user. -- --
--   getUserWithName =
--       select $
--       from $ user ->
--       pure (user, subSelectForeign user UserProfile (^. ProfileName)
--   
subSelectForeign :: (BackendCompatible SqlBackend (PersistEntityBackend val1), PersistEntity val1, PersistEntity val2, PersistField a) => SqlExpr (Entity val2) -> EntityField val2 (Key val1) -> (SqlExpr (Entity val1) -> SqlExpr (Value a)) -> SqlExpr (Value a) -- | Execute a subquery SELECT in a SqlExpr that returns a -- list. This is an alias for subList_select and is provided for -- symmetry with the other safe subselect functions. subSelectList :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (ValueList a) -- | Performs a COUNT of the given query in a subSelect -- manner. This is always guaranteed to return a result value, and is -- completely safe. subSelectCount :: (Num a, PersistField a) => SqlQuery ignored -> SqlExpr (Value a) -- | Execute a subquery SELECT in a SqlExpr. This function -- is a shorthand for the common joinV . subSelect -- idiom, where you are calling subSelect on an expression that -- would be Maybe already. -- -- As an example, you would use this function when calling sum_ or -- max_, which have Maybe in the result type (for a 0 row -- query). subSelectMaybe :: PersistField a => SqlQuery (SqlExpr (Value (Maybe a))) -> SqlExpr (Value (Maybe a)) -- | Execute a subquery SELECT in a SqlExpr. The query -- passed to this function will only return a single result - it has a -- LIMIT 1 passed in to the query to make it safe, and the -- return type is Maybe to indicate that the subquery might result -- in 0 rows. -- -- If you find yourself writing joinV . subSelect, -- then consider using subSelectMaybe. -- -- If you're performing a countRows, then you can use -- subSelectCount which is safe. -- -- If you know that the subquery will always return exactly one row (eg a -- foreign key constraint guarantees that you'll get exactly one row), -- then consider subSelectUnsafe, along with a comment explaining -- why it is safe. subSelect :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value (Maybe a)) -- | Execute a subquery SELECT in an SqlExpression. Returns a -- simple value so should be used only when the SELECT query is -- guaranteed to return just one row. -- -- Deprecated in 3.2.0. sub_select :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value a) -- | Add a locking clause to the query. Please read LockingKind -- documentation and your RDBMS manual. -- -- If multiple calls to locking are made on the same query, the -- last one is used. locking :: LockingKind -> SqlQuery () -- | HAVING. having :: SqlExpr (Value Bool) -> SqlQuery () -- | ORDER BY random() clause. rand :: SqlExpr OrderBy -- | A convenience function that calls both distinctOn and -- orderBy. In other words, -- --
--   distinctOnOrderBy [asc foo, desc bar, desc quux] $ do
--     ...
--   
-- -- is the same as: -- --
--   distinctOn [don foo, don  bar, don  quux] $ do
--     orderBy  [asc foo, desc bar, desc quux]
--     ...
--   
distinctOnOrderBy :: [SqlExpr OrderBy] -> SqlQuery a -> SqlQuery a -- | Erase an SqlExpression's type so that it's suitable to be used by -- distinctOn. don :: SqlExpr (Value a) -> SqlExpr DistinctOn -- | DISTINCT ON. Change the current SELECT into -- SELECT DISTINCT ON (SqlExpressions). For example: -- --
--   select $
--     from \foo ->
--     distinctOn [don (foo ^. FooName), don (foo ^. FooState)] $ do
--     ...
--   
-- -- You can also chain different calls to distinctOn. The above is -- equivalent to: -- --
--   select $
--     from \foo ->
--     distinctOn [don (foo ^. FooName)] $
--     distinctOn [don (foo ^. FooState)] $ do
--     ...
--   
-- -- Each call to distinctOn adds more SqlExpressions. Calls to -- distinctOn override any calls to distinct. -- -- Note that PostgreSQL requires the SqlExpressions on DISTINCT -- ON to be the first ones to appear on a ORDER BY. This is -- not managed automatically by esqueleto, keeping its spirit of trying -- to be close to raw SQL. -- -- Supported by PostgreSQL only. distinctOn :: [SqlExpr DistinctOn] -> SqlQuery a -> SqlQuery a -- | DISTINCT. Change the current SELECT into SELECT -- DISTINCT. For example: -- --
--   select $ distinct $
--     from \foo -> do
--     ...
--   
-- -- Note that this also has the same effect: -- --
--   select $
--     from \foo -> do
--     distinct (return ())
--     ...
--   
distinct :: SqlQuery a -> SqlQuery a -- | OFFSET. Usually used with limit. offset :: Int64 -> SqlQuery () -- | LIMIT. Limit the number of returned rows. limit :: Int64 -> SqlQuery () -- | Descending order of this field or SqlExpression. desc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy -- | Ascending order of this field or SqlExpression. asc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy -- | ORDER BY clause. See also asc and desc. -- -- Multiple calls to orderBy get concatenated on the final query, -- including distinctOnOrderBy. orderBy :: [SqlExpr OrderBy] -> SqlQuery () -- | GROUP BY clause. You can enclose multiple columns in a tuple. -- --
--   select $ from \(foo `InnerJoin` bar) -> do
--     on (foo ^. FooBarId ==. bar ^. BarId)
--     groupBy (bar ^. BarId, bar ^. BarName)
--     return (bar ^. BarId, bar ^. BarName, countRows)
--   
-- -- With groupBy you can sort by aggregate functions, like so (we used -- let to restrict the more general countRows to -- SqlSqlExpr (Value Int) to avoid ambiguity---the second use of -- countRows has its type restricted by the :: Int -- below): -- --
--   r <- select $ from \(foo `InnerJoin` bar) -> do
--     on (foo ^. FooBarId ==. bar ^. BarId)
--     groupBy $ bar ^. BarName
--     let countRows' = countRows
--     orderBy [asc countRows']
--     return (bar ^. BarName, countRows')
--   forM_ r $ \(Value name, Value count) -> do
--     print name
--     print (count :: Int)
--   
-- --

Need more columns?

-- -- The ToSomeValues class is defined for SqlExpr and tuples -- of SqlExprs. We only have definitions for up to 8 elements in a -- tuple right now, so it's possible that you may need to have more than -- 8 elements. -- -- For example, consider a query with a groupBy call like this: -- --
--   groupBy (e0, e1, e2, e3, e4, e5, e6, e7)
--   
-- -- This is the biggest you can get with a single tuple. However, you can -- easily nest the tuples to add more: -- --
--   groupBy ((e0, e1, e2, e3, e4, e5, e6, e7), e8, e9)
--   
groupBy :: ToSomeValues a => a -> SqlQuery () -- | WHERE clause: restrict the query's result. where_ :: SqlExpr (Value Bool) -> SqlQuery () -- | A single value (as opposed to a whole entity). You may use -- (^.) or (?.) to get a Value -- from an Entity. newtype Value a Value :: a -> Value a [unValue] :: Value a -> a -- | A list of single values. There's a limited set of functions able to -- work with this data type (such as subList_select, -- valList, in_ and exists). newtype ValueList a ValueList :: a -> ValueList a -- | Data type that represents an INNER JOIN (see -- LeftOuterJoin for an example). data InnerJoin a b InnerJoin :: a -> b -> InnerJoin a b infixl 2 `InnerJoin` infixl 2 `InnerJoin` -- | Data type that represents a CROSS JOIN (see -- LeftOuterJoin for an example). data CrossJoin a b CrossJoin :: a -> b -> CrossJoin a b infixl 2 `CrossJoin` infixl 2 `CrossJoin` -- | Data type that represents a LEFT OUTER JOIN. For example, -- --
--   select $
--   from $ \(person `LeftOuterJoin` pet) ->
--     ...
--   
-- -- is translated into -- --
--   SELECT ...
--   FROM Person LEFT OUTER JOIN Pet
--   ...
--   
-- -- See also: from. data LeftOuterJoin a b LeftOuterJoin :: a -> b -> LeftOuterJoin a b infixl 2 `LeftOuterJoin` infixl 2 `LeftOuterJoin` -- | Data type that represents a RIGHT OUTER JOIN (see -- LeftOuterJoin for an example). data RightOuterJoin a b RightOuterJoin :: a -> b -> RightOuterJoin a b infixl 2 `RightOuterJoin` infixl 2 `RightOuterJoin` -- | Data type that represents a FULL OUTER JOIN (see -- LeftOuterJoin for an example). data FullOuterJoin a b FullOuterJoin :: a -> b -> FullOuterJoin a b infixl 2 `FullOuterJoin` infixl 2 `FullOuterJoin` -- | (Internal) A kind of JOIN. data JoinKind -- |
--   INNER JOIN
--   
InnerJoinKind :: JoinKind -- |
--   CROSS JOIN
--   
CrossJoinKind :: JoinKind -- |
--   LEFT OUTER JOIN
--   
LeftOuterJoinKind :: JoinKind -- |
--   RIGHT OUTER JOIN
--   
RightOuterJoinKind :: JoinKind -- |
--   FULL OUTER JOIN
--   
FullOuterJoinKind :: JoinKind -- | Exception thrown whenever on is used to create an ON -- clause but no matching JOIN is found. data OnClauseWithoutMatchingJoinException OnClauseWithoutMatchingJoinException :: String -> OnClauseWithoutMatchingJoinException -- | Phantom type used by orderBy, asc and desc. data OrderBy -- | Phantom type used by distinctOn and don. data DistinctOn -- | Different kinds of locking clauses supported by locking. -- -- Note that each RDBMS has different locking support. The constructors -- of this datatype specify only the syntax of the locking -- mechanism, not its semantics. For example, even though both -- MySQL and PostgreSQL support ForUpdate, there are no guarantees -- that they will behave the same. data LockingKind -- | FOR UPDATE syntax. Supported by MySQL, Oracle and PostgreSQL. ForUpdate :: LockingKind -- | FOR UPDATE SKIP LOCKED syntax. Supported by MySQL, Oracle and -- PostgreSQL. ForUpdateSkipLocked :: LockingKind -- | FOR SHARE syntax. Supported by PostgreSQL. ForShare :: LockingKind -- | LOCK IN SHARE MODE syntax. Supported by MySQL. LockInShareMode :: LockingKind -- | Phantom class of data types that are treated as strings by the RDBMS. -- It has no methods because it's only used to avoid type errors such as -- trying to concatenate integers. -- -- If you have a custom data type or newtype, feel free to make -- it an instance of this class. class PersistField a => SqlString a -- | e.g. type BaseEnt MyBase = MyChild type family BaseEnt ent -- | Class that enables one to use toBaseId to convert an entity's -- key on a query into another (cf. toBaseId). class ToBaseId ent where { -- | e.g. type BaseEnt MyBase = MyChild type family BaseEnt ent; } -- | Convert from the key of the BaseEnt(ity) to the key of the child -- entity. This function is not actually called, but that it typechecks -- proves this operation is safe. toBaseIdWitness :: ToBaseId ent => Key (BaseEnt ent) -> Key ent -- | SQL backend for esqueleto using SqlPersistT. data SqlQuery a -- | Constraint synonym for persistent entities whose backend is -- SqlBackend. type SqlEntity ent = (PersistEntity ent, PersistEntityBackend ent ~ SqlBackend) -- | An expression on the SQL backend. -- -- Raw expression: Contains a SqlExprMeta and a function for -- building the expr. It recieves a parameter telling it whether it is in -- a parenthesized context, and takes information about the SQL -- connection (mainly for escaping names) and returns both an string -- (Builder) and a list of values to be interpolated by the SQL -- backend. data SqlExpr 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 -> Type -> Type -> Type; 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 type family PersistConfigBackend c :: Type -> Type -> Type -> Type type family PersistConfigPool c -- | An ConstraintNameHS represents the Haskell-side name that -- persistent will use for a constraint. newtype ConstraintNameHS ConstraintNameHS :: Text -> ConstraintNameHS [unConstraintNameHS] :: ConstraintNameHS -> Text -- | A ConstraintNameDB represents the datastore-side name that -- persistent will use for a constraint. newtype ConstraintNameDB ConstraintNameDB :: Text -> ConstraintNameDB [unConstraintNameDB] :: ConstraintNameDB -> Text -- | An EntityNameDB represents the datastore-side name that -- persistent will use for an entity. newtype EntityNameDB EntityNameDB :: Text -> EntityNameDB [unEntityNameDB] :: EntityNameDB -> Text -- | An EntityNameHS represents the Haskell-side name that -- persistent will use for an entity. newtype EntityNameHS EntityNameHS :: Text -> EntityNameHS [unEntityNameHS] :: EntityNameHS -> Text -- | A FieldNameHS represents the Haskell-side name that -- persistent will use for a field. newtype FieldNameHS FieldNameHS :: Text -> FieldNameHS [unFieldNameHS] :: FieldNameHS -> Text -- | An EntityNameDB represents the datastore-side name that -- persistent will use for an entity. newtype FieldNameDB FieldNameDB :: Text -> FieldNameDB [unFieldNameDB] :: FieldNameDB -> Text -- | Convenience operations for working with '-NameDB' types. class DatabaseName a escapeWith :: DatabaseName a => (Text -> str) -> a -> str -- | A type that determines how a backend should handle the literal. data LiteralType -- | The accompanying value will be escaped before inserting into the -- database. This is the correct default choice to use. Escaped :: LiteralType -- | The accompanying value will not be escaped when inserting into the -- database. This is potentially dangerous - use this with care. Unescaped :: LiteralType -- | The DbSpecific constructor corresponds to the legacy -- PersistDbSpecific constructor. We need to keep this around -- because old databases may have serialized JSON representations that -- reference this. We don't want to break the ability of a database to -- load rows. DbSpecific :: LiteralType -- | 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 -- | This constructor is used to specify some raw literal value for the -- backend. The LiteralType value specifies how the value should -- be escaped. This can be used to make special, custom types avaialable -- in the back end. PersistLiteral_ :: LiteralType -> ByteString -> PersistValue -- | This pattern synonym used to be a data constructor on -- PersistValue, but was changed into a catch-all pattern synonym -- to allow backwards compatiblity with database types. See the -- documentation on PersistDbSpecific for more details. pattern PersistLiteral :: ByteString -> PersistValue -- | This pattern synonym used to be a data constructor for the -- PersistValue type. It was changed to be a pattern so that -- JSON-encoded database values could be parsed into their corresponding -- values. You should not use this, and instead prefer to pattern match -- on PersistLiteral_ directly. -- -- If you use this, it will overlap a patern match on the -- 'PersistLiteral_, PersistLiteral, and -- PersistLiteralEscaped patterns. If you need to disambiguate -- between these constructors, pattern match on PersistLiteral_ -- directly. pattern PersistDbSpecific :: ByteString -> PersistValue -- | This pattern synonym used to be a data constructor on -- PersistValue, but was changed into a catch-all pattern synonym -- to allow backwards compatiblity with database types. See the -- documentation on PersistDbSpecific for more details. pattern PersistLiteralEscaped :: ByteString -> PersistValue fromPersistValueText :: PersistValue -> Either Text Text -- | 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 -- | 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 :: !FieldNameHS -> !FieldNameDB -> !FieldType -> !SqlType -> ![FieldAttr] -> !Bool -> !ReferenceDef -> !FieldCascade -> !Maybe Text -> !Maybe Text -> !Bool -> 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 FieldNameHS "name" for -- a type User will have a record field userName. [fieldHaskell] :: FieldDef -> !FieldNameHS -- | The name of the field in the database. For SQL databases, this -- corresponds to the column name. [fieldDB] :: FieldDef -> !FieldNameDB -- | 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 -> ![FieldAttr] -- | 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 -- | Defines how operations on the field cascade on to the referenced -- tables. This doesn't have any meaning if the fieldReference is -- set to NoReference or SelfReference. The cascade option -- here should be the same as the one obtained in the -- fieldReference. [fieldCascade] :: FieldDef -> !FieldCascade -- | Optional comments for a Field. There is not currently a way -- to attach comments to a field in the quasiquoter. [fieldComments] :: FieldDef -> !Maybe Text -- | Whether or not the field is a GENERATED column, and -- additionally the expression to use for generation. [fieldGenerated] :: FieldDef -> !Maybe Text -- | True if the field is an implicit ID column. False -- otherwise. [fieldIsImplicitIdColumn] :: FieldDef -> !Bool data PersistUpdate Assign :: PersistUpdate Add :: PersistUpdate Subtract :: PersistUpdate Multiply :: PersistUpdate Divide :: PersistUpdate BackendSpecificUpdate :: Text -> PersistUpdate data UpdateException KeyNotFound :: String -> UpdateException UpsertError :: String -> UpdateException data PersistFilter Eq :: PersistFilter Ne :: PersistFilter Gt :: PersistFilter Lt :: PersistFilter Ge :: PersistFilter Le :: PersistFilter In :: PersistFilter NotIn :: PersistFilter -- | 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 PersistException -- | Generic Exception PersistError :: Text -> PersistException PersistMarshalError :: Text -> PersistException PersistInvalidField :: Text -> PersistException PersistForeignConstraintUnmet :: Text -> PersistException PersistMongoDBError :: Text -> PersistException PersistMongoDBUnsupported :: Text -> PersistException -- | An action that might happen on a deletion or update on a foreign key -- change. data CascadeAction Cascade :: CascadeAction Restrict :: CascadeAction SetNull :: CascadeAction SetDefault :: CascadeAction -- | This datatype describes how a foreign reference field cascades deletes -- or updates. -- -- This type is used in both parsing the model definitions and performing -- migrations. A Nothing in either of the field values means that -- the user has not specified a CascadeAction. An unspecified -- CascadeAction is defaulted to Restrict when doing -- migrations. data FieldCascade FieldCascade :: !Maybe CascadeAction -> !Maybe CascadeAction -> FieldCascade [fcOnUpdate] :: FieldCascade -> !Maybe CascadeAction [fcOnDelete] :: FieldCascade -> !Maybe CascadeAction data ForeignDef ForeignDef :: !EntityNameHS -> !EntityNameDB -> !ConstraintNameHS -> !ConstraintNameDB -> !FieldCascade -> ![(ForeignFieldDef, ForeignFieldDef)] -> ![Attr] -> Bool -> Bool -> ForeignDef [foreignRefTableHaskell] :: ForeignDef -> !EntityNameHS [foreignRefTableDBName] :: ForeignDef -> !EntityNameDB [foreignConstraintNameHaskell] :: ForeignDef -> !ConstraintNameHS [foreignConstraintNameDBName] :: ForeignDef -> !ConstraintNameDB -- | Determine how the field will cascade on updates and deletions. [foreignFieldCascade] :: ForeignDef -> !FieldCascade [foreignFields] :: ForeignDef -> ![(ForeignFieldDef, ForeignFieldDef)] [foreignAttrs] :: ForeignDef -> ![Attr] [foreignNullable] :: ForeignDef -> Bool -- | Determines if the reference is towards a Primary Key or not. [foreignToPrimary] :: ForeignDef -> Bool -- | Used instead of FieldDef to generate a smaller amount of code type ForeignFieldDef = (FieldNameHS, FieldNameDB) data CompositeDef CompositeDef :: !NonEmpty FieldDef -> ![Attr] -> CompositeDef [compositeFields] :: CompositeDef -> !NonEmpty FieldDef [compositeAttrs] :: CompositeDef -> ![Attr] -- | Type for storing the Uniqueness constraint in the Schema. Assume you -- have the following schema with a uniqueness constraint: -- --
--   Person
--     name String
--     age Int
--     UniqueAge age
--   
-- -- This will be represented as: -- --
--   UniqueDef
--       { uniqueHaskell = ConstraintNameHS (packPTH UniqueAge)
--       , uniqueDBName = ConstraintNameDB (packPTH "unique_age")
--       , uniqueFields = [(FieldNameHS (packPTH "age"), FieldNameDB (packPTH "age"))]
--       , uniqueAttrs = []
--       }
--   
data UniqueDef UniqueDef :: !ConstraintNameHS -> !ConstraintNameDB -> !NonEmpty (FieldNameHS, FieldNameDB) -> ![Attr] -> UniqueDef [uniqueHaskell] :: UniqueDef -> !ConstraintNameHS [uniqueDBName] :: UniqueDef -> !ConstraintNameDB [uniqueFields] :: UniqueDef -> !NonEmpty (FieldNameHS, FieldNameDB) [uniqueAttrs] :: UniqueDef -> ![Attr] -- | 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 :: FieldNameDB -> Maybe (Either SelfEmbed EntityNameHS) -> EmbedFieldDef [emFieldDB] :: EmbedFieldDef -> FieldNameDB [emFieldEmbed] :: EmbedFieldDef -> Maybe (Either SelfEmbed EntityNameHS) -- | 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 :: EntityNameHS -> [EmbedFieldDef] -> EmbedEntityDef [embeddedHaskell] :: EmbedEntityDef -> EntityNameHS [embeddedFields] :: EmbedEntityDef -> [EmbedFieldDef] -- | 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 -- name and has the Haskell type of the foreign key in the form of -- FieldType ForeignRef :: !EntityNameHS -> ReferenceDef EmbedRef :: EntityNameHS -> ReferenceDef CompositeRef :: CompositeDef -> ReferenceDef -- | A SelfReference stops an immediate cycle which causes non-termination -- at compile-time (issue #311). SelfReference :: ReferenceDef -- | A FieldType describes a field parsed from the QuasiQuoter and -- is used to determine the Haskell type in the generated code. -- -- name Text parses into FTTypeCon Nothing Text -- -- name T.Text parses into FTTypeCon (Just T -- Text) -- -- name (Jsonb User) parses into: -- --
--   FTApp (FTTypeCon Nothing Jsonb) (FTTypeCon Nothing User)
--   
data FieldType -- | Optional module and name. FTTypeCon :: Maybe Text -> Text -> FieldType FTTypePromoted :: Text -> FieldType FTApp :: FieldType -> FieldType -> FieldType FTList :: FieldType -> FieldType -- | Attributes that may be attached to fields that can affect migrations -- and serialization in backend-specific ways. -- -- While we endeavor to, we can't forsee all use cases for all backends, -- and so FieldAttr is extensible through its constructor -- FieldAttrOther. data FieldAttr -- | The Maybe keyword goes after the type. This indicates that the -- column is nullable, and the generated Haskell code will have a -- Maybe type for it. -- -- Example: -- --
--   User
--       name Text Maybe
--   
FieldAttrMaybe :: FieldAttr -- | This indicates that the column is nullable, but should not have a -- Maybe type. For this to work out, you need to ensure that the -- PersistField instance for the type in question can support a -- PersistNull value. -- --
--   data What = NoWhat | Hello Text
--   
--   instance PersistField What where
--       fromPersistValue PersistNull =
--           pure NoWhat
--       fromPersistValue pv =
--           Hello $ fromPersistValue pv
--   
--   instance PersistFieldSql What where
--       sqlType _ = SqlString
--   
--   User
--       what What nullable
--   
FieldAttrNullable :: FieldAttr -- | This tag means that the column will not be present on the Haskell -- code, but will not be removed from the database. Useful to deprecate -- fields in phases. -- -- You should set the column to be nullable in the database. Otherwise, -- inserts won't have values. -- --
--   User
--       oldName Text MigrationOnly
--       newName Text
--   
FieldAttrMigrationOnly :: FieldAttr -- | A SafeToRemove attribute is not present on the Haskell -- datatype, and the backend migrations should attempt to drop the column -- without triggering any unsafe migration warnings. -- -- Useful after you've used MigrationOnly to remove a column -- from the database in phases. -- --
--   User
--       oldName Text SafeToRemove
--       newName Text
--   
FieldAttrSafeToRemove :: FieldAttr -- | This attribute indicates that we should create a foreign key reference -- from a column. By default, persistent will try and create a -- foreign key reference for a column if it can determine that the type -- of the column is a Key entity or an -- EntityId and the Entity's name was present in -- mkPersist. -- -- This is useful if you want to use the explicit foreign key syntax. -- --
--   Post
--       title    Text
--   
--   Comment
--       postId   PostId      noreference
--       Foreign Post fk_comment_post postId
--   
FieldAttrNoreference :: FieldAttr -- | This is set to specify precisely the database table the column refers -- to. -- --
--   Post
--       title    Text
--   
--   Comment
--       postId   PostId references="post"
--   
-- -- You should not need this - persistent should be capable of -- correctly determining the target table's name. If you do need this, -- please file an issue describing why. FieldAttrReference :: Text -> FieldAttr -- | Specify a name for the constraint on the foreign key reference for -- this table. -- --
--   Post
--       title    Text
--   
--   Comment
--       postId   PostId constraint="my_cool_constraint_name"
--   
FieldAttrConstraint :: Text -> FieldAttr -- | Specify the default value for a column. -- --
--   User
--       createdAt    UTCTime     default="NOW()"
--   
-- -- Note that a default= attribute does not mean you can omit the -- value while inserting. FieldAttrDefault :: Text -> FieldAttr -- | Specify a custom SQL type for the column. Generally, you should define -- a custom datatype with a custom PersistFieldSql instance -- instead of using this. -- --
--   User
--       uuid     Text    sqltype=UUID
--   
FieldAttrSqltype :: Text -> FieldAttr -- | Set a maximum length for a column. Useful for VARCHAR and indexes. -- --
--   User
--       name     Text    maxlen=200
--   
--       UniqueName name
--   
FieldAttrMaxlen :: Integer -> FieldAttr -- | Specify the database name of the column. -- --
--   User
--       blarghle     Int     sql="b_l_a_r_g_h_l_e"
--   
-- -- Useful for performing phased migrations, where one column is renamed -- to another column over time. FieldAttrSql :: Text -> FieldAttr -- | A grab bag of random attributes that were unrecognized by the parser. FieldAttrOther :: Text -> FieldAttr type Attr = Text type ExtraLine = [Text] -- | The definition for the entity's primary key ID. data EntityIdDef -- | The entity has a single key column, and it is a surrogate key - that -- is, you can't go from rec -> Key rec. EntityIdField :: !FieldDef -> EntityIdDef -- | The entity has a natural key. This means you can write rec -> -- Key rec because all the key fields are present on the datatype. -- -- A natural key can have one or more columns. EntityIdNaturalKey :: !CompositeDef -> EntityIdDef -- | 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 -- | 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 data IsNullable Nullable :: !WhyNullable -> IsNullable NotNullable :: IsNullable -- | 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 fieldAttrsContainsNullable :: [FieldAttr] -> IsNullable -- | Return the [FieldDef] for the entity keys. entitiesPrimary :: EntityDef -> NonEmpty FieldDef entityPrimary :: EntityDef -> Maybe CompositeDef -- | Returns a NonEmpty list of FieldDef that correspond with -- the key columns for an EntityDef. keyAndEntityFields :: EntityDef -> NonEmpty FieldDef -- | Parse raw field attributes into structured form. Any unrecognized -- attributes will be preserved, identically as they are encountered, as -- FieldAttrOther values. parseFieldAttrs :: [Text] -> [FieldAttr] isFieldNotGenerated :: FieldDef -> Bool -- | Returns True if the FieldDef does not have a -- MigrationOnly or SafeToRemove flag from the -- QuasiQuoter. isHaskellField :: FieldDef -> Bool -- | A FieldCascade that does nothing. noCascade :: FieldCascade -- | Renders a FieldCascade value such that it can be used in SQL -- migrations. renderFieldCascade :: FieldCascade -> Text -- | Render a CascadeAction to Text such that it can be used -- in a SQL command. renderCascadeAction :: CascadeAction -> Text -- | A Statement is a representation of a database query that has -- been prepared and stored on the server side. data Statement Statement :: IO () -> IO () -> ([PersistValue] -> IO Int64) -> (forall (m :: Type -> Type). MonadIO m => [PersistValue] -> Acquire (ConduitM () [PersistValue] m ())) -> Statement [stmtFinalize] :: Statement -> IO () [stmtReset] :: Statement -> IO () [stmtExecute] :: Statement -> [PersistValue] -> IO Int64 [stmtQuery] :: Statement -> forall (m :: Type -> Type). MonadIO m => [PersistValue] -> Acquire (ConduitM () [PersistValue] m ()) data InsertSqlResult ISRSingle :: Text -> InsertSqlResult ISRInsertGet :: Text -> Text -> InsertSqlResult ISRManyKeys :: Text -> [PersistValue] -> InsertSqlResult type LogFunc = Loc -> LogSource -> LogLevel -> LogStr -> IO () -- | Replace the FieldDef FieldAttr with the new list. setFieldAttrs :: [FieldAttr] -> FieldDef -> FieldDef -- | Modify the list of field attributes. overFieldAttrs :: ([FieldAttr] -> [FieldAttr]) -> FieldDef -> FieldDef -- | Add an attribute to the list of field attributes. addFieldAttr :: FieldAttr -> FieldDef -> FieldDef -- | Check if the field definition is nullable isFieldNullable :: FieldDef -> IsNullable -- | Check if the field is `Maybe a` isFieldMaybe :: FieldDef -> Bool -- | Retrieve the list of UniqueDef from an EntityDef. This -- currently does not include a Primary key, if one is defined. -- A future version of persistent will include a -- Primary key among the Unique constructors for the -- Entity. getEntityUniques :: EntityDef -> [UniqueDef] -- | Retrieve the Haskell name of the given entity. getEntityHaskellName :: EntityDef -> EntityNameHS -- | Return the database name for the given entity. getEntityDBName :: EntityDef -> EntityNameDB getEntityExtra :: EntityDef -> Map Text [[Text]] setEntityDBName :: EntityNameDB -> EntityDef -> EntityDef getEntityComments :: EntityDef -> Maybe Text getEntityForeignDefs :: EntityDef -> [ForeignDef] -- | Retrieve the list of FieldDef that makes up the fields of the -- entity. -- -- This does not return the fields for an Id column or an -- implicit id. It will return the key columns if you used the -- Primary syntax for defining the primary key. -- -- This does not return fields that are marked SafeToRemove or -- MigrationOnly - so it only returns fields that are -- represented in the Haskell type. If you need those fields, use -- getEntityFieldsDatabase. getEntityFields :: EntityDef -> [FieldDef] -- | This returns all of the FieldDef defined for the -- EntityDef, including those fields that are marked as -- MigrationOnly (and therefore only present in the database) or -- SafeToRemove (and a migration will drop the column if it -- exists in the database). -- -- For all the fields that are present on the Haskell-type, see -- getEntityFields. getEntityFieldsDatabase :: EntityDef -> [FieldDef] isEntitySum :: EntityDef -> Bool getEntityId :: EntityDef -> EntityIdDef getEntityIdField :: EntityDef -> Maybe FieldDef -- | Set an entityId to be the given FieldDef. setEntityId :: FieldDef -> EntityDef -> EntityDef setEntityIdDef :: EntityIdDef -> EntityDef -> EntityDef getEntityKeyFields :: EntityDef -> NonEmpty FieldDef -- | Perform a mapping function over all of the entity fields, as -- determined by getEntityFieldsDatabase. overEntityFields :: ([FieldDef] -> [FieldDef]) -> EntityDef -> EntityDef data SomePersistField SomePersistField :: a -> SomePersistField -- | Prior to persistent-2.11.0, we provided an instance of -- PersistField for the Natural type. This was in error, -- because Natural represents an infinite value, and databases -- don't have reasonable types for this. -- -- The instance for Natural used the Int64 underlying type, -- which will cause underflow and overflow errors. This type has the -- exact same code in the instances, and will work seamlessly. -- -- A more appropriate type for this is the Word series of types -- from Data.Word. These have a bounded size, are guaranteed to be -- non-negative, and are quite efficient for the database to store. newtype OverflowNatural OverflowNatural :: Natural -> OverflowNatural [unOverflowNatural] :: OverflowNatural -> Natural -- | 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 -- | This type class is used with the OverloadedLabels extension -- to provide a more convenient means of using the EntityField -- type. EntityField definitions are prefixed with the type name -- to avoid ambiguity, but this ambiguity can result in verbose code. -- -- If you have a table User with a name Text field, -- then the corresponding EntityField is UserName. With -- this, we can write #name :: EntityField User Text. -- -- What's more fun is that the type is more general: it's actually -- #name :: (SymbolToField "name" rec typ) => EntityField rec -- typ -- -- Which means it is *polymorphic* over the actual record. This allows -- you to write code that can be generic over the tables, provided they -- have the right fields. class SymbolToField (sym :: Symbol) rec typ | sym rec -> typ symbolToField :: SymbolToField sym rec typ => EntityField rec typ -- | 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 -- | Value to filter with. Highly dependant on the type of filter used. data FilterValue typ [FilterValue] :: forall typ. typ -> FilterValue typ [FilterValues] :: forall typ. [typ] -> FilterValue typ [UnsafeValue] :: forall a typ. PersistField a => a -> FilterValue typ type family BackendSpecificUpdate backend record -- | 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. -- -- As of persistent-2.11.0.0, it's possible to use the -- OverloadedLabels language extension to refer to -- EntityField values polymorphically. See the documentation on -- SymbolToField for more information. data family EntityField record :: Type -> Type; -- | 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 => proxy 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 -> NonEmpty (FieldNameHS, FieldNameDB) -- | A lower level operation. persistUniqueToValues :: PersistEntity record => Unique record -> [PersistValue] -- | Use a PersistField as a lens. fieldLens :: PersistEntity record => EntityField record field -> forall (f :: Type -> Type). Functor f => (field -> f field) -> Entity record -> f (Entity record) -- | Extract a Key record from a record value. -- Currently, this is only defined for entities using the -- Primary syntax for natural/composite keys. In a future -- version of persistent which incorporates the ID directly into -- the entity, this will always be Just. keyFromRecordM :: PersistEntity record => Maybe (record -> Key record) -- | 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. -- -- As of persistent-2.11.0.0, it's possible to use the -- OverloadedLabels language extension to refer to -- EntityField values polymorphically. See the documentation on -- SymbolToField for more information. data family EntityField record :: Type -> Type -- | Unique keys besides the Key. data family Unique record -- | Get list of values corresponding to given entity. entityValues :: PersistEntity record => Entity record -> [PersistValue] -- | 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 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 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 :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m [Key record] -- | 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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> 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 :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> [Update record] -> ReaderT backend m record 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 class PersistCore backend where { data family BackendKey backend; } data family BackendKey backend -- | 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 -- | A convenient alias for common type signatures type PersistRecordBackend record backend = (PersistEntity record, PersistEntityBackend record ~ BaseBackend backend) -- | 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' = withCompatibleBackend asdf
--   
class BackendCompatible sup sub projectBackend :: BackendCompatible sup sub => sub -> sup -- | 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 -- | 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 type family BaseBackend backend -- | Run a query against a larger backend by plucking out BaseBackend -- backend -- -- This is a helper for reusing existing queries when expanding the -- backend type. withBaseBackend :: forall backend (m :: Type -> Type) a. HasPersistBackend backend => ReaderT (BaseBackend backend) m a -> ReaderT backend m a -- | Run a query against a compatible backend, by projecting the backend -- -- This is a helper for using queries which run against a specific -- backend type that your backend is compatible with. withCompatibleBackend :: forall sup sub (m :: Type -> Type) a. BackendCompatible sup sub => ReaderT sup m a -> ReaderT sub m a liftPersist :: (MonadIO m, MonadReader backend m) => ReaderT backend IO b -> m b -- | 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 :: forall record backend (m :: Type -> Type). (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 :: forall record backend (m :: Type -> Type). (PersistEntityBackend record ~ BaseBackend backend, MonadIO m, PersistEntity record, PersistStoreRead backend) => Key record -> ReaderT backend m (Entity record) -- | Curry this to make a convenience function that loads an associated -- model. -- --
--   foreign = belongsTo foreignId
--   
belongsTo :: forall ent1 ent2 backend (m :: Type -> Type). (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 :: forall ent1 ent2 backend (m :: Type -> Type). (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 :: forall e backend (m :: Type -> Type). (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 :: forall record backend (m :: Type -> Type). (PersistEntityBackend record ~ BaseBackend backend, PersistEntity record, MonadIO m, PersistStoreWrite backend) => record -> ReaderT backend m record -- | A SqlBackend represents a handle or connection to a database. -- It contains functions and values that allow databases to have more -- optimized implementations, as well as references that benefit -- performance and sharing. -- -- Instead of using the SqlBackend constructor directly, use the -- mkSqlBackend function. -- -- A SqlBackend is *not* thread-safe. You should not assume that a -- SqlBackend can be shared among threads and run concurrent -- queries. This *will* result in problems. Instead, you should create a -- Pool SqlBackend, known as a -- ConnectionPool, and pass that around in multi-threaded -- applications. -- -- To run actions in the persistent library, you should use the -- runSqlConn function. If you're using a multithreaded -- application, use the runSqlPool function. data SqlBackend -- | 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 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." -- | 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 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 -- | 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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> record -> [Update record] -> ReaderT backend m (Entity record) -- | Put many records into db -- -- putMany :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m () -- | 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 PersistStoreRead backend => PersistUniqueRead backend -- | Given a proxy for a PersistEntity record, this returns the sole -- UniqueDef for that entity. onlyOneUniqueDef :: (OnlyOneUniqueKey record, Monad proxy) => proxy record -> UniqueDef -- | 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 :: forall record backend (m :: Type -> Type). (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 :: forall record backend (m :: Type -> Type). (MonadIO m, PersistRecordBackend record backend, PersistUniqueWrite backend) => record -> ReaderT backend m (Maybe (Entity 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 :: forall record backend (m :: Type -> Type). (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> ReaderT backend m (Unique record) -- | 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 :: Type -> Type) backend. (MonadIO m, PersistUniqueRead backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record) => 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 :: forall record backend (m :: Type -> Type). (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 :: forall record backend (m :: Type -> Type). (MonadIO m, PersistRecordBackend record backend, PersistUniqueRead backend) => 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 stay unique, and could thus -- safely be updated. on a conflict returns the conflicting key -- -- This is similar to checkUnique, except it's useful for updating -- - when the particular entity already exists, it would normally -- conflict with itself. This variant ignores those conflicts -- --

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
--   
checkUniqueUpdateable :: forall record backend (m :: Type -> Type). (MonadIO m, PersistRecordBackend record backend, PersistUniqueRead backend) => Entity record -> ReaderT backend m (Maybe (Unique record)) -- | Backends supporting conditional write operations class (PersistQueryRead backend, PersistStoreWrite backend) => PersistQueryWrite backend -- | 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. -- -- NOTE: This function returns an Acquire and a ConduitM, -- which implies that it streams from the database. It does not. Please -- use selectList to simplify the code. If you want streaming -- behavior, consider persistent-pagination which efficiently -- chunks a query into ranges, or investigate a backend-specific -- streaming solution. selectSourceRes :: forall record (m1 :: Type -> Type) (m2 :: Type -> Type). (PersistQueryRead backend, PersistRecordBackend record backend, MonadIO m1, MonadIO m2) => [Filter record] -> [SelectOpt record] -> ReaderT backend m1 (Acquire (ConduitM () (Entity record) m2 ())) -- | Get the Keys of all records matching the given criterion. selectKeysRes :: forall (m1 :: Type -> Type) (m2 :: Type -> Type) record. (PersistQueryRead backend, MonadIO m1, MonadIO m2, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> ReaderT backend m1 (Acquire (ConduitM () (Key record) m2 ())) -- | Get the Keys of all records matching the given criterion. -- -- For an example, see selectList. selectKeys :: forall record backend (m :: Type -> Type). (PersistQueryRead backend, MonadResource m, PersistRecordBackend record backend, MonadReader backend m) => [Filter record] -> [SelectOpt record] -> ConduitM () (Key record) m () -- | 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 :: forall (m :: Type -> Type). (DeleteCascade record backend, MonadIO m) => Key record -> ReaderT backend m () -- | Cascade-deletion of entries satisfying given filters. deleteCascadeWhere :: forall record backend (m :: Type -> Type). (MonadIO m, DeleteCascade record backend, PersistQueryWrite backend) => [Filter record] -> ReaderT backend m () -- | 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 -- | 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 -- | A backend which is a wrapper around SqlBackend. type IsSqlBackend backend = (IsPersistBackend backend, BaseBackend backend ~ SqlBackend) -- | Like SqlPersistT but compatible with any SQL backend which -- can handle read and write queries. type SqlWriteT (m :: Type -> Type) a = forall backend. SqlBackendCanWrite backend => ReaderT backend m a -- | Like SqlPersistT but compatible with any SQL backend which -- can handle read queries. type SqlReadT (m :: Type -> Type) a = forall backend. SqlBackendCanRead backend => ReaderT backend m a -- | 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) -- | 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) -- | An SQL backend which can handle read or write queries -- -- The constructor was exposed in 2.10.0 newtype SqlWriteBackend SqlWriteBackend :: SqlBackend -> SqlWriteBackend [$sel:unSqlWriteBackend:SqlWriteBackend] :: SqlWriteBackend -> SqlBackend -- | An SQL backend which can only handle read queries -- -- The constructor was exposed in 2.10.0. newtype SqlReadBackend SqlReadBackend :: SqlBackend -> SqlReadBackend [$sel:unSqlReadBackend:SqlReadBackend] :: SqlReadBackend -> SqlBackend -- | Useful for running a write query against an untagged backend with -- unknown capabilities. writeToUnknown :: forall (m :: Type -> Type) a. Monad m => ReaderT SqlWriteBackend m a -> ReaderT SqlBackend m a -- | Useful for running a read query against a backend with read and write -- capabilities. readToWrite :: forall (m :: Type -> Type) a. Monad m => ReaderT SqlReadBackend m a -> ReaderT SqlWriteBackend m a -- | Useful for running a read query against a backend with unknown -- capabilities. readToUnknown :: forall (m :: Type -> Type) a. Monad m => ReaderT SqlReadBackend m a -> ReaderT SqlBackend m a -- | 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 -- | Values to configure a pool of database connections. See -- Data.Pool for details. data ConnectionPoolConfig ConnectionPoolConfig :: Int -> NominalDiffTime -> Int -> ConnectionPoolConfig -- | How many stripes to divide the pool into. See Data.Pool for -- details. Default: 1. [connectionPoolConfigStripes] :: ConnectionPoolConfig -> Int -- | How long connections can remain idle before being disposed of, in -- seconds. Default: 600 [connectionPoolConfigIdleTimeout] :: ConnectionPoolConfig -> NominalDiffTime -- | How many connections should be held in the connection pool. Default: -- 10 [connectionPoolConfigSize] :: ConnectionPoolConfig -> Int type ConnectionPool = Pool SqlBackend type SqlPersistM = SqlPersistT NoLoggingT ResourceT IO type SqlPersistT = ReaderT SqlBackend data PersistentSqlException StatementAlreadyFinalized :: Text -> PersistentSqlException Couldn'tGetSQLConnection :: PersistentSqlException -- | This value specifies how a field references another table. data ColumnReference ColumnReference :: !EntityNameDB -> !ConstraintNameDB -> !FieldCascade -> ColumnReference -- | The table name that the [crTableName] :: ColumnReference -> !EntityNameDB -- | The name of the foreign key constraint. [crConstraintName] :: ColumnReference -> !ConstraintNameDB -- | Whether or not updates/deletions to the referenced table cascade to -- this table. [crFieldCascade] :: ColumnReference -> !FieldCascade data Column Column :: !FieldNameDB -> !Bool -> !SqlType -> !Maybe Text -> !Maybe Text -> !Maybe ConstraintNameDB -> !Maybe Integer -> !Maybe ColumnReference -> Column [cName] :: Column -> !FieldNameDB [cNull] :: Column -> !Bool [cSqlType] :: Column -> !SqlType [cDefault] :: Column -> !Maybe Text [cGenerated] :: Column -> !Maybe Text [cDefaultConstraintName] :: Column -> !Maybe ConstraintNameDB [cMaxLen] :: Column -> !Maybe Integer [cReference] :: Column -> !Maybe ColumnReference -- | Initializes a ConnectionPoolConfig with default values. See the -- documentation of ConnectionPoolConfig for each field's default -- value. defaultConnectionPoolConfig :: ConnectionPoolConfig -- | Record of functions to override the default behavior in -- mkColumns. It is recommended you initialize this with -- emptyBackendSpecificOverrides and override the default values, -- so that as new fields are added, your code still compiles. -- -- For added safety, use the getBackendSpecific* and -- setBackendSpecific* functions, as a breaking change to the -- record field labels won't be reflected in a major version bump of the -- library. data BackendSpecificOverrides -- | If the override is defined, then this returns a function that accepts -- an entity name and field name and provides the ConstraintNameDB -- for the foreign key constraint. -- -- An abstract accessor for the BackendSpecificOverrides getBackendSpecificForeignKeyName :: BackendSpecificOverrides -> Maybe (EntityNameDB -> FieldNameDB -> ConstraintNameDB) -- | Set the backend's foreign key generation function to this value. setBackendSpecificForeignKeyName :: (EntityNameDB -> FieldNameDB -> ConstraintNameDB) -> BackendSpecificOverrides -> BackendSpecificOverrides -- | Creates an empty BackendSpecificOverrides (i.e. use the default -- behavior; no overrides) emptyBackendSpecificOverrides :: BackendSpecificOverrides defaultAttribute :: [FieldAttr] -> Maybe Text -- | Create the list of columns for the given entity. mkColumns :: [EntityDef] -> EntityDef -> BackendSpecificOverrides -> ([Column], [UniqueDef], [ForeignDef]) -- | A more general way to convert instances of ToJSON type class to -- strict text Text. toJsonText :: ToJSON j => j -> Text -- | 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 = PersistLiteralEncoded . toASCIIBytes
--     fromPersistValue (PersistLiteralEncoded 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 PersistLiteralEncoded, 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 -- | 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 => (Text -> 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 -- | 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 = fmap (unPrefix @"p") $ rawSql query []
--     where
--       query = "SELECT ?? FROM person AS p"
--   
unPrefix :: forall (prefix :: Symbol) record. EntityWithPrefix prefix record -> Entity record rawQuery :: forall (m :: Type -> Type) env. (MonadResource m, MonadReader env m, BackendCompatible SqlBackend env) => Text -> [PersistValue] -> ConduitM () [PersistValue] m () rawQueryRes :: forall (m1 :: Type -> Type) (m2 :: Type -> Type) env. (MonadIO m1, MonadIO m2, BackendCompatible SqlBackend env) => Text -> [PersistValue] -> ReaderT env m1 (Acquire (ConduitM () [PersistValue] m2 ())) -- | Execute a raw SQL statement rawExecute :: forall (m :: Type -> Type) backend. (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 :: forall (m :: Type -> Type) backend. (MonadIO m, BackendCompatible SqlBackend backend) => Text -> [PersistValue] -> ReaderT backend m Int64 getStmtConn :: SqlBackend -> Text -> IO Statement -- | 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 :: forall a (m :: Type -> Type) backend. (RawSql a, MonadIO m, BackendCompatible SqlBackend backend) => Text -> [PersistValue] -> ReaderT backend m [a] -- | Get a connection from the pool, run the given action, and then return -- the connection to the pool. -- -- This function performs the given action in a transaction. If an -- exception occurs during the action, then the transaction is rolled -- back. -- -- 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 :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> m a -- | Like runSqlPool, but supports specifying an isolation level. runSqlPoolWithIsolation :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> IsolationLevel -> m a -- | Like runSqlPool, but does not surround the action in a -- transaction. This action might leave your database in a weird state. runSqlPoolNoTransaction :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> Maybe IsolationLevel -> m a -- | This function is how runSqlPool and -- runSqlPoolNoTransaction are defined. In addition to the action -- to be performed and the Pool of conections to use, we give you -- the opportunity to provide three actions - initialize, afterwards, and -- onException. runSqlPoolWithHooks :: forall backend m a before after onException. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> Maybe IsolationLevel -> (backend -> m before) -> (backend -> m after) -> (backend -> SomeException -> m onException) -> m a -- | This function is how runSqlPoolWithHooks is defined. -- -- It's currently the most general function for using a SQL pool. runSqlPoolWithExtensibleHooks :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> Maybe IsolationLevel -> SqlPoolHooks m backend -> 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 :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> backend -> m a -- | Like runSqlConn, but supports specifying an isolation level. runSqlConnWithIsolation :: forall backend m a. (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 :: forall backend m a. (MonadIO m, BackendCompatible SqlBackend backend) => ReaderT backend (NoLoggingT (ResourceT IO)) a -> Pool backend -> m a withSqlPool :: forall backend m a. (MonadLoggerIO m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> (Pool backend -> m a) -> m a -- | Creates a pool of connections to a SQL database which can be used by -- the Pool backend -> m a function. After the function -- completes, the connections are destroyed. withSqlPoolWithConfig :: forall backend m a. (MonadLoggerIO m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> ConnectionPoolConfig -> (Pool backend -> m a) -> m a createSqlPool :: forall backend m. (MonadLoggerIO m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> m (Pool backend) -- | Creates a pool of connections to a SQL database. createSqlPoolWithConfig :: (MonadLoggerIO m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> ConnectionPoolConfig -> m (Pool backend) -- | 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 :: forall backend m a. (MonadUnliftIO m, MonadLoggerIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> (backend -> m a) -> m a close' :: BackendCompatible SqlBackend backend => backend -> IO () withRawQuery :: forall (m :: Type -> Type) a. MonadIO m => Text -> [PersistValue] -> ConduitM [PersistValue] Void IO a -> ReaderT SqlBackend m a toSqlKey :: ToBackendKey SqlBackend record => Int64 -> Key record fromSqlKey :: ToBackendKey SqlBackend record => Key record -> Int64 -- | 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 :: Type -> Type) 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 -> EntityNameDB -- | 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 :: Type -> Type) backend. (PersistEntity record, PersistEntityBackend record ~ SqlBackend, BackendCompatible SqlBackend backend, Monad m) => EntityField record typ -> ReaderT backend m Text -- | useful for a backend to implement fieldName by adding escaping fieldDBName :: PersistEntity record => EntityField record typ -> FieldNameDB -- | Used when determining how to prefix a column name in a WHERE -- clause. data FilterTablePrefix -- | Prefix the column with the table name. This is useful if the column -- name might be ambiguous. PrefixTableName :: FilterTablePrefix -- | Prefix the column name with the EXCLUDED keyword. This is -- used with the Postgresql backend when doing ON CONFLICT DO -- UPDATE clauses - see the documentation on upsertWhere -- and upsertManyWhere. PrefixExcluded :: FilterTablePrefix -- | Render a [Filter record] into a Text value -- suitable for inclusion into a SQL query. filterClause :: PersistEntity val => Maybe FilterTablePrefix -> SqlBackend -> [Filter val] -> Text -- | Render a [Filter record] into a Text value -- suitable for inclusion into a SQL query, as well as the -- [PersistValue] to properly fill in the ? -- place holders. filterClauseWithVals :: PersistEntity val => Maybe FilterTablePrefix -> SqlBackend -> [Filter val] -> (Text, [PersistValue]) -- | Render a [SelectOpt record] made up *only* of -- Asc and Desc constructors into a Text value -- suitable for inclusion into a SQL query. orderClause :: PersistEntity val => Maybe FilterTablePrefix -> SqlBackend -> [SelectOpt val] -> Text -- | Generates sql for limit and offset for postgres, sqlite and mysql. decorateSQLWithLimitOffset :: Text -> (Int, Int) -> Text -> Text -- | An exception indicating that Persistent refused to run some unsafe -- migrations. Contains a list of pairs where the Bool tracks whether the -- migration was unsafe (True means unsafe), and the Sql is the sql -- statement for the migration. newtype PersistUnsafeMigrationException PersistUnsafeMigrationException :: [(Bool, Sql)] -> PersistUnsafeMigrationException -- | A Migration is a four level monad stack consisting of: -- -- type Migration = WriterT [Text] WriterT CautiousMigration ReaderT SqlBackend IO () -- | A list of SQL operations, marked with a safety flag. If the -- Bool is True, then the operation is *unsafe* - it might -- be destructive, or otherwise not idempotent. If the Bool is -- False, then the operation is *safe*, and can be run repeatedly -- without issues. type CautiousMigration = [(Bool, Sql)] type Sql = Text -- | 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 :: forall (m :: Type -> Type). (HasCallStack, 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' :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m CautiousMigration -- | Prints a migration. printMigration :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m () -- | Convert a Migration to a list of Text values -- corresponding to their Sql statements. showMigration :: forall (m :: Type -> Type). (HasCallStack, 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 :: forall (m :: Type -> Type). (MonadIO m, HasCallStack) => Migration -> ReaderT SqlBackend m [Sql] -- | Runs a migration. If the migration fails to parse or if any of the -- migrations are unsafe, then this throws a -- PersistUnsafeMigrationException. runMigration :: forall (m :: Type -> Type). 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 :: forall (m :: Type -> Type). 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 :: forall (m :: Type -> Type). MonadUnliftIO m => Migration -> ReaderT SqlBackend m [Text] -- | Like runMigration, but this will perform the unsafe database -- migrations instead of erroring out. runMigrationUnsafe :: forall (m :: Type -> Type). 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 :: forall (m :: Type -> Type). (HasCallStack, 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 a single error in a Migration. reportError :: Text -> Migration -- | Report multiple errors in a Migration. reportErrors :: [Text] -> Migration -- | Add a migration to the migration plan. addMigration :: Bool -> Sql -> Migration -- | Add a CautiousMigration (aka a [(Bool, -- Text)]) to the migration plan. addMigrations :: CautiousMigration -> Migration -- | Run an action against the database during a migration. Can be useful -- for eg creating Postgres extensions: -- --
--   runSqlCommand $ rawExecute "CREATE EXTENSION IF NOT EXISTS "uuid-ossp";" []
--   
runSqlCommand :: SqlPersistT IO () -> Migration -- | 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 :: forall (m :: Type -> Type). MonadIO m => ReaderT SqlBackend m () -- | Commit the current transaction and begin a new one with the specified -- isolation level. transactionSaveWithIsolation :: forall (m :: Type -> Type). 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 :: forall (m :: Type -> Type). MonadIO m => ReaderT SqlBackend m () -- | Roll back the current transaction and begin a new one with the -- specified isolation level. transactionUndoWithIsolation :: forall (m :: Type -> Type). MonadIO m => IsolationLevel -> ReaderT SqlBackend m () -- | The lifted version of deleteWhere deleteWhere :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [Filter record] -> m () -- | The lifted version of updateWhere updateWhere :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [Filter record] -> [Update record] -> m () -- | The lifted version of selectFirst selectFirst :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [Filter record] -> [SelectOpt record] -> m (Maybe (Entity record)) -- | The lifted version of getBy getBy :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => Unique record -> m (Maybe (Entity record)) -- | The lifted version of insertKey insertKey :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => Key record -> record -> m () -- | The lifted version of insertEntityMany insertEntityMany :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [Entity record] -> m () -- | The lifted version of insertMany_ insertMany_ :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [record] -> m () -- | The lifted version of insert_ insert_ :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => record -> m () -- | The lifted version of insert insert :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => record -> m (Key record) -- | The lifted version of getEntity getEntity :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => Key record -> m (Maybe (Entity record)) -- | The lifted version of getMany getMany :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [Key record] -> m (Map (Key record) record) -- | The lifted version of get get :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => Key record -> m (Maybe record) -- | Classy version of select select :: (MonadSqlQuery m, SqlSelect a r) => SqlQuery a -> m [r] -- | Classy version of selectOne selectOne :: (MonadSqlQuery m, SqlSelect a r) => SqlQuery a -> m (Maybe r) -- | Classy version of delete delete :: MonadSqlQuery m => SqlQuery () -> m () -- | Classy version of update update :: (MonadSqlQuery m, PersistEntity val, BackendCompatible SqlBackend (PersistEntityBackend val)) => (SqlExpr (Entity val) -> SqlQuery ()) -> m () renderQuerySelect :: (MonadSqlQuery m, SqlSelect a r) => SqlQuery a -> m (Text, [PersistValue]) -- | WITH RECURSIVE allows one to make a recursive -- subquery, which can reference itself. Like WITH, this is -- supported in most modern SQL engines. Useful for hierarchical, -- self-referential data, like a tree of data. -- --
--   select $ do
--   cte <- withRecursive
--            (do
--                person <- from $ table @Person
--                where_ $ person ^. PersonId ==. val personId
--                pure person
--            )
--            unionAll_
--            (\self -> do
--                (p :& f :& p2 :& pSelf) <- from self
--                         `innerJoin` $ table @Follow
--                         `on` (\(p :& f) ->
--                                 p ^. PersonId ==. f ^. FollowFollower)
--                         `innerJoin` $ table @Person
--                         `on` (\(p :& f :& p2) ->
--                                 f ^. FollowFollowed ==. p2 ^. PersonId)
--                         `leftJoin` self
--                         `on` (\(_ :& _ :& p2 :& pSelf) ->
--                                 just (p2 ^. PersonId) ==. pSelf ?. PersonId)
--                where_ $ isNothing (pSelf ?. PersonId)
--                groupBy (p2 ^. PersonId)
--                pure p2
--            )
--   from cte
--   
-- -- Since: 3.4.0.0 withRecursive :: (ToAlias a, ToAliasReference a, SqlSelect a r) => SqlQuery a -> UnionKind -> (From a -> SqlQuery a) -> SqlQuery (From a) -- | WITH clause used to introduce a Common Table Expression -- (CTE). CTEs are supported in most modern SQL engines and can be -- useful in performance tuning. In Esqueleto, CTEs should be used as a -- subquery memoization tactic. When writing plain SQL, CTEs are -- sometimes used to organize the SQL code, in Esqueleto, this is better -- achieved through function that return SqlQuery values. -- --
--   select $ do
--   cte <- with subQuery
--   cteResult <- from cte
--   where_ $ cteResult ...
--   pure cteResult
--   
-- -- WARNING: In some SQL engines using a CTE can diminish -- performance. In these engines the CTE is treated as an optimization -- fence. You should always verify that using a CTE will in fact improve -- your performance over a regular subquery. -- -- Notably, in PostgreSQL prior to version 12, CTEs are always fully -- calculated, which can potentially significantly pessimize queries. As -- of PostgreSQL 12, non-recursive and side-effect-free queries may be -- inlined and optimized accordingly if not declared -- MATERIALIZED to get the previous behaviour. See the -- PostgreSQL CTE documentation, section Materialization, for more -- information. -- -- Since: 3.4.0.0 with :: (ToAlias a, ToAliasReference a, SqlSelect a r) => SqlQuery a -> SqlQuery (From a) -- | FULL OUTER JOIN -- -- Join where both sides of the join may not exist. Because of this the -- result needs to be handled as a Maybe -- -- Used as an infix operator `fullOuterJoin` -- --
--   select $
--   from $ table @Person
--   `fullOuterJoin` table @BlogPost
--   `on` (\(p :& bp) ->
--           p ?. PersonId ==. bp ?. BlogPostAuthorId)
--   
fullOuterJoin :: (ToFrom a a', ToFrom b b', ToMaybe a', ToMaybe b', HasOnClause rhs (ToMaybeT a' :& ToMaybeT b'), rhs ~ (b, (ToMaybeT a' :& ToMaybeT b') -> SqlExpr (Value Bool))) => a -> rhs -> From (ToMaybeT a' :& ToMaybeT b') infixl 2 `fullOuterJoin` -- | RIGHT OUTER JOIN -- -- Join where the left side may not exist. If the on clause fails then -- the left side will be NULL'ed Because of this the left side needs to -- be handled as a Maybe -- -- Used as an infix operator `rightJoin` -- --
--   select $
--   from $ table @Person
--   `rightJoin` table @BlogPost
--   `on` (\(p :& bp) ->
--           p ?. PersonId ==. bp ^. BlogPostAuthorId)
--   
rightJoin :: (ToFrom a a', ToFrom b b', ToMaybe a', HasOnClause rhs (ToMaybeT a' :& b'), rhs ~ (b, (ToMaybeT a' :& b') -> SqlExpr (Value Bool))) => a -> rhs -> From (ToMaybeT a' :& b') infixl 2 `rightJoin` -- | LEFT OUTER JOIN LATERAL -- -- Lateral join where the right side may not exist. In the case that the -- query returns nothing or the on clause fails the right side of the -- join will be NULL'ed Because of this the right side needs to be -- handled as a Maybe -- -- Used as an infix operator `leftJoinLateral` -- -- See example 6 for how to use LATERAL leftJoinLateral :: (ToFrom a a', SqlSelect b r, HasOnClause rhs (a' :& ToMaybeT b), ToAlias b, ToAliasReference b, ToMaybe b, rhs ~ (a' -> SqlQuery b, (a' :& ToMaybeT b) -> SqlExpr (Value Bool))) => a -> rhs -> From (a' :& ToMaybeT b) infixl 2 `leftJoinLateral` -- | LEFT OUTER JOIN -- -- Join where the right side may not exist. If the on clause fails then -- the right side will be NULL'ed Because of this the right side needs to -- be handled as a Maybe -- -- Used as an infix operator `leftJoin` -- --
--   select $
--   from $ table @Person
--   `leftJoin` table @BlogPost
--   `on` (\(p :& bp) ->
--           p ^. PersonId ==. bp ?. BlogPostAuthorId)
--   
leftJoin :: (ToFrom a a', ToFrom b b', ToMaybe b', HasOnClause rhs (a' :& ToMaybeT b'), rhs ~ (b, (a' :& ToMaybeT b') -> SqlExpr (Value Bool))) => a -> rhs -> From (a' :& ToMaybeT b') infixl 2 `leftJoin` -- | CROSS JOIN LATERAL -- -- A Lateral subquery join allows the joined query to reference entities -- from the left hand side of the join. -- -- Used as an infix operator `crossJoinLateral` -- -- See example 6 crossJoinLateral :: (ToFrom a a', SqlSelect b r, ToAlias b, ToAliasReference b) => a -> (a' -> SqlQuery b) -> From (a' :& b) infixl 2 `crossJoinLateral` -- | CROSS JOIN -- -- Used as an infix `crossJoin` -- --
--   select $ do
--   from $ table @Person
--   `crossJoin` table @BlogPost
--   
crossJoin :: (ToFrom a a', ToFrom b b') => a -> b -> From (a' :& b') infixl 2 `crossJoin` -- | INNER JOIN LATERAL -- -- A Lateral subquery join allows the joined query to reference entities -- from the left hand side of the join. Discards rows that don't match -- the on clause -- -- Used as an infix operator `innerJoinLateral` -- -- See example 6 innerJoinLateral :: (ToFrom a a', HasOnClause rhs (a' :& b), SqlSelect b r, ToAlias b, ToAliasReference b, rhs ~ (a' -> SqlQuery b, (a' :& b) -> SqlExpr (Value Bool))) => a -> rhs -> From (a' :& b) infixl 2 `innerJoinLateral` -- | INNER JOIN -- -- Used as an infix operator `innerJoin` -- --
--   select $
--   from $ table @Person
--   `innerJoin` table @BlogPost
--   `on` (\(p :& bp) ->
--           p ^. PersonId ==. bp ^. BlogPostAuthorId)
--   
innerJoin :: (ToFrom a a', ToFrom b b', HasOnClause rhs (a' :& b'), rhs ~ (b, (a' :& b') -> SqlExpr (Value Bool))) => a -> rhs -> From (a' :& b') infixl 2 `innerJoin` -- | An ON clause that describes how two tables are related. This -- should be used as an infix operator after a JOIN. For -- example, -- --
--   select $
--   from $ table @Person
--   `innerJoin` table @BlogPost
--   `on` (\(p :& bP) ->
--           p ^. PersonId ==. bP ^. BlogPostAuthorId)
--   
on :: ValidOnClause a => a -> (b -> SqlExpr (Value Bool)) -> (a, b -> SqlExpr (Value Bool)) infix 9 `on` -- | A left-precedence pair. Pronounced "and". Used to represent -- expressions that have been joined together. -- -- The precedence behavior can be demonstrated by: -- --
--   a :& b :& c == ((a :& b) :& c)
--   
-- -- See the examples at the beginning of this module to see how this -- operator is used in JOIN operations. data a :& b (:&) :: a -> b -> (:&) a b infixl 2 :& infixl 2 :& -- | INTERSECT SQL set operation. Can be used as an infix function -- between SqlQuery values. intersect_ :: (ToSqlSetOperation a a', ToSqlSetOperation b a') => a -> b -> SqlSetOperation a' -- | EXCEPT SQL set operation. Can be used as an infix function -- between SqlQuery values. except_ :: (ToSqlSetOperation a a', ToSqlSetOperation b a') => a -> b -> SqlSetOperation a' pattern SelectQuery :: p -> p -- | Type class to support direct use of SqlQuery in a set -- operation tree class ToSqlSetOperation a r | a -> r toSqlSetOperation :: ToSqlSetOperation a r => a -> SqlSetOperation r data Union a b Union :: a -> b -> Union a b -- | UNION SQL set operation. Can be used as an infix function -- between SqlQuery values. union_ :: Union_ a => a -- | UNION ALL SQL set operation. Can be used as an infix -- function between SqlQuery values. unionAll_ :: UnionAll_ a => a data UnionAll a b UnionAll :: a -> b -> UnionAll a b data Except a b Except :: a -> b -> Except a b data Intersect a b Intersect :: a -> b -> Intersect a b -- | Select from a subquery, often used in conjuction with joins but can be -- used without any joins. Because SqlQuery has a -- ToFrom instance you probably dont need to use this function -- directly. -- --
--   select $
--        p <- from $
--                selectQuery do
--                p <- from $ table @Person
--                limit 5
--                orderBy [ asc p ^. PersonAge ]
--        ...
--   
selectQuery :: (SqlSelect a r, ToAlias a, ToAliasReference a) => SqlQuery a -> From a -- | Bring a PersistEntity into scope from a table -- --
--   select $ from $ table @People
--   
table :: PersistEntity ent => From (SqlExpr (Entity ent)) -- | FROM clause, used to bring entities into scope. -- -- Internally, this function uses the From datatype. Unlike the -- old from, this does not take a function as a parameter, but -- rather a value that represents a JOIN tree constructed out of -- instances of From. This implementation eliminates certain types -- of runtime errors by preventing the construction of invalid SQL (e.g. -- illegal nested-from). from :: ToFrom a a' => a -> SqlQuery a' -- | Data type defining the From language. This should not -- constructed directly in application code. -- -- A From is a SqlQuery which returns a reference to the result -- of calling from and a function that produces a portion of a FROM -- clause. This gets passed to the FromRaw FromClause constructor -- directly when converting from a From to a SqlQuery -- using from newtype From a From :: SqlQuery (a, RawFn) -> From a [unFrom] :: From a -> SqlQuery (a, RawFn) data Table a Table :: Table a newtype SubQuery a SubQuery :: a -> SubQuery a type ToAliasT a = a class ToAlias a toAlias :: ToAlias a => a -> SqlQuery a type ToAliasReferenceT a = a class ToAliasReference a toAliasReference :: ToAliasReference a => Ident -> a -> SqlQuery a type family ToMaybeT a class ToMaybe a where { type family ToMaybeT a; } toMaybe :: ToMaybe a => a -> ToMaybeT a -- | Avoid N+1 queries and join entities into a map structure. -- -- This function is useful to call on the result of a single -- JOIN. For example, suppose you have this query: -- --
--   getFoosAndNestedBarsFromParent
--       :: ParentId
--       -> SqlPersistT IO [(Entity Foo, Maybe (Entity Bar))]
--   getFoosAndNestedBarsFromParent parentId =
--       select $ do
--           (foo :& bar) <- from $
--               table Foo
--               `LeftOuterJoin`
--               table Bar
--                   `on` do
--                       \(foo :& bar) ->
--                           foo ^. FooId ==. bar ?. BarFooId
--           where_ $
--               foo ^. FooParentId ==. val parentId
--           pure (foo, bar)
--   
-- -- This is a natural result type for SQL - a list of tuples. However, -- it's not what we usually want in Haskell - each Foo in the -- list will be represented multiple times, once for each Bar. -- -- We can write fmap associateJoin and it will -- translate it into a Map that is keyed on the Key of -- the left Entity, and the value is a tuple of the entity's value -- as well as the list of each coresponding entity. -- --
--   getFoosAndNestedBarsFromParentHaskellese
--       :: ParentId
--       -> SqlPersistT (Map (Key Foo) (Foo, [Maybe (Entity Bar)]))
--   getFoosAndNestedBarsFromParentHaskellese parentId =
--       fmap associateJoin $ getFoosdAndNestedBarsFromParent parentId
--   
-- -- What if you have multiple joins? -- -- Let's use associateJoin with a *two* join query. -- --
--   userPostComments
--       :: SqlQuery (SqlExpr (Entity User, Entity Post, Entity Comment))
--   userPostsComment = do
--       (u :& p :& c) <- from $
--           table User
--           `InnerJoin`
--           table Post
--               on do
--                   \(u :& p) ->
--                       u ^. UserId ==. p ^. PostUserId
--           `InnerJoin`
--           table @Comment
--               `on` do
--                   \(_ :& p :& c) ->
--                       p ^. PostId ==. c ^. CommentPostId
--       pure (u, p, c)
--   
-- -- This query returns a User, with all of the users Posts, and then all -- of the Comments on that post. -- -- First, we *nest* the tuple. -- --
--   nest :: (a, b, c) -> (a, (b, c))
--   nest (a, b, c) = (a, (b, c))
--   
-- -- This makes the return of the query conform to the input expected from -- associateJoin. -- --
--   nestedUserPostComments
--       :: SqlPersistT IO [(Entity User, (Entity Post, Entity Comment))]
--   nestedUserPostComments =
--       fmap nest $ select userPostsComments
--   
-- -- Now, we can call associateJoin on it. -- --
--   associateUsers
--       :: [(Entity User, (Entity Post, Entity Comment))]
--       -> Map UserId (User, [(Entity Post, Entity Comment)])
--   associateUsers =
--       associateJoin
--   
-- -- Next, we'll use the Functor instances for Map and -- tuple to call associateJoin on the [(Entity Post, Entity -- Comment)]. -- --
--   associatePostsAndComments
--       :: Map UserId (User, [(Entity Post, Entity Comment)])
--       -> Map UserId (User, Map PostId (Post, [Entity Comment]))
--   associatePostsAndComments =
--       fmap (fmap associateJoin)
--   
-- -- For more reading on this topic, see this Foxhound Systems blog -- post. associateJoin :: forall e1 e0. Ord (Key e0) => [(Entity e0, e1)] -> Map (Key e0) (e0, [e1]) -- | Synonym for delete that does not clash with -- esqueleto's delete. deleteKey :: forall backend val (m :: Type -> Type). (PersistStore backend, BaseBackend backend ~ PersistEntityBackend val, MonadIO m, PersistEntity val) => Key val -> ReaderT backend m () -- | valJ is like val but for something that is already a -- Value. The use case it was written for was, given a -- Value lift the Key for that Value into the -- query expression in a type safe way. However, the implementation is -- more generic than that so we call it valJ. -- -- Its important to note that the input entity and the output entity are -- constrained to be the same by the type signature on the function -- (https://github.com/prowdsponsor/esqueleto/pull/69). valJ :: PersistField (Key entity) => Value (Key entity) -> SqlExpr (Value (Key entity)) -- | valkey i = val . toSqlKey -- (https://github.com/prowdsponsor/esqueleto/issues/9). valkey :: (ToBackendKey SqlBackend entity, PersistField (Key entity)) => Int64 -> SqlExpr (Value (Key entity)) -- | Insert a PersistField for every selected value, return the -- count afterward insertSelectCount :: forall (m :: Type -> Type) a backend. (MonadIO m, PersistEntity a, SqlBackendCanWrite backend) => SqlQuery (SqlExpr (Insertion a)) -> ReaderT backend m Int64 -- | Insert a PersistField for every selected value. insertSelect :: forall (m :: Type -> Type) a backend. (MonadIO m, PersistEntity a, SqlBackendCanWrite backend) => SqlQuery (SqlExpr (Insertion a)) -> ReaderT backend m () -- | Renders a SqlQuery into a Text value along with the -- list of PersistValues that would be supplied to the database -- for ? placeholders. renderQueryInsertInto :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m) => SqlQuery a -> ReaderT backend m (Text, [PersistValue]) -- | Renders a SqlQuery into a Text value along with the -- list of PersistValues that would be supplied to the database -- for ? placeholders. renderQueryUpdate :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m) => SqlQuery a -> ReaderT backend m (Text, [PersistValue]) -- | Renders a SqlQuery into a Text value along with the -- list of PersistValues that would be supplied to the database -- for ? placeholders. renderQueryDelete :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m) => SqlQuery a -> ReaderT backend m (Text, [PersistValue]) -- | Renders a SqlQuery into a Text value along with the -- list of PersistValues that would be supplied to the database -- for ? placeholders. -- -- You must ensure that the Mode you pass to this function -- corresponds with the actual SqlQuery. If you pass a query that -- uses incompatible features (like an INSERT statement with a -- SELECT mode) then you'll get a weird result. renderQueryToText :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, Monad m) => Mode -> SqlQuery a -> ReaderT backend m (Text, [PersistValue]) -- | Same as update, but returns the number of rows affected. updateCount :: forall (m :: Type -> Type) val backend. (MonadIO m, PersistEntity val, BackendCompatible SqlBackend (PersistEntityBackend val), SqlBackendCanWrite backend) => (SqlExpr (Entity val) -> SqlQuery ()) -> ReaderT backend m Int64 -- | Same as delete, but returns the number of rows affected. deleteCount :: forall (m :: Type -> Type) backend. (MonadIO m, SqlBackendCanWrite backend) => SqlQuery () -> ReaderT backend m Int64 -- | Execute an esqueleto SELECT query inside -- persistent's SqlPersistT monad and return a -- Source of rows. selectSource :: forall a r backend (m :: Type -> Type). (SqlSelect a r, BackendCompatible SqlBackend backend, IsPersistBackend backend, PersistQueryRead backend, PersistStoreRead backend, PersistUniqueRead backend, MonadResource m) => SqlQuery a -> ConduitT () r (ReaderT backend m) () -- | Syntax sugar for case_. else_ :: expr a -> expr a -- | Syntax sugar for case_. then_ :: () -- | Syntax sugar for case_. when_ :: expr (Value Bool) -> () -> expr a -> (expr (Value Bool), expr a) -- | Convert an entity's key into another entity's. -- -- This function is to be used when you change an entity's Id to -- be that of another entity. For example: -- --
--   Bar
--     barNum Int
--   Foo
--     bar BarId
--     fooNum Int
--     Primary bar
--   
-- -- In this example, Bar is said to be the BaseEnt(ity), and Foo the -- child. To model this in Esqueleto, declare: -- --
--   instance ToBaseId Foo where
--     type BaseEnt Foo = Bar
--     toBaseIdWitness barId = FooKey barId
--   
-- -- Now you're able to write queries such as: -- --
--   select $
--   from $ (bar `InnerJoin` foo) -> do
--   on (toBaseId (foo ^. FooId) ==. bar ^. BarId)
--   return (bar, foo)
--   
-- -- Note: this function may be unsafe to use in conditions not like the -- one of the example above. toBaseId :: ToBaseId ent => SqlExpr (Value (Key ent)) -> SqlExpr (Value (Key (BaseEnt ent))) -- | CASE statement. For example: -- --
--   select $
--   return $
--   case_
--      [ when_
--          (exists $
--          from $ \p -> do
--          where_ (p ^. PersonName ==. val "Mike"))
--        then_
--          (sub_select $
--          from $ \v -> do
--          let sub =
--                  from $ \c -> do
--                  where_ (c ^. PersonName ==. val "Mike")
--                  return (c ^. PersonFavNum)
--          where_ (v ^. PersonFavNum >. sub_select sub)
--          return $ count (v ^. PersonName) +. val (1 :: Int)) ]
--      (else_ $ val (-1))
--   
-- -- This query is a bit complicated, but basically it checks if a person -- named "Mike" exists, and if that person does, run the -- subquery to find out how many people have a ranking (by Fav Num) -- higher than "Mike". -- -- NOTE: There are a few things to be aware about this statement. -- -- case_ :: PersistField a => [(SqlExpr (Value Bool), SqlExpr (Value a))] -> SqlExpr (Value a) -> SqlExpr (Value a) -- | Apply extra SqlExpr Value arguments to a PersistField -- constructor (<&>) :: SqlExpr (Insertion (a -> b)) -> SqlExpr (Value a) -> SqlExpr (Insertion b) -- | Apply a PersistField constructor to SqlExpr Value -- arguments. (<#) :: (a -> b) -> SqlExpr (Value a) -> SqlExpr (Insertion b) (/=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 /=. (*=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 *=. (-=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 -=. (+=.) :: (PersistEntity val, PersistField a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 +=. (=.) :: (PersistEntity val, PersistField typ) => EntityField val typ -> SqlExpr (Value typ) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 =. -- | SET clause used on UPDATEs. Note that while it's not -- a type error to use this function on a SELECT, it will most -- certainly result in a runtime error. set :: PersistEntity val => SqlExpr (Entity val) -> [SqlExpr (Entity val) -> SqlExpr Update] -> SqlQuery () -- | NOT EXISTS operator. notExists :: SqlQuery () -> SqlExpr (Value Bool) -- | EXISTS operator. For example: -- --
--   select $
--   from $ \person -> do
--   where_ $ exists $
--            from $ \post -> do
--            where_ (post ^. BlogPostAuthorId ==. person ^. PersonId)
--   return person
--   
exists :: SqlQuery () -> SqlExpr (Value Bool) -- | NOT IN operator. notIn :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (ValueList typ) -> SqlExpr (Value Bool) -- | IN operator. For example if you want to select all -- Persons by a list of IDs: -- --
--   SELECT *
--   FROM Person
--   WHERE Person.id IN (?)
--   
-- -- In esqueleto, we may write the same query above as: -- --
--   select $
--   from $ \person -> do
--   where_ $ person ^. PersonId `in_` valList personIds
--   return person
--   
-- -- Where personIds is of type [Key Person]. in_ :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (ValueList typ) -> SqlExpr (Value Bool) -- | Same as just but for ValueList. Most of the time you -- won't need it, though, because you can use just from inside -- subList_select or Just from inside valList. justList :: SqlExpr (ValueList typ) -> SqlExpr (ValueList (Maybe typ)) -- | Lift a list of constant value from Haskell-land to the query. valList :: PersistField typ => [typ] -> SqlExpr (ValueList typ) -- | Execute a subquery SELECT in an SqlExpression. Returns a list -- of values. subList_select :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (ValueList a) -- | Cast a string type into Text. This function is very useful if -- you want to use newtypes, or if you want to apply functions -- such as like to strings of different types. -- -- Safety: This is a slightly unsafe function, especially if you -- have defined your own instances of SqlString. Also, since -- Maybe is an instance of SqlString, it's possible to turn -- a nullable value into a non-nullable one. Avoid using this function if -- possible. castString :: (SqlString s, SqlString r) => SqlExpr (Value s) -> SqlExpr (Value r) -- | The || string concatenation operator (named after Haskell's -- ++ in order to avoid naming clash with ||.). Supported -- by SQLite and PostgreSQL. (++.) :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value s) infixr 5 ++. -- | The CONCAT function with a variable number of parameters. -- Supported by MySQL and PostgreSQL. concat_ :: SqlString s => [SqlExpr (Value s)] -> SqlExpr (Value s) -- | The string %. May be useful while using like -- and concatenation (concat_ or ++., depending on your -- database). Note that you always have to type the parenthesis, for -- example: -- --
--   name `like` (%) ++. val "John" ++. (%)
--   
(%) :: SqlString s => SqlExpr (Value s) -- | ILIKE operator (case-insensitive LIKE). -- -- Supported by PostgreSQL only. ilike :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool) infixr 2 `ilike` -- | LIKE operator. like :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool) infixr 2 `like` -- | RIGHT function. @since 3.3.0 right_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s) -- | LEFT function. @since 3.3.0 left_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s) -- | LENGTH function. @since 3.3.0 length_ :: (SqlString s, Num a) => SqlExpr (Value s) -> SqlExpr (Value a) -- | LTRIM function. @since 3.3.0 ltrim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | RTRIM function. @since 3.3.0 rtrim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | TRIM function. @since 3.3.0 trim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | UPPER function. @since 3.3.0 upper_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | LOWER function. lower_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | Like coalesce, but takes a non-nullable SqlExpression placed -- at the end of the SqlExpression list, which guarantees a non-NULL -- result. coalesceDefault :: PersistField a => [SqlExpr (Value (Maybe a))] -> SqlExpr (Value a) -> SqlExpr (Value a) -- | COALESCE function. Evaluates the arguments in order and -- returns the value of the first non-NULL SqlExpression, or NULL -- (Nothing) otherwise. Some RDBMSs (such as SQLite) require at least two -- arguments; please refer to the appropriate documentation. coalesce :: PersistField a => [SqlExpr (Value (Maybe a))] -> SqlExpr (Value (Maybe a)) -- | Same as castNum, but for nullable values. castNumM :: (Num a, Num b) => SqlExpr (Value (Maybe a)) -> SqlExpr (Value (Maybe b)) -- | Allow a number of one type to be used as one of another type via an -- implicit cast. An explicit cast is not made, this function changes -- only the types on the Haskell side. -- -- Caveat: Trying to use castNum from Double to -- Int will not result in an integer, the original fractional -- number will still be used! Use round_, ceiling_ or -- floor_ instead. -- -- Safety: This operation is mostly safe due to the Num -- constraint between the types and the fact that RDBMSs usually allow -- numbers of different types to be used interchangeably. However, there -- may still be issues with the query not being accepted by the RDBMS or -- persistent not being able to parse it. castNum :: (Num a, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) avg_ :: (PersistField a, PersistField b) => SqlExpr (Value a) -> SqlExpr (Value (Maybe b)) max_ :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value (Maybe a)) min_ :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value (Maybe a)) sum_ :: (PersistField a, PersistField b) => SqlExpr (Value a) -> SqlExpr (Value (Maybe b)) floor_ :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) ceiling_ :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) round_ :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) random_ :: (PersistField a, Num a) => SqlExpr (Value a) -- | BETWEEN. -- -- @since: 3.1.0 between :: PersistField a => SqlExpr (Value a) -> (SqlExpr (Value a), SqlExpr (Value a)) -> SqlExpr (Value Bool) (*.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 7 *. (/.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 7 /. (-.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 6 -. (+.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 6 +. (||.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool) infixr 2 ||. (&&.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool) infixr 3 &&. (!=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 !=. (<.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 <. (<=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 <=. (>.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 >. (>=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 >=. (==.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 ==. not_ :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -- | COUNT(DISTINCT x). countDistinct :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a) -- | COUNT. count :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a) -- | COUNT(*) value. countRows :: Num a => SqlExpr (Value a) -- | Join nested Maybes in a Value into one. This is useful -- when calling aggregate functions on nullable fields. joinV :: SqlExpr (Value (Maybe (Maybe typ))) -> SqlExpr (Value (Maybe typ)) -- | NULL value. nothing :: SqlExpr (Value (Maybe typ)) -- | Analogous to Just, promotes a value of type typ into -- one of type Maybe typ. It should hold that val . -- Just === just . val. just :: SqlExpr (Value typ) -> SqlExpr (Value (Maybe typ)) -- | IS NULL comparison. -- -- For IS NOT NULL, you can negate this with not_, as in -- not_ (isNothing (person ^. PersonAge)) -- -- Warning: Persistent and Esqueleto have different behavior for != -- Nothing: -- -- TODO: table -- -- In SQL, = NULL and != NULL return NULL instead of -- true or false. For this reason, you very likely do not want to use -- !=. Nothing in Esqueleto. You may find these -- hlint rules helpful to enforce this: -- --
--   - error: {lhs: v Database.Esqueleto.==. Database.Esqueleto.nothing, rhs: Database.Esqueleto.isNothing v, name: Use Esqueleto's isNothing}
--   - error: {lhs: v Database.Esqueleto.==. Database.Esqueleto.val Nothing, rhs: Database.Esqueleto.isNothing v, name: Use Esqueleto's isNothing}
--   - error: {lhs: v Database.Esqueleto.!=. Database.Esqueleto.nothing, rhs: not_ (Database.Esqueleto.isNothing v), name: Use Esqueleto's not isNothing}
--   - error: {lhs: v Database.Esqueleto.!=. Database.Esqueleto.val Nothing, rhs: not_ (Database.Esqueleto.isNothing v), name: Use Esqueleto's not isNothing}
--   
isNothing :: PersistField typ => SqlExpr (Value (Maybe typ)) -> SqlExpr (Value Bool) -- | Lift a constant value from Haskell-land to the query. val :: PersistField typ => typ -> SqlExpr (Value typ) -- | Project a field of an entity that may be null. (?.) :: (PersistEntity val, PersistField typ) => SqlExpr (Maybe (Entity val)) -> EntityField val typ -> SqlExpr (Value (Maybe typ)) -- | Project an SqlExpression that may be null, guarding against null -- cases. withNonNull :: PersistField typ => SqlExpr (Value (Maybe typ)) -> (SqlExpr (Value typ) -> SqlQuery a) -> SqlQuery a -- | Project a field of an entity. (^.) :: forall typ val. (PersistEntity val, PersistField typ) => SqlExpr (Entity val) -> EntityField val typ -> SqlExpr (Value typ) infixl 9 ^. -- | Execute a subquery SELECT in a SqlExpr. This function -- is unsafe, because it can throw runtime exceptions in two cases: -- --
    --
  1. If the query passed has 0 result rows, then it will return a -- NULL value. The persistent parsing operations will -- fail on an unexpected NULL.
  2. --
  3. If the query passed returns more than one row, then the SQL engine -- will fail with an error like "More than one row returned by a subquery -- used as an expression".
  4. --
-- -- This function is safe if you guarantee that exactly one row will be -- returned, or if the result already has a Maybe type for some -- reason. -- -- For variants with the safety encoded already, see subSelect and -- subSelectMaybe. For the most common safe use of this, see -- subSelectCount. subSelectUnsafe :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value a) -- | Performs a sub-select using the given foreign key on the entity. This -- is useful to extract values that are known to be present by the -- database schema. -- -- As an example, consider the following persistent definition: -- --
--   User
--     profile ProfileId
--   
--   Profile
--     name    Text
--   
-- -- The following query will return the name of the user. -- --
--   getUserWithName =
--       select $
--       from $ user ->
--       pure (user, subSelectForeign user UserProfile (^. ProfileName)
--   
subSelectForeign :: (BackendCompatible SqlBackend (PersistEntityBackend val1), PersistEntity val1, PersistEntity val2, PersistField a) => SqlExpr (Entity val2) -> EntityField val2 (Key val1) -> (SqlExpr (Entity val1) -> SqlExpr (Value a)) -> SqlExpr (Value a) -- | Execute a subquery SELECT in a SqlExpr that returns a -- list. This is an alias for subList_select and is provided for -- symmetry with the other safe subselect functions. subSelectList :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (ValueList a) -- | Performs a COUNT of the given query in a subSelect -- manner. This is always guaranteed to return a result value, and is -- completely safe. subSelectCount :: (Num a, PersistField a) => SqlQuery ignored -> SqlExpr (Value a) -- | Execute a subquery SELECT in a SqlExpr. This function -- is a shorthand for the common joinV . subSelect -- idiom, where you are calling subSelect on an expression that -- would be Maybe already. -- -- As an example, you would use this function when calling sum_ or -- max_, which have Maybe in the result type (for a 0 row -- query). subSelectMaybe :: PersistField a => SqlQuery (SqlExpr (Value (Maybe a))) -> SqlExpr (Value (Maybe a)) -- | Execute a subquery SELECT in a SqlExpr. The query -- passed to this function will only return a single result - it has a -- LIMIT 1 passed in to the query to make it safe, and the -- return type is Maybe to indicate that the subquery might result -- in 0 rows. -- -- If you find yourself writing joinV . subSelect, -- then consider using subSelectMaybe. -- -- If you're performing a countRows, then you can use -- subSelectCount which is safe. -- -- If you know that the subquery will always return exactly one row (eg a -- foreign key constraint guarantees that you'll get exactly one row), -- then consider subSelectUnsafe, along with a comment explaining -- why it is safe. subSelect :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value (Maybe a)) -- | Execute a subquery SELECT in an SqlExpression. Returns a -- simple value so should be used only when the SELECT query is -- guaranteed to return just one row. -- -- Deprecated in 3.2.0. sub_select :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value a) -- | Add a locking clause to the query. Please read LockingKind -- documentation and your RDBMS manual. -- -- If multiple calls to locking are made on the same query, the -- last one is used. locking :: LockingKind -> SqlQuery () -- | HAVING. having :: SqlExpr (Value Bool) -> SqlQuery () -- | ORDER BY random() clause. rand :: SqlExpr OrderBy -- | A convenience function that calls both distinctOn and -- orderBy. In other words, -- --
--   distinctOnOrderBy [asc foo, desc bar, desc quux] $ do
--     ...
--   
-- -- is the same as: -- --
--   distinctOn [don foo, don  bar, don  quux] $ do
--     orderBy  [asc foo, desc bar, desc quux]
--     ...
--   
distinctOnOrderBy :: [SqlExpr OrderBy] -> SqlQuery a -> SqlQuery a -- | Erase an SqlExpression's type so that it's suitable to be used by -- distinctOn. don :: SqlExpr (Value a) -> SqlExpr DistinctOn -- | DISTINCT ON. Change the current SELECT into -- SELECT DISTINCT ON (SqlExpressions). For example: -- --
--   select $
--     from \foo ->
--     distinctOn [don (foo ^. FooName), don (foo ^. FooState)] $ do
--     ...
--   
-- -- You can also chain different calls to distinctOn. The above is -- equivalent to: -- --
--   select $
--     from \foo ->
--     distinctOn [don (foo ^. FooName)] $
--     distinctOn [don (foo ^. FooState)] $ do
--     ...
--   
-- -- Each call to distinctOn adds more SqlExpressions. Calls to -- distinctOn override any calls to distinct. -- -- Note that PostgreSQL requires the SqlExpressions on DISTINCT -- ON to be the first ones to appear on a ORDER BY. This is -- not managed automatically by esqueleto, keeping its spirit of trying -- to be close to raw SQL. -- -- Supported by PostgreSQL only. distinctOn :: [SqlExpr DistinctOn] -> SqlQuery a -> SqlQuery a -- | DISTINCT. Change the current SELECT into SELECT -- DISTINCT. For example: -- --
--   select $ distinct $
--     from \foo -> do
--     ...
--   
-- -- Note that this also has the same effect: -- --
--   select $
--     from \foo -> do
--     distinct (return ())
--     ...
--   
distinct :: SqlQuery a -> SqlQuery a -- | OFFSET. Usually used with limit. offset :: Int64 -> SqlQuery () -- | LIMIT. Limit the number of returned rows. limit :: Int64 -> SqlQuery () -- | Descending order of this field or SqlExpression. desc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy -- | Ascending order of this field or SqlExpression. asc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy -- | ORDER BY clause. See also asc and desc. -- -- Multiple calls to orderBy get concatenated on the final query, -- including distinctOnOrderBy. orderBy :: [SqlExpr OrderBy] -> SqlQuery () -- | GROUP BY clause. You can enclose multiple columns in a tuple. -- --
--   select $ from \(foo `InnerJoin` bar) -> do
--     on (foo ^. FooBarId ==. bar ^. BarId)
--     groupBy (bar ^. BarId, bar ^. BarName)
--     return (bar ^. BarId, bar ^. BarName, countRows)
--   
-- -- With groupBy you can sort by aggregate functions, like so (we used -- let to restrict the more general countRows to -- SqlSqlExpr (Value Int) to avoid ambiguity---the second use of -- countRows has its type restricted by the :: Int -- below): -- --
--   r <- select $ from \(foo `InnerJoin` bar) -> do
--     on (foo ^. FooBarId ==. bar ^. BarId)
--     groupBy $ bar ^. BarName
--     let countRows' = countRows
--     orderBy [asc countRows']
--     return (bar ^. BarName, countRows')
--   forM_ r $ \(Value name, Value count) -> do
--     print name
--     print (count :: Int)
--   
-- --

Need more columns?

-- -- The ToSomeValues class is defined for SqlExpr and tuples -- of SqlExprs. We only have definitions for up to 8 elements in a -- tuple right now, so it's possible that you may need to have more than -- 8 elements. -- -- For example, consider a query with a groupBy call like this: -- --
--   groupBy (e0, e1, e2, e3, e4, e5, e6, e7)
--   
-- -- This is the biggest you can get with a single tuple. However, you can -- easily nest the tuples to add more: -- --
--   groupBy ((e0, e1, e2, e3, e4, e5, e6, e7), e8, e9)
--   
groupBy :: ToSomeValues a => a -> SqlQuery () -- | WHERE clause: restrict the query's result. where_ :: SqlExpr (Value Bool) -> SqlQuery () -- | A single value (as opposed to a whole entity). You may use -- (^.) or (?.) to get a Value -- from an Entity. newtype Value a Value :: a -> Value a [unValue] :: Value a -> a -- | A list of single values. There's a limited set of functions able to -- work with this data type (such as subList_select, -- valList, in_ and exists). newtype ValueList a ValueList :: a -> ValueList a -- | Data type that represents an INNER JOIN (see -- LeftOuterJoin for an example). data InnerJoin a b InnerJoin :: a -> b -> InnerJoin a b infixl 2 `InnerJoin` infixl 2 `InnerJoin` -- | Data type that represents a CROSS JOIN (see -- LeftOuterJoin for an example). data CrossJoin a b CrossJoin :: a -> b -> CrossJoin a b infixl 2 `CrossJoin` infixl 2 `CrossJoin` -- | Data type that represents a LEFT OUTER JOIN. For example, -- --
--   select $
--   from $ \(person `LeftOuterJoin` pet) ->
--     ...
--   
-- -- is translated into -- --
--   SELECT ...
--   FROM Person LEFT OUTER JOIN Pet
--   ...
--   
-- -- See also: from. data LeftOuterJoin a b LeftOuterJoin :: a -> b -> LeftOuterJoin a b infixl 2 `LeftOuterJoin` infixl 2 `LeftOuterJoin` -- | Data type that represents a RIGHT OUTER JOIN (see -- LeftOuterJoin for an example). data RightOuterJoin a b RightOuterJoin :: a -> b -> RightOuterJoin a b infixl 2 `RightOuterJoin` infixl 2 `RightOuterJoin` -- | Data type that represents a FULL OUTER JOIN (see -- LeftOuterJoin for an example). data FullOuterJoin a b FullOuterJoin :: a -> b -> FullOuterJoin a b infixl 2 `FullOuterJoin` infixl 2 `FullOuterJoin` -- | (Internal) A kind of JOIN. data JoinKind -- |
--   INNER JOIN
--   
InnerJoinKind :: JoinKind -- |
--   CROSS JOIN
--   
CrossJoinKind :: JoinKind -- |
--   LEFT OUTER JOIN
--   
LeftOuterJoinKind :: JoinKind -- |
--   RIGHT OUTER JOIN
--   
RightOuterJoinKind :: JoinKind -- |
--   FULL OUTER JOIN
--   
FullOuterJoinKind :: JoinKind -- | Exception thrown whenever on is used to create an ON -- clause but no matching JOIN is found. data OnClauseWithoutMatchingJoinException OnClauseWithoutMatchingJoinException :: String -> OnClauseWithoutMatchingJoinException -- | Phantom type used by orderBy, asc and desc. data OrderBy -- | Phantom type used by distinctOn and don. data DistinctOn -- | Different kinds of locking clauses supported by locking. -- -- Note that each RDBMS has different locking support. The constructors -- of this datatype specify only the syntax of the locking -- mechanism, not its semantics. For example, even though both -- MySQL and PostgreSQL support ForUpdate, there are no guarantees -- that they will behave the same. data LockingKind -- | FOR UPDATE syntax. Supported by MySQL, Oracle and PostgreSQL. ForUpdate :: LockingKind -- | FOR UPDATE SKIP LOCKED syntax. Supported by MySQL, Oracle and -- PostgreSQL. ForUpdateSkipLocked :: LockingKind -- | FOR SHARE syntax. Supported by PostgreSQL. ForShare :: LockingKind -- | LOCK IN SHARE MODE syntax. Supported by MySQL. LockInShareMode :: LockingKind -- | Phantom class of data types that are treated as strings by the RDBMS. -- It has no methods because it's only used to avoid type errors such as -- trying to concatenate integers. -- -- If you have a custom data type or newtype, feel free to make -- it an instance of this class. class PersistField a => SqlString a -- | e.g. type BaseEnt MyBase = MyChild type family BaseEnt ent -- | Class that enables one to use toBaseId to convert an entity's -- key on a query into another (cf. toBaseId). class ToBaseId ent where { -- | e.g. type BaseEnt MyBase = MyChild type family BaseEnt ent; } -- | Convert from the key of the BaseEnt(ity) to the key of the child -- entity. This function is not actually called, but that it typechecks -- proves this operation is safe. toBaseIdWitness :: ToBaseId ent => Key (BaseEnt ent) -> Key ent -- | SQL backend for esqueleto using SqlPersistT. data SqlQuery a -- | Constraint synonym for persistent entities whose backend is -- SqlBackend. type SqlEntity ent = (PersistEntity ent, PersistEntityBackend ent ~ SqlBackend) -- | An expression on the SQL backend. -- -- Raw expression: Contains a SqlExprMeta and a function for -- building the expr. It recieves a parameter telling it whether it is in -- a parenthesized context, and takes information about the SQL -- connection (mainly for escaping names) and returns both an string -- (Builder) and a list of values to be interpolated by the SQL -- backend. data SqlExpr 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 -> Type -> Type -> Type; 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 type family PersistConfigBackend c :: Type -> Type -> Type -> Type type family PersistConfigPool c -- | An ConstraintNameHS represents the Haskell-side name that -- persistent will use for a constraint. newtype ConstraintNameHS ConstraintNameHS :: Text -> ConstraintNameHS [unConstraintNameHS] :: ConstraintNameHS -> Text -- | A ConstraintNameDB represents the datastore-side name that -- persistent will use for a constraint. newtype ConstraintNameDB ConstraintNameDB :: Text -> ConstraintNameDB [unConstraintNameDB] :: ConstraintNameDB -> Text -- | An EntityNameDB represents the datastore-side name that -- persistent will use for an entity. newtype EntityNameDB EntityNameDB :: Text -> EntityNameDB [unEntityNameDB] :: EntityNameDB -> Text -- | An EntityNameHS represents the Haskell-side name that -- persistent will use for an entity. newtype EntityNameHS EntityNameHS :: Text -> EntityNameHS [unEntityNameHS] :: EntityNameHS -> Text -- | A FieldNameHS represents the Haskell-side name that -- persistent will use for a field. newtype FieldNameHS FieldNameHS :: Text -> FieldNameHS [unFieldNameHS] :: FieldNameHS -> Text -- | An EntityNameDB represents the datastore-side name that -- persistent will use for an entity. newtype FieldNameDB FieldNameDB :: Text -> FieldNameDB [unFieldNameDB] :: FieldNameDB -> Text -- | Convenience operations for working with '-NameDB' types. class DatabaseName a escapeWith :: DatabaseName a => (Text -> str) -> a -> str -- | A type that determines how a backend should handle the literal. data LiteralType -- | The accompanying value will be escaped before inserting into the -- database. This is the correct default choice to use. Escaped :: LiteralType -- | The accompanying value will not be escaped when inserting into the -- database. This is potentially dangerous - use this with care. Unescaped :: LiteralType -- | The DbSpecific constructor corresponds to the legacy -- PersistDbSpecific constructor. We need to keep this around -- because old databases may have serialized JSON representations that -- reference this. We don't want to break the ability of a database to -- load rows. DbSpecific :: LiteralType -- | 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 -- | This constructor is used to specify some raw literal value for the -- backend. The LiteralType value specifies how the value should -- be escaped. This can be used to make special, custom types avaialable -- in the back end. PersistLiteral_ :: LiteralType -> ByteString -> PersistValue -- | This pattern synonym used to be a data constructor on -- PersistValue, but was changed into a catch-all pattern synonym -- to allow backwards compatiblity with database types. See the -- documentation on PersistDbSpecific for more details. pattern PersistLiteral :: ByteString -> PersistValue -- | This pattern synonym used to be a data constructor for the -- PersistValue type. It was changed to be a pattern so that -- JSON-encoded database values could be parsed into their corresponding -- values. You should not use this, and instead prefer to pattern match -- on PersistLiteral_ directly. -- -- If you use this, it will overlap a patern match on the -- 'PersistLiteral_, PersistLiteral, and -- PersistLiteralEscaped patterns. If you need to disambiguate -- between these constructors, pattern match on PersistLiteral_ -- directly. pattern PersistDbSpecific :: ByteString -> PersistValue -- | This pattern synonym used to be a data constructor on -- PersistValue, but was changed into a catch-all pattern synonym -- to allow backwards compatiblity with database types. See the -- documentation on PersistDbSpecific for more details. pattern PersistLiteralEscaped :: ByteString -> PersistValue fromPersistValueText :: PersistValue -> Either Text Text -- | 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 -- | 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 :: !FieldNameHS -> !FieldNameDB -> !FieldType -> !SqlType -> ![FieldAttr] -> !Bool -> !ReferenceDef -> !FieldCascade -> !Maybe Text -> !Maybe Text -> !Bool -> 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 FieldNameHS "name" for -- a type User will have a record field userName. [fieldHaskell] :: FieldDef -> !FieldNameHS -- | The name of the field in the database. For SQL databases, this -- corresponds to the column name. [fieldDB] :: FieldDef -> !FieldNameDB -- | 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 -> ![FieldAttr] -- | 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 -- | Defines how operations on the field cascade on to the referenced -- tables. This doesn't have any meaning if the fieldReference is -- set to NoReference or SelfReference. The cascade option -- here should be the same as the one obtained in the -- fieldReference. [fieldCascade] :: FieldDef -> !FieldCascade -- | Optional comments for a Field. There is not currently a way -- to attach comments to a field in the quasiquoter. [fieldComments] :: FieldDef -> !Maybe Text -- | Whether or not the field is a GENERATED column, and -- additionally the expression to use for generation. [fieldGenerated] :: FieldDef -> !Maybe Text -- | True if the field is an implicit ID column. False -- otherwise. [fieldIsImplicitIdColumn] :: FieldDef -> !Bool data PersistUpdate Assign :: PersistUpdate Add :: PersistUpdate Subtract :: PersistUpdate Multiply :: PersistUpdate Divide :: PersistUpdate BackendSpecificUpdate :: Text -> PersistUpdate data UpdateException KeyNotFound :: String -> UpdateException UpsertError :: String -> UpdateException data PersistFilter Eq :: PersistFilter Ne :: PersistFilter Gt :: PersistFilter Lt :: PersistFilter Ge :: PersistFilter Le :: PersistFilter In :: PersistFilter NotIn :: PersistFilter -- | 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 PersistException -- | Generic Exception PersistError :: Text -> PersistException PersistMarshalError :: Text -> PersistException PersistInvalidField :: Text -> PersistException PersistForeignConstraintUnmet :: Text -> PersistException PersistMongoDBError :: Text -> PersistException PersistMongoDBUnsupported :: Text -> PersistException -- | An action that might happen on a deletion or update on a foreign key -- change. data CascadeAction Cascade :: CascadeAction Restrict :: CascadeAction SetNull :: CascadeAction SetDefault :: CascadeAction -- | This datatype describes how a foreign reference field cascades deletes -- or updates. -- -- This type is used in both parsing the model definitions and performing -- migrations. A Nothing in either of the field values means that -- the user has not specified a CascadeAction. An unspecified -- CascadeAction is defaulted to Restrict when doing -- migrations. data FieldCascade FieldCascade :: !Maybe CascadeAction -> !Maybe CascadeAction -> FieldCascade [fcOnUpdate] :: FieldCascade -> !Maybe CascadeAction [fcOnDelete] :: FieldCascade -> !Maybe CascadeAction data ForeignDef ForeignDef :: !EntityNameHS -> !EntityNameDB -> !ConstraintNameHS -> !ConstraintNameDB -> !FieldCascade -> ![(ForeignFieldDef, ForeignFieldDef)] -> ![Attr] -> Bool -> Bool -> ForeignDef [foreignRefTableHaskell] :: ForeignDef -> !EntityNameHS [foreignRefTableDBName] :: ForeignDef -> !EntityNameDB [foreignConstraintNameHaskell] :: ForeignDef -> !ConstraintNameHS [foreignConstraintNameDBName] :: ForeignDef -> !ConstraintNameDB -- | Determine how the field will cascade on updates and deletions. [foreignFieldCascade] :: ForeignDef -> !FieldCascade [foreignFields] :: ForeignDef -> ![(ForeignFieldDef, ForeignFieldDef)] [foreignAttrs] :: ForeignDef -> ![Attr] [foreignNullable] :: ForeignDef -> Bool -- | Determines if the reference is towards a Primary Key or not. [foreignToPrimary] :: ForeignDef -> Bool -- | Used instead of FieldDef to generate a smaller amount of code type ForeignFieldDef = (FieldNameHS, FieldNameDB) data CompositeDef CompositeDef :: !NonEmpty FieldDef -> ![Attr] -> CompositeDef [compositeFields] :: CompositeDef -> !NonEmpty FieldDef [compositeAttrs] :: CompositeDef -> ![Attr] -- | Type for storing the Uniqueness constraint in the Schema. Assume you -- have the following schema with a uniqueness constraint: -- --
--   Person
--     name String
--     age Int
--     UniqueAge age
--   
-- -- This will be represented as: -- --
--   UniqueDef
--       { uniqueHaskell = ConstraintNameHS (packPTH UniqueAge)
--       , uniqueDBName = ConstraintNameDB (packPTH "unique_age")
--       , uniqueFields = [(FieldNameHS (packPTH "age"), FieldNameDB (packPTH "age"))]
--       , uniqueAttrs = []
--       }
--   
data UniqueDef UniqueDef :: !ConstraintNameHS -> !ConstraintNameDB -> !NonEmpty (FieldNameHS, FieldNameDB) -> ![Attr] -> UniqueDef [uniqueHaskell] :: UniqueDef -> !ConstraintNameHS [uniqueDBName] :: UniqueDef -> !ConstraintNameDB [uniqueFields] :: UniqueDef -> !NonEmpty (FieldNameHS, FieldNameDB) [uniqueAttrs] :: UniqueDef -> ![Attr] -- | 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 :: FieldNameDB -> Maybe (Either SelfEmbed EntityNameHS) -> EmbedFieldDef [emFieldDB] :: EmbedFieldDef -> FieldNameDB [emFieldEmbed] :: EmbedFieldDef -> Maybe (Either SelfEmbed EntityNameHS) -- | 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 :: EntityNameHS -> [EmbedFieldDef] -> EmbedEntityDef [embeddedHaskell] :: EmbedEntityDef -> EntityNameHS [embeddedFields] :: EmbedEntityDef -> [EmbedFieldDef] -- | 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 -- name and has the Haskell type of the foreign key in the form of -- FieldType ForeignRef :: !EntityNameHS -> ReferenceDef EmbedRef :: EntityNameHS -> ReferenceDef CompositeRef :: CompositeDef -> ReferenceDef -- | A SelfReference stops an immediate cycle which causes non-termination -- at compile-time (issue #311). SelfReference :: ReferenceDef -- | A FieldType describes a field parsed from the QuasiQuoter and -- is used to determine the Haskell type in the generated code. -- -- name Text parses into FTTypeCon Nothing Text -- -- name T.Text parses into FTTypeCon (Just T -- Text) -- -- name (Jsonb User) parses into: -- --
--   FTApp (FTTypeCon Nothing Jsonb) (FTTypeCon Nothing User)
--   
data FieldType -- | Optional module and name. FTTypeCon :: Maybe Text -> Text -> FieldType FTTypePromoted :: Text -> FieldType FTApp :: FieldType -> FieldType -> FieldType FTList :: FieldType -> FieldType -- | Attributes that may be attached to fields that can affect migrations -- and serialization in backend-specific ways. -- -- While we endeavor to, we can't forsee all use cases for all backends, -- and so FieldAttr is extensible through its constructor -- FieldAttrOther. data FieldAttr -- | The Maybe keyword goes after the type. This indicates that the -- column is nullable, and the generated Haskell code will have a -- Maybe type for it. -- -- Example: -- --
--   User
--       name Text Maybe
--   
FieldAttrMaybe :: FieldAttr -- | This indicates that the column is nullable, but should not have a -- Maybe type. For this to work out, you need to ensure that the -- PersistField instance for the type in question can support a -- PersistNull value. -- --
--   data What = NoWhat | Hello Text
--   
--   instance PersistField What where
--       fromPersistValue PersistNull =
--           pure NoWhat
--       fromPersistValue pv =
--           Hello $ fromPersistValue pv
--   
--   instance PersistFieldSql What where
--       sqlType _ = SqlString
--   
--   User
--       what What nullable
--   
FieldAttrNullable :: FieldAttr -- | This tag means that the column will not be present on the Haskell -- code, but will not be removed from the database. Useful to deprecate -- fields in phases. -- -- You should set the column to be nullable in the database. Otherwise, -- inserts won't have values. -- --
--   User
--       oldName Text MigrationOnly
--       newName Text
--   
FieldAttrMigrationOnly :: FieldAttr -- | A SafeToRemove attribute is not present on the Haskell -- datatype, and the backend migrations should attempt to drop the column -- without triggering any unsafe migration warnings. -- -- Useful after you've used MigrationOnly to remove a column -- from the database in phases. -- --
--   User
--       oldName Text SafeToRemove
--       newName Text
--   
FieldAttrSafeToRemove :: FieldAttr -- | This attribute indicates that we should create a foreign key reference -- from a column. By default, persistent will try and create a -- foreign key reference for a column if it can determine that the type -- of the column is a Key entity or an -- EntityId and the Entity's name was present in -- mkPersist. -- -- This is useful if you want to use the explicit foreign key syntax. -- --
--   Post
--       title    Text
--   
--   Comment
--       postId   PostId      noreference
--       Foreign Post fk_comment_post postId
--   
FieldAttrNoreference :: FieldAttr -- | This is set to specify precisely the database table the column refers -- to. -- --
--   Post
--       title    Text
--   
--   Comment
--       postId   PostId references="post"
--   
-- -- You should not need this - persistent should be capable of -- correctly determining the target table's name. If you do need this, -- please file an issue describing why. FieldAttrReference :: Text -> FieldAttr -- | Specify a name for the constraint on the foreign key reference for -- this table. -- --
--   Post
--       title    Text
--   
--   Comment
--       postId   PostId constraint="my_cool_constraint_name"
--   
FieldAttrConstraint :: Text -> FieldAttr -- | Specify the default value for a column. -- --
--   User
--       createdAt    UTCTime     default="NOW()"
--   
-- -- Note that a default= attribute does not mean you can omit the -- value while inserting. FieldAttrDefault :: Text -> FieldAttr -- | Specify a custom SQL type for the column. Generally, you should define -- a custom datatype with a custom PersistFieldSql instance -- instead of using this. -- --
--   User
--       uuid     Text    sqltype=UUID
--   
FieldAttrSqltype :: Text -> FieldAttr -- | Set a maximum length for a column. Useful for VARCHAR and indexes. -- --
--   User
--       name     Text    maxlen=200
--   
--       UniqueName name
--   
FieldAttrMaxlen :: Integer -> FieldAttr -- | Specify the database name of the column. -- --
--   User
--       blarghle     Int     sql="b_l_a_r_g_h_l_e"
--   
-- -- Useful for performing phased migrations, where one column is renamed -- to another column over time. FieldAttrSql :: Text -> FieldAttr -- | A grab bag of random attributes that were unrecognized by the parser. FieldAttrOther :: Text -> FieldAttr type Attr = Text type ExtraLine = [Text] -- | The definition for the entity's primary key ID. data EntityIdDef -- | The entity has a single key column, and it is a surrogate key - that -- is, you can't go from rec -> Key rec. EntityIdField :: !FieldDef -> EntityIdDef -- | The entity has a natural key. This means you can write rec -> -- Key rec because all the key fields are present on the datatype. -- -- A natural key can have one or more columns. EntityIdNaturalKey :: !CompositeDef -> EntityIdDef -- | 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 -- | 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 data IsNullable Nullable :: !WhyNullable -> IsNullable NotNullable :: IsNullable -- | 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 fieldAttrsContainsNullable :: [FieldAttr] -> IsNullable -- | Return the [FieldDef] for the entity keys. entitiesPrimary :: EntityDef -> NonEmpty FieldDef entityPrimary :: EntityDef -> Maybe CompositeDef -- | Returns a NonEmpty list of FieldDef that correspond with -- the key columns for an EntityDef. keyAndEntityFields :: EntityDef -> NonEmpty FieldDef -- | Parse raw field attributes into structured form. Any unrecognized -- attributes will be preserved, identically as they are encountered, as -- FieldAttrOther values. parseFieldAttrs :: [Text] -> [FieldAttr] isFieldNotGenerated :: FieldDef -> Bool -- | Returns True if the FieldDef does not have a -- MigrationOnly or SafeToRemove flag from the -- QuasiQuoter. isHaskellField :: FieldDef -> Bool -- | A FieldCascade that does nothing. noCascade :: FieldCascade -- | Renders a FieldCascade value such that it can be used in SQL -- migrations. renderFieldCascade :: FieldCascade -> Text -- | Render a CascadeAction to Text such that it can be used -- in a SQL command. renderCascadeAction :: CascadeAction -> Text -- | A Statement is a representation of a database query that has -- been prepared and stored on the server side. data Statement Statement :: IO () -> IO () -> ([PersistValue] -> IO Int64) -> (forall (m :: Type -> Type). MonadIO m => [PersistValue] -> Acquire (ConduitM () [PersistValue] m ())) -> Statement [stmtFinalize] :: Statement -> IO () [stmtReset] :: Statement -> IO () [stmtExecute] :: Statement -> [PersistValue] -> IO Int64 [stmtQuery] :: Statement -> forall (m :: Type -> Type). MonadIO m => [PersistValue] -> Acquire (ConduitM () [PersistValue] m ()) data InsertSqlResult ISRSingle :: Text -> InsertSqlResult ISRInsertGet :: Text -> Text -> InsertSqlResult ISRManyKeys :: Text -> [PersistValue] -> InsertSqlResult type LogFunc = Loc -> LogSource -> LogLevel -> LogStr -> IO () -- | Replace the FieldDef FieldAttr with the new list. setFieldAttrs :: [FieldAttr] -> FieldDef -> FieldDef -- | Modify the list of field attributes. overFieldAttrs :: ([FieldAttr] -> [FieldAttr]) -> FieldDef -> FieldDef -- | Add an attribute to the list of field attributes. addFieldAttr :: FieldAttr -> FieldDef -> FieldDef -- | Check if the field definition is nullable isFieldNullable :: FieldDef -> IsNullable -- | Check if the field is `Maybe a` isFieldMaybe :: FieldDef -> Bool -- | Retrieve the list of UniqueDef from an EntityDef. This -- currently does not include a Primary key, if one is defined. -- A future version of persistent will include a -- Primary key among the Unique constructors for the -- Entity. getEntityUniques :: EntityDef -> [UniqueDef] -- | Retrieve the Haskell name of the given entity. getEntityHaskellName :: EntityDef -> EntityNameHS -- | Return the database name for the given entity. getEntityDBName :: EntityDef -> EntityNameDB getEntityExtra :: EntityDef -> Map Text [[Text]] setEntityDBName :: EntityNameDB -> EntityDef -> EntityDef getEntityComments :: EntityDef -> Maybe Text getEntityForeignDefs :: EntityDef -> [ForeignDef] -- | Retrieve the list of FieldDef that makes up the fields of the -- entity. -- -- This does not return the fields for an Id column or an -- implicit id. It will return the key columns if you used the -- Primary syntax for defining the primary key. -- -- This does not return fields that are marked SafeToRemove or -- MigrationOnly - so it only returns fields that are -- represented in the Haskell type. If you need those fields, use -- getEntityFieldsDatabase. getEntityFields :: EntityDef -> [FieldDef] -- | This returns all of the FieldDef defined for the -- EntityDef, including those fields that are marked as -- MigrationOnly (and therefore only present in the database) or -- SafeToRemove (and a migration will drop the column if it -- exists in the database). -- -- For all the fields that are present on the Haskell-type, see -- getEntityFields. getEntityFieldsDatabase :: EntityDef -> [FieldDef] isEntitySum :: EntityDef -> Bool getEntityId :: EntityDef -> EntityIdDef getEntityIdField :: EntityDef -> Maybe FieldDef -- | Set an entityId to be the given FieldDef. setEntityId :: FieldDef -> EntityDef -> EntityDef setEntityIdDef :: EntityIdDef -> EntityDef -> EntityDef getEntityKeyFields :: EntityDef -> NonEmpty FieldDef -- | Perform a mapping function over all of the entity fields, as -- determined by getEntityFieldsDatabase. overEntityFields :: ([FieldDef] -> [FieldDef]) -> EntityDef -> EntityDef data SomePersistField SomePersistField :: a -> SomePersistField -- | Prior to persistent-2.11.0, we provided an instance of -- PersistField for the Natural type. This was in error, -- because Natural represents an infinite value, and databases -- don't have reasonable types for this. -- -- The instance for Natural used the Int64 underlying type, -- which will cause underflow and overflow errors. This type has the -- exact same code in the instances, and will work seamlessly. -- -- A more appropriate type for this is the Word series of types -- from Data.Word. These have a bounded size, are guaranteed to be -- non-negative, and are quite efficient for the database to store. newtype OverflowNatural OverflowNatural :: Natural -> OverflowNatural [unOverflowNatural] :: OverflowNatural -> Natural -- | 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 -- | This type class is used with the OverloadedLabels extension -- to provide a more convenient means of using the EntityField -- type. EntityField definitions are prefixed with the type name -- to avoid ambiguity, but this ambiguity can result in verbose code. -- -- If you have a table User with a name Text field, -- then the corresponding EntityField is UserName. With -- this, we can write #name :: EntityField User Text. -- -- What's more fun is that the type is more general: it's actually -- #name :: (SymbolToField "name" rec typ) => EntityField rec -- typ -- -- Which means it is *polymorphic* over the actual record. This allows -- you to write code that can be generic over the tables, provided they -- have the right fields. class SymbolToField (sym :: Symbol) rec typ | sym rec -> typ symbolToField :: SymbolToField sym rec typ => EntityField rec typ -- | 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 -- | Value to filter with. Highly dependant on the type of filter used. data FilterValue typ [FilterValue] :: forall typ. typ -> FilterValue typ [FilterValues] :: forall typ. [typ] -> FilterValue typ [UnsafeValue] :: forall a typ. PersistField a => a -> FilterValue typ type family BackendSpecificUpdate backend record -- | 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. -- -- As of persistent-2.11.0.0, it's possible to use the -- OverloadedLabels language extension to refer to -- EntityField values polymorphically. See the documentation on -- SymbolToField for more information. data family EntityField record :: Type -> Type; -- | 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 => proxy 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 -> NonEmpty (FieldNameHS, FieldNameDB) -- | A lower level operation. persistUniqueToValues :: PersistEntity record => Unique record -> [PersistValue] -- | Use a PersistField as a lens. fieldLens :: PersistEntity record => EntityField record field -> forall (f :: Type -> Type). Functor f => (field -> f field) -> Entity record -> f (Entity record) -- | Extract a Key record from a record value. -- Currently, this is only defined for entities using the -- Primary syntax for natural/composite keys. In a future -- version of persistent which incorporates the ID directly into -- the entity, this will always be Just. keyFromRecordM :: PersistEntity record => Maybe (record -> Key record) -- | 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. -- -- As of persistent-2.11.0.0, it's possible to use the -- OverloadedLabels language extension to refer to -- EntityField values polymorphically. See the documentation on -- SymbolToField for more information. data family EntityField record :: Type -> Type -- | Unique keys besides the Key. data family Unique record -- | Get list of values corresponding to given entity. entityValues :: PersistEntity record => Entity record -> [PersistValue] -- | 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 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 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 :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m [Key record] -- | 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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> 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 :: forall record (m :: Type -> Type). (PersistStoreWrite backend, MonadIO m, PersistRecordBackend record backend) => Key record -> [Update record] -> ReaderT backend m record 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 class PersistCore backend where { data family BackendKey backend; } data family BackendKey backend -- | 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 -- | A convenient alias for common type signatures type PersistRecordBackend record backend = (PersistEntity record, PersistEntityBackend record ~ BaseBackend backend) -- | 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' = withCompatibleBackend asdf
--   
class BackendCompatible sup sub projectBackend :: BackendCompatible sup sub => sub -> sup -- | 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 -- | 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 type family BaseBackend backend -- | Run a query against a larger backend by plucking out BaseBackend -- backend -- -- This is a helper for reusing existing queries when expanding the -- backend type. withBaseBackend :: forall backend (m :: Type -> Type) a. HasPersistBackend backend => ReaderT (BaseBackend backend) m a -> ReaderT backend m a -- | Run a query against a compatible backend, by projecting the backend -- -- This is a helper for using queries which run against a specific -- backend type that your backend is compatible with. withCompatibleBackend :: forall sup sub (m :: Type -> Type) a. BackendCompatible sup sub => ReaderT sup m a -> ReaderT sub m a liftPersist :: (MonadIO m, MonadReader backend m) => ReaderT backend IO b -> m b -- | 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 :: forall record backend (m :: Type -> Type). (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 :: forall record backend (m :: Type -> Type). (PersistEntityBackend record ~ BaseBackend backend, MonadIO m, PersistEntity record, PersistStoreRead backend) => Key record -> ReaderT backend m (Entity record) -- | Curry this to make a convenience function that loads an associated -- model. -- --
--   foreign = belongsTo foreignId
--   
belongsTo :: forall ent1 ent2 backend (m :: Type -> Type). (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 :: forall ent1 ent2 backend (m :: Type -> Type). (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 :: forall e backend (m :: Type -> Type). (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 :: forall record backend (m :: Type -> Type). (PersistEntityBackend record ~ BaseBackend backend, PersistEntity record, MonadIO m, PersistStoreWrite backend) => record -> ReaderT backend m record -- | A SqlBackend represents a handle or connection to a database. -- It contains functions and values that allow databases to have more -- optimized implementations, as well as references that benefit -- performance and sharing. -- -- Instead of using the SqlBackend constructor directly, use the -- mkSqlBackend function. -- -- A SqlBackend is *not* thread-safe. You should not assume that a -- SqlBackend can be shared among threads and run concurrent -- queries. This *will* result in problems. Instead, you should create a -- Pool SqlBackend, known as a -- ConnectionPool, and pass that around in multi-threaded -- applications. -- -- To run actions in the persistent library, you should use the -- runSqlConn function. If you're using a multithreaded -- application, use the runSqlPool function. data SqlBackend -- | 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 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." -- | 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 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 -- | 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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (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 :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => Unique record -> record -> [Update record] -> ReaderT backend m (Entity record) -- | Put many records into db -- -- putMany :: forall record (m :: Type -> Type). (PersistUniqueWrite backend, MonadIO m, PersistRecordBackend record backend) => [record] -> ReaderT backend m () -- | 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 PersistStoreRead backend => PersistUniqueRead backend -- | Given a proxy for a PersistEntity record, this returns the sole -- UniqueDef for that entity. onlyOneUniqueDef :: (OnlyOneUniqueKey record, Monad proxy) => proxy record -> UniqueDef -- | 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 :: forall record backend (m :: Type -> Type). (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 :: forall record backend (m :: Type -> Type). (MonadIO m, PersistRecordBackend record backend, PersistUniqueWrite backend) => record -> ReaderT backend m (Maybe (Entity 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 :: forall record backend (m :: Type -> Type). (MonadIO m, PersistUniqueWrite backend, PersistRecordBackend record backend, OnlyOneUniqueKey record) => record -> ReaderT backend m (Unique record) -- | 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 :: Type -> Type) backend. (MonadIO m, PersistUniqueRead backend, PersistRecordBackend record backend, AtLeastOneUniqueKey record) => 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 :: forall record backend (m :: Type -> Type). (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 :: forall record backend (m :: Type -> Type). (MonadIO m, PersistRecordBackend record backend, PersistUniqueRead backend) => 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 stay unique, and could thus -- safely be updated. on a conflict returns the conflicting key -- -- This is similar to checkUnique, except it's useful for updating -- - when the particular entity already exists, it would normally -- conflict with itself. This variant ignores those conflicts -- --

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
--   
checkUniqueUpdateable :: forall record backend (m :: Type -> Type). (MonadIO m, PersistRecordBackend record backend, PersistUniqueRead backend) => Entity record -> ReaderT backend m (Maybe (Unique record)) -- | Backends supporting conditional write operations class (PersistQueryRead backend, PersistStoreWrite backend) => PersistQueryWrite backend -- | 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. -- -- NOTE: This function returns an Acquire and a ConduitM, -- which implies that it streams from the database. It does not. Please -- use selectList to simplify the code. If you want streaming -- behavior, consider persistent-pagination which efficiently -- chunks a query into ranges, or investigate a backend-specific -- streaming solution. selectSourceRes :: forall record (m1 :: Type -> Type) (m2 :: Type -> Type). (PersistQueryRead backend, PersistRecordBackend record backend, MonadIO m1, MonadIO m2) => [Filter record] -> [SelectOpt record] -> ReaderT backend m1 (Acquire (ConduitM () (Entity record) m2 ())) -- | Get the Keys of all records matching the given criterion. selectKeysRes :: forall (m1 :: Type -> Type) (m2 :: Type -> Type) record. (PersistQueryRead backend, MonadIO m1, MonadIO m2, PersistRecordBackend record backend) => [Filter record] -> [SelectOpt record] -> ReaderT backend m1 (Acquire (ConduitM () (Key record) m2 ())) -- | Get the Keys of all records matching the given criterion. -- -- For an example, see selectList. selectKeys :: forall record backend (m :: Type -> Type). (PersistQueryRead backend, MonadResource m, PersistRecordBackend record backend, MonadReader backend m) => [Filter record] -> [SelectOpt record] -> ConduitM () (Key record) m () -- | 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 :: forall (m :: Type -> Type). (DeleteCascade record backend, MonadIO m) => Key record -> ReaderT backend m () -- | Cascade-deletion of entries satisfying given filters. deleteCascadeWhere :: forall record backend (m :: Type -> Type). (MonadIO m, DeleteCascade record backend, PersistQueryWrite backend) => [Filter record] -> ReaderT backend m () -- | 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 -- | 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 -- | A backend which is a wrapper around SqlBackend. type IsSqlBackend backend = (IsPersistBackend backend, BaseBackend backend ~ SqlBackend) -- | Like SqlPersistT but compatible with any SQL backend which -- can handle read and write queries. type SqlWriteT (m :: Type -> Type) a = forall backend. SqlBackendCanWrite backend => ReaderT backend m a -- | Like SqlPersistT but compatible with any SQL backend which -- can handle read queries. type SqlReadT (m :: Type -> Type) a = forall backend. SqlBackendCanRead backend => ReaderT backend m a -- | 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) -- | 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) -- | An SQL backend which can handle read or write queries -- -- The constructor was exposed in 2.10.0 newtype SqlWriteBackend SqlWriteBackend :: SqlBackend -> SqlWriteBackend [$sel:unSqlWriteBackend:SqlWriteBackend] :: SqlWriteBackend -> SqlBackend -- | An SQL backend which can only handle read queries -- -- The constructor was exposed in 2.10.0. newtype SqlReadBackend SqlReadBackend :: SqlBackend -> SqlReadBackend [$sel:unSqlReadBackend:SqlReadBackend] :: SqlReadBackend -> SqlBackend -- | Useful for running a write query against an untagged backend with -- unknown capabilities. writeToUnknown :: forall (m :: Type -> Type) a. Monad m => ReaderT SqlWriteBackend m a -> ReaderT SqlBackend m a -- | Useful for running a read query against a backend with read and write -- capabilities. readToWrite :: forall (m :: Type -> Type) a. Monad m => ReaderT SqlReadBackend m a -> ReaderT SqlWriteBackend m a -- | Useful for running a read query against a backend with unknown -- capabilities. readToUnknown :: forall (m :: Type -> Type) a. Monad m => ReaderT SqlReadBackend m a -> ReaderT SqlBackend m a -- | 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 -- | Values to configure a pool of database connections. See -- Data.Pool for details. data ConnectionPoolConfig ConnectionPoolConfig :: Int -> NominalDiffTime -> Int -> ConnectionPoolConfig -- | How many stripes to divide the pool into. See Data.Pool for -- details. Default: 1. [connectionPoolConfigStripes] :: ConnectionPoolConfig -> Int -- | How long connections can remain idle before being disposed of, in -- seconds. Default: 600 [connectionPoolConfigIdleTimeout] :: ConnectionPoolConfig -> NominalDiffTime -- | How many connections should be held in the connection pool. Default: -- 10 [connectionPoolConfigSize] :: ConnectionPoolConfig -> Int type ConnectionPool = Pool SqlBackend type SqlPersistM = SqlPersistT NoLoggingT ResourceT IO type SqlPersistT = ReaderT SqlBackend data PersistentSqlException StatementAlreadyFinalized :: Text -> PersistentSqlException Couldn'tGetSQLConnection :: PersistentSqlException -- | This value specifies how a field references another table. data ColumnReference ColumnReference :: !EntityNameDB -> !ConstraintNameDB -> !FieldCascade -> ColumnReference -- | The table name that the [crTableName] :: ColumnReference -> !EntityNameDB -- | The name of the foreign key constraint. [crConstraintName] :: ColumnReference -> !ConstraintNameDB -- | Whether or not updates/deletions to the referenced table cascade to -- this table. [crFieldCascade] :: ColumnReference -> !FieldCascade data Column Column :: !FieldNameDB -> !Bool -> !SqlType -> !Maybe Text -> !Maybe Text -> !Maybe ConstraintNameDB -> !Maybe Integer -> !Maybe ColumnReference -> Column [cName] :: Column -> !FieldNameDB [cNull] :: Column -> !Bool [cSqlType] :: Column -> !SqlType [cDefault] :: Column -> !Maybe Text [cGenerated] :: Column -> !Maybe Text [cDefaultConstraintName] :: Column -> !Maybe ConstraintNameDB [cMaxLen] :: Column -> !Maybe Integer [cReference] :: Column -> !Maybe ColumnReference -- | Initializes a ConnectionPoolConfig with default values. See the -- documentation of ConnectionPoolConfig for each field's default -- value. defaultConnectionPoolConfig :: ConnectionPoolConfig -- | Record of functions to override the default behavior in -- mkColumns. It is recommended you initialize this with -- emptyBackendSpecificOverrides and override the default values, -- so that as new fields are added, your code still compiles. -- -- For added safety, use the getBackendSpecific* and -- setBackendSpecific* functions, as a breaking change to the -- record field labels won't be reflected in a major version bump of the -- library. data BackendSpecificOverrides -- | If the override is defined, then this returns a function that accepts -- an entity name and field name and provides the ConstraintNameDB -- for the foreign key constraint. -- -- An abstract accessor for the BackendSpecificOverrides getBackendSpecificForeignKeyName :: BackendSpecificOverrides -> Maybe (EntityNameDB -> FieldNameDB -> ConstraintNameDB) -- | Set the backend's foreign key generation function to this value. setBackendSpecificForeignKeyName :: (EntityNameDB -> FieldNameDB -> ConstraintNameDB) -> BackendSpecificOverrides -> BackendSpecificOverrides -- | Creates an empty BackendSpecificOverrides (i.e. use the default -- behavior; no overrides) emptyBackendSpecificOverrides :: BackendSpecificOverrides defaultAttribute :: [FieldAttr] -> Maybe Text -- | Create the list of columns for the given entity. mkColumns :: [EntityDef] -> EntityDef -> BackendSpecificOverrides -> ([Column], [UniqueDef], [ForeignDef]) -- | A more general way to convert instances of ToJSON type class to -- strict text Text. toJsonText :: ToJSON j => j -> Text -- | 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 = PersistLiteralEncoded . toASCIIBytes
--     fromPersistValue (PersistLiteralEncoded 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 PersistLiteralEncoded, 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 -- | 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 => (Text -> 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 -- | 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 = fmap (unPrefix @"p") $ rawSql query []
--     where
--       query = "SELECT ?? FROM person AS p"
--   
unPrefix :: forall (prefix :: Symbol) record. EntityWithPrefix prefix record -> Entity record rawQuery :: forall (m :: Type -> Type) env. (MonadResource m, MonadReader env m, BackendCompatible SqlBackend env) => Text -> [PersistValue] -> ConduitM () [PersistValue] m () rawQueryRes :: forall (m1 :: Type -> Type) (m2 :: Type -> Type) env. (MonadIO m1, MonadIO m2, BackendCompatible SqlBackend env) => Text -> [PersistValue] -> ReaderT env m1 (Acquire (ConduitM () [PersistValue] m2 ())) -- | Execute a raw SQL statement rawExecute :: forall (m :: Type -> Type) backend. (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 :: forall (m :: Type -> Type) backend. (MonadIO m, BackendCompatible SqlBackend backend) => Text -> [PersistValue] -> ReaderT backend m Int64 getStmtConn :: SqlBackend -> Text -> IO Statement -- | 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 :: forall a (m :: Type -> Type) backend. (RawSql a, MonadIO m, BackendCompatible SqlBackend backend) => Text -> [PersistValue] -> ReaderT backend m [a] -- | Get a connection from the pool, run the given action, and then return -- the connection to the pool. -- -- This function performs the given action in a transaction. If an -- exception occurs during the action, then the transaction is rolled -- back. -- -- 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 :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> m a -- | Like runSqlPool, but supports specifying an isolation level. runSqlPoolWithIsolation :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> IsolationLevel -> m a -- | Like runSqlPool, but does not surround the action in a -- transaction. This action might leave your database in a weird state. runSqlPoolNoTransaction :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> Maybe IsolationLevel -> m a -- | This function is how runSqlPool and -- runSqlPoolNoTransaction are defined. In addition to the action -- to be performed and the Pool of conections to use, we give you -- the opportunity to provide three actions - initialize, afterwards, and -- onException. runSqlPoolWithHooks :: forall backend m a before after onException. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> Maybe IsolationLevel -> (backend -> m before) -> (backend -> m after) -> (backend -> SomeException -> m onException) -> m a -- | This function is how runSqlPoolWithHooks is defined. -- -- It's currently the most general function for using a SQL pool. runSqlPoolWithExtensibleHooks :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> Maybe IsolationLevel -> SqlPoolHooks m backend -> 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 :: forall backend m a. (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> backend -> m a -- | Like runSqlConn, but supports specifying an isolation level. runSqlConnWithIsolation :: forall backend m a. (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 :: forall backend m a. (MonadIO m, BackendCompatible SqlBackend backend) => ReaderT backend (NoLoggingT (ResourceT IO)) a -> Pool backend -> m a withSqlPool :: forall backend m a. (MonadLoggerIO m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> (Pool backend -> m a) -> m a -- | Creates a pool of connections to a SQL database which can be used by -- the Pool backend -> m a function. After the function -- completes, the connections are destroyed. withSqlPoolWithConfig :: forall backend m a. (MonadLoggerIO m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> ConnectionPoolConfig -> (Pool backend -> m a) -> m a createSqlPool :: forall backend m. (MonadLoggerIO m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> Int -> m (Pool backend) -- | Creates a pool of connections to a SQL database. createSqlPoolWithConfig :: (MonadLoggerIO m, MonadUnliftIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> ConnectionPoolConfig -> m (Pool backend) -- | 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 :: forall backend m a. (MonadUnliftIO m, MonadLoggerIO m, BackendCompatible SqlBackend backend) => (LogFunc -> IO backend) -> (backend -> m a) -> m a close' :: BackendCompatible SqlBackend backend => backend -> IO () withRawQuery :: forall (m :: Type -> Type) a. MonadIO m => Text -> [PersistValue] -> ConduitM [PersistValue] Void IO a -> ReaderT SqlBackend m a toSqlKey :: ToBackendKey SqlBackend record => Int64 -> Key record fromSqlKey :: ToBackendKey SqlBackend record => Key record -> Int64 -- | 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 :: Type -> Type) 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 -> EntityNameDB -- | 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 :: Type -> Type) backend. (PersistEntity record, PersistEntityBackend record ~ SqlBackend, BackendCompatible SqlBackend backend, Monad m) => EntityField record typ -> ReaderT backend m Text -- | useful for a backend to implement fieldName by adding escaping fieldDBName :: PersistEntity record => EntityField record typ -> FieldNameDB -- | Used when determining how to prefix a column name in a WHERE -- clause. data FilterTablePrefix -- | Prefix the column with the table name. This is useful if the column -- name might be ambiguous. PrefixTableName :: FilterTablePrefix -- | Prefix the column name with the EXCLUDED keyword. This is -- used with the Postgresql backend when doing ON CONFLICT DO -- UPDATE clauses - see the documentation on upsertWhere -- and upsertManyWhere. PrefixExcluded :: FilterTablePrefix -- | Render a [Filter record] into a Text value -- suitable for inclusion into a SQL query. filterClause :: PersistEntity val => Maybe FilterTablePrefix -> SqlBackend -> [Filter val] -> Text -- | Render a [Filter record] into a Text value -- suitable for inclusion into a SQL query, as well as the -- [PersistValue] to properly fill in the ? -- place holders. filterClauseWithVals :: PersistEntity val => Maybe FilterTablePrefix -> SqlBackend -> [Filter val] -> (Text, [PersistValue]) -- | Render a [SelectOpt record] made up *only* of -- Asc and Desc constructors into a Text value -- suitable for inclusion into a SQL query. orderClause :: PersistEntity val => Maybe FilterTablePrefix -> SqlBackend -> [SelectOpt val] -> Text -- | Generates sql for limit and offset for postgres, sqlite and mysql. decorateSQLWithLimitOffset :: Text -> (Int, Int) -> Text -> Text -- | An exception indicating that Persistent refused to run some unsafe -- migrations. Contains a list of pairs where the Bool tracks whether the -- migration was unsafe (True means unsafe), and the Sql is the sql -- statement for the migration. newtype PersistUnsafeMigrationException PersistUnsafeMigrationException :: [(Bool, Sql)] -> PersistUnsafeMigrationException -- | A Migration is a four level monad stack consisting of: -- -- type Migration = WriterT [Text] WriterT CautiousMigration ReaderT SqlBackend IO () -- | A list of SQL operations, marked with a safety flag. If the -- Bool is True, then the operation is *unsafe* - it might -- be destructive, or otherwise not idempotent. If the Bool is -- False, then the operation is *safe*, and can be run repeatedly -- without issues. type CautiousMigration = [(Bool, Sql)] type Sql = Text -- | 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 :: forall (m :: Type -> Type). (HasCallStack, 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' :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m CautiousMigration -- | Prints a migration. printMigration :: forall (m :: Type -> Type). (HasCallStack, MonadIO m) => Migration -> ReaderT SqlBackend m () -- | Convert a Migration to a list of Text values -- corresponding to their Sql statements. showMigration :: forall (m :: Type -> Type). (HasCallStack, 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 :: forall (m :: Type -> Type). (MonadIO m, HasCallStack) => Migration -> ReaderT SqlBackend m [Sql] -- | Runs a migration. If the migration fails to parse or if any of the -- migrations are unsafe, then this throws a -- PersistUnsafeMigrationException. runMigration :: forall (m :: Type -> Type). 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 :: forall (m :: Type -> Type). 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 :: forall (m :: Type -> Type). MonadUnliftIO m => Migration -> ReaderT SqlBackend m [Text] -- | Like runMigration, but this will perform the unsafe database -- migrations instead of erroring out. runMigrationUnsafe :: forall (m :: Type -> Type). 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 :: forall (m :: Type -> Type). (HasCallStack, 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 a single error in a Migration. reportError :: Text -> Migration -- | Report multiple errors in a Migration. reportErrors :: [Text] -> Migration -- | Add a migration to the migration plan. addMigration :: Bool -> Sql -> Migration -- | Add a CautiousMigration (aka a [(Bool, -- Text)]) to the migration plan. addMigrations :: CautiousMigration -> Migration -- | Run an action against the database during a migration. Can be useful -- for eg creating Postgres extensions: -- --
--   runSqlCommand $ rawExecute "CREATE EXTENSION IF NOT EXISTS "uuid-ossp";" []
--   
runSqlCommand :: SqlPersistT IO () -> Migration -- | 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 :: forall (m :: Type -> Type). MonadIO m => ReaderT SqlBackend m () -- | Commit the current transaction and begin a new one with the specified -- isolation level. transactionSaveWithIsolation :: forall (m :: Type -> Type). 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 :: forall (m :: Type -> Type). MonadIO m => ReaderT SqlBackend m () -- | Roll back the current transaction and begin a new one with the -- specified isolation level. transactionUndoWithIsolation :: forall (m :: Type -> Type). MonadIO m => IsolationLevel -> ReaderT SqlBackend m () module Persistent.EventSource.EventStore.Default defaultStoreMany :: (PersistRecordBackend record SqlBackend, Typeable record, MonadSqlQuery m) => [record] -> m [Key record] defaultGetLastAppliedEventId :: (PersistEntity record, Typeable record, MonadSqlQuery m, PersistEntityBackend record ~ SqlBackend) => EntityField record typ -> (record -> b) -> m (Maybe b) defaultMarkEventsApplied :: (MonadIO m, PersistEntity record, Typeable record, MonadSqlQuery m, PersistEntityBackend record ~ SqlBackend) => (t -> Key record) -> (UTCTime -> t -> record) -> [t] -> m () defaultLoadUnappliedEvents :: (Traversable t, MonadSqlQuery m, PersistEntity val1, PersistEntity val2, PersistField a) => EntityField val1 a -> EntityField val2 a -> t a -> m [Entity val1] module Persistent.EventSource.Projection -- | Projection is about setting your event sourced table to data in the -- event. class Projection a where { type family Event a = ev | ev -> a; } -- | Apply event to this context Intended to have write access to the -- database for updating views apply :: (Projection a, MonadUnliftIO m, MonadLogger m, MonadSqlQuery m) => Event a -> m () module Persistent.EventSource.EventStore -- | Determines how events are stored and retrieved. class Projection a => EventStore a storeMany :: (EventStore a, MonadIO m, MonadSqlQuery m) => [Event a] -> m [Key (Event a)] -- | Nothing if no last applied event found. getLastAppliedEventId :: (EventStore a, MonadIO m, MonadSqlQuery m) => m (Maybe (Key (Event a))) markEventsApplied :: (EventStore a, MonadIO m, MonadSqlQuery m) => [Key (Event a)] -> m () -- | Will load all events on nothing loadUnappliedEvents :: (EventStore a, MonadIO m, MonadSqlQuery m) => Maybe (Key (Event a)) -> m [Entity (Event a)] module Persistent.EventSource.Aggregate -- | Aggregate is an intermediate step, allowing you to specify how your -- changeable commands are stored. stored events should be stable like an -- API. class Projection a => Aggregate a where { -- | The command is a sumtype with all your possible event sourced actions. type family Command a = cmd | cmd -> a; -- | allows you to specify who executed a command. for audit purposes. set -- this to () if you don't care about this. type family Actor a; } -- | Validate action and generate events, if any. act :: (Aggregate a, MonadSqlQuery m, MonadIO m) => Maybe (Actor a) -> Command a -> m [Event a] module Persistent.EventSource -- | Executes command and applies events, as well as storing them, aka -- transact or actAndApply handleCmdWithAuthor :: (Aggregate a, EventStore a, MonadUnliftIO m, MonadSqlQuery m, MonadLogger m) => Maybe (Actor a) -> Command a -> m [Entity (Event a)] applyEventsSince :: (EventStore a, MonadUnliftIO m, MonadSqlQuery m, MonadLogger m) => Maybe (Key (Event a)) -> m ()