packages feed

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 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