module Database.Seakale.Request ( query , query_ , queryWith , execute , execute_ , executeMany , executeMany_ , returning , returningWith , returning_ , returningWith_ , MonadRequest , throwSeakaleError , getBackend ) where import Database.Seakale.Request.Internal (MonadRequest) import Database.Seakale.FromRow import Database.Seakale.ToRow import Database.Seakale.Types import qualified Database.Seakale.Request.Internal as I -- | Replace holes in the query with the provided values and send it to the -- database. This is to be used for @SELECT@ queries. query :: (MonadRequest b m, ToRow b n r, FromRow b n' s) => Query n -> r -> m [s] query = queryWith fromRow -- | Like 'query' but the query should not have any hole. query_ :: (MonadRequest b m, FromRow b n r) => Query Zero -> m [r] query_ req = query req () -- | Provide a way to specify a custom parser for 'query'. queryWith :: (MonadRequest b m, ToRow b n r) => RowParser b n' s -> Query n -> r -> m [s] queryWith parser req dat = do backend <- getBackend (cols, rows) <- I.query $ formatQuery req $ toRow backend dat case parseRows parser backend cols rows of Left err -> throwSeakaleError $ RowParseError err Right xs -> return xs -- | Replace holes in the query with the provided values, send it to the -- database and return the number of rows affected. This is to be used with -- @DELETE@, @UPDATE@ and @INSERT@ queries (without any @RETURNING@ clause). execute :: (MonadRequest b m, ToRow b n r) => Query n -> r -> m Integer execute req dat = do backend <- getBackend I.execute $ formatQuery req $ toRow backend dat -- | Like 'execute' but the query should not have any hole. execute_ :: MonadRequest b m => Query Zero -> m Integer execute_ req = I.execute $ formatQuery req Nil -- | Like 'execute' but for a 'RepeatQuery' where a piece of the query is -- repeated as many times as the number of values of type 'r2'. executeMany :: (MonadRequest b m, ToRow b n1 r1, ToRow b n2 r2, ToRow b n3 r3) => RepeatQuery n1 n2 n3 -> r1 -> r3 -> [r2] -> m Integer executeMany req bdat adat dat = do backend <- getBackend I.execute $ formatMany req (toRow backend bdat) (toRow backend adat) (map (toRow backend) dat) -- | Like 'executeMany' but the query should not have any hole before and after -- the repeating piece. executeMany_ :: (MonadRequest b m, ToRow b n r) => RepeatQuery Zero n Zero -> [r] -> m Integer executeMany_ req dat = executeMany req () () dat -- | Replace holes in a 'RepeatQuery' and send it to the database. This is to be -- used for @INSERT@ queries with a @RETURNING@ clause. returning :: ( MonadRequest b m, ToRow b n1 r1, ToRow b n2 r2, ToRow b n3 r3 , FromRow b n s ) => RepeatQuery n1 n2 n3 -> r1 -> r3 -> [r2] -> m [s] returning = returningWith fromRow -- | Provide a way to a custom parser for 'returning'. returningWith :: ( MonadRequest b m, ToRow b n1 r1, ToRow b n2 r2, ToRow b n3 r3 , FromRow b n s ) => RowParser b n s -> RepeatQuery n1 n2 n3 -> r1 -> r3 -> [r2] -> m [s] returningWith parser req bdat adat dat = do backend <- getBackend (cols, rows) <- I.query $ formatMany req (toRow backend bdat) (toRow backend adat) (map (toRow backend) dat) case parseRows parser backend cols rows of Left err -> throwSeakaleError $ RowParseError err Right xs -> return xs -- | Like 'returning' but the query should not have any hole before and after -- the repeating piece. returning_ :: (MonadRequest b m, ToRow b n r, FromRow b n' s) => RepeatQuery Zero n Zero -> [r] -> m [s] returning_ req dat = returningWith fromRow req () () dat -- | Like 'returningWith' but the query should not have any hole before and -- after the repeating piece. returningWith_ :: (MonadRequest b m, ToRow b n r, FromRow b n' s) => RowParser b n' s -> RepeatQuery Zero n Zero -> [r] -> m [s] returningWith_ parser req dat = returningWith parser req () () dat