esqueleto 2.2 → 2.2.1
raw patch · 4 files changed
+101/−106 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- esqueleto.cabal +1/−3
- src/Database/Esqueleto.hs +25/−25
- src/Database/Esqueleto/Internal/Language.hs +64/−67
- src/Database/Esqueleto/Internal/Sql.hs +11/−11
esqueleto.cabal view
@@ -1,5 +1,5 @@ name: esqueleto-version: 2.2+version: 2.2.1 synopsis: Type-safe EDSL for SQL queries on persistent backends. homepage: https://github.com/prowdsponsor/esqueleto license: BSD3@@ -11,8 +11,6 @@ build-type: Simple cabal-version: >=1.8 description:- This version is a beta release that works with the persistent-2.0 beta.- . @esqueleto@ is a bare bones, type-safe EDSL for SQL queries that works with unmodified @persistent@ SQL backends. Its language closely resembles SQL, so you don't have to learn
src/Database/Esqueleto.hs view
@@ -214,8 +214,8 @@ -- In @esqueleto@, we may write the same query above as: -- -- @--- select $--- from $ \\p -> do+-- 'select' $+-- 'from' $ \\p -> do -- 'where_' (p '^.' PersonName '==.' 'val' \"John\") -- return p -- @@@ -238,14 +238,14 @@ -- In @esqueleto@, we may write the same query above as: -- -- @--- select $--- from $ \\p -> do--- where_ (p ^. PersonAge '>=.' 'just' (val 18))+-- 'select' $+-- 'from' $ \\p -> do+-- 'where_' (p '^.' PersonAge '>=.' 'just' ('val' 18)) -- return p -- @ -- -- Since @age@ is an optional @Person@ field, we use 'just' lift--- @val 18 :: SqlExpr (Value Int)@ into @just (val 18) ::+-- @'val' 18 :: SqlExpr (Value Int)@ into @just ('val' 18) :: -- SqlExpr (Value (Maybe Int))@. -- -- Implicit joins are represented by tuples. For example, to get@@ -261,10 +261,10 @@ -- In @esqueleto@, we may write the same query above as: -- -- @--- select $--- from $ \\(b, p) -> do--- where_ (b ^. BlogPostAuthorId ==. p ^. PersonId)--- 'orderBy' ['asc' (b ^. BlogPostTitle)]+-- 'select' $+-- 'from' $ \\(b, p) -> do+-- 'where_' (b '^.' BlogPostAuthorId '==.' p '^.' PersonId)+-- 'orderBy' ['asc' (b '^.' BlogPostTitle)] -- return (b, p) -- @ --@@ -281,10 +281,10 @@ -- In @esqueleto@, we may write the same query above as: -- -- @--- select $--- from $ \\(p ``LeftOuterJoin`` mb) -> do--- 'on' (just (p ^. PersonId) ==. mb '?.' BlogPostAuthorId)--- orderBy [asc (p ^. PersonName), asc (mb '?.' BlogPostTitle)]+-- 'select' $+-- 'from' $ \\(p `'LeftOuterJoin`` mb) -> do+-- 'on' ('just' (p '^.' PersonId) '==.' mb '?.' BlogPostAuthorId)+-- 'orderBy' ['asc' (p '^.' PersonName), 'asc' (mb '?.' BlogPostTitle)] -- return (p, mb) -- @ --@@ -310,10 +310,10 @@ -- In @esqueleto@, we may write the same query above as: -- -- @--- select $--- from $ \\(p1 ``InnerJoin`` f ``InnerJoin`` p2) -> do--- on (p2 ^. PersonId ==. f ^. FollowFollowed)--- on (p1 ^. PersonId ==. f ^. FollowFollower)+-- 'select' $+-- 'from' $ \\(p1 `'InnerJoin`` f `'InnerJoin`` p2) -> do+-- 'on' (p2 '^.' PersonId '==.' f '^.' FollowFollowed)+-- 'on' (p1 '^.' PersonId '==.' f '^.' FollowFollower) -- return (p1, f, p2) -- @ --@@ -327,11 +327,11 @@ -- -- @ -- do 'update' $ \\p -> do--- 'set' p [ PersonName '=.' val \"João\" ]--- where_ (p ^. PersonName ==. val \"Joao\")+-- 'set' p [ PersonName '=.' 'val' \"João\" ]+-- 'where_' (p '^.' PersonName '==.' 'val' \"Joao\") -- 'delete' $--- from $ \\p -> do--- where_ (p ^. PersonAge <. just (val 14))+-- 'from' $ \\p -> do+-- 'where_' (p '^.' PersonAge '<.' 'just' ('val' 14)) -- @ -- -- The results of queries can also be used for insertions.@@ -347,8 +347,8 @@ -- In @esqueleto@, we may write the same query above as: -- -- @--- insertSelect $ from $ \\p->--- return $ BlogPost \<# \"Group Blog Post\" \<&\> (p ^. PersonId)+-- 'insertSelect' $ 'from' $ \\p->+-- return $ BlogPost '<#' \"Group Blog Post\" '<&>' (p '^.' PersonId) -- @ -- -- Individual insertions can be performed through Persistent's@@ -377,7 +377,7 @@ ---------------------------------------------------------------------- --- | @valkey i = val (Key (PersistInt64 i))@+-- | @valkey i = 'val' . 'toSqlKey'@ -- (<https://github.com/meteficha/esqueleto/issues/9>). valkey :: (Esqueleto query expr backend, ToBackendKey SqlBackend entity, PersistField (Key entity)) => Int64 -> expr (Value (Key entity))
src/Database/Esqueleto/Internal/Language.hs view
@@ -99,8 +99,8 @@ -- -- @ -- select $- -- from $ \\(foo ``InnerJoin`` bar) -> do- -- on (foo ^. FooId ==. bar ^. BarFooId)+ -- 'from' $ \\(foo `'InnerJoin`` bar) -> do+ -- 'on' (foo '^.' FooId '==.' bar '^.' BarFooId) -- ... -- @ --@@ -111,9 +111,9 @@ -- -- @ -- select $- -- from $ \\(foo ``InnerJoin`` bar ``InnerJoin`` baz) -> do- -- on (baz ^. BazId ==. bar ^. BarBazId)- -- on (foo ^. FooId ==. bar ^. BarFooId)+ -- 'from' $ \\(foo `'InnerJoin`` bar `'InnerJoin`` baz) -> do+ -- 'on' (baz '^.' BazId '==.' bar '^.' BarBazId)+ -- 'on' (foo '^.' FooId '==.' bar '^.' BarFooId) -- ... -- @ --@@ -122,11 +122,11 @@ -- -- @ -- let query1 =- -- from $ \\(foo ``InnerJoin`` bar) -> do- -- on (foo ^. FooId ==. bar ^. BarFooId)+ -- 'from' $ \\(foo `'InnerJoin`` bar) -> do+ -- 'on' (foo '^.' FooId '==.' bar '^.' BarFooId) -- query2 =- -- from $ \\(mbaz ``LeftOuterJoin`` quux) -> do- -- return (mbaz ?. BazName, quux)+ -- 'from' $ \\(mbaz `'LeftOuterJoin`` quux) -> do+ -- return (mbaz '?.' BazName, quux) -- test1 = (,) \<$\> query1 \<*\> query2 -- test2 = flip (,) \<$\> query2 \<*\> query1 -- @@@ -140,24 +140,25 @@ -- 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)+ -- 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- -- @SqlExpr (Value Int)@ to avoid ambiguity):+ -- With groupBy you can sort by aggregate functions, like so+ -- (we used @let@ to restrict the more general 'countRows' to+ -- @SqlExpr (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+ -- 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) -- @@@ -211,8 +212,8 @@ isNothing :: PersistField typ => expr (Value (Maybe typ)) -> expr (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@.+ -- one of type @Maybe typ@. It should hold that @'val' . Just+ -- === just . 'val'@. just :: expr (Value typ) -> expr (Value (Maybe typ)) -- | @NULL@ value.@@ -281,7 +282,7 @@ -- for example: -- -- @- -- name ``'like'`` (%) ++. val "John" ++. (%)+ -- name `'like`` (%) ++. 'val' \"John\" ++. (%) -- @ (%) :: (PersistField s, IsString s) => expr (Value s) -- | The @CONCAT@ function with a variable number of@@ -312,10 +313,10 @@ -- -- @ -- select $- -- from $ \\person -> do- -- where_ $ exists $- -- from $ \\post -> do- -- where_ (post ^. BlogPostAuthorId ==. person ^. PersonId)+ -- 'from' $ \\person -> do+ -- 'where_' $ 'exists' $+ -- 'from' $ \\post -> do+ -- 'where_' (post '^.' BlogPostAuthorId '==.' person '^.' PersonId) -- return person -- @ exists :: query () -> expr (Value Bool)@@ -345,31 +346,31 @@ -- @ -- select $ -- return $- -- case_- -- [ when_- -- (exists $- -- from $ \\p -> do- -- where_ (p ^. PersonName ==. val "Mike"))- -- then_- -- (sub_select $- -- from $ \\v -> do+ -- '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))+ -- '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".+ -- 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. -- -- * This only implements the full CASE statement, it does not- -- implement the "simple" CASE statement.+ -- implement the \"simple\" CASE statement. -- -- -- * At least one 'when_' and 'then_' is mandatory otherwise it will@@ -443,8 +444,8 @@ SomeValue :: Esqueleto query expr backend => expr (Value a) -> SomeValue expr -- | A class of things that can be converted into a list of SomeValue. It has--- instances for tuples and is the reason why groupBy can take tuples, like--- @groupBy (foo ^. FooId, foo ^. FooName, foo ^. FooType)@.+-- instances for tuples and is the reason why 'groupBy' can take tuples, like+-- @'groupBy' (foo '^.' FooId, foo '^.' FooName, foo '^.' FooType)@. class ToSomeValues expr a where toSomeValues :: a -> [SomeValue expr] @@ -522,7 +523,7 @@ -- -- @ -- select $--- from $ \\(person ``LeftOuterJoin`` pet) ->+-- 'from' $ \\(person `'LeftOuterJoin`` pet) -> -- ... -- @ --@@ -622,7 +623,7 @@ -- * A @JOIN@ of any other two types allowed by the innermost -- magic, where a @JOIN@ may be an 'InnerJoin', a 'CrossJoin', a -- 'LeftOuterJoin', a 'RightOuterJoin', or a 'FullOuterJoin'.--- The @JOINs@ have right fixity, the same as in SQL.+-- The @JOINs@ have left fixity. -- -- The outermost magic allows you to use @from@ on any tuples of -- types supported by innermost magic (and also tuples of tuples,@@ -636,11 +637,11 @@ -- 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) -> ...+-- '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,@@ -654,25 +655,21 @@ -- ) => expr (Entity Person) -- (person, blogPost) -- :: (...) => (expr (Entity Person), expr (Entity BlogPost))--- (p ``LeftOuterJoin`` mb)+-- (p `'LeftOuterJoin`` mb) -- :: (...) => InnerJoin (expr (Entity Person)) (expr (Maybe (Entity BlogPost)))--- (p1 ``InnerJoin`` f ``InnerJoin`` p2)--- :: (...) => InnerJoin--- (expr (Entity Person))--- (InnerJoin (expr (Entity Follow))--- (expr (Entity Person)))--- ((p1 ``InnerJoin`` f) ``InnerJoin`` p2) ::+-- (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 @JOIN@s.--- For example, when using the SQL backend with SQLite, it will--- not accept the last example above (which is associated to the--- left, instead of being to the right) and will not accept--- 'RightOuterJoin's or 'FullOuterJoin's. from :: From query expr backend a => (a -> query b) -> query b from = (from_ >>=)
src/Database/Esqueleto/Internal/Sql.hs view
@@ -712,12 +712,12 @@ -- allow type information to flow both from @a@ to @r@ and -- vice-versa. This means that you'll almost never have to give -- any type signatures for @esqueleto@ queries. For example, the--- query @select $ from $ \\p -> return p@ alone is ambiguous, but+-- query @'select' $ from $ \\p -> return p@ alone is ambiguous, but -- in the context of -- -- @--- do ps <- select $--- from $ \\p ->+-- do ps <- 'select' $+-- 'from' $ \\p -> -- return p -- liftIO $ mapM_ (putStrLn . personName . entityVal) ps -- @@@ -791,9 +791,9 @@ -- Example of usage: -- -- @--- delete $--- from $ \\appointment ->--- where_ (appointment ^. AppointmentDate <. val now)+-- 'delete' $+-- 'from' $ \\appointment ->+-- 'where_' (appointment '^.' AppointmentDate '<.' 'val' now) -- @ -- -- Unlike 'select', there is a useful way of using 'delete' that@@ -801,8 +801,8 @@ -- (i.e., no 'where_' clause), you'll have to use a type signature: -- -- @--- delete $--- from $ \\(appointment :: SqlExpr (Entity Appointment)) ->+-- 'delete' $+-- 'from' $ \\(appointment :: 'SqlExpr' ('Entity' Appointment)) -> -- return () -- @ delete :: ( MonadIO m )@@ -826,9 +826,9 @@ -- Example of usage: -- -- @--- update $ \p -> do--- set p [ PersonAge =. just (val thisYear) -. p ^. PersonBorn ]--- where_ $ isNothing (p ^. PersonAge)+-- 'update' $ \p -> do+-- 'set' p [ PersonAge '=.' 'just' ('val' thisYear) -. p '^.' PersonBorn ]+-- 'where_' $ isNothing (p '^.' PersonAge) -- @ update :: ( MonadIO m , SqlEntity val )