module Database.MySQL.Query where
import Data.String (IsString (..))
import Control.Exception (throw, Exception)
import Data.Typeable
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Char8 as LC
import qualified Data.ByteString.Builder as BB
import Control.Arrow (first)
import Database.MySQL.Protocol.MySQLValue
import Data.Binary.Put
newtype Query = Query { fromQuery :: L.ByteString } deriving (Eq, Ord, Typeable)
instance Show Query where
show = show . fromQuery
instance Read Query where
readsPrec i = fmap (first Query) . readsPrec i
instance IsString Query where
fromString = Query . BB.toLazyByteString . BB.stringUtf8
data Param = One MySQLValue
| Many [MySQLValue]
class QueryParam a where
render :: a -> Put
instance QueryParam Param where
render (One x) = putTextField x
render (Many []) = putTextField MySQLNull
render (Many (x:[]))= putTextField x
render (Many (x:xs))= do putTextField x
mapM_ (\f -> putCharUtf8 ',' >> putTextField f) xs
instance QueryParam MySQLValue where
render = putTextField
renderParams :: QueryParam p => Query -> [p] -> Query
renderParams (Query qry) params =
let fragments = LC.split '?' qry
in Query . runPut $ merge fragments params
where
merge [x] [] = putLazyByteString x
merge (x:xs) (y:ys) = putLazyByteString x >> render y >> merge xs ys
merge _ _ = throw WrongParamsCount
data WrongParamsCount = WrongParamsCount deriving (Show, Typeable)
instance Exception WrongParamsCount