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
|
||||
, withRecursive
|
||||
|
||||
, agg
|
||||
|
||||
-- ** Internals
|
||||
, From(..)
|
||||
, ToMaybe(..)
|
||||
|
||||
@ -16,11 +16,13 @@ module Database.Esqueleto.Experimental.Aggregates
|
||||
import Control.Monad.IO.Class
|
||||
import qualified Control.Monad.Trans.Writer as W
|
||||
import Data.Coerce (Coercible, coerce)
|
||||
import Data.Proxy
|
||||
import Database.Esqueleto.Internal.Internal
|
||||
( GroupByClause(..)
|
||||
, SideData(..)
|
||||
, SqlExpr(..)
|
||||
, SqlQuery(..)
|
||||
, SqlQueryHaving(..)
|
||||
, SqlSelect(..)
|
||||
, ToSomeValues(..)
|
||||
, noMeta
|
||||
@ -53,8 +55,16 @@ instance SqlExprEntity SqlExpr where
|
||||
(^.) = (I.^.)
|
||||
(?.) = (I.?.)
|
||||
|
||||
newtype SqlAggregate a = SqlAggregate { agg :: SqlExpr a }
|
||||
newtype SqlAggregate a = SqlAggregate { unsafeSqlAggregate :: SqlExpr a }
|
||||
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)
|
||||
=> SqlExpr (Maybe (Entity ent))
|
||||
|
||||
@ -62,7 +62,7 @@ example =
|
||||
<> orderBy_ [asc (val @Int64 10)]
|
||||
)
|
||||
|
||||
data NeedsWindow a
|
||||
example2 = countRows_ @Int64 `over_` ()
|
||||
|
||||
lag :: SqlExpr (Value a) -> WindowExpr a
|
||||
lag v = lag_ v Nothing Nothing
|
||||
@ -254,7 +254,7 @@ currentRow :: FrameRange
|
||||
currentRow = FrameRangeCurrentRow
|
||||
|
||||
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 }
|
||||
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 }
|
||||
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
|
||||
(w, vw) = renderWindow info window
|
||||
in (parensM p $ b <> " OVER " <> parens w , v <> vw)
|
||||
|
||||
@ -377,11 +377,16 @@ distinctOnOrderBy exprs act =
|
||||
rand :: SqlExpr OrderBy
|
||||
rand = ERaw noMeta $ \_ _ -> ("RANDOM()", [])
|
||||
|
||||
-- | @HAVING@.
|
||||
--
|
||||
-- @since 1.2.2
|
||||
having :: SqlExpr Bool -> SqlQuery ()
|
||||
having expr = Q $ W.tell mempty { sdHavingClause = Where expr }
|
||||
class SqlQueryHaving expr where
|
||||
-- | @HAVING@.
|
||||
--
|
||||
-- @since 1.2.2
|
||||
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
|
||||
-- 'LockingKind' documentation and your RDBMS manual.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user