Add between (#127)
* Update between so it works with SQL values * Add support for composite keys in between clause * Remove unused values from ERaw in construct * Update unsafeSqlBinOp to handle composite keys and between to use >=., <=. and &&. * Support composite keys in unsafeSqlBinOp correctly * Updated changelog * Update version number of between to 3.1.0
This commit is contained in:
parent
a452946f58
commit
5d8f5b53e6
@ -6,6 +6,8 @@ Unreleased
|
||||
|
||||
- @Vlix
|
||||
- [#128](https://github.com/bitemyapp/esqueleto/pull/128): Added `Database.Esqueleto.PostgreSQL.JSON` module with JSON operators and `JSONB` data type.
|
||||
- @ibarrae
|
||||
- [#127](https://github.com/bitemyapp/esqueleto/pull/127): Added `between` and support for composite keys in `unsafeSqlBinOp`.
|
||||
|
||||
3.0.0
|
||||
=======
|
||||
|
||||
@ -44,7 +44,7 @@ module Database.Esqueleto
|
||||
, val, isNothing, just, nothing, joinV, withNonNull
|
||||
, countRows, count, countDistinct
|
||||
, not_, (==.), (>=.), (>.), (<=.), (<.), (!=.), (&&.), (||.)
|
||||
, (+.), (-.), (/.), (*.)
|
||||
, between, (+.), (-.), (/.), (*.)
|
||||
, random_, round_, ceiling_, floor_
|
||||
, min_, max_, sum_, avg_, castNum, castNumM
|
||||
, coalesce, coalesceDefault
|
||||
|
||||
@ -455,6 +455,11 @@ not_ (ECompositeKey _) = throw (CompositeKeyErr NotError)
|
||||
(*.) :: PersistField a => SqlExpr (Value a) -> SqlExpr (Value a) -> SqlExpr (Value a)
|
||||
(*.) = unsafeSqlBinOp " * "
|
||||
|
||||
-- | @BETWEEN@.
|
||||
--
|
||||
-- @since: 3.1.0
|
||||
between :: PersistField a => SqlExpr (Value a) -> (SqlExpr (Value a), SqlExpr (Value a)) -> SqlExpr (Value Bool)
|
||||
a `between` (b, c) = a >=. b &&. a <=. c
|
||||
|
||||
random_ :: (PersistField a, Num a) => SqlExpr (Value a)
|
||||
random_ = unsafeSqlValue "RANDOM()"
|
||||
@ -1242,7 +1247,6 @@ data CompositeKeyError =
|
||||
| CombineInsertionError
|
||||
| FoldHelpError
|
||||
| SqlCaseError
|
||||
| SqlBinOpError
|
||||
| SqlCastAsError
|
||||
| MakeOnClauseError
|
||||
| MakeExcError
|
||||
@ -1641,7 +1645,16 @@ unsafeSqlBinOp op (ERaw p1 f1) (ERaw p2 f2) = ERaw Parens f
|
||||
(b2, vals2) = f2 info
|
||||
in ( parensM p1 b1 <> op <> parensM p2 b2
|
||||
, vals1 <> vals2 )
|
||||
unsafeSqlBinOp _ _ _ = throw (CompositeKeyErr SqlBinOpError)
|
||||
unsafeSqlBinOp op a b = unsafeSqlBinOp op (construct a) (construct b)
|
||||
where construct :: SqlExpr (Value a) -> SqlExpr (Value a)
|
||||
construct (ERaw p f) = ERaw Parens $ \info ->
|
||||
let (b1, vals) = f info
|
||||
build ("?", [PersistList vals']) =
|
||||
(uncommas $ replicate (length vals') "?", vals')
|
||||
build expr = expr
|
||||
in build (parensM p b1, vals)
|
||||
construct (ECompositeKey f) =
|
||||
ERaw Parens $ \info -> (uncommas $ f info, mempty)
|
||||
{-# INLINE unsafeSqlBinOp #-}
|
||||
|
||||
|
||||
@ -2785,4 +2798,3 @@ insertSelect = void . insertSelectCount
|
||||
insertSelectCount :: (MonadIO m, PersistEntity a) =>
|
||||
SqlQuery (SqlExpr (Insertion a)) -> SqlWriteT m Int64
|
||||
insertSelectCount = rawEsqueleto INSERT_INTO . fmap EInsertFinal
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ module Database.Esqueleto.Internal.Language
|
||||
, val, isNothing, just, nothing, joinV, withNonNull
|
||||
, countRows, count, countDistinct
|
||||
, not_, (==.), (>=.), (>.), (<=.), (<.), (!=.), (&&.), (||.)
|
||||
, (+.), (-.), (/.), (*.)
|
||||
, between, (+.), (-.), (/.), (*.)
|
||||
, random_, round_, ceiling_, floor_
|
||||
, min_, max_, sum_, avg_, castNum, castNumM
|
||||
, coalesce, coalesceDefault
|
||||
|
||||
@ -630,6 +630,54 @@ testSelectWhere run = do
|
||||
return p
|
||||
liftIO $ ret `shouldBe` [ p3e ]
|
||||
|
||||
describe "when using between" $ do
|
||||
it "works for a simple example with [uses just . val]" $
|
||||
run $ do
|
||||
p1e <- insert' p1
|
||||
_ <- insert' p2
|
||||
_ <- insert' p3
|
||||
ret <- select $
|
||||
from $ \p -> do
|
||||
where_ ((p ^. PersonAge) `between` (just $ val 20, just $ val 40))
|
||||
return p
|
||||
liftIO $ ret `shouldBe` [ p1e ]
|
||||
it "works for a proyected fields value" $
|
||||
run $ do
|
||||
_ <- insert' p1 >> insert' p2 >> insert' p3
|
||||
ret <-
|
||||
select $
|
||||
from $ \p -> do
|
||||
where_ $
|
||||
just (p ^. PersonFavNum)
|
||||
`between`
|
||||
(p ^. PersonAge, p ^. PersonWeight)
|
||||
liftIO $ ret `shouldBe` []
|
||||
describe "when projecting composite keys" $ do
|
||||
it "works when using composite keys with val" $
|
||||
run $ do
|
||||
insert_ $ Point 1 2 ""
|
||||
ret <-
|
||||
select $
|
||||
from $ \p -> do
|
||||
where_ $
|
||||
p ^. PointId
|
||||
`between`
|
||||
( val $ PointKey 1 2
|
||||
, val $ PointKey 5 6 )
|
||||
liftIO $ ret `shouldBe` [()]
|
||||
it "works when using ECompositeKey constructor" $
|
||||
run $ do
|
||||
insert_ $ Point 1 2 ""
|
||||
ret <-
|
||||
select $
|
||||
from $ \p -> do
|
||||
where_ $
|
||||
p ^. PointId
|
||||
`between`
|
||||
( EI.ECompositeKey $ const ["3", "4"]
|
||||
, EI.ECompositeKey $ const ["5", "6"] )
|
||||
liftIO $ ret `shouldBe` []
|
||||
|
||||
it "works with avg_" $
|
||||
run $ do
|
||||
_ <- insert' p1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user