Bryan O'Sullivan avatar Bryan O'Sullivan committed 52c7e1e

More docs.

Comments (0)

Files changed (4)

Database/MySQL/Simple.hs

     -- $inference
 
     -- ** Substituting a single parameter
-    -- $only
+    -- $only_param
 
     -- ** Representing a list of values
     -- $in
     -- ** Modifying multiple rows at once
     -- $many
 
+    -- * Extracting results
+    -- $result
+
+    -- ** Handling null values
+    -- $null
+
+    -- ** Type conversions
+    -- $types
+
     -- * Types
       Base.ConnectInfo(..)
     , Connection
 
 -- | Execute an action inside a SQL transaction.
 --
--- You are assumed to have started the transaction yourself.
+-- This function initiates a transaction with a \"@begin
+-- transaction@\" statement, then executes the supplied action.  If
+-- the action succeeds, the transaction will be completed with
+-- 'Base.commit' before this function returns.
 --
--- If your action succeeds, the transaction will be 'Base.commit'ted
--- before this function returns.
---
--- If your action throws any exception (not just a SQL exception), the
--- transaction will be rolled back 'Base.rollback' before the
--- exception is propagated.
+-- If the action throws /any/ kind of exception (not just a
+-- MySQL-related exception), the transaction will be rolled back using
+-- 'Base.rollback', then the exception will be rethrown.
 withTransaction :: Connection -> IO a -> IO a
 withTransaction conn act = do
+  execute_ conn "start transaction"
   r <- act `onException` Base.rollback conn
   Base.commit conn
   return r
 -- the @OverloadedStrings@ language extension enabled.  Again, just
 -- use an explicit type signature if this happens.
 
--- $only
+-- $only_param
 --
 -- Haskell lacks a single-element tuple type, so if you have just one
 -- value you want substituted into a query, what should you do?
 -- The last argument to 'executeMany' is a list of parameter
 -- tuples. These will be substituted into the query where the @(?,?)@
 -- string appears, in a form suitable for use in a multi-row @INSERT@
--- or @UPDATE@..
+-- or @UPDATE@.
 --
 -- Here is an example:
 --
 --
 -- > insert into users (first_name,last_name) values
 -- >   ('Boris','Karloff'),('Ed','Wood')
+
+-- $result
+--
+-- The 'query' and 'query_' functions return a list of values in the
+-- 'QueryResults' typeclass. This class performs automatic extraction
+-- and type conversion of rows from a query result.
+--
+-- Here is a simple example of how to extract results:
+--
+-- > import qualified Data.Text as Text
+-- >
+-- > xs <- query_ conn "select name,age from users"
+-- > forM_ xs $ \(name,age) ->
+-- >   putStrLn $ Text.unpack name ++ " is " ++ show (age :: Int)
+--
+-- Notice two important details about this code:
+--
+-- * The number of columns we ask for in the query template must
+--   exactly match the number of elements we specify in a row of the
+--   result tuple.  If they do not match, a 'ResultError' exception
+--   will be thrown.
+--
+-- * Sometimes, the compiler needs our help in specifying types. It
+--   can infer that @name@ must be a 'Text', due to our use of the
+--   @unpack@ function. However, we have to tell it the type of @age@,
+--   as it has no other information to determine the exact type.
+
+-- $null
+--
+-- The type of a result tuple will look something like this:
+--
+-- > (Text, Int, Int)
+--
+-- Although SQL can accommodate @NULL@ as a value for any of these
+-- types, Haskell cannot. If your result contains columns that may be
+-- @NULL@, be sure that you use 'Maybe' in those positions of of your
+-- tuple.
+--
+-- > (Text, Maybe Int, Int)
+--
+-- If 'query' encounters a @NULL@ in a row where the corresponding
+-- Haskell type is not 'Maybe', it will throw a 'ResultError'
+-- exception.
+
+-- $only_result
+--
+-- To specify that a query returns a single-column result, use the
+-- 'Only' type.
+--
+-- > xs <- query_ conn "select id from users"
+-- > forM_ xs $ \(Only dbid) -> {- ... -}
+
+-- $types
+--
+-- Conversion of SQL values to Haskell values is somewhat
+-- permissive. Here are the rules.
+--
+-- * For numeric types, any Haskell type that can accurately represent
+--   all values of the given MySQL type is considered \"compatible\".
+--   For instance, you can always extract a MySQL @TINYINT@ column to
+--   a Haskell 'Int'.  The Haskell 'Float' type can accurately
+--   represent MySQL integer types of size up to @INT24@, so it is
+--   considered compatble with those types.
+--
+-- * A numeric compatibility check is based only on the type of a
+--   column, /not/ on its values. For instance, a MySQL @LONG_LONG@
+--   column will be considered incompatible with a Haskell 'Int8',
+--   even if it contains the value @1@.
+--
+-- * If a numeric incompatibility is found, 'query' will throw a
+--   'ResultError'.
+--
+-- * The 'String' and 'Text' types are assumed to be encoded as
+--   UTF-8. If you use some other encoding, decoding may fail or give
+--   wrong results. In such cases, write a @newtype@ wrapper and a
+--   custom 'Result' instance to handle your encoding.

Database/MySQL/Simple/QueryParams.hs

 --
 -- The 'QueryParams' typeclass, for rendering a collection of
 -- parameters to a SQL query.
+--
+-- Predefined instances are provided for tuples containing up to ten
+-- elements.
 
 module Database.MySQL.Simple.QueryParams
     (
 
 -- | A collection type that can be turned into a list of rendering
 -- 'Action's.
+--
+-- Instances should use the 'render' method of the 'Param' class
+-- to perform conversion of each element of the collection.
 class QueryParams a where
     renderParams :: a -> [Action]
     -- ^ Render a collection of values.

Database/MySQL/Simple/QueryResults.hs

 --
 -- The 'QueryResults' typeclass, for converting a row of results
 -- returned by a SQL query into a more useful Haskell representation.
+--
+-- Predefined instances are provided for tuples containing up to ten
+-- elements.
 
 module Database.MySQL.Simple.QueryResults
     (
 -- * Ensure that any 'ResultError' that might arise is thrown
 --   immediately, rather than some place later in application code
 --   that cannot handle it.
+--
+-- You can also declare Haskell types of your own to be instances of
+-- 'QueryResults'.
+--
+-- @
+--data User { firstName :: String, lastName :: String }
+--
+--instance 'QueryResults' User where
+--    'convertResults' [fa,fb] [va,vb] = User a b
+--        where !a = 'convert' fa va
+--              !b = 'convert' fb vb
+--    'convertResults' fs vs  = 'convertError' fs vs
+-- @
+
 class QueryResults a where
     convertResults :: [Field] -> [Maybe ByteString] -> a
     -- ^ Convert values from a row into a Haskell collection.

Database/MySQL/Simple/Types.hs

 -- >
 -- > q :: Query
 -- > q = "select ?"
+--
+-- The underlying type is a 'ByteString', and literal Haskell strings
+-- that contain Unicode characters will be correctly transformed to
+-- UTF-8.
 newtype Query = Query {
       fromQuery :: ByteString
     } deriving (Eq, Ord, Typeable)
     mappend (Query a) (Query b) = Query (B.append a b)
     {-# INLINE mappend #-}
 
--- | A single-value collection.
+-- | A single-value \"collection\".
 --
--- This can be handy if you need to supply a single parameter to a SQL
--- query.
+-- This is useful if you need to supply a single parameter to a SQL
+-- query, or extract a single column from a SQL result.
 --
--- Example:
+-- Parameter example:
 --
--- @query \"select x from scores where x > ?\" ('Only' (42::Int))@
+-- @query c \"select x from scores where x > ?\" ('Only' (42::Int))@
+--
+-- Result example:
+--
+-- @xs <- query_ c \"select id from users\"
+--forM_ xs $ \\('Only' id) -> {- ... -}@
 newtype Only a = Only {
       fromOnly :: a
     } deriving (Eq, Ord, Read, Show, Typeable, Functor)
 --
 -- Example:
 --
--- > query "select * from whatever where id in ?" (In [3,4,5])
+-- > query c "select * from whatever where id in ?" (In [3,4,5])
 newtype In a = In a
     deriving (Eq, Ord, Read, Show, Typeable, Functor)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.