beam-0.3.2.0: src/Database/Beam/Query/Internal.hs
module Database.Beam.Query.Internal where
import Database.Beam.SQL.Types
import Database.Beam.Schema
import qualified Data.Text as T
import Data.Typeable
import Data.Coerce
import Control.Applicative
import Control.Monad.State
import Control.Monad.Writer hiding (All)
import Control.Monad.Identity
import Database.HDBC
-- | Type class for any query like entity, currently `Q` and `TopLevelQ`
class IsQuery q where
toQ :: q db s a -> Q db s a
-- | The type of queries over the database `db` returning results of type `a`. The `s` argument is a
-- threading argument meant to restrict cross-usage of `QExpr`s although this is not yet
-- implemented.
newtype Q (db :: (((* -> *) -> *) -> *) -> *) s a = Q { runQ :: State QueryBuilder a}
deriving (Monad, Applicative, Functor, MonadFix, MonadState QueryBuilder)
-- | Wrapper for 'Q's that have been modified in such a way that they can no longer be joined against
-- without the use of 'subquery_'. 'TopLevelQ' is also an instance of 'IsQuery', and so can be passed
-- directly to 'query' or 'queryList'
newtype TopLevelQ db s a = TopLevelQ (Q db s a)
data QNested s
data QueryBuilder = QueryBuilder
{ qbNextTblRef :: Int
, qbFrom :: Maybe SQLFrom
, qbWhere :: SQLExpr' QField
, qbLimit :: Maybe Integer
, qbOffset :: Maybe Integer
, qbOrdering :: [SQLOrdering]
, qbGrouping :: Maybe SQLGrouping }
-- * QExpr type
data QField = QField
{ qFieldTblName :: T.Text
, qFieldTblOrd :: Maybe Int
, qFieldName :: T.Text }
deriving (Show, Eq, Ord)
-- | The type of lifted beam expressions that will yield the haskell type `t` when run with
-- `queryList` or `query`. In the future, this will include a thread argument meant to prevent
-- cross-usage of expressions, but this is unimplemented for technical reasons.
newtype QExpr s t = QExpr (SQLExpr' QField)
deriving (Show, Eq)
-- * Aggregations
data Aggregation s a = GroupAgg (SQLExpr' QField)
| ProjectAgg (SQLExpr' QField)
-- * Sql Projections
--
-- | Typeclass for all haskell data types that can be used to create a projection in a SQL select
-- statement. This includes all tables as well as all tuple classes. Projections are only defined on
-- tuples up to size 5. If you need more, follow the implementations here.
class Projectible a where
project :: a -> [SQLExpr' QField]
instance Typeable a => Projectible (QExpr s a) where
project (QExpr x) = [x]
instance Projectible () where
project () = [SQLValE (SqlInteger 1)]
instance (Projectible a, Projectible b) => Projectible (a, b) where
project (a, b) = project a ++ project b
instance ( Projectible a
, Projectible b
, Projectible c ) => Projectible (a, b, c) where
project (a, b, c) = project a ++ project b ++ project c
instance ( Projectible a
, Projectible b
, Projectible c
, Projectible d ) => Projectible (a, b, c, d) where
project (a, b, c, d) = project a ++ project b ++ project c ++ project d
instance ( Projectible a
, Projectible b
, Projectible c
, Projectible d
, Projectible e ) => Projectible (a, b, c, d, e) where
project (a, b, c, d, e) = project a ++ project b ++ project c ++ project d ++ project e
instance Table t => Projectible (t (QExpr s)) where
project t = fieldAllValues (\(Columnar' (QExpr e)) -> e) t
instance Table t => Projectible (t (Nullable (QExpr s))) where
project t = fieldAllValues (\(Columnar' (QExpr e)) -> e) t
tableVal :: Table tbl => tbl Identity -> tbl (QExpr s)
tableVal = changeRep valToQExpr . makeSqlValues
where valToQExpr :: Columnar' SqlValue' a -> Columnar' (QExpr s) a
valToQExpr (Columnar' (SqlValue' v)) = Columnar' (QExpr (SQLValE v))