{-# LANGUAGE ScopedTypeVariables #-}
module Database.Selda.Unsafe
( fun, fun2, fun0, operator
, aggr
, cast, castAggr, sink, sink2
, unsafeSelector
, QueryFragment, inj, injLit, rawName, rawExp, rawStm, rawQuery, rawQuery1
) where
import Control.Exception (throw)
import Control.Monad.State.Strict
import Database.Selda.Backend.Internal
import Database.Selda.Column
import Database.Selda.Exp (UntypedCol (..))
import Database.Selda.Inner (Inner, Aggr, aggr, liftAggr)
import Database.Selda.Selectors (unsafeSelector)
import Database.Selda.Query.Type (Query (..), sources, renameAll, rename)
import Database.Selda.SQL (QueryFragment (..), SqlSource (RawSql), sqlFrom)
import Database.Selda.SQL.Print (compRaw)
import Database.Selda.SqlRow (SqlRow (..))
import Database.Selda.Types (ColName)
import Data.Text (Text)
import Data.Proxy
import Unsafe.Coerce
cast :: forall s a b. SqlType b => Col s a -> Col s b
cast = liftC $ Cast (sqlType (Proxy :: Proxy b))
castAggr :: forall s a b. SqlType b => Aggr s a -> Aggr s b
castAggr = liftAggr cast
sink :: (f s a -> f s b) -> f (Inner s) a -> f (Inner s) b
sink = unsafeCoerce
sink2 :: (f s a -> f s b -> f s c) -> f (Inner s) a -> f (Inner s) b -> f (Inner s) c
sink2 = unsafeCoerce
fun :: Text -> Col s a -> Col s b
fun = liftC . UnOp . Fun
fun2 :: Text -> Col s a -> Col s b -> Col s c
fun2 = liftC2 . Fun2
operator :: Text -> Col s a -> Col s b -> Col s c
operator = liftC2 . BinOp . CustomOp
fun0 :: Text -> Col s a
fun0 = One . NulOp . Fun0
inj :: Col s a -> QueryFragment
inj (One x) = RawExp x
injLit :: SqlType a => a -> QueryFragment
injLit = RawExp . Lit . mkLit
rawName :: SqlType a => ColName -> Col s a
rawName = One . Col
rawExp :: SqlType a => Text -> Col s a
rawExp = One . Raw
rawStm :: MonadSelda m => QueryFragment -> m ()
rawStm q = withBackend $ \b -> liftIO $ do
void $ uncurry (runStmt b) $ compRaw (ppConfig b) q
rawQuery :: forall a s. SqlRow a => [ColName] -> QueryFragment -> Query s (Row s a)
rawQuery names q
| length names /= nestedCols (Proxy :: Proxy a) = do
let err = concat
[ "rawQuery: return type has ", show (nestedCols (Proxy :: Proxy a))
, " columns, but only ", show (length names), " names were given"
]
throw (UnsafeError err)
| otherwise = Query $ do
rns <- renameAll [Untyped (Col name) | name <- names]
st <- get
put $ st { sources = sqlFrom rns (RawSql q) : sources st }
return (Many (map hideRenaming rns))
rawQuery1 :: SqlType a => ColName -> QueryFragment -> Query s (Col s a)
rawQuery1 name q = Query $ do
name' <- head <$> rename (Untyped (Col name))
st <- get
put $ st { sources = sqlFrom [name'] (RawSql q) : sources st }
case name' of
Named n _ -> return (One (Col n))
_ -> error "BUG: renaming did not rename"