{-# LANGUAGE FlexibleContexts #-}

-- |
-- Module      : Database.HDBC.Record.Update
-- Copyright   : 2013 Kei Hibino
-- License     : BSD3
--
-- Maintainer  : ex8k.hibino@gmail.com
-- Stability   : experimental
-- Portability : unknown
--
-- This module provides typed 'Update' running sequence
-- which intermediate structures are typed.
module Database.HDBC.Record.Update (
  PreparedUpdate, prepare, prepareUpdate, withPrepareUpdate,

  runPreparedUpdate, runUpdate, mapUpdate
  ) where

import Database.HDBC (IConnection, SqlValue)

import Database.Relational (Update)
import Database.Record (ToSql)

import Database.HDBC.Record.Statement
  (prepareNoFetch, withPrepareNoFetch, PreparedStatement, executeNoFetch, runNoFetch, mapNoFetch)


-- | Typed prepared update type.
type PreparedUpdate p = PreparedStatement p ()

-- | Typed prepare update operation.
prepare :: IConnection conn
        => conn
        -> Update p
        -> IO (PreparedUpdate p)
prepare :: forall conn p.
IConnection conn =>
conn -> Update p -> IO (PreparedUpdate p)
prepare =  forall (s :: * -> *) conn p.
(UntypeableNoFetch s, IConnection conn) =>
conn -> s p -> IO (PreparedStatement p ())
prepareNoFetch

-- | Same as 'prepare'.
prepareUpdate :: IConnection conn
              => conn
              -> Update p
              -> IO (PreparedUpdate p)
prepareUpdate :: forall conn p.
IConnection conn =>
conn -> Update p -> IO (PreparedUpdate p)
prepareUpdate =  forall conn p.
IConnection conn =>
conn -> Update p -> IO (PreparedUpdate p)
prepare

-- | Bracketed prepare operation.
withPrepareUpdate :: IConnection conn
                  => conn
                  -> Update p
                  -> (PreparedUpdate p -> IO a)
                  -> IO a
withPrepareUpdate :: forall conn p a.
IConnection conn =>
conn -> Update p -> (PreparedUpdate p -> IO a) -> IO a
withPrepareUpdate = forall (s :: * -> *) conn p a.
(UntypeableNoFetch s, IConnection conn) =>
conn -> s p -> (PreparedStatement p () -> IO a) -> IO a
withPrepareNoFetch

-- | Bind parameters, execute statement and get execution result.
runPreparedUpdate :: ToSql SqlValue p
                  => PreparedUpdate p
                  -> p
                  -> IO Integer
runPreparedUpdate :: forall p. ToSql SqlValue p => PreparedUpdate p -> p -> IO Integer
runPreparedUpdate = forall p. ToSql SqlValue p => PreparedUpdate p -> p -> IO Integer
executeNoFetch

-- | Prepare update statement, bind parameters,
--   execute statement and get execution result.
runUpdate :: (IConnection conn, ToSql SqlValue p)
          => conn
          -> Update p
          -> p
          -> IO Integer
runUpdate :: forall conn p.
(IConnection conn, ToSql SqlValue p) =>
conn -> Update p -> p -> IO Integer
runUpdate =  forall (s :: * -> *) conn a.
(UntypeableNoFetch s, IConnection conn, ToSql SqlValue a) =>
conn -> s a -> a -> IO Integer
runNoFetch

-- | Prepare and update with each parameter list.
mapUpdate :: (IConnection conn, ToSql SqlValue a)
          => conn
          -> Update a
          -> [a]
          -> IO [Integer]
mapUpdate :: forall conn a.
(IConnection conn, ToSql SqlValue a) =>
conn -> Update a -> [a] -> IO [Integer]
mapUpdate = forall (s :: * -> *) conn a.
(UntypeableNoFetch s, IConnection conn, ToSql SqlValue a) =>
conn -> s a -> [a] -> IO [Integer]
mapNoFetch