-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Monad classes for running queries with Persistent and Esqueleto -- -- This package introduces two classes: MonadSqlBackend for monadic -- contexts in which a SqlBackend is available, and MonadSqlTx for -- contexts in which we can execute a SQL transaction. -- -- Additionally, this package provides variants of query-running -- utilities from Persistent and Esqueleto which are concretized to use -- SqlBackend, generalized to a MonadSqlBackend m constraint rather than -- "ReaderT backend", and wrapped in checkpointCallStack so that -- exceptions will include call stacks. @package persistent-sql-lifted @version 0.4.0.0 module Database.Persist.Sql.Lifted.Expression.Bool not_ :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -- | This operator translates to the SQL operator AND. -- -- Example: -- --
-- where_ $ -- user ^. UserName ==. val Matt -- &&. user ^. UserAge >=. val 21 --(&&.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool) infixr 3 &&. -- | This operator translates to the SQL operator AND. -- -- Example: -- --
-- where_ $ -- user ^. UserName ==. val Matt -- ||. user ^. UserName ==. val John --(||.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool) infixr 2 ||. module Database.Persist.Sql.Lifted.Expression.Case -- | CASE statement. For example: -- --
-- select $ -- return $ -- case_ -- [ when_ -- (exists $ -- from $ \p -> do -- where_ (p ^. PersonName ==. val "Mike")) -- then_ -- (subSelect $ -- from $ \v -> do -- let sub = -- from $ \c -> do -- where_ (c ^. PersonName ==. val "Mike") -- return (c ^. PersonFavNum) -- where_ (just (v ^. PersonFavNum) >. subSelect 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. -- --
-- query :: UserId -> SqlPersistT IO [Entity User] -- query userId = select $ do -- user <- from $ table @User -- where_ (user ^. UserId ==. val userId) -- pure user ---- -- This would generate the following SQL: -- --
-- SELECT user.* -- FROM user -- WHERE user.id = ? --(==.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 ==. -- | This operator translates to the SQL operator !=. -- -- Example: -- --
-- where_ $ user ^. UserName !=. val Bob --(!=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 !=. -- | This operator translates to the SQL operator >=. -- -- Example: -- --
-- where_ $ user ^. UserAge >=. val 21 --(>=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 >=. -- | This operator translates to the SQL operator >. -- -- Example: -- --
-- where_ $ user ^. UserAge >. val 20 --(>.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 >. -- | This operator translates to the SQL operator <=. -- -- Example: -- --
-- where_ $ val 21 <=. user ^. UserAge --(<=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 <=. -- | This operator translates to the SQL operator <. -- -- Example: -- --
-- where_ $ val 20 <. user ^. UserAge --(<.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 <. -- | a between (b, c) translates to the SQL expression -- a >= b AND a <= c. It does not use a SQL -- BETWEEN operator. -- -- @since: 3.1.0 between :: PersistField a => SqlExpr (Value a) -> (SqlExpr (Value a), SqlExpr (Value a)) -> SqlExpr (Value Bool) module Database.Persist.Sql.Lifted.Expression.Constant -- | Lift a constant value from Haskell-land to the query. val :: PersistField typ => typ -> SqlExpr (Value typ) module Database.Persist.Sql.Lifted.Expression.Count -- | COUNT. count :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a) -- | COUNT(*) value. countRows :: Num a => SqlExpr (Value a) -- | COUNT(DISTINCT x). countDistinct :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a) module Database.Persist.Sql.Lifted.Expression.Exists -- | 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 EXISTS operator. notExists :: SqlQuery () -> SqlExpr (Value Bool) module Database.Persist.Sql.Lifted.Expression.Insert -- | Apply a PersistField constructor to SqlExpr Value -- arguments. (<#) :: (a -> b) -> SqlExpr (Value a) -> SqlExpr (Insertion b) -- | Apply extra SqlExpr Value arguments to a PersistField -- constructor (<&>) :: SqlExpr (Insertion (a -> b)) -> SqlExpr (Value a) -> SqlExpr (Insertion b) module Database.Persist.Sql.Lifted.Expression.Key -- | 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))) -- | 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 module Database.Persist.Sql.Lifted.Expression.List -- | 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) -- | NOT IN operator. notIn :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (ValueList typ) -> SqlExpr (Value Bool) -- | Execute a subquery SELECT in an SqlExpression. Returns a list -- of values. subList_select :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (ValueList a) -- | Lift a list of constant value from Haskell-land to the query. valList :: PersistField typ => [typ] -> SqlExpr (ValueList typ) -- | 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)) module Database.Persist.Sql.Lifted.Expression.Maybe -- | 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)
-- | An alias for isNothing that avoids clashing with the function
-- from Data.Maybe isNothing.
isNothing_ :: PersistField typ => SqlExpr (Value (Maybe typ)) -> SqlExpr (Value Bool)
-- | Analogous to Just, promotes a value of type typ into
-- one of type Maybe typ. It should hold that val .
-- Just === just . val.
--
-- This function will try not to produce a nested Maybe. This is
-- in accord with how SQL represents NULL. That means that
-- just . just = just. This behavior was
-- changed in v3.6.0.0. If you want to produce nested Maybe, see
-- just'.
just :: NullableFieldProjection typ typ' => SqlExpr (Value typ) -> SqlExpr (Value (Maybe typ'))
-- | NULL value.
nothing :: SqlExpr (Value (Maybe typ))
-- | Join nested Maybes in a Value into one. This is useful
-- when calling aggregate functions on nullable fields.
--
-- As of v3.6.0.0, this function will attempt to work on both
-- SqlExpr (Value (Maybe a)) as well as
-- SqlExpr (Value (Maybe (Maybe a)))
-- inputs to make transitioning to NullableFieldProjection easier.
-- This may make type inference worse in some cases. If you want the
-- monomorphic variant, see joinV'
joinV :: NullableFieldProjection typ typ' => SqlExpr (Value (Maybe typ)) -> SqlExpr (Value (Maybe typ'))
-- | 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, NullableFieldProjection a a') => [SqlExpr (Value (Maybe a))] -> SqlExpr (Value (Maybe a'))
-- | 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)
module Database.Persist.Sql.Lifted.Expression.Number
-- | This operator translates to the SQL operator +.
--
-- This does not require or assume anything about the SQL values.
-- Interpreting what +. means for a given type is left to the
-- database engine.
--
-- Example:
--
-- -- user ^. UserAge +. val 10 --(+.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 6 +. -- | This operator translates to the SQL operator -. -- -- This does not require or assume anything about the SQL values. -- Interpreting what -. means for a given type is left to the -- database engine. -- -- Example: -- --
-- user ^. UserAge -. val 10 --(-.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 6 -. -- | This operator translates to the SQL operator /. -- -- This does not require or assume anything about the SQL values. -- Interpreting what /. means for a given type is left to the -- database engine. -- -- Example: -- --
-- user ^. UserAge /. val 10 --(/.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 7 /. -- | This operator translates to the SQL operator *. -- -- This does not require or assume anything about the SQL values. -- Interpreting what *. means for a given type is left to the -- database engine. -- -- Example: -- --
-- user ^. UserAge *. val 10 --(*.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 7 *. round_ :: (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) floor_ :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) min_ :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value (Maybe (Nullable a))) max_ :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value (Maybe (Nullable a))) sum_ :: (PersistField a, PersistField b) => SqlExpr (Value a) -> SqlExpr (Value (Maybe b)) avg_ :: (PersistField a, PersistField b) => SqlExpr (Value 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) -- | Same as castNum, but for nullable values. castNumM :: (Num a, Num b) => SqlExpr (Value (Maybe a)) -> SqlExpr (Value (Maybe b)) module Database.Persist.Sql.Lifted.Expression.OrderBy -- | Ascending order of this field or SqlExpression. asc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy -- | Descending order of this field or SqlExpression. desc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy module Database.Persist.Sql.Lifted.Expression.Projection -- | Project a field of an entity. (^.) :: forall typ val. (PersistEntity val, PersistField typ) => SqlExpr (Entity val) -> EntityField val typ -> SqlExpr (Value typ) infixl 9 ^. -- | Project an EntityField of a nullable entity. The result type -- will be Nullable, meaning that nested Maybe won't be -- produced here. -- -- As of v3.6.0.0, this will attempt to combine nested Maybe. If -- you want to keep nested Maybe, then see ??.. (?.) :: (PersistEntity val, PersistField typ) => SqlExpr (Maybe (Entity val)) -> EntityField val typ -> SqlExpr (Value (Maybe (Nullable typ))) infixl 9 ?. module Database.Persist.Sql.Lifted.Expression.String -- | LOWER function. lower_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | UPPER function. @since 3.3.0 upper_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | TRIM function. @since 3.3.0 trim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | 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) -- | LENGTH function. @since 3.3.0 length_ :: (SqlString s, Num a) => SqlExpr (Value s) -> SqlExpr (Value a) -- | LEFT function. @since 3.3.0 left_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s) -- | RIGHT function. @since 3.3.0 right_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s) -- | LIKE operator. like :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool) infixr 2 `like` -- | ILIKE operator (case-insensitive LIKE). -- -- Supported by PostgreSQL only. Deprecated in version 3.6.0 in favor of -- the version available from Database.Esqueleto.PostgreSQL. ilike :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool) infixr 2 `ilike` -- | 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) -- | The CONCAT function with a variable number of parameters. -- Supported by MySQL and PostgreSQL. SQLite supports this in versions -- after 3.44.0, and persistent-sqlite supports this in versions -- 2.13.3.0 and after. concat_ :: SqlString s => [SqlExpr (Value s)] -> SqlExpr (Value s) -- | The || string concatenation operator (named after Haskell's -- ++ in order to avoid naming clash with ||.). -- -- Supported by SQLite and PostgreSQL. -- -- MySQL support requires setting the SQL mode to -- PIPES_AS_CONCAT or ANSI - see this StackOverflow -- answer. (++.) :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value s) infixr 5 ++. -- | 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) module Database.Persist.Sql.Lifted.Expression.SubSelect -- | 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, NullableFieldProjection a a') => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value (Maybe 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)) -- | 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) -- | 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) -- | Execute a subquery SELECT in a SqlExpr. This function -- is unsafe, because it can throw runtime exceptions in two cases: -- --
-- select $ do -- (people :& followers :& blogPosts) <- -- from $ table @Person -- `innerJoin` table @Follow -- `on` (\(person :& follow) -> -- person ^. PersonId ==. follow ^. FollowFollowed) -- `innerJoin` table @BlogPost -- `on` (\((getTable @Follow -> follow) :& blogPost) -> -- blogPost ^. BlogPostAuthorId ==. follow ^. FollowFollower) -- where_ (people1 ^. PersonName ==. val "John") -- pure (followers, people2) ---- -- This example is a bit trivial, but once you've joined five or six -- tables it becomes enormously helpful. The above example uses a -- ViewPattern to call the function and assign the variable -- directly, but you can also imagine it being written like this: -- --
-- `on` (\(prev :& blogPost) -> -- let -- follow = getTable @Follow prev -- in -- blogPost ^. BlogPostAuthorId ==. follow ^. FollowFollower) ---- -- This function will pluck out the first table that matches the applied -- type, so if you join on the same table multiple times, it will always -- select the first one provided. -- -- The (:&) operator associates so that the left hand side can -- be a wildcard for an arbitrary amount of nesting, and the "most -- recent" or "newest" table in a join sequence is always available on -- the rightmost - so (prev :& bar) is a pattern that -- matches bar table (the most recent table added) and -- prev tables (all prior tables in the join match). -- -- By calling getTable on the prev, you can select -- exactly the table you want, allowing you to omit a large number of -- spurious pattern matches. Consider a query that does several LEFT -- JOIN on a first table: -- --
-- SELECT * -- FROM person -- LEFT JOIN car -- ON person.id = car.person_id -- LEFT JOIN bike -- ON person.id = bike.person_id -- LEFT JOIN food -- ON person.id = food.person_id -- LEFT JOIN address -- ON person.id = address.person_id ---- -- The final on clause in esqueleto would look like this: -- --
-- `on` do -- \(person :& _car :& _bike :& _food :& address) -> -- person.id ==. address.personId ---- -- First, we can change it to a prev :& newest match. We can -- do this because of the operator associativity. This is kind of like -- how a list : operator associates, but in the other direction: -- a : (b : c) = a : b : c. -- --
-- `on` do -- \(prev :& address) -> -- let (person :& _car :& _bike :& _food) = prev -- in person.id ==. address.personId ---- -- Then, we can use getTable to select the Person table -- directly, instead of pattern matching manually. -- --
-- `on` do -- \(prev :& address) -> -- let person = getTable @Person prev -- in person.id ==. address.personId ---- -- Finally, we can use a ViewPattern language extension to -- "inline" the access. -- --
-- `on` do -- \((getTable @Person -> person) :& address) -> -- person.id ==. address.personId ---- -- With this form, you do not need to be concerned about the number and -- wildcard status of tables that do not matter to the specific -- ON clause. getTable :: GetFirstTable (SqlExpr (Entity t)) ts => ts -> SqlExpr (Entity t) -- | A variant of getTable that operates on possibly-null entities. getTableMaybe :: GetFirstTable (SqlExpr (Maybe (Entity t))) ts => ts -> SqlExpr (Maybe (Entity t)) module Database.Persist.Sql.Lifted.Expression.Type -- | 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 module Database.Persist.Sql.Lifted.Expression.Update (=.) :: (PersistEntity val, PersistField typ) => EntityField val typ -> SqlExpr (Value typ) -> 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 a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 /=. module Database.Persist.Sql.Lifted.Expression -- | 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 -- | Lift a constant value from Haskell-land to the query. val :: PersistField typ => typ -> SqlExpr (Value typ) not_ :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -- | This operator translates to the SQL operator AND. -- -- Example: -- --
-- where_ $ -- user ^. UserName ==. val Matt -- &&. user ^. UserAge >=. val 21 --(&&.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool) infixr 3 &&. -- | This operator translates to the SQL operator AND. -- -- Example: -- --
-- where_ $ -- user ^. UserName ==. val Matt -- ||. user ^. UserName ==. val John --(||.) :: SqlExpr (Value Bool) -> SqlExpr (Value Bool) -> SqlExpr (Value Bool) infixr 2 ||. -- | CASE statement. For example: -- --
-- select $ -- return $ -- case_ -- [ when_ -- (exists $ -- from $ \p -> do -- where_ (p ^. PersonName ==. val "Mike")) -- then_ -- (subSelect $ -- from $ \v -> do -- let sub = -- from $ \c -> do -- where_ (c ^. PersonName ==. val "Mike") -- return (c ^. PersonFavNum) -- where_ (just (v ^. PersonFavNum) >. subSelect 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. -- --
-- query :: UserId -> SqlPersistT IO [Entity User] -- query userId = select $ do -- user <- from $ table @User -- where_ (user ^. UserId ==. val userId) -- pure user ---- -- This would generate the following SQL: -- --
-- SELECT user.* -- FROM user -- WHERE user.id = ? --(==.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 ==. -- | This operator translates to the SQL operator !=. -- -- Example: -- --
-- where_ $ user ^. UserName !=. val Bob --(!=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 !=. -- | This operator translates to the SQL operator >=. -- -- Example: -- --
-- where_ $ user ^. UserAge >=. val 21 --(>=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 >=. -- | This operator translates to the SQL operator >. -- -- Example: -- --
-- where_ $ user ^. UserAge >. val 20 --(>.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 >. -- | This operator translates to the SQL operator <=. -- -- Example: -- --
-- where_ $ val 21 <=. user ^. UserAge --(<=.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 <=. -- | This operator translates to the SQL operator <. -- -- Example: -- --
-- where_ $ val 20 <. user ^. UserAge --(<.) :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (Value typ) -> SqlExpr (Value Bool) infix 4 <. -- | a between (b, c) translates to the SQL expression -- a >= b AND a <= c. It does not use a SQL -- BETWEEN operator. -- -- @since: 3.1.0 between :: PersistField a => SqlExpr (Value a) -> (SqlExpr (Value a), SqlExpr (Value a)) -> SqlExpr (Value Bool) -- | COUNT. count :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a) -- | COUNT(*) value. countRows :: Num a => SqlExpr (Value a) -- | COUNT(DISTINCT x). countDistinct :: Num a => SqlExpr (Value typ) -> SqlExpr (Value a) -- | 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 EXISTS operator. notExists :: SqlQuery () -> SqlExpr (Value Bool) -- | Apply a PersistField constructor to SqlExpr Value -- arguments. (<#) :: (a -> b) -> SqlExpr (Value a) -> SqlExpr (Insertion b) -- | Apply extra SqlExpr Value arguments to a PersistField -- constructor (<&>) :: SqlExpr (Insertion (a -> b)) -> SqlExpr (Value a) -> SqlExpr (Insertion b) -- | 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))) -- | 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 -- | 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) -- | NOT IN operator. notIn :: PersistField typ => SqlExpr (Value typ) -> SqlExpr (ValueList typ) -> SqlExpr (Value Bool) -- | Execute a subquery SELECT in an SqlExpression. Returns a list -- of values. subList_select :: PersistField a => SqlQuery (SqlExpr (Value a)) -> SqlExpr (ValueList a) -- | Lift a list of constant value from Haskell-land to the query. valList :: PersistField typ => [typ] -> SqlExpr (ValueList typ) -- | 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)) -- | 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)
-- | An alias for isNothing that avoids clashing with the function
-- from Data.Maybe isNothing.
isNothing_ :: PersistField typ => SqlExpr (Value (Maybe typ)) -> SqlExpr (Value Bool)
-- | Analogous to Just, promotes a value of type typ into
-- one of type Maybe typ. It should hold that val .
-- Just === just . val.
--
-- This function will try not to produce a nested Maybe. This is
-- in accord with how SQL represents NULL. That means that
-- just . just = just. This behavior was
-- changed in v3.6.0.0. If you want to produce nested Maybe, see
-- just'.
just :: NullableFieldProjection typ typ' => SqlExpr (Value typ) -> SqlExpr (Value (Maybe typ'))
-- | NULL value.
nothing :: SqlExpr (Value (Maybe typ))
-- | Join nested Maybes in a Value into one. This is useful
-- when calling aggregate functions on nullable fields.
--
-- As of v3.6.0.0, this function will attempt to work on both
-- SqlExpr (Value (Maybe a)) as well as
-- SqlExpr (Value (Maybe (Maybe a)))
-- inputs to make transitioning to NullableFieldProjection easier.
-- This may make type inference worse in some cases. If you want the
-- monomorphic variant, see joinV'
joinV :: NullableFieldProjection typ typ' => SqlExpr (Value (Maybe typ)) -> SqlExpr (Value (Maybe typ'))
-- | 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, NullableFieldProjection a a') => [SqlExpr (Value (Maybe a))] -> SqlExpr (Value (Maybe a'))
-- | 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)
-- | This operator translates to the SQL operator +.
--
-- This does not require or assume anything about the SQL values.
-- Interpreting what +. means for a given type is left to the
-- database engine.
--
-- Example:
--
-- -- user ^. UserAge +. val 10 --(+.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 6 +. -- | This operator translates to the SQL operator -. -- -- This does not require or assume anything about the SQL values. -- Interpreting what -. means for a given type is left to the -- database engine. -- -- Example: -- --
-- user ^. UserAge -. val 10 --(-.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 6 -. -- | This operator translates to the SQL operator /. -- -- This does not require or assume anything about the SQL values. -- Interpreting what /. means for a given type is left to the -- database engine. -- -- Example: -- --
-- user ^. UserAge /. val 10 --(/.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 7 /. -- | This operator translates to the SQL operator *. -- -- This does not require or assume anything about the SQL values. -- Interpreting what *. means for a given type is left to the -- database engine. -- -- Example: -- --
-- user ^. UserAge *. val 10 --(*.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a) infixl 7 *. round_ :: (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) floor_ :: (PersistField a, Num a, PersistField b, Num b) => SqlExpr (Value a) -> SqlExpr (Value b) min_ :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value (Maybe (Nullable a))) max_ :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value (Maybe (Nullable a))) sum_ :: (PersistField a, PersistField b) => SqlExpr (Value a) -> SqlExpr (Value (Maybe b)) avg_ :: (PersistField a, PersistField b) => SqlExpr (Value 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) -- | Same as castNum, but for nullable values. castNumM :: (Num a, Num b) => SqlExpr (Value (Maybe a)) -> SqlExpr (Value (Maybe b)) -- | Ascending order of this field or SqlExpression. asc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy -- | Descending order of this field or SqlExpression. desc :: PersistField a => SqlExpr (Value a) -> SqlExpr OrderBy -- | Project a field of an entity. (^.) :: forall typ val. (PersistEntity val, PersistField typ) => SqlExpr (Entity val) -> EntityField val typ -> SqlExpr (Value typ) infixl 9 ^. -- | Project an EntityField of a nullable entity. The result type -- will be Nullable, meaning that nested Maybe won't be -- produced here. -- -- As of v3.6.0.0, this will attempt to combine nested Maybe. If -- you want to keep nested Maybe, then see ??.. (?.) :: (PersistEntity val, PersistField typ) => SqlExpr (Maybe (Entity val)) -> EntityField val typ -> SqlExpr (Value (Maybe (Nullable typ))) infixl 9 ?. -- | LOWER function. lower_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | UPPER function. @since 3.3.0 upper_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | TRIM function. @since 3.3.0 trim_ :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -- | 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) -- | LENGTH function. @since 3.3.0 length_ :: (SqlString s, Num a) => SqlExpr (Value s) -> SqlExpr (Value a) -- | LEFT function. @since 3.3.0 left_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s) -- | RIGHT function. @since 3.3.0 right_ :: (SqlString s, Num a) => (SqlExpr (Value s), SqlExpr (Value a)) -> SqlExpr (Value s) -- | LIKE operator. like :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool) infixr 2 `like` -- | ILIKE operator (case-insensitive LIKE). -- -- Supported by PostgreSQL only. Deprecated in version 3.6.0 in favor of -- the version available from Database.Esqueleto.PostgreSQL. ilike :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value Bool) infixr 2 `ilike` -- | 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) -- | The CONCAT function with a variable number of parameters. -- Supported by MySQL and PostgreSQL. SQLite supports this in versions -- after 3.44.0, and persistent-sqlite supports this in versions -- 2.13.3.0 and after. concat_ :: SqlString s => [SqlExpr (Value s)] -> SqlExpr (Value s) -- | The || string concatenation operator (named after Haskell's -- ++ in order to avoid naming clash with ||.). -- -- Supported by SQLite and PostgreSQL. -- -- MySQL support requires setting the SQL mode to -- PIPES_AS_CONCAT or ANSI - see this StackOverflow -- answer. (++.) :: SqlString s => SqlExpr (Value s) -> SqlExpr (Value s) -> SqlExpr (Value s) infixr 5 ++. -- | 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) -- | 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, NullableFieldProjection a a') => SqlQuery (SqlExpr (Value a)) -> SqlExpr (Value (Maybe 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)) -- | 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) -- | 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) -- | Execute a subquery SELECT in a SqlExpr. This function -- is unsafe, because it can throw runtime exceptions in two cases: -- --
-- select $ do -- (people :& followers :& blogPosts) <- -- from $ table @Person -- `innerJoin` table @Follow -- `on` (\(person :& follow) -> -- person ^. PersonId ==. follow ^. FollowFollowed) -- `innerJoin` table @BlogPost -- `on` (\((getTable @Follow -> follow) :& blogPost) -> -- blogPost ^. BlogPostAuthorId ==. follow ^. FollowFollower) -- where_ (people1 ^. PersonName ==. val "John") -- pure (followers, people2) ---- -- This example is a bit trivial, but once you've joined five or six -- tables it becomes enormously helpful. The above example uses a -- ViewPattern to call the function and assign the variable -- directly, but you can also imagine it being written like this: -- --
-- `on` (\(prev :& blogPost) -> -- let -- follow = getTable @Follow prev -- in -- blogPost ^. BlogPostAuthorId ==. follow ^. FollowFollower) ---- -- This function will pluck out the first table that matches the applied -- type, so if you join on the same table multiple times, it will always -- select the first one provided. -- -- The (:&) operator associates so that the left hand side can -- be a wildcard for an arbitrary amount of nesting, and the "most -- recent" or "newest" table in a join sequence is always available on -- the rightmost - so (prev :& bar) is a pattern that -- matches bar table (the most recent table added) and -- prev tables (all prior tables in the join match). -- -- By calling getTable on the prev, you can select -- exactly the table you want, allowing you to omit a large number of -- spurious pattern matches. Consider a query that does several LEFT -- JOIN on a first table: -- --
-- SELECT * -- FROM person -- LEFT JOIN car -- ON person.id = car.person_id -- LEFT JOIN bike -- ON person.id = bike.person_id -- LEFT JOIN food -- ON person.id = food.person_id -- LEFT JOIN address -- ON person.id = address.person_id ---- -- The final on clause in esqueleto would look like this: -- --
-- `on` do -- \(person :& _car :& _bike :& _food :& address) -> -- person.id ==. address.personId ---- -- First, we can change it to a prev :& newest match. We can -- do this because of the operator associativity. This is kind of like -- how a list : operator associates, but in the other direction: -- a : (b : c) = a : b : c. -- --
-- `on` do -- \(prev :& address) -> -- let (person :& _car :& _bike :& _food) = prev -- in person.id ==. address.personId ---- -- Then, we can use getTable to select the Person table -- directly, instead of pattern matching manually. -- --
-- `on` do -- \(prev :& address) -> -- let person = getTable @Person prev -- in person.id ==. address.personId ---- -- Finally, we can use a ViewPattern language extension to -- "inline" the access. -- --
-- `on` do -- \((getTable @Person -> person) :& address) -> -- person.id ==. address.personId ---- -- With this form, you do not need to be concerned about the number and -- wildcard status of tables that do not matter to the specific -- ON clause. getTable :: GetFirstTable (SqlExpr (Entity t)) ts => ts -> SqlExpr (Entity t) -- | A variant of getTable that operates on possibly-null entities. getTableMaybe :: GetFirstTable (SqlExpr (Maybe (Entity t))) ts => ts -> SqlExpr (Maybe (Entity t)) (=.) :: (PersistEntity val, PersistField typ) => EntityField val typ -> SqlExpr (Value typ) -> 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 a) => EntityField val a -> SqlExpr (Value a) -> SqlExpr (Entity val) -> SqlExpr Update infixr 3 /=. module Database.Persist.Sql.Lifted.Filter -- | Filters which are available for select, updateWhere -- and deleteWhere. Each filter constructor specifies the field -- being filtered on, the type of comparison applied (equals, not equals, -- etc) and the argument for the comparison. -- -- Persistent users use combinators to create these. -- -- Note that it's important to be careful about the PersistFilter -- that you are using, if you use this directly. For example, using the -- In PersistFilter requires that you have an array- or -- list-shaped EntityField. It is possible to construct values -- using this that will create malformed runtime values. data () => Filter record -- | Check for equality. -- --
-- selectSPJ :: MonadIO m => ReaderT SqlBackend m [Entity User] -- selectSPJ = selectList [UserName ==. "SPJ" ] [] ---- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+-----+ -- |id |name |age | -- +-----+-----+-----+ -- |1 |SPJ |40 | -- +-----+-----+-----+ --(==.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Filter v infix 4 ==. -- | Non-equality check. -- --
-- selectSimon :: MonadIO m => ReaderT SqlBackend m [Entity User] -- selectSimon = selectList [UserName !=. "SPJ" ] [] ---- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+-----+ -- |id |name |age | -- +-----+-----+-----+ -- |2 |Simon|41 | -- +-----+-----+-----+ --(!=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Filter v infix 4 !=. -- | Less-than check. -- --
-- selectLessAge :: MonadIO m => ReaderT SqlBackend m [Entity User] -- selectLessAge = selectList [UserAge <. 41 ] [] ---- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+-----+ -- |id |name |age | -- +-----+-----+-----+ -- |1 |SPJ |40 | -- +-----+-----+-----+ --(<.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Filter v infix 4 <. -- | Greater-than check. -- --
-- selectGreaterAge :: MonadIO m => ReaderT SqlBackend m [Entity User] -- selectGreaterAge = selectList [UserAge >. 40 ] [] ---- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+-----+ -- |id |name |age | -- +-----+-----+-----+ -- |2 |Simon|41 | -- +-----+-----+-----+ --(>.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Filter v infix 4 >. -- | Less-than or equal check. -- --
-- selectLessEqualAge :: MonadIO m => ReaderT SqlBackend m [Entity User] -- selectLessEqualAge = selectList [UserAge <=. 40 ] [] ---- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+-----+ -- |id |name |age | -- +-----+-----+-----+ -- |1 |SPJ |40 | -- +-----+-----+-----+ --(<=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Filter v infix 4 <=. -- | Greater-than or equal check. -- --
-- selectGreaterEqualAge :: MonadIO m => ReaderT SqlBackend m [Entity User] -- selectGreaterEqualAge = selectList [UserAge >=. 41 ] [] ---- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+-----+ -- |id |name |age | -- +-----+-----+-----+ -- |2 |Simon|41 | -- +-----+-----+-----+ --(>=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Filter v infix 4 >=. -- | Check if value is in given list. -- --
-- selectUsers :: MonadIO m => ReaderT SqlBackend m [Entity User] -- selectUsers = selectList [UserAge <-. [40, 41]] [] ---- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+-----+ -- |id |name |age | -- +-----+-----+-----+ -- |1 |SPJ |40 | -- +-----+-----+-----+ -- |2 |Simon|41 | -- +-----+-----+-----+ ---- --
-- selectSPJ :: MonadIO m => ReaderT SqlBackend m [Entity User] -- selectSPJ = selectList [UserAge <-. [40]] [] ---- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+-----+ -- |id |name |age | -- +-----+-----+-----+ -- |1 |SPJ |40 | -- +-----+-----+-----+ --(<-.) :: forall v typ. PersistField typ => EntityField v typ -> [typ] -> Filter v infix 4 <-. -- | Check if value is not in given list. -- --
-- selectSimon :: MonadIO m => ReaderT SqlBackend m [Entity User] -- selectSimon = selectList [UserAge /<-. [40]] [] ---- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+-----+ -- |id |name |age | -- +-----+-----+-----+ -- |2 |Simon|41 | -- +-----+-----+-----+ --(/<-.) :: forall v typ. PersistField typ => EntityField v typ -> [typ] -> Filter v infix 4 /<-. -- | The OR of two lists of filters. For example: -- --
-- selectList -- ([ PersonAge >. 25 -- , PersonAge <. 30 ] ||. -- [ PersonIncome >. 15000 -- , PersonIncome <. 25000 ]) -- [] ---- -- will filter records where a person's age is between 25 and 30 -- or a person's income is between (15000 and 25000). -- -- If you are looking for an (&&.) operator to do (A -- AND B AND (C OR D)) you can use the (++) operator -- instead as there is no (&&.). For example: -- --
-- selectList -- ([ PersonAge >. 25 -- , PersonAge <. 30 ] ++ -- ([PersonCategory ==. 1] ||. -- [PersonCategory ==. 5])) -- [] ---- -- will filter records where a person's age is between 25 and 30 -- and (person's category is either 1 or 5). (||.) :: [Filter v] -> [Filter v] -> [Filter v] infixl 3 ||. module Database.Persist.Sql.Lifted.From -- | 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 data () => From a -- | 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' -- | Bring a PersistEntity into scope from a table -- --
-- select $ from $ table @People --table :: PersistEntity ent => From (SqlExpr (Entity ent)) -- | 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 :& -- | 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` -- | 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` -- | 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` -- | 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) -> -- just (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` -- | 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` -- | 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` -- | 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` -- | 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` -- | 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` module Database.Persist.Sql.Lifted.HasSqlBackend class HasSqlBackend a getSqlBackend :: HasSqlBackend a => a -> SqlBackend instance Database.Persist.Sql.Lifted.HasSqlBackend.HasSqlBackend Database.Persist.SqlBackend.Internal.SqlBackend module Database.Persist.Sql.Lifted.MonadSqlBackend -- | A monadic context in which a SQL backend is available for running -- database queries class MonadUnliftIO m => MonadSqlBackend m getSqlBackendM :: MonadSqlBackend m => m SqlBackend -- | Generalize from SqlPersistT to MonadSqlBackend liftSql :: (MonadSqlBackend m, HasCallStack) => ReaderT SqlBackend m a -> m a instance (Database.Persist.Sql.Lifted.HasSqlBackend.HasSqlBackend r, Control.Monad.IO.Unlift.MonadUnliftIO m) => Database.Persist.Sql.Lifted.MonadSqlBackend.MonadSqlBackend (Control.Monad.Trans.Reader.ReaderT r m) module Database.Persist.Sql.Lifted.MonadSqlTx -- | The constraint MonadSqlTx db m indicates that -- m is a monadic context that can run db actions, -- usually as a SQL transaction. Typically, this means that db -- needs a connection and m can provide one, e.g. from a -- connection pool. class (MonadSqlBackend db, MonadUnliftIO m) => MonadSqlTx db m | m -> db -- | Runs the action in a SQL transaction runSqlTx :: (MonadSqlTx db m, HasCallStack) => db a -> m a module Database.Persist.Sql.Lifted.Core -- | The constraint MonadSqlTx db m indicates that -- m is a monadic context that can run db actions, -- usually as a SQL transaction. Typically, this means that db -- needs a connection and m can provide one, e.g. from a -- connection pool. class (MonadSqlBackend db, MonadUnliftIO m) => MonadSqlTx db m | m -> db -- | Runs the action in a SQL transaction runSqlTx :: (MonadSqlTx db m, HasCallStack) => db a -> m a class HasSqlBackend a getSqlBackend :: HasSqlBackend a => a -> SqlBackend -- | 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 -- | A monadic context in which a SQL backend is available for running -- database queries class MonadUnliftIO m => MonadSqlBackend m getSqlBackendM :: MonadSqlBackend m => m SqlBackend -- | Generalize from SqlPersistT to MonadSqlBackend liftSql :: (MonadSqlBackend m, HasCallStack) => ReaderT SqlBackend m a -> m a -- | Wrappers that apply liftSql to Esqueleto utilities of the same -- name. module Database.Persist.Sql.Lifted.Esqueleto -- | Execute an Esqueleto DELETE query delete :: forall m. (MonadSqlBackend m, HasCallStack) => SqlQuery () -> m () -- | Execute an Esqueleto DELETE query deleteCount :: forall m. (MonadSqlBackend m, HasCallStack) => SqlQuery () -> m Int64 -- | Delete a specific record by identifier -- -- Does nothing if record does not exist. deleteKey :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => Key a -> m () -- | Insert a PersistField for every selected value insertSelect :: forall a m. (PersistEntity a, MonadSqlBackend m, HasCallStack) => SqlQuery (SqlExpr (Insertion a)) -> m () -- | Insert a PersistField for every selected value, returning the -- count insertSelectCount :: forall a m. (PersistEntity a, MonadSqlBackend m, HasCallStack) => SqlQuery (SqlExpr (Insertion a)) -> m Int64 -- | Renders a SqlQuery to Text along with the list of -- PersistValues that would be supplied to the database for -- ? placeholders renderQueryDelete :: forall a r m. (SqlSelect a r, MonadSqlBackend m, HasCallStack) => SqlQuery a -> m (Text, [PersistValue]) -- | Renders a SqlQuery to Text along with the list of -- PersistValues that would be supplied to the database for -- ? placeholders renderQueryInsertInto :: forall a r m. (SqlSelect a r, MonadSqlBackend m, HasCallStack) => SqlQuery a -> m (Text, [PersistValue]) -- | Renders a SqlQuery to Text along with the list of -- PersistValues that would be supplied to the database for -- ? placeholders renderQuerySelect :: forall a r m. (SqlSelect a r, MonadSqlBackend m, HasCallStack) => SqlQuery a -> m (Text, [PersistValue]) -- | Renders a SqlQuery to Text along with the list of -- PersistValues that would be supplied to the database for -- ? placeholders renderQueryToText :: forall a r m. (SqlSelect a r, MonadSqlBackend m, HasCallStack) => Mode -> SqlQuery a -> m (Text, [PersistValue]) -- | Renders a SqlQuery to Text along with the list of -- PersistValues that would be supplied to the database for -- ? placeholders renderQueryUpdate :: forall a r m. (SqlSelect a r, MonadSqlBackend m, HasCallStack) => SqlQuery a -> m (Text, [PersistValue]) -- | Execute an Esqueleto SELECT query select :: forall a r m. (SqlSelect a r, MonadSqlBackend m, HasCallStack) => SqlQuery a -> m [r] -- | Execute an Esqueleto SELECT query, getting only the first row selectOne :: forall a r m. (SqlSelect a r, MonadSqlBackend m, HasCallStack) => SqlQuery a -> m (Maybe r) -- | Execute an Esqueleto UPDATE query update :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => (SqlExpr (Entity a) -> SqlQuery ()) -> m () -- | Execute an Esqueleto UPDATE query, returning the count updateCount :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => (SqlExpr (Entity a) -> SqlQuery ()) -> m Int64 -- | Wrappers that apply liftSql to Persistent utilities of the same -- name. module Database.Persist.Sql.Lifted.Persistent -- | Check whether there are any conflicts for unique keys with this entity -- and existing entities in the database checkUnique :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => a -> m (Maybe (Unique a)) -- | Check whether there are any conflicts for unique keys with this entity -- and existing entities in the database -- -- This is useful for updating because it ignores conflicts when the -- particular entity already exists. checkUniqueUpdateable :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => Entity a -> m (Maybe (Unique a)) -- | The total number of records fulfilling the given criteria count :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => [Filter a] -> m Int -- | Delete a specific record by identifier -- -- Does nothing if record does not exist. delete :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => Key a -> m () -- | Delete a specific record by unique key -- -- Does nothing if no record matches. deleteBy :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => Unique a -> m () -- | Delete all records matching the given criteria deleteWhere :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => [Filter a] -> m () -- | Delete all records matching the given criteria deleteWhereCount :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => [Filter a] -> m Int64 -- | Check if there is at least one record fulfilling the given criteria exists :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => [Filter a] -> m Bool -- | Check if a record with this unique key exists existsBy :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => Unique a -> m Bool -- | Get a record by identifier, if available get :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => Key a -> m (Maybe a) -- | Get a record by unique key, if available, returning both the -- identifier and the record getBy :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => Unique a -> m (Maybe (Entity a)) getByValue :: forall a m. (PersistEntityBackend a ~ SqlBackend, AtLeastOneUniqueKey a, MonadSqlBackend m, HasCallStack) => a -> m (Maybe (Entity a)) -- | Get a record by identifier, if available getEntity :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => Key a -> m (Maybe (Entity a)) -- | Get the SQL string for the field that an EntityField represents getFieldName :: forall a t m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => EntityField a t -> m Text -- | Get a record by identifier, if available, for a non-null (not -- Maybe) foreign key -- -- Unsafe unless your database is enforcing that the foreign key is -- valid. getJust :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => Key a -> m a -- | Get a record by identifier, if available, for a non-null (not -- Maybe) foreign key -- -- Unsafe unless your database is enforcing that the foreign key is -- valid. getJustEntity :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => Key a -> m (Entity a) -- | Get many records by their respective identifiers, if available getMany :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => [Key a] -> m (Map (Key a) a) -- | Get the SQL string for the table that a PersistEntity -- represents getTableName :: forall a m. (PersistEntity a, MonadSqlBackend m, HasCallStack) => a -> m Text -- | Create a new record in the database insert :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, SafeToInsert a, MonadSqlBackend m, HasCallStack) => a -> m (Key a) -- | Create a new record in the database insert_ :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, SafeToInsert a, MonadSqlBackend m, HasCallStack) => a -> m () -- | Insert a value, checking for conflicts with any unique constraints insertBy :: forall a m. (PersistEntityBackend a ~ SqlBackend, AtLeastOneUniqueKey a, SafeToInsert a, MonadSqlBackend m, HasCallStack) => a -> m (Either (Entity a) (Key a)) -- | Create a new record in the database, returning an auto-increment ID -- and the inserted record insertEntity :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, SafeToInsert a, MonadSqlBackend m, HasCallStack) => a -> m (Entity a) -- | Create multiple records in the database, with specified keys insertEntityMany :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => [Entity a] -> m () -- | Create a new record in the database using the given key insertKey :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, MonadSqlBackend m, HasCallStack) => Key a -> a -> m () -- | Create multiple records in the database and return their Keys insertMany :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, SafeToInsert a, MonadSqlBackend m, HasCallStack) => [a] -> m [Key a] -- | Create multiple records in the database insertMany_ :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, SafeToInsert a, MonadSqlBackend m, HasCallStack) => [a] -> m () -- | Create a new record in the database insertRecord :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, SafeToInsert a, MonadSqlBackend m, HasCallStack) => a -> m a -- | Create a new record in the database insertUnique :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, SafeToInsert a, MonadSqlBackend m, HasCallStack) => a -> m (Maybe (Key a)) -- | Create a new record in the database insertUnique_ :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, SafeToInsert a, MonadSqlBackend m, HasCallStack) => a -> m (Maybe ()) -- | Create a new record in the database insertUniqueEntity :: forall a m. (PersistEntity a, PersistEntityBackend a ~ SqlBackend, SafeToInsert a, MonadSqlBackend m, HasCallStack) => a -> m (Maybe (Entity a)) -- | Return the single unique key for a record onlyUnique :: forall a m. (PersistEntityBackend a ~ SqlBackend, OnlyOneUniqueKey a, MonadSqlBackend m, HasCallStack) => a -> m (Unique a) -- | Put many records into the database -- --
-- 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) ---- --
-- 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 alias for groupBy that avoids conflict with the term from -- Data.List groupBy. groupBy_ :: ToSomeValues a => a -> SqlQuery () -- | HAVING. having :: SqlExpr (Value Bool) -> SqlQuery () module Database.Persist.Sql.Lifted.Query.CommonTableExpressions -- | 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. To use a MATERIALIZED query in Esquelto, see -- functions withMaterialized and -- withRecursiveMaterialized. -- -- Since: 3.4.0.0 with :: (ToAlias a, ToAliasReference a, SqlSelect a r) => SqlQuery a -> SqlQuery (From a) -- | 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) module Database.Persist.Sql.Lifted.Query.Core -- | SQL backend for esqueleto using SqlPersistT. data () => SqlQuery a -- | WHERE clause: restrict the query's result. where_ :: SqlExpr (Value Bool) -> SqlQuery () -- | LIMIT. Limit the number of returned rows. limit :: Int64 -> SqlQuery () -- | OFFSET. Usually used with limit. offset :: Int64 -> SqlQuery () -- | 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 -- | 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 -- | ORDER BY clause. See also asc and desc. -- -- Multiple calls to orderBy get concatenated on the final query, -- including distinctOnOrderBy. orderBy :: [SqlExpr OrderBy] -> SqlQuery () -- | Erase an SqlExpression's type so that it's suitable to be used by -- distinctOn. don :: SqlExpr (Value a) -> SqlExpr DistinctOn -- | 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 -- | 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 module Database.Persist.Sql.Lifted.Query.Locking -- | Add a locking clause to the query. Please read LockingKind -- documentation and your RDBMS manual. Unsafe since not all locking -- clauses are implemented for every RDBMS -- -- If multiple calls to locking are made on the same query, the -- last one is used. locking :: LockingKind -> SqlQuery () -- | 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 module Database.Persist.Sql.Lifted.Query.SetOperations -- | 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 -- | 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' -- | 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' module Database.Persist.Sql.Lifted.Query.Update -- | 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 () module Database.Persist.Sql.Lifted.Query -- | SQL backend for esqueleto using SqlPersistT. data () => SqlQuery a -- | WHERE clause: restrict the query's result. where_ :: SqlExpr (Value Bool) -> 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) ---- --
-- 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 alias for groupBy that avoids conflict with the term from -- Data.List groupBy. groupBy_ :: ToSomeValues a => a -> SqlQuery () -- | HAVING. having :: SqlExpr (Value Bool) -> SqlQuery () -- | LIMIT. Limit the number of returned rows. limit :: Int64 -> SqlQuery () -- | OFFSET. Usually used with limit. offset :: Int64 -> SqlQuery () -- | 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 -- | 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 -- | ORDER BY clause. See also asc and desc. -- -- Multiple calls to orderBy get concatenated on the final query, -- including distinctOnOrderBy. orderBy :: [SqlExpr OrderBy] -> SqlQuery () -- | Erase an SqlExpression's type so that it's suitable to be used by -- distinctOn. don :: SqlExpr (Value a) -> SqlExpr DistinctOn -- | 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 -- | 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 () -- | 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 -- | Add a locking clause to the query. Please read LockingKind -- documentation and your RDBMS manual. Unsafe since not all locking -- clauses are implemented for every RDBMS -- -- If multiple calls to locking are made on the same query, the -- last one is used. locking :: LockingKind -> SqlQuery () -- | 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 -- | 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 -- | 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' -- | 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' -- | 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. To use a MATERIALIZED query in Esquelto, see -- functions withMaterialized and -- withRecursiveMaterialized. -- -- Since: 3.4.0.0 with :: (ToAlias a, ToAliasReference a, SqlSelect a r) => SqlQuery a -> SqlQuery (From a) -- | 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) module Database.Persist.Sql.Lifted.Update -- | Updating a database entity. -- -- Persistent users use combinators to create these. data () => Update record -- | Assign a field a value. -- --
-- updateAge :: MonadIO m => ReaderT SqlBackend m () -- updateAge = updateWhere [UserName ==. "SPJ" ] [UserAge =. 45] ---- -- Similar to updateWhere which is shown in the above example you -- can use other functions present in the module -- Database.Persist.Class. Note that the first parameter of -- updateWhere is [Filter val] and second parameter is -- [Update val]. By comparing this with the type of ==. and -- =., you can see that they match up in the above usage. -- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+--------+ -- |id |name |age | -- +-----+-----+--------+ -- |1 |SPJ |40 -> 45| -- +-----+-----+--------+ -- |2 |Simon|41 | -- +-----+-----+--------+ --(=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Update v infixr 3 =. -- | Assign a field by addition (+=). -- --
-- addAge :: MonadIO m => ReaderT SqlBackend m () -- addAge = updateWhere [UserName ==. "SPJ" ] [UserAge +=. 1] ---- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+---------+ -- |id |name |age | -- +-----+-----+---------+ -- |1 |SPJ |40 -> 41 | -- +-----+-----+---------+ -- |2 |Simon|41 | -- +-----+-----+---------+ --(+=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Update v infixr 3 +=. -- | Assign a field by subtraction (-=). -- --
-- subtractAge :: MonadIO m => ReaderT SqlBackend m () -- subtractAge = updateWhere [UserName ==. "SPJ" ] [UserAge -=. 1] ---- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+---------+ -- |id |name |age | -- +-----+-----+---------+ -- |1 |SPJ |40 -> 39 | -- +-----+-----+---------+ -- |2 |Simon|41 | -- +-----+-----+---------+ --(-=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Update v infixr 3 -=. -- | Assign a field by multiplication (*=). -- --
-- multiplyAge :: MonadIO m => ReaderT SqlBackend m () -- multiplyAge = updateWhere [UserName ==. "SPJ" ] [UserAge *=. 2] ---- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+--------+ -- |id |name |age | -- +-----+-----+--------+ -- |1 |SPJ |40 -> 80| -- +-----+-----+--------+ -- |2 |Simon|41 | -- +-----+-----+--------+ --(*=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Update v infixr 3 *=. -- | Assign a field by division (/=). -- --
-- divideAge :: MonadIO m => ReaderT SqlBackend m () -- divideAge = updateWhere [UserName ==. "SPJ" ] [UserAge /=. 2] ---- -- The above query when applied on dataset-1, will produce this: -- --
-- +-----+-----+---------+ -- |id |name |age | -- +-----+-----+---------+ -- |1 |SPJ |40 -> 20 | -- +-----+-----+---------+ -- |2 |Simon|41 | -- +-----+-----+---------+ --(/=.) :: forall v typ. PersistField typ => EntityField v typ -> typ -> Update v infixr 3 /=.