mysql-simple (empty) → 0.1.0.0
raw patch · 11 files changed
+795/−0 lines, 11 filesdep +attoparsecdep +basedep +blaze-buildersetup-changed
Dependencies added: attoparsec, base, blaze-builder, blaze-textual, bytestring, deepseq, mysql, old-locale, text, time
Files
- Database/MySQL/Simple.hs +72/−0
- Database/MySQL/Simple/Orphans.hs +40/−0
- Database/MySQL/Simple/Param.hs +143/−0
- Database/MySQL/Simple/QueryParams.hs +64/−0
- Database/MySQL/Simple/QueryResults.hs +101/−0
- Database/MySQL/Simple/Result.hs +197/−0
- Database/MySQL/Simple/Types.hs +33/−0
- LICENSE +30/−0
- README.markdown +42/−0
- Setup.lhs +3/−0
- mysql-simple.cabal +70/−0
+ Database/MySQL/Simple.hs view
@@ -0,0 +1,72 @@+module Database.MySQL.Simple+ (+ execute+ , query+ , query_+ , formatQuery+ ) where++import Blaze.ByteString.Builder (fromByteString, toByteString)+import Control.Applicative ((<$>), pure)+import Control.DeepSeq (NFData(..))+import Control.Monad.Fix (fix)+import Data.ByteString (ByteString)+import Data.Int (Int64)+import Data.Monoid (mappend, mempty)+import Database.MySQL.Base (Connection)+import Database.MySQL.Simple.Param (Action(..), inQuotes)+import Database.MySQL.Simple.QueryParams (QueryParams(..))+import Database.MySQL.Simple.QueryResults (QueryResults(..))+import Database.MySQL.Simple.Types (Query(..))+import qualified Data.ByteString.Char8 as B+import qualified Database.MySQL.Base as Base++formatQuery :: QueryParams q => Connection -> Query -> q -> IO ByteString+formatQuery conn (Query template) qs+ | '?' `B.notElem` template = return template+ | otherwise =+ toByteString . zipParams (split template) <$> mapM sub (renderParams qs)+ where sub (Plain b) = pure b+ sub (Escape s) = (inQuotes . fromByteString) <$> Base.escape conn s+ split q = fromByteString h : if B.null t then [] else split (B.tail t)+ where (h,t) = B.break (=='?') q+ zipParams (t:ts) (p:ps) = t `mappend` p `mappend` zipParams ts ps+ zipParams [] [] = mempty+ zipParams [] _ = fmtError "more parameters than '?' characters"+ zipParams _ [] = fmtError "more '?' characters than parameters"++execute :: (QueryParams q) => Connection -> Query -> q -> IO Int64+execute conn template qs = do+ Base.query conn =<< formatQuery conn template qs+ ncols <- Base.fieldCount (Left conn)+ if ncols /= 0+ then error "execute: executed a select!"+ else Base.affectedRows conn+ +query :: (QueryParams q, QueryResults r) => Connection -> Query -> q -> IO [r]+query conn template qs = do+ Base.query conn =<< formatQuery conn template qs+ finishQuery conn+ +query_ :: (QueryResults r) => Connection -> Query -> IO [r]+query_ conn (Query q) = do+ Base.query conn q+ finishQuery conn++finishQuery :: (QueryResults r) => Connection -> IO [r]+finishQuery conn = do+ r <- Base.storeResult conn+ ncols <- Base.fieldCount (Right r)+ if ncols == 0+ then return []+ else do+ fs <- Base.fetchFields r+ flip fix [] $ \loop acc -> do+ row <- Base.fetchRow r+ case row of+ [] -> return (reverse acc)+ _ -> let c = convertResults fs row+ in rnf c `seq` loop (c:acc)++fmtError :: String -> a+fmtError msg = error $ "Database.MySQL.formatQuery: " ++ msg
+ Database/MySQL/Simple/Orphans.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE BangPatterns #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Database.MySQL.Simple.Orphans () where++import Control.DeepSeq (NFData(..))+import Data.Time.Calendar (Day(..))+import Data.Time.Clock (UTCTime(..))+import Data.Time.LocalTime (TimeOfDay(..))+import qualified Data.ByteString.Internal as SB+import qualified Data.ByteString.Lazy.Internal as LB++instance NFData SB.ByteString where+ rnf (SB.PS _ _ _) = ()+ {-# INLINE rnf #-}++instance NFData LB.ByteString where+ rnf (LB.Chunk (SB.PS _ _ _) cs) = rnf cs+ rnf LB.Empty = ()++instance NFData Day where+ rnf (ModifiedJulianDay !_) = ()+ {-# INLINE rnf #-}++instance NFData TimeOfDay where+ rnf (TimeOfDay !_ !_ !_) = ()+ {-# INLINE rnf #-}++instance NFData UTCTime where+ rnf (UTCTime !_ !_) = ()+ {-# INLINE rnf #-}++instance (NFData a, NFData b, NFData c, NFData d, NFData e, NFData f,+ NFData g, NFData h, NFData i, NFData j) =>+ NFData (a,b,c,d,e,f,g,h,i,j)+ where+ rnf (a,b,c,d,e,f,g,h,i,j) =+ rnf a `seq` rnf b `seq` rnf c `seq` rnf d `seq` rnf e `seq`+ rnf f `seq` rnf g `seq` rnf h `seq` rnf i `seq` rnf j+ {-# INLINE rnf #-}
+ Database/MySQL/Simple/Param.hs view
@@ -0,0 +1,143 @@+{-# LANGUAGE FlexibleInstances, OverloadedStrings #-}++module Database.MySQL.Simple.Param+ (+ Action(..)+ , Param(..)+ , inQuotes+ ) where++import Blaze.ByteString.Builder (Builder, fromByteString, toByteString)+import Blaze.Text (integral, double, float)+import Data.ByteString (ByteString)+import Data.Int (Int8, Int16, Int32, Int64)+import Data.Monoid (mappend)+import Data.Time.Calendar (Day, showGregorian)+import Data.Time.Clock (UTCTime)+import Data.Time.Format (formatTime)+import Data.Time.LocalTime (TimeOfDay)+import Data.Word (Word, Word8, Word16, Word32, Word64)+import Database.MySQL.Simple.Types (Null)+import System.Locale (defaultTimeLocale)+import qualified Blaze.ByteString.Builder.Char.Utf8 as Utf8+import qualified Data.ByteString as SB+import qualified Data.ByteString.Lazy as LB+import qualified Data.Text as ST+import qualified Data.Text.Encoding as ST+import qualified Data.Text.Lazy as LT++data Action = Plain Builder+ | Escape ByteString++class Param a where+ render :: a -> Action++instance Param Action where+ render a = a+ {-# INLINE render #-}++instance (Param a) => Param (Maybe a) where+ render Nothing = renderNull+ render (Just a) = render a+ {-# INLINE render #-}++renderNull :: Action+renderNull = Plain (fromByteString "null")++instance Param Null where+ render _ = renderNull+ {-# INLINE render #-}++instance Param Bool where+ render = Plain . integral . fromEnum+ {-# INLINE render #-}++instance Param Int8 where+ render = Plain . integral+ {-# INLINE render #-}++instance Param Int16 where+ render = Plain . integral+ {-# INLINE render #-}++instance Param Int32 where+ render = Plain . integral+ {-# INLINE render #-}++instance Param Int where+ render = Plain . integral+ {-# INLINE render #-}++instance Param Int64 where+ render = Plain . integral+ {-# INLINE render #-}++instance Param Integer where+ render = Plain . integral+ {-# INLINE render #-}++instance Param Word8 where+ render = Plain . integral+ {-# INLINE render #-}++instance Param Word16 where+ render = Plain . integral+ {-# INLINE render #-}++instance Param Word32 where+ render = Plain . integral+ {-# INLINE render #-}++instance Param Word where+ render = Plain . integral+ {-# INLINE render #-}++instance Param Word64 where+ render = Plain . integral+ {-# INLINE render #-}++instance Param Float where+ render v | isNaN v || isInfinite v = renderNull+ | otherwise = Plain (float v)+ {-# INLINE render #-}++instance Param Double where+ render v | isNaN v || isInfinite v = renderNull+ | otherwise = Plain (double v)+ {-# INLINE render #-}++instance Param SB.ByteString where+ render = Escape+ {-# INLINE render #-}++instance Param LB.ByteString where+ render = render . SB.concat . LB.toChunks+ {-# INLINE render #-}++instance Param ST.Text where+ render = Escape . ST.encodeUtf8+ {-# INLINE render #-}++instance Param [Char] where+ render = Escape . toByteString . Utf8.fromString+ {-# INLINE render #-}++instance Param LT.Text where+ render = render . LT.toStrict+ {-# INLINE render #-}++instance Param UTCTime where+ render = Plain . Utf8.fromString . formatTime defaultTimeLocale "'%F %T'"+ {-# INLINE render #-}++instance Param Day where+ render = Plain . inQuotes . Utf8.fromString . showGregorian+ {-# INLINE render #-}++instance Param TimeOfDay where+ render = Plain . inQuotes . Utf8.fromString . show+ {-# INLINE render #-}++inQuotes :: Builder -> Builder+inQuotes b = quote `mappend` b `mappend` quote+ where quote = Utf8.fromChar '\''
+ Database/MySQL/Simple/QueryParams.hs view
@@ -0,0 +1,64 @@+module Database.MySQL.Simple.QueryParams+ (+ QueryParams(..)+ ) where++import Database.MySQL.Simple.Param (Action(..), Param(..))+import Database.MySQL.Simple.Types (Only(..))++class QueryParams a where+ renderParams :: a -> [Action]++instance QueryParams () where+ renderParams _ = []++instance (Param a) => QueryParams (Only a) where+ renderParams (Only v) = [render v]++instance (Param a, Param b) => QueryParams (a,b) where+ renderParams (a,b) = [render a, render b]++instance (Param a, Param b, Param c) => QueryParams (a,b,c) where+ renderParams (a,b,c) = [render a, render b, render c]++instance (Param a, Param b, Param c, Param d) => QueryParams (a,b,c,d) where+ renderParams (a,b,c,d) = [render a, render b, render c, render d]++instance (Param a, Param b, Param c, Param d, Param e)+ => QueryParams (a,b,c,d,e) where+ renderParams (a,b,c,d,e) =+ [render a, render b, render c, render d, render e]++instance (Param a, Param b, Param c, Param d, Param e, Param f)+ => QueryParams (a,b,c,d,e,f) where+ renderParams (a,b,c,d,e,f) =+ [render a, render b, render c, render d, render e, render f]++instance (Param a, Param b, Param c, Param d, Param e, Param f, Param g)+ => QueryParams (a,b,c,d,e,f,g) where+ renderParams (a,b,c,d,e,f,g) =+ [render a, render b, render c, render d, render e, render f, render g]++instance (Param a, Param b, Param c, Param d, Param e, Param f, Param g,+ Param h)+ => QueryParams (a,b,c,d,e,f,g,h) where+ renderParams (a,b,c,d,e,f,g,h) =+ [render a, render b, render c, render d, render e, render f, render g,+ render h]++instance (Param a, Param b, Param c, Param d, Param e, Param f, Param g,+ Param h, Param i)+ => QueryParams (a,b,c,d,e,f,g,h,i) where+ renderParams (a,b,c,d,e,f,g,h,i) =+ [render a, render b, render c, render d, render e, render f, render g,+ render h, render i]++instance (Param a, Param b, Param c, Param d, Param e, Param f, Param g,+ Param h, Param i, Param j)+ => QueryParams (a,b,c,d,e,f,g,h,i,j) where+ renderParams (a,b,c,d,e,f,g,h,i,j) =+ [render a, render b, render c, render d, render e, render f, render g,+ render h, render i, render j]++instance (Param a) => QueryParams [a] where+ renderParams = map render
+ Database/MySQL/Simple/QueryResults.hs view
@@ -0,0 +1,101 @@+module Database.MySQL.Simple.QueryResults+ (+ QueryResults(..)+ ) where++import Control.DeepSeq (NFData(..))+import Control.Exception (throw)+import Data.ByteString (ByteString)+import Database.MySQL.Base.Types (Field)+import Database.MySQL.Simple.Result (ResultError(..), Result(..))+import Database.MySQL.Simple.Types (Only(..))++class (NFData a) => QueryResults a where+ convertResults :: [Field] -> [Maybe ByteString] -> a++instance (NFData a, Result a) => QueryResults (Only a) where+ convertResults [fa] [va] = Only (convert fa va)+ convertResults fs vs = convError fs vs++instance (NFData a, NFData b,+ Result a, Result b) => QueryResults (a,b) where+ convertResults [fa,fb] [va,vb] = (convert fa va, convert fb vb)+ convertResults fs vs = convError fs vs++instance (NFData a, NFData b, NFData c,+ Result a, Result b, Result c) => QueryResults (a,b,c) where+ convertResults [fa,fb,fc] [va,vb,vc] =+ (convert fa va, convert fb vb, convert fc vc)+ convertResults fs vs = convError fs vs++instance (NFData a, NFData b, NFData c, NFData d,+ Result a, Result b, Result c, Result d) =>+ QueryResults (a,b,c,d) where+ convertResults [fa,fb,fc,fd] [va,vb,vc,vd] =+ (convert fa va, convert fb vb, convert fc vc, convert fd vd)+ convertResults fs vs = convError fs vs++instance (NFData a, NFData b, NFData c, NFData d, NFData e,+ Result a, Result b, Result c, Result d, Result e) =>+ QueryResults (a,b,c,d,e) where+ convertResults [fa,fb,fc,fd,fe] [va,vb,vc,vd,ve] =+ (convert fa va, convert fb vb, convert fc vc, convert fd vd,+ convert fe ve)+ convertResults fs vs = convError fs vs++instance (NFData a, NFData b, NFData c, NFData d, NFData e, NFData f,+ Result a, Result b, Result c, Result d, Result e, Result f) =>+ QueryResults (a,b,c,d,e,f) where+ convertResults [fa,fb,fc,fd,fe,ff] [va,vb,vc,vd,ve,vf] =+ (convert fa va, convert fb vb, convert fc vc, convert fd vd,+ convert fe ve, convert ff vf)+ convertResults fs vs = convError fs vs++instance (NFData a, NFData b, NFData c, NFData d, NFData e, NFData f,+ NFData g,+ Result a, Result b, Result c, Result d, Result e, Result f,+ Result g) =>+ QueryResults (a,b,c,d,e,f,g) where+ convertResults [fa,fb,fc,fd,fe,ff,fg] [va,vb,vc,vd,ve,vf,vg] =+ (convert fa va, convert fb vb, convert fc vc, convert fd vd,+ convert fe ve, convert ff vf, convert fg vg)+ convertResults fs vs = convError fs vs++instance (NFData a, NFData b, NFData c, NFData d, NFData e, NFData f,+ NFData g, NFData h,+ Result a, Result b, Result c, Result d, Result e, Result f,+ Result g, Result h) =>+ QueryResults (a,b,c,d,e,f,g,h) where+ convertResults [fa,fb,fc,fd,fe,ff,fg,fh] [va,vb,vc,vd,ve,vf,vg,vh] =+ (convert fa va, convert fb vb, convert fc vc, convert fd vd,+ convert fe ve, convert ff vf, convert fg vg, convert fh vh)+ convertResults fs vs = convError fs vs++instance (NFData a, NFData b, NFData c, NFData d, NFData e, NFData f,+ NFData g, NFData h, NFData i,+ Result a, Result b, Result c, Result d, Result e, Result f,+ Result g, Result h, Result i) =>+ QueryResults (a,b,c,d,e,f,g,h,i) where+ convertResults [fa,fb,fc,fd,fe,ff,fg,fh,fi] [va,vb,vc,vd,ve,vf,vg,vh,vi] =+ (convert fa va, convert fb vb, convert fc vc, convert fd vd,+ convert fe ve, convert ff vf, convert fg vg, convert fh vh,+ convert fi vi)+ convertResults fs vs = convError fs vs++instance (NFData a, NFData b, NFData c, NFData d, NFData e, NFData f,+ NFData g, NFData h, NFData i, NFData j,+ Result a, Result b, Result c, Result d, Result e, Result f,+ Result g, Result h, Result i, Result j) =>+ QueryResults (a,b,c,d,e,f,g,h,i,j) where+ convertResults [fa,fb,fc,fd,fe,ff,fg,fh,fi,fj]+ [va,vb,vc,vd,ve,vf,vg,vh,vi,vj] =+ (convert fa va, convert fb vb, convert fc vc, convert fd vd,+ convert fe ve, convert ff vf, convert fg vg, convert fh vh,+ convert fi vi, convert fj vj)+ convertResults fs vs = convError fs vs++convError :: [Field] -> [Maybe ByteString] -> a+convError fs vs = throw $ ConversionFailed+ (show (length fs) ++ " columns left in result")+ (show (length vs) ++ " values left in row")+ "mismatch between number of columns to convert"
+ Database/MySQL/Simple/Result.hs view
@@ -0,0 +1,197 @@+{-# LANGUAGE CPP, DeriveDataTypeable, FlexibleInstances #-}++module Database.MySQL.Simple.Result+ (+ Result(..)+ , ResultError(..)+ ) where++#include "MachDeps.h"++import Control.Applicative ((<$>), (<*>), (<*), pure)+import Control.DeepSeq (NFData)+import Control.Exception (Exception, throw)+import Data.Attoparsec.Char8 hiding (Result)+import Data.Bits ((.&.), (.|.), shiftL)+import Data.ByteString (ByteString)+import Data.Int (Int8, Int16, Int32, Int64)+import Data.List (foldl')+import Data.Ratio (Ratio)+import Data.Time.Calendar (Day, fromGregorian)+import Data.Time.Clock (UTCTime)+import Data.Time.Format (parseTime)+import Data.Time.LocalTime (TimeOfDay, makeTimeOfDayValid)+import Data.Typeable (TypeRep, Typeable, typeOf)+import Data.Word (Word, Word8, Word16, Word32, Word64)+import Database.MySQL.Base.Types (Field(..), Type(..))+import Database.MySQL.Simple.Orphans ()+import System.Locale (defaultTimeLocale)+import qualified Data.ByteString as SB+import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString.Lazy as LB+import qualified Data.Text as ST+import qualified Data.Text.Encoding as ST+import qualified Data.Text.Lazy as LT++data ResultError = Incompatible { errSourceType :: String+ , errDestType :: String+ , errMessage :: String }+ | UnexpectedNull { errSourceType :: String+ , errDestType :: String+ , errMessage :: String }+ | ConversionFailed { errSourceType :: String+ , errDestType :: String+ , errMessage :: String }+ deriving (Eq, Show, Typeable)++instance Exception ResultError++class (NFData a) => Result a where+ convert :: Field -> Maybe ByteString -> a++instance (Result a) => Result (Maybe a) where+ convert _ Nothing = Nothing+ convert f bs = Just (convert f bs)++instance Result Bool where+ convert = atto ok8 ((/=(0::Int)) <$> decimal)++instance Result Int8 where+ convert = atto ok8 $ signed decimal++instance Result Int16 where+ convert = atto ok16 $ signed decimal++instance Result Int32 where+ convert = atto ok32 $ signed decimal++instance Result Int where+ convert = atto okWord $ signed decimal++instance Result Int64 where+ convert = atto ok64 $ signed decimal++instance Result Integer where+ convert = atto ok64 $ signed decimal++instance Result Word8 where+ convert = atto ok8 decimal++instance Result Word16 where+ convert = atto ok16 decimal++instance Result Word32 where+ convert = atto ok32 decimal++instance Result Word where+ convert = atto okWord decimal++instance Result Word64 where+ convert = atto ok64 decimal++instance Result Float where+ convert = atto ok ((fromRational . toRational) <$> double)+ where ok = mkCompats [Float,Double,Decimal,NewDecimal]++instance Result Double where+ convert = atto ok double+ where ok = mkCompats [Float,Double,Decimal,NewDecimal]++instance Result (Ratio Integer) where+ convert = atto ok rational+ where ok = mkCompats [Float,Double,Decimal,NewDecimal]++instance Result SB.ByteString where+ convert f = doConvert f okText $ id++instance Result LB.ByteString where+ convert f = LB.fromChunks . (:[]) . convert f++instance Result ST.Text where+ convert f | isText f = doConvert f okText $ ST.decodeUtf8+ | otherwise = incompatible f (typeOf ST.empty)+ "attempt to mix binary and text"++instance Result LT.Text where+ convert f = LT.fromStrict . convert f++instance Result [Char] where+ convert f = ST.unpack . convert f++instance Result UTCTime where+ convert f = doConvert f ok $ \bs ->+ case parseTime defaultTimeLocale "%F %T" (B8.unpack bs) of+ Just t -> t+ Nothing -> conversionFailed f "UTCTime" "could not parse"+ where ok = mkCompats [DateTime,Timestamp]++instance Result Day where+ convert f = flip (atto ok) f $ case fieldType f of+ Year -> year+ _ -> date+ where ok = mkCompats [Year,Date,NewDate]+ year = fromGregorian <$> decimal <*> pure 1 <*> pure 1+ date = fromGregorian <$> (decimal <* char '-')+ <*> (decimal <* char '-')+ <*> decimal++instance Result TimeOfDay where+ convert f = flip (atto ok) f $ do+ hours <- decimal <* char ':'+ mins <- decimal <* char ':'+ secs <- decimal :: Parser Int+ case makeTimeOfDayValid hours mins (fromIntegral secs) of+ Just t -> return t+ _ -> conversionFailed f "TimeOfDay" "could not parse"+ where ok = mkCompats [Time]++isText :: Field -> Bool+isText f = fieldCharSet f /= 63++newtype Compat = Compat Word32+ +mkCompats :: [Type] -> Compat+mkCompats = foldl' f (Compat 0) . map mkCompat+ where f (Compat a) (Compat b) = Compat (a .|. b)++mkCompat :: Type -> Compat+mkCompat = Compat . shiftL 1 . fromEnum++compat :: Compat -> Compat -> Bool+compat (Compat a) (Compat b) = a .&. b /= 0++okText, ok8, ok16, ok32, ok64, okWord :: Compat+okText = mkCompats [VarChar,TinyBlob,MediumBlob,LongBlob,Blob,VarString,String,+ Set,Enum]+ok8 = mkCompats [Tiny]+ok16 = mkCompats [Tiny,Short]+ok32 = mkCompats [Tiny,Short,Int24,Long]+ok64 = mkCompats [Tiny,Short,Int24,Long,LongLong]+#if WORD_SIZE_IN_BITS < 64+okWord = ok32+#else+okWord = ok64+#endif++doConvert :: (Typeable a) =>+ Field -> Compat -> (ByteString -> a) -> Maybe ByteString -> a+doConvert f types cvt (Just bs)+ | mkCompat (fieldType f) `compat` types = cvt bs+ | otherwise = incompatible f (typeOf (cvt undefined)) "types incompatible"+doConvert f _ cvt _ = throw $ UnexpectedNull (show (fieldType f))+ (show (typeOf (cvt undefined))) ""++incompatible :: Field -> TypeRep -> String -> a+incompatible f r = throw . Incompatible (show (fieldType f)) (show r)++conversionFailed :: Field -> String -> String -> a+conversionFailed f s = throw . ConversionFailed (show (fieldType f)) s++atto :: (Typeable a) => Compat -> Parser a -> Field -> Maybe ByteString -> a+atto types p0 f = doConvert f types $ go undefined p0+ where+ go :: (Typeable a) => a -> Parser a -> ByteString -> a+ go dummy p s =+ case parseOnly p s of+ Left err -> conversionFailed f (show (typeOf dummy)) err+ Right v -> v
+ Database/MySQL/Simple/Types.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Database.MySQL.Simple.Types+ (+ Null(..)+ , Only(..)+ , Query(..)+ ) where++import Control.Arrow+import Control.DeepSeq (NFData)+import Blaze.ByteString.Builder+import Data.String (IsString(..))+import qualified Blaze.ByteString.Builder.Char.Utf8 as Utf8+import Data.ByteString (ByteString)++data Null = Null++newtype Query = Query {+ fromQuery :: ByteString+ } deriving (Eq, Ord)++instance Show Query where+ show = show . fromQuery++instance Read Query where+ readsPrec i = fmap (first Query) . readsPrec i++instance IsString Query where+ fromString = Query . toByteString . Utf8.fromString++newtype Only a = Only a+ deriving (Eq, Ord, Read, Show, NFData)
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2011, MailRank, Inc.++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ README.markdown view
@@ -0,0 +1,42 @@+# mysql-simple: mid-level bindings to the mysqlclient library++This library is a mid-level Haskell binding to the MySQL `mysqlclient`+client library. It is aimed at speed and ease of use.++# Licensing++This library is BSD-licensed under the terms of the+[MySQL FOSS License Exception](http://www.mysql.com/about/legal/licensing/foss-exception/).++Since this library links against the GPL-licensed `mysqlclient`+library, a non-open-source application that uses it *may* be subject+to the terms of the GPL.++# To do++* Add support for prepared statements. This API is huge and of dubious+ performance worth, so it's not currently a priority for me. Patches+ welcome!++# Get involved!++We are happy to receive bug reports, fixes, documentation enhancements,+and other improvements.++Please report bugs via the+[github issue tracker](http://github.com/mailrank/mysql-simple/issues).++Master [git repository](http://github.com/mailrank/mysql-simple):++* `git clone git://github.com/mailrank/mysql-simple.git`++There's also a [Mercurial mirror](http://bitbucket.org/bos/mysql-simple):++* `hg clone http://bitbucket.org/bos/mysql-simple`++(You can create and contribute changes using either git or Mercurial.)++# Authors++This library is written and maintained by Bryan O'Sullivan,+<bos@mailrank.com>.
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ mysql-simple.cabal view
@@ -0,0 +1,70 @@+name: mysql-simple+version: 0.1.0.0+homepage: https://github.com/mailrank/mysql-simple+bug-reports: https://github.com/mailrank/mysql-simple/issues+synopsis: A mid-level MySQL client library.+description: + A mid-level client library for the MySQL database, intended to be+ fast and easy to use.+ .+ /Important licensing note/: This library is BSD-licensed under the+ terms of the MySQL FOSS License Exception+ <http://www.mysql.com/about/legal/licensing/foss-exception/>.+ .+ Since this library links against the GPL-licensed @mysqlclient@+ library, a non-open-source application that uses it /may/ be+ subject to the terms of the GPL.+license: BSD3+license-file: LICENSE+author: Bryan O'Sullivan <bos@mailrank.com>+maintainer: Bryan O'Sullivan <bos@mailrank.com>+copyright: 2011 MailRank, Inc.+category: Database+build-type: Simple+cabal-version: >= 1.6+extra-source-files:+ README.markdown++flag developer+ description: operate in developer mode+ default: False++library+ exposed-modules:+ Database.MySQL.Simple+ Database.MySQL.Simple.Param+ Database.MySQL.Simple.QueryParams+ Database.MySQL.Simple.QueryResults+ Database.MySQL.Simple.Result+ Database.MySQL.Simple.Types++ other-modules:+ Database.MySQL.Simple.Orphans++ build-depends:+ attoparsec >= 0.8.5.3,+ base < 5,+ blaze-builder,+ blaze-textual,+ bytestring >= 0.9,+ deepseq,+ mysql,+ old-locale,+ text >= 0.11.0.2,+ time++ ghc-options: -Wall+ if impl(ghc >= 6.8)+ ghc-options: -fwarn-tabs+ if flag(developer)+ ghc-prof-options: -auto-all+ ghc-options: -Werror+ cpp-options: -DASSERTS++source-repository head+ type: git+ location: http://github.com/mailrank/mysql-simple++source-repository head+ type: mercurial+ location: http://bitbucket.org/bos/mysql-simple