module Opaleye.SQLite.Internal.Optimize where import Prelude hiding (product) import qualified Opaleye.SQLite.Internal.PrimQuery as PQ import qualified Data.List.NonEmpty as NEL optimize :: PQ.PrimQuery -> PQ.PrimQuery optimize :: PrimQuery -> PrimQuery optimize = PrimQuery -> PrimQuery mergeProduct (PrimQuery -> PrimQuery) -> (PrimQuery -> PrimQuery) -> PrimQuery -> PrimQuery forall b c a. (b -> c) -> (a -> b) -> a -> c . PrimQuery -> PrimQuery removeUnit removeUnit :: PQ.PrimQuery -> PQ.PrimQuery removeUnit :: PrimQuery -> PrimQuery removeUnit = PrimQueryFold PrimQuery -> PrimQuery -> PrimQuery forall p. PrimQueryFold p -> PrimQuery -> p PQ.foldPrimQuery (PrimQuery PQ.Unit, String -> [(Symbol, PrimExpr)] -> PrimQuery PQ.BaseTable, NonEmpty PrimQuery -> [PrimExpr] -> PrimQuery product, [(Symbol, (Maybe AggrOp, PrimExpr))] -> PrimQuery -> PrimQuery PQ.Aggregate, [OrderExpr] -> PrimQuery -> PrimQuery PQ.Order, LimitOp -> PrimQuery -> PrimQuery PQ.Limit, JoinType -> PrimExpr -> PrimQuery -> PrimQuery -> PrimQuery PQ.Join, [Symbol] -> [[PrimExpr]] -> PrimQuery PQ.Values, BinOp -> [(Symbol, (PrimExpr, PrimExpr))] -> (PrimQuery, PrimQuery) -> PrimQuery PQ.Binary) where product :: NonEmpty PrimQuery -> [PrimExpr] -> PrimQuery product NonEmpty PrimQuery pqs [PrimExpr] pes = NonEmpty PrimQuery -> [PrimExpr] -> PrimQuery PQ.Product NonEmpty PrimQuery pqs' [PrimExpr] pes where pqs' :: NonEmpty PrimQuery pqs' = case (PrimQuery -> Bool) -> NonEmpty PrimQuery -> [PrimQuery] forall a. (a -> Bool) -> NonEmpty a -> [a] NEL.filter (Bool -> Bool not (Bool -> Bool) -> (PrimQuery -> Bool) -> PrimQuery -> Bool forall b c a. (b -> c) -> (a -> b) -> a -> c . PrimQuery -> Bool PQ.isUnit) NonEmpty PrimQuery pqs of [] -> PrimQuery -> NonEmpty PrimQuery forall (m :: * -> *) a. Monad m => a -> m a return PrimQuery PQ.Unit [PrimQuery] xs -> [PrimQuery] -> NonEmpty PrimQuery forall a. [a] -> NonEmpty a NEL.fromList [PrimQuery] xs mergeProduct :: PQ.PrimQuery -> PQ.PrimQuery mergeProduct :: PrimQuery -> PrimQuery mergeProduct = PrimQueryFold PrimQuery -> PrimQuery -> PrimQuery forall p. PrimQueryFold p -> PrimQuery -> p PQ.foldPrimQuery (PrimQuery PQ.Unit, String -> [(Symbol, PrimExpr)] -> PrimQuery PQ.BaseTable, NonEmpty PrimQuery -> [PrimExpr] -> PrimQuery product, [(Symbol, (Maybe AggrOp, PrimExpr))] -> PrimQuery -> PrimQuery PQ.Aggregate, [OrderExpr] -> PrimQuery -> PrimQuery PQ.Order, LimitOp -> PrimQuery -> PrimQuery PQ.Limit, JoinType -> PrimExpr -> PrimQuery -> PrimQuery -> PrimQuery PQ.Join, [Symbol] -> [[PrimExpr]] -> PrimQuery PQ.Values, BinOp -> [(Symbol, (PrimExpr, PrimExpr))] -> (PrimQuery, PrimQuery) -> PrimQuery PQ.Binary) where product :: NonEmpty PrimQuery -> [PrimExpr] -> PrimQuery product NonEmpty PrimQuery pqs [PrimExpr] pes = NonEmpty PrimQuery -> [PrimExpr] -> PrimQuery PQ.Product NonEmpty PrimQuery pqs' ([PrimExpr] pes [PrimExpr] -> [PrimExpr] -> [PrimExpr] forall a. [a] -> [a] -> [a] ++ [PrimExpr] pes') where pqs' :: NonEmpty PrimQuery pqs' = NonEmpty PrimQuery pqs NonEmpty PrimQuery -> (PrimQuery -> NonEmpty PrimQuery) -> NonEmpty PrimQuery forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= PrimQuery -> NonEmpty PrimQuery queries queries :: PrimQuery -> NonEmpty PrimQuery queries (PQ.Product NonEmpty PrimQuery qs [PrimExpr] _) = NonEmpty PrimQuery qs queries PrimQuery q = PrimQuery -> NonEmpty PrimQuery forall (m :: * -> *) a. Monad m => a -> m a return PrimQuery q pes' :: [PrimExpr] pes' = NonEmpty PrimQuery -> [PrimQuery] forall a. NonEmpty a -> [a] NEL.toList NonEmpty PrimQuery pqs [PrimQuery] -> (PrimQuery -> [PrimExpr]) -> [PrimExpr] forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= PrimQuery -> [PrimExpr] conds conds :: PrimQuery -> [PrimExpr] conds (PQ.Product NonEmpty PrimQuery _ [PrimExpr] cs) = [PrimExpr] cs conds PrimQuery _ = []