Add source to SqlAggregate, the Over instance uses this to prevent pseudo-aggregates(from groupBy) and already windowed values from being windowed
This commit is contained in:
parent
8efca2ba05
commit
ceab69a4e9
@ -90,7 +90,7 @@ module Database.Esqueleto.Experimental
|
|||||||
, joinV
|
, joinV
|
||||||
, withNonNull
|
, withNonNull
|
||||||
|
|
||||||
, countRows
|
, countRows_
|
||||||
, count
|
, count
|
||||||
, countDistinct
|
, countDistinct
|
||||||
|
|
||||||
|
|||||||
@ -55,15 +55,15 @@ instance SqlExprEntity SqlExpr where
|
|||||||
(^.) = (I.^.)
|
(^.) = (I.^.)
|
||||||
(?.) = (I.?.)
|
(?.) = (I.?.)
|
||||||
|
|
||||||
newtype SqlAggregate a = SqlAggregate { unsafeSqlAggregate :: SqlExpr a }
|
newtype SqlAggregate source a = SqlAggregate { unsafeSqlAggregate :: SqlExpr a }
|
||||||
deriving via SqlExpr instance SqlExprEntity SqlAggregate
|
deriving via SqlExpr instance SqlExprEntity (SqlAggregate source)
|
||||||
instance forall a. PersistField a => SqlSelect (SqlAggregate a) a where
|
instance forall a source. PersistField a => SqlSelect (SqlAggregate source a) a where
|
||||||
sqlSelectCols info (SqlAggregate e) = sqlSelectCols info e
|
sqlSelectCols info (SqlAggregate e) = sqlSelectCols info e
|
||||||
sqlSelectColCount = const 1
|
sqlSelectColCount = const 1
|
||||||
sqlSelectProcessRow _ = sqlSelectProcessRow (Proxy :: Proxy (SqlExpr a))
|
sqlSelectProcessRow _ = sqlSelectProcessRow (Proxy :: Proxy (SqlExpr a))
|
||||||
instance SqlQueryHaving (SqlAggregate Bool) where
|
instance SqlQueryHaving (SqlAggregate source Bool) where
|
||||||
having expr = Q $ W.tell mempty { sdHavingClause = I.Where (coerce expr) }
|
having expr = Q $ W.tell mempty { sdHavingClause = I.Where (coerce expr) }
|
||||||
instance SqlQueryHaving (SqlAggregate (Maybe Bool)) where
|
instance SqlQueryHaving (SqlAggregate source (Maybe Bool)) where
|
||||||
having expr = Q $ W.tell mempty { sdHavingClause = I.Where (coerce expr) }
|
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)
|
||||||
@ -76,8 +76,6 @@ test ent field y other = do
|
|||||||
groupBy (ent, y) $ \(ent', y') ->
|
groupBy (ent, y) $ \(ent', y') ->
|
||||||
pure (ent' ?. field, y', sum_ other, countRows_)
|
pure (ent' ?. field, y', sum_ other, countRows_)
|
||||||
|
|
||||||
countRows_ :: (PersistField n, Integral n) => SqlAggregate n
|
|
||||||
countRows_ = SqlAggregate $ ERaw noMeta $ \_ _ -> ("COUNT(*)", [])
|
|
||||||
|
|
||||||
-- Tuple magic, only SqlExprs are on the leaves.
|
-- Tuple magic, only SqlExprs are on the leaves.
|
||||||
-- The Coercible instance from the SqlExpr a -> SqlExpr b allows 0 cost casting
|
-- The Coercible instance from the SqlExpr a -> SqlExpr b allows 0 cost casting
|
||||||
@ -88,8 +86,9 @@ class Coercible a r => Aggregateable a r | a -> r, r -> a where
|
|||||||
fromAggregate :: r -> a
|
fromAggregate :: r -> a
|
||||||
fromAggregate = coerce
|
fromAggregate = coerce
|
||||||
|
|
||||||
|
data GroupedValue
|
||||||
instance Aggregateable () () where
|
instance Aggregateable () () where
|
||||||
instance Aggregateable (SqlExpr a) (SqlAggregate a) where
|
instance Aggregateable (SqlExpr a) (SqlAggregate GroupedValue a) where
|
||||||
instance (Aggregateable a ra, Aggregateable b rb) => Aggregateable (a,b) (ra, rb) where
|
instance (Aggregateable a ra, Aggregateable b rb) => Aggregateable (a,b) (ra, rb) where
|
||||||
instance
|
instance
|
||||||
( Aggregateable a ra
|
( Aggregateable a ra
|
||||||
@ -137,9 +136,6 @@ instance
|
|||||||
, Aggregateable h rh
|
, Aggregateable h rh
|
||||||
) => Aggregateable (a,b,c,d,e,f,g,h) (ra,rb,rc,rd,re,rf,rg,rh) where
|
) => Aggregateable (a,b,c,d,e,f,g,h) (ra,rb,rc,rd,re,rf,rg,rh) where
|
||||||
|
|
||||||
sum_ :: (PersistField a, PersistField n, Integral n) => SqlExpr a -> SqlAggregate (Maybe n)
|
|
||||||
sum_ = coerce . unsafeSqlFunction "SUM"
|
|
||||||
|
|
||||||
groupBy :: ( ToSomeValues a
|
groupBy :: ( ToSomeValues a
|
||||||
, Aggregateable a a'
|
, Aggregateable a a'
|
||||||
, Aggregateable b b'
|
, Aggregateable b b'
|
||||||
@ -147,3 +143,11 @@ groupBy :: ( ToSomeValues a
|
|||||||
groupBy a f = do
|
groupBy a f = do
|
||||||
Q $ W.tell $ mempty{sdGroupByClause = GroupBy $ toSomeValues a }
|
Q $ W.tell $ mempty{sdGroupByClause = GroupBy $ toSomeValues a }
|
||||||
fmap fromAggregate $ f $ toAggregate a
|
fmap fromAggregate $ f $ toAggregate a
|
||||||
|
|
||||||
|
-- Aggregation Functions
|
||||||
|
countRows_ :: forall n s. (PersistField n, Integral n) => SqlAggregate s n
|
||||||
|
countRows_ = SqlAggregate $ ERaw noMeta $ \_ _ -> ("COUNT(*)", [])
|
||||||
|
|
||||||
|
sum_ :: forall n a w. (PersistField a, PersistField n, Integral n) => SqlExpr a -> SqlAggregate w (Maybe n)
|
||||||
|
sum_ = coerce . unsafeSqlFunction "SUM"
|
||||||
|
|
||||||
|
|||||||
@ -253,16 +253,9 @@ unboundedFollowing = FrameRangeFollowing FrameRangeUnbounded
|
|||||||
currentRow :: FrameRange
|
currentRow :: FrameRange
|
||||||
currentRow = FrameRangeCurrentRow
|
currentRow = FrameRangeCurrentRow
|
||||||
|
|
||||||
|
data WindowAggregate
|
||||||
class Over expr where
|
class Over expr where
|
||||||
over_ :: RenderWindow window => expr a -> window -> SqlAggregate (WindowedValue a)
|
over_ :: RenderWindow window => expr a -> window -> SqlAggregate WindowAggregate a
|
||||||
|
|
||||||
data WindowedValue a = WindowedValue { unWindowedValue :: a }
|
|
||||||
instance PersistField a => SqlSelect (SqlExpr (WindowedValue a)) (WindowedValue a) where
|
|
||||||
sqlSelectCols info expr = sqlSelectCols info (coerce expr :: SqlExpr a)
|
|
||||||
sqlSelectColCount = const 1
|
|
||||||
sqlSelectProcessRow _ [pv] = WindowedValue <$> fromPersistValue pv
|
|
||||||
sqlSelectProcessRow _ pvs = WindowedValue <$> fromPersistValue (PersistList pvs)
|
|
||||||
|
|
||||||
|
|
||||||
newtype WindowExpr a = WindowExpr { unsafeWindowExpr :: SqlExpr a }
|
newtype WindowExpr a = WindowExpr { unsafeWindowExpr :: SqlExpr a }
|
||||||
instance Over WindowExpr where
|
instance Over WindowExpr where
|
||||||
@ -271,4 +264,7 @@ instance Over WindowExpr where
|
|||||||
(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)
|
||||||
|
|
||||||
deriving via WindowExpr instance Over SqlAggregate
|
-- Only universally quantified SqlAggregate's can be used
|
||||||
|
-- TODO Add nicer type error
|
||||||
|
data NoWindow
|
||||||
|
deriving via WindowExpr instance (s ~ NoWindow) => Over (SqlAggregate s)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user