module Database.Selda.Frontend
( Result, Res, MonadIO (..), MonadSelda (..), SeldaT
, query
, insert, insert_, insertWithPK
, update, update_
, deleteFrom, deleteFrom_
, createTable, tryCreateTable
, dropTable, tryDropTable
, transaction, setLocalCache
) where
import Database.Selda.Backend
import Database.Selda.Caching
import Database.Selda.Column
import Database.Selda.Compile
import Database.Selda.Query.Type
import Database.Selda.SQL
import Database.Selda.Table
import Database.Selda.Table.Compile
import Data.Proxy
import Data.Text (Text)
import Control.Monad
import Control.Monad.Catch
query :: (MonadSelda m, Result a) => Query s a -> m [Res a]
query q = do
backend <- seldaBackend
queryWith (runStmt backend) q
insert :: (MonadSelda m, Insert a) => Table a -> [a] -> m Int
insert _ [] = do
return 0
insert t cs = do
kw <- defaultKeyword <$> seldaBackend
res <- uncurry exec $ compileInsert kw t cs
invalidateTable t
return res
insert_ :: (MonadSelda m, Insert a) => Table a -> [a] -> m ()
insert_ t cs = void $ insert t cs
insertWithPK :: (MonadSelda m, Insert a) => Table a -> [a] -> m Int
insertWithPK t cs = do
backend <- seldaBackend
res <- liftIO $ do
uncurry (runStmtWithPK backend) $ compileInsert (defaultKeyword backend) t cs
invalidateTable t
return res
update :: (MonadSelda m, Columns (Cols s a), Result (Cols s a))
=> Table a
-> (Cols s a -> Col s Bool)
-> (Cols s a -> Cols s a)
-> m Int
update tbl check upd = do
res <- uncurry exec $ compileUpdate tbl upd check
invalidateTable tbl
return res
update_ :: (MonadSelda m, Columns (Cols s a), Result (Cols s a))
=> Table a
-> (Cols s a -> Col s Bool)
-> (Cols s a -> Cols s a)
-> m ()
update_ tbl check upd = void $ update tbl check upd
deleteFrom :: (MonadSelda m, Columns (Cols s a))
=> Table a -> (Cols s a -> Col s Bool) -> m Int
deleteFrom tbl f = do
res <- uncurry exec $ compileDelete tbl f
invalidateTable tbl
return res
deleteFrom_ :: (MonadSelda m, Columns (Cols s a))
=> Table a -> (Cols s a -> Col s Bool) -> m ()
deleteFrom_ tbl f = void $ deleteFrom tbl f
createTable :: MonadSelda m => Table a -> m ()
createTable tbl = do
cct <- customColType <$> seldaBackend
void . flip exec [] $ compileCreateTable cct Fail tbl
tryCreateTable :: MonadSelda m => Table a -> m ()
tryCreateTable tbl = do
cct <- customColType <$> seldaBackend
void . flip exec [] $ compileCreateTable cct Ignore tbl
dropTable :: MonadSelda m => Table a -> m ()
dropTable = withInval $ void . flip exec [] . compileDropTable Fail
tryDropTable :: MonadSelda m => Table a -> m ()
tryDropTable = withInval $ void . flip exec [] . compileDropTable Ignore
transaction :: (MonadSelda m, MonadThrow m, MonadCatch m) => m a -> m a
transaction m = do
beginTransaction
void $ exec "BEGIN TRANSACTION" []
res <- try m
case res of
Left (SomeException e) -> do
void $ exec "ROLLBACK" []
endTransaction False
throwM e
Right x -> do
void $ exec "COMMIT" []
endTransaction True
return x
setLocalCache :: MonadSelda m => Int -> m ()
setLocalCache = liftIO . setMaxItems
queryWith :: forall s m a. (MonadSelda m, Result a)
=> QueryRunner (Int, [[SqlValue]]) -> Query s a -> m [Res a]
queryWith qr q = do
mres <- liftIO $ cached qry
case mres of
Just res -> do
return res
_ -> do
res <- fmap snd . liftIO $ uncurry qr qry
let res' = mkResults (Proxy :: Proxy a) res
liftIO $ cache tables qry res'
return res'
where
(tables, qry) = compileWithTables q
mkResults :: Result a => Proxy a -> [[SqlValue]] -> [Res a]
mkResults p = map (toRes p)
withInval :: MonadSelda m => (Table a -> m b) -> Table a -> m b
withInval f t = do
res <- f t
invalidateTable t
return res
exec :: MonadSelda m => Text -> [Param] -> m Int
exec q ps = do
backend <- seldaBackend
fmap fst . liftIO $ runStmt backend q ps