Make SqlAggregate selectable, window now returns a SqlAggregate since the results are legal in a grouped query. Added SqlQueryHaving to allow use of SqlAggregate in the having clause.
This commit is contained in:
parent
1fd1d64d6d
commit
8efca2ba05
@ -53,8 +53,6 @@ module Database.Esqueleto.Experimental
|
|||||||
, with
|
, with
|
||||||
, withRecursive
|
, withRecursive
|
||||||
|
|
||||||
, agg
|
|
||||||
|
|
||||||
-- ** Internals
|
-- ** Internals
|
||||||
, From(..)
|
, From(..)
|
||||||
, ToMaybe(..)
|
, ToMaybe(..)
|
||||||
|
|||||||
@ -16,11 +16,13 @@ module Database.Esqueleto.Experimental.Aggregates
|
|||||||
import Control.Monad.IO.Class
|
import Control.Monad.IO.Class
|
||||||
import qualified Control.Monad.Trans.Writer as W
|
import qualified Control.Monad.Trans.Writer as W
|
||||||
import Data.Coerce (Coercible, coerce)
|
import Data.Coerce (Coercible, coerce)
|
||||||
|
import Data.Proxy
|
||||||
import Database.Esqueleto.Internal.Internal
|
import Database.Esqueleto.Internal.Internal
|
||||||
( GroupByClause(..)
|
( GroupByClause(..)
|
||||||
, SideData(..)
|
, SideData(..)
|
||||||
, SqlExpr(..)
|
, SqlExpr(..)
|
||||||
, SqlQuery(..)
|
, SqlQuery(..)
|
||||||
|
, SqlQueryHaving(..)
|
||||||
, SqlSelect(..)
|
, SqlSelect(..)
|
||||||
, ToSomeValues(..)
|
, ToSomeValues(..)
|
||||||
, noMeta
|
, noMeta
|
||||||
@ -53,8 +55,16 @@ instance SqlExprEntity SqlExpr where
|
|||||||
(^.) = (I.^.)
|
(^.) = (I.^.)
|
||||||
(?.) = (I.?.)
|
(?.) = (I.?.)
|
||||||
|
|
||||||
newtype SqlAggregate a = SqlAggregate { agg :: SqlExpr a }
|
newtype SqlAggregate a = SqlAggregate { unsafeSqlAggregate :: SqlExpr a }
|
||||||
deriving via SqlExpr instance SqlExprEntity SqlAggregate
|
deriving via SqlExpr instance SqlExprEntity SqlAggregate
|
||||||
|
instance forall a. PersistField a => SqlSelect (SqlAggregate a) a where
|
||||||
|
sqlSelectCols info (SqlAggregate e) = sqlSelectCols info e
|
||||||
|
sqlSelectColCount = const 1
|
||||||
|
sqlSelectProcessRow _ = sqlSelectProcessRow (Proxy :: Proxy (SqlExpr a))
|
||||||
|
instance SqlQueryHaving (SqlAggregate Bool) where
|
||||||
|
having expr = Q $ W.tell mempty { sdHavingClause = I.Where (coerce expr) }
|
||||||
|
instance SqlQueryHaving (SqlAggregate (Maybe Bool)) where
|
||||||
|
having expr = Q $ W.tell mempty { sdHavingClause = I.Where (coerce expr) }
|
||||||
|
|
||||||
test :: (PersistEntity ent, PersistField a, PersistField b, PersistField c)
|
test :: (PersistEntity ent, PersistField a, PersistField b, PersistField c)
|
||||||
=> SqlExpr (Maybe (Entity ent))
|
=> SqlExpr (Maybe (Entity ent))
|
||||||
|
|||||||
@ -62,7 +62,7 @@ example =
|
|||||||
<> orderBy_ [asc (val @Int64 10)]
|
<> orderBy_ [asc (val @Int64 10)]
|
||||||
)
|
)
|
||||||
|
|
||||||
data NeedsWindow a
|
example2 = countRows_ @Int64 `over_` ()
|
||||||
|
|
||||||
lag :: SqlExpr (Value a) -> WindowExpr a
|
lag :: SqlExpr (Value a) -> WindowExpr a
|
||||||
lag v = lag_ v Nothing Nothing
|
lag v = lag_ v Nothing Nothing
|
||||||
@ -254,7 +254,7 @@ currentRow :: FrameRange
|
|||||||
currentRow = FrameRangeCurrentRow
|
currentRow = FrameRangeCurrentRow
|
||||||
|
|
||||||
class Over expr where
|
class Over expr where
|
||||||
over_ :: RenderWindow window => expr a -> window -> SqlExpr (WindowedValue a)
|
over_ :: RenderWindow window => expr a -> window -> SqlAggregate (WindowedValue a)
|
||||||
|
|
||||||
data WindowedValue a = WindowedValue { unWindowedValue :: a }
|
data WindowedValue a = WindowedValue { unWindowedValue :: a }
|
||||||
instance PersistField a => SqlSelect (SqlExpr (WindowedValue a)) (WindowedValue a) where
|
instance PersistField a => SqlSelect (SqlExpr (WindowedValue a)) (WindowedValue a) where
|
||||||
@ -266,7 +266,7 @@ instance PersistField a => SqlSelect (SqlExpr (WindowedValue a)) (WindowedValue
|
|||||||
|
|
||||||
newtype WindowExpr a = WindowExpr { unsafeWindowExpr :: SqlExpr a }
|
newtype WindowExpr a = WindowExpr { unsafeWindowExpr :: SqlExpr a }
|
||||||
instance Over WindowExpr where
|
instance Over WindowExpr where
|
||||||
(WindowExpr (ERaw _ f)) `over_` window = ERaw noMeta $ \p info ->
|
(WindowExpr (ERaw _ f)) `over_` window = SqlAggregate $ ERaw noMeta $ \p info ->
|
||||||
let (b, v) = f Never info
|
let (b, v) = f Never info
|
||||||
(w, vw) = renderWindow info window
|
(w, vw) = renderWindow info window
|
||||||
in (parensM p $ b <> " OVER " <> parens w , v <> vw)
|
in (parensM p $ b <> " OVER " <> parens w , v <> vw)
|
||||||
|
|||||||
@ -377,11 +377,16 @@ distinctOnOrderBy exprs act =
|
|||||||
rand :: SqlExpr OrderBy
|
rand :: SqlExpr OrderBy
|
||||||
rand = ERaw noMeta $ \_ _ -> ("RANDOM()", [])
|
rand = ERaw noMeta $ \_ _ -> ("RANDOM()", [])
|
||||||
|
|
||||||
-- | @HAVING@.
|
class SqlQueryHaving expr where
|
||||||
--
|
-- | @HAVING@.
|
||||||
-- @since 1.2.2
|
--
|
||||||
having :: SqlExpr Bool -> SqlQuery ()
|
-- @since 1.2.2
|
||||||
having expr = Q $ W.tell mempty { sdHavingClause = Where expr }
|
having :: expr -> SqlQuery ()
|
||||||
|
|
||||||
|
instance SqlQueryHaving (SqlExpr Bool) where
|
||||||
|
having expr = Q $ W.tell mempty { sdHavingClause = Where expr }
|
||||||
|
instance SqlQueryHaving (SqlExpr (Maybe Bool)) where
|
||||||
|
having expr = Q $ W.tell mempty { sdHavingClause = Where (coerce expr) }
|
||||||
|
|
||||||
-- | Add a locking clause to the query. Please read
|
-- | Add a locking clause to the query. Please read
|
||||||
-- 'LockingKind' documentation and your RDBMS manual.
|
-- 'LockingKind' documentation and your RDBMS manual.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user