HDBC 1.1.6 → 2.0.0
raw patch · 8 files changed
+1038/−409 lines, 8 filesdep +HUnitdep +QuickCheckdep +convertibledep ~basedep ~bytestringdep ~containersnew-component:exe:runtestsPVP ok
version bump matches the API change (PVP)
Dependencies added: HUnit, QuickCheck, convertible, old-locale, testpack, time, utf8-string
Dependency ranges changed: base, bytestring, containers, mtl, old-time
API changes (from Hackage documentation)
- Database.HDBC: class (Show a) => SqlType a
- Database.HDBC.Statement: class (Show a) => SqlType a
- Database.HDBC.Statement: instance (SqlType a) => SqlType (Maybe a)
- Database.HDBC.Statement: instance Eq SqlValue
- Database.HDBC.Statement: instance Show SqlValue
- Database.HDBC.Statement: instance SqlType Bool
- Database.HDBC.Statement: instance SqlType ByteString
- Database.HDBC.Statement: instance SqlType CalendarTime
- Database.HDBC.Statement: instance SqlType Char
- Database.HDBC.Statement: instance SqlType ClockTime
- Database.HDBC.Statement: instance SqlType Double
- Database.HDBC.Statement: instance SqlType Int
- Database.HDBC.Statement: instance SqlType Int32
- Database.HDBC.Statement: instance SqlType Int64
- Database.HDBC.Statement: instance SqlType Integer
- Database.HDBC.Statement: instance SqlType Rational
- Database.HDBC.Statement: instance SqlType String
- Database.HDBC.Statement: instance SqlType TimeDiff
- Database.HDBC.Statement: instance SqlType Word32
- Database.HDBC.Statement: instance SqlType Word64
- Database.HDBC.Types: class (Show a) => SqlType a
+ Database.HDBC: SqlDiffTime :: NominalDiffTime -> SqlValue
+ Database.HDBC: SqlLocalDate :: Day -> SqlValue
+ Database.HDBC: SqlLocalTime :: LocalTime -> SqlValue
+ Database.HDBC: SqlLocalTimeOfDay :: TimeOfDay -> SqlValue
+ Database.HDBC: SqlPOSIXTime :: POSIXTime -> SqlValue
+ Database.HDBC: SqlUTCTime :: UTCTime -> SqlValue
+ Database.HDBC: SqlZonedLocalTimeOfDay :: TimeOfDay -> TimeZone -> SqlValue
+ Database.HDBC: SqlZonedTime :: ZonedTime -> SqlValue
+ Database.HDBC: posixToSql :: POSIXTime -> SqlValue
+ Database.HDBC: safeFromSql :: (Convertible SqlValue a) => SqlValue -> ConvertResult a
+ Database.HDBC: throwSqlError :: SqlError -> IO a
+ Database.HDBC.ColTypes: SqlTimeWithZoneT :: SqlTypeId
+ Database.HDBC.ColTypes: SqlTimestampWithZoneT :: SqlTypeId
+ Database.HDBC.SqlValue: SqlBool :: Bool -> SqlValue
+ Database.HDBC.SqlValue: SqlByteString :: ByteString -> SqlValue
+ Database.HDBC.SqlValue: SqlChar :: Char -> SqlValue
+ Database.HDBC.SqlValue: SqlDiffTime :: NominalDiffTime -> SqlValue
+ Database.HDBC.SqlValue: SqlDouble :: Double -> SqlValue
+ Database.HDBC.SqlValue: SqlEpochTime :: Integer -> SqlValue
+ Database.HDBC.SqlValue: SqlInt32 :: Int32 -> SqlValue
+ Database.HDBC.SqlValue: SqlInt64 :: Int64 -> SqlValue
+ Database.HDBC.SqlValue: SqlInteger :: Integer -> SqlValue
+ Database.HDBC.SqlValue: SqlLocalDate :: Day -> SqlValue
+ Database.HDBC.SqlValue: SqlLocalTime :: LocalTime -> SqlValue
+ Database.HDBC.SqlValue: SqlLocalTimeOfDay :: TimeOfDay -> SqlValue
+ Database.HDBC.SqlValue: SqlNull :: SqlValue
+ Database.HDBC.SqlValue: SqlPOSIXTime :: POSIXTime -> SqlValue
+ Database.HDBC.SqlValue: SqlRational :: Rational -> SqlValue
+ Database.HDBC.SqlValue: SqlString :: String -> SqlValue
+ Database.HDBC.SqlValue: SqlTimeDiff :: Integer -> SqlValue
+ Database.HDBC.SqlValue: SqlUTCTime :: UTCTime -> SqlValue
+ Database.HDBC.SqlValue: SqlWord32 :: Word32 -> SqlValue
+ Database.HDBC.SqlValue: SqlWord64 :: Word64 -> SqlValue
+ Database.HDBC.SqlValue: SqlZonedLocalTimeOfDay :: TimeOfDay -> TimeZone -> SqlValue
+ Database.HDBC.SqlValue: SqlZonedTime :: ZonedTime -> SqlValue
+ Database.HDBC.SqlValue: data SqlValue
+ Database.HDBC.SqlValue: fromSql :: (Convertible SqlValue a) => SqlValue -> a
+ Database.HDBC.SqlValue: iToSql :: Int -> SqlValue
+ Database.HDBC.SqlValue: instance (Convertible SqlValue a) => Convertible SqlValue (Maybe a)
+ Database.HDBC.SqlValue: instance (Convertible a SqlValue) => Convertible (Maybe a) SqlValue
+ Database.HDBC.SqlValue: instance Convertible (TimeOfDay, TimeZone) SqlValue
+ Database.HDBC.SqlValue: instance Convertible Bool SqlValue
+ Database.HDBC.SqlValue: instance Convertible ByteString SqlValue
+ Database.HDBC.SqlValue: instance Convertible CalendarTime SqlValue
+ Database.HDBC.SqlValue: instance Convertible Char SqlValue
+ Database.HDBC.SqlValue: instance Convertible ClockTime SqlValue
+ Database.HDBC.SqlValue: instance Convertible Day SqlValue
+ Database.HDBC.SqlValue: instance Convertible DiffTime SqlValue
+ Database.HDBC.SqlValue: instance Convertible Double SqlValue
+ Database.HDBC.SqlValue: instance Convertible Int SqlValue
+ Database.HDBC.SqlValue: instance Convertible Int32 SqlValue
+ Database.HDBC.SqlValue: instance Convertible Int64 SqlValue
+ Database.HDBC.SqlValue: instance Convertible Integer SqlValue
+ Database.HDBC.SqlValue: instance Convertible LocalTime SqlValue
+ Database.HDBC.SqlValue: instance Convertible NominalDiffTime SqlValue
+ Database.HDBC.SqlValue: instance Convertible Rational SqlValue
+ Database.HDBC.SqlValue: instance Convertible SqlValue (TimeOfDay, TimeZone)
+ Database.HDBC.SqlValue: instance Convertible SqlValue Bool
+ Database.HDBC.SqlValue: instance Convertible SqlValue ByteString
+ Database.HDBC.SqlValue: instance Convertible SqlValue CalendarTime
+ Database.HDBC.SqlValue: instance Convertible SqlValue Char
+ Database.HDBC.SqlValue: instance Convertible SqlValue ClockTime
+ Database.HDBC.SqlValue: instance Convertible SqlValue Day
+ Database.HDBC.SqlValue: instance Convertible SqlValue DiffTime
+ Database.HDBC.SqlValue: instance Convertible SqlValue Double
+ Database.HDBC.SqlValue: instance Convertible SqlValue Int
+ Database.HDBC.SqlValue: instance Convertible SqlValue Int32
+ Database.HDBC.SqlValue: instance Convertible SqlValue Int64
+ Database.HDBC.SqlValue: instance Convertible SqlValue Integer
+ Database.HDBC.SqlValue: instance Convertible SqlValue LocalTime
+ Database.HDBC.SqlValue: instance Convertible SqlValue NominalDiffTime
+ Database.HDBC.SqlValue: instance Convertible SqlValue Rational
+ Database.HDBC.SqlValue: instance Convertible SqlValue String
+ Database.HDBC.SqlValue: instance Convertible SqlValue TimeDiff
+ Database.HDBC.SqlValue: instance Convertible SqlValue TimeOfDay
+ Database.HDBC.SqlValue: instance Convertible SqlValue UTCTime
+ Database.HDBC.SqlValue: instance Convertible SqlValue Word32
+ Database.HDBC.SqlValue: instance Convertible SqlValue Word64
+ Database.HDBC.SqlValue: instance Convertible SqlValue ZonedTime
+ Database.HDBC.SqlValue: instance Convertible String SqlValue
+ Database.HDBC.SqlValue: instance Convertible TimeDiff SqlValue
+ Database.HDBC.SqlValue: instance Convertible TimeOfDay SqlValue
+ Database.HDBC.SqlValue: instance Convertible UTCTime SqlValue
+ Database.HDBC.SqlValue: instance Convertible Word32 SqlValue
+ Database.HDBC.SqlValue: instance Convertible Word64 SqlValue
+ Database.HDBC.SqlValue: instance Convertible ZonedTime SqlValue
+ Database.HDBC.SqlValue: instance Eq SqlValue
+ Database.HDBC.SqlValue: instance Show SqlValue
+ Database.HDBC.SqlValue: instance Typeable ClockTime
+ Database.HDBC.SqlValue: instance Typeable Day
+ Database.HDBC.SqlValue: instance Typeable DiffTime
+ Database.HDBC.SqlValue: instance Typeable LocalTime
+ Database.HDBC.SqlValue: instance Typeable SqlValue
+ Database.HDBC.SqlValue: instance Typeable TimeDiff
+ Database.HDBC.SqlValue: instance Typeable TimeOfDay
+ Database.HDBC.SqlValue: instance Typeable TimeZone
+ Database.HDBC.SqlValue: instance Typeable ZonedTime
+ Database.HDBC.SqlValue: nToSql :: (Integral a) => a -> SqlValue
+ Database.HDBC.SqlValue: posixToSql :: POSIXTime -> SqlValue
+ Database.HDBC.SqlValue: safeFromSql :: (Convertible SqlValue a) => SqlValue -> ConvertResult a
+ Database.HDBC.SqlValue: toSql :: (Convertible a SqlValue) => a -> SqlValue
+ Database.HDBC.Statement: SqlDiffTime :: NominalDiffTime -> SqlValue
+ Database.HDBC.Statement: SqlLocalDate :: Day -> SqlValue
+ Database.HDBC.Statement: SqlLocalTime :: LocalTime -> SqlValue
+ Database.HDBC.Statement: SqlLocalTimeOfDay :: TimeOfDay -> SqlValue
+ Database.HDBC.Statement: SqlPOSIXTime :: POSIXTime -> SqlValue
+ Database.HDBC.Statement: SqlUTCTime :: UTCTime -> SqlValue
+ Database.HDBC.Statement: SqlZonedLocalTimeOfDay :: TimeOfDay -> TimeZone -> SqlValue
+ Database.HDBC.Statement: SqlZonedTime :: ZonedTime -> SqlValue
+ Database.HDBC.Statement: instance Exception SqlError
+ Database.HDBC.Statement: posixToSql :: POSIXTime -> SqlValue
+ Database.HDBC.Statement: safeFromSql :: (Convertible SqlValue a) => SqlValue -> ConvertResult a
+ Database.HDBC.Types: SqlDiffTime :: NominalDiffTime -> SqlValue
+ Database.HDBC.Types: SqlLocalDate :: Day -> SqlValue
+ Database.HDBC.Types: SqlLocalTime :: LocalTime -> SqlValue
+ Database.HDBC.Types: SqlLocalTimeOfDay :: TimeOfDay -> SqlValue
+ Database.HDBC.Types: SqlPOSIXTime :: POSIXTime -> SqlValue
+ Database.HDBC.Types: SqlUTCTime :: UTCTime -> SqlValue
+ Database.HDBC.Types: SqlZonedLocalTimeOfDay :: TimeOfDay -> TimeZone -> SqlValue
+ Database.HDBC.Types: SqlZonedTime :: ZonedTime -> SqlValue
+ Database.HDBC.Types: posixToSql :: POSIXTime -> SqlValue
+ Database.HDBC.Types: safeFromSql :: (Convertible SqlValue a) => SqlValue -> ConvertResult a
- Database.HDBC: fromSql :: (SqlType a) => SqlValue -> a
+ Database.HDBC: fromSql :: (Convertible SqlValue a) => SqlValue -> a
- Database.HDBC: sqlExceptions :: Exception -> Maybe SqlError
+ Database.HDBC: sqlExceptions :: SqlError -> Maybe SqlError
- Database.HDBC: toSql :: (SqlType a) => a -> SqlValue
+ Database.HDBC: toSql :: (Convertible a SqlValue) => a -> SqlValue
- Database.HDBC.Statement: fromSql :: (SqlType a) => SqlValue -> a
+ Database.HDBC.Statement: fromSql :: (Convertible SqlValue a) => SqlValue -> a
- Database.HDBC.Statement: toSql :: (SqlType a) => a -> SqlValue
+ Database.HDBC.Statement: toSql :: (Convertible a SqlValue) => a -> SqlValue
- Database.HDBC.Types: fromSql :: (SqlType a) => SqlValue -> a
+ Database.HDBC.Types: fromSql :: (Convertible SqlValue a) => SqlValue -> a
- Database.HDBC.Types: toSql :: (SqlType a) => a -> SqlValue
+ Database.HDBC.Types: toSql :: (Convertible a SqlValue) => a -> SqlValue
Files
- COPYRIGHT +1/−1
- Database/HDBC.hs +15/−11
- Database/HDBC/ColTypes.hs +4/−2
- Database/HDBC/SqlValue.hs +920/−0
- Database/HDBC/Statement.hs +13/−378
- Database/HDBC/Types.hs +4/−3
- Database/HDBC/Utils.hs +51/−4
- HDBC.cabal +30/−10
COPYRIGHT view
@@ -1,4 +1,4 @@-Copyright (C) 2005-2008 John Goerzen <jgoerzen@complete.org>+Copyright (C) 2005-2009 John Goerzen <jgoerzen@complete.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
Database/HDBC.hs view
@@ -19,7 +19,7 @@ {- | Module : Database.HDBC- Copyright : Copyright (C) 2005-2007 John Goerzen+ Copyright : Copyright (C) 2005-2009 John Goerzen License : GNU LGPL, version 2.1 or above Maintainer : John Goerzen <jgoerzen@complete.org>@@ -42,8 +42,8 @@ -- $drivers -- * Typing of transfer data- SqlType(..), nToSql, iToSql, SqlValue(..),+ toSql, fromSql, safeFromSql, nToSql, iToSql, posixToSql, -- * Database Connections IConnection,@@ -78,6 +78,7 @@ -- * Exceptions SqlError(..),+ throwSqlError, catchSql, handleSql, sqlExceptions, handleSqlError, -- * Column Types@@ -102,7 +103,7 @@ quickQuery, fetchRowMap, fetchAllRowsMap, quickQuery', fetchAllRowsMap', fetchRowAL, fetchAllRowsAL,- fetchAllRowsAL')+ fetchAllRowsAL', throwSqlError) import Database.HDBC.Types import Database.HDBC.ColTypes @@ -158,22 +159,25 @@ {- $drivers -Here is a list of known drivers as of March 28, 2006:+Here is a list of known drivers as of January 26, 2009: [@Sqlite v3@] Available from <http://software.complete.org/hdbc-sqlite3>. Or, to participate in development, use -@darcs get --partial <http://darcs.complete.org/hdbc-sqlite3>@+@git clone <git://git.complete.org/hdbc-sqlite3>@ [@PostgreSQL@] Available from <http://software.complete.org/hdbc-postgresql>. Or, to participate in development, use-@darcs get --partial <http://darcs.complete.org/hdbc-postgresql>@+@git clone <git://git.complete.org/hdbc-postgresql>@ [@ODBC@] Available from <http://software.complete.org/hdbc-odbc>. Or, to partitipace in development, use-@darcs get --partial <http://darcs.complete.org/hdbc-odbc>@+@git clone <git://git.complete.org/hdbc-odbc>@ -[@MySQL@] MySQL users are encouraged to use the ODBC driver, which works-and has been tested against MySQL on both Linux\/Unix and Windows platforms.+[@MySQL@] MySQL users have two choices: the first is the ODBC driver, which works+and has been tested against MySQL on both Linux\/Unix and Windows platforms. There is+also an alpha-quality native MySQL driver available for download at+<http://hackage.haskell.org/cgi-bin/hackage-scripts/package/HDBC-mysql> with a homepage+at <http://www.maubi.net/~waterson/hacks/hdbc-mysql.html>. In addition, there is one integration package: /hdbc-anydbm/. This integrates with the AnyDBM library <http://software.complete.org/anydbm>.@@ -184,7 +188,7 @@ The latest version of HDBC itself is available from <http://software.complete.org/hdbc>. Or, to participate in development, use-@darcs get --partial <http://darcs.complete.org/hdbc>@.+@git clone <git://git.complete.org/hdbc>@. -} {- $transactions@@ -255,7 +259,7 @@ -} {- $legal-Copyright (C) 2005-2007 John Goerzen <jgoerzen@complete.org>+Copyright (C) 2005-2009 John Goerzen <jgoerzen@complete.org> This library is free software; you can redistribute it and\/or modify it under the terms of the GNU Lesser General Public
Database/HDBC/ColTypes.hs view
@@ -96,8 +96,10 @@ | SqlVarBinaryT -- ^ Variable-length binary data | SqlLongVarBinaryT -- ^ Variable-length binary data, max length implementation dependant | SqlDateT -- ^ A date- | SqlTimeT -- ^ A time- | SqlTimestampT -- ^ Combined date and time+ | SqlTimeT -- ^ A time, no timezone+ | SqlTimeWithZoneT -- ^ A time, with timezone+ | SqlTimestampT -- ^ Combined date and time, no timezone+ | SqlTimestampWithZoneT -- ^ Combined date and time, with timezone | SqlUTCDateTimeT -- ^ UTC date\/time | SqlUTCTimeT -- ^ UTC time | SqlIntervalT SqlInterval -- ^ A time or date difference
+ Database/HDBC/SqlValue.hs view
@@ -0,0 +1,920 @@+module Database.HDBC.SqlValue+ (+ -- * SQL value marshalling+ SqlValue(..),+ safeFromSql, toSql, fromSql,+ nToSql, iToSql, posixToSql+ )++where+import Data.Dynamic+import qualified Data.ByteString.UTF8 as BUTF8+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BSL+import Data.Char(ord,toUpper)+import Data.Word+import Data.Int+import qualified System.Time as ST+import Data.Time+import Data.Time.Clock+import Data.Time.Clock.POSIX+import System.Locale+import Data.Ratio+import Control.Monad.Error+import Data.Convertible++quickError :: (Typeable a, Convertible SqlValue a) => SqlValue -> ConvertResult a+quickError sv = convError "incompatible types" sv+ +{- | Convert a value to an 'SqlValue'. This function is simply+a restricted-type wrapper around 'convert'. See extended notes on 'SqlValue'. -}+toSql :: Convertible a SqlValue => a -> SqlValue+toSql = convert++{- | Conversions to and from 'SqlValue's and standard Haskell types.++This function converts from an 'SqlValue' to a Haskell value. Many people will use the simpler+ 'fromSql' instead. This function is simply a restricted-type wrapper around+ 'safeConvert'. -}+safeFromSql :: Convertible SqlValue a => SqlValue -> ConvertResult a+safeFromSql = safeConvert++{- | Convert from an 'SqlValue' to a Haskell value. Any problem is indicated by+ calling 'error'. This function is simply a restricted-type wrapper around+ 'convert'. See extended notes on 'SqlValue'. -}+fromSql :: Convertible SqlValue a => SqlValue -> a+fromSql = convert++{- | Converts any Integral type to a 'SqlValue' by using toInteger. -}+nToSql :: Integral a => a -> SqlValue+nToSql n = SqlInteger (toInteger n)++{- | Convenience function for using numeric literals in your program. -}+iToSql :: Int -> SqlValue+iToSql = toSql++{- | Convenience function for converting 'POSIXTime' to a 'SqlValue', because+'toSql' cannot do the correct thing in this instance. -}+posixToSql :: POSIXTime -> SqlValue+posixToSql x = SqlPOSIXTime x++{- | 'SqlValue' is he main type for expressing Haskell values to SQL databases.++/INTRODUCTION TO SQLVALUE/++This type is used to marshall Haskell data to and from database APIs.+HDBC driver interfaces will do their best to use the most accurate and+efficient way to send a particular value to the database server.++Values read back from the server are constructed with the most appropriate 'SqlValue'+constructor. 'fromSql' or 'safeFromSql' +can then be used to convert them into whatever type+is needed locally in Haskell.++Most people will use 'toSql' and 'fromSql' instead of manipulating+'SqlValue's directly.++/EASY CONVERSIONS BETWEEN HASKELL TYPES/++Conversions are powerful; for instance, you can call 'fromSql' on a SqlInt32+and get a String or a Double out of it. This class attempts to Do+The Right Thing whenever possible, and will raise an error when asked to+do something incorrect. In particular, when converting to any type+except a Maybe, 'SqlNull' as the input will cause an error to be raised.++Conversions are implemented in terms of the "Data.Convertible" module, part of the+convertible package. You can refer to its documentation, and import that module,+if you wish to parse the Left result from 'safeFromSql' yourself, or write your+own conversion instances.++Here are some notes about conversion:++ * Fractions of a second are not preserved on time values++ * There is no @safeToSql@ because 'toSql' never fails.++See also 'toSql', 'safeFromSql', 'fromSql', 'nToSql', 'iToSql', 'posixToSql'.++/ERROR CONDITIONS/++There may sometimes be an error during conversion. For instance, if you have a+'SqlString' and are attempting to convert it to an Integer, but it doesn't parse as+an Integer, you will get an error. This will be indicated as an exception if using+'fromSql', or a Left result if using 'safeFromSql'.++/SPECIAL NOTE ON POSIXTIME/++Note that a 'NominalDiffTime' or 'POSIXTime' is converted to 'SqlDiffTime' by+'toSql'. HDBC cannot differentiate between 'NominalDiffTime' and 'POSIXTime'+since they are the same underlying type. You must construct 'SqlPOSIXTime'+manually or via 'posixToSql', or use 'SqlUTCTime'.++/DETAILS ON SQL TYPES/++HDBC database backends are expected to marshal date and time data back and+forth using the appropriate representation for the underlying database engine.+Databases such as PostgreSQL with builtin date and time types should see automatic+conversion between these Haskell types to database types. Other databases will be+presented with an integer or a string. Care should be taken to use the same type on+the Haskell side as you use on the database side. For instance, if your database+type lacks timezone information, you ought not to use ZonedTime, but+instead LocalTime or UTCTime. Database type systems are not always as rich+as Haskell. For instance, for data stored in a TIMESTAMP+WITHOUT TIME ZONE column, HDBC may not be able to tell if it is intended+as UTCTime or LocalTime data, and will happily convert it to both, +upon your request. It is+your responsibility to ensure that you treat timezone issues with due care.++This behavior also exists for other types. For instance, many databases do not+have a Rational type, so they will just use the show function and+store a Rational as a string.++The conversion between Haskell types and database types is complex,+and generic code in HDBC or its backends cannot possibly accomodate+every possible situation. In some cases, you may be best served by converting your+Haskell type to a String, and passing that to the database.++/UNICODE AND BYTESTRINGS/++Beginning with HDBC v2.0, interactions with a database are presumed to occur in UTF-8.++To accomplish this, whenever a ByteString must be converted to or from a String,+the ByteString is assumed to be in UTF-8 encoding, and will be decoded or encoded+as appropriate. Database drivers will generally present text or string data they have+received from the database as a SqlValue holding a ByteString, which 'fromSql' will+automatically convert to a String, and thus automatically decode UTF-8, when+you need it. In the other direction, database drivers will generally convert+a 'SqlString' to a ByteString in UTF-8 encoding before passing it to the+database engine.++If you are handling some sort of binary data that is not in UTF-8, you can of course+work with the ByteString directly, which will bypass any conversion.++Due to lack of support by database engines, lazy ByteStrings are not passed to database+drivers. When you use 'toSql' on a lazy ByteString, it will be converted to a strict+ByteString for storage. Similarly, 'fromSql' will convert a strict ByteString to+a lazy ByteString if you demand it.++/EQUALITY OF SQLVALUE/++Two SqlValues are considered to be equal if one of these hold. The+first comparison that can be made is controlling; if none of these+comparisons can be made, then they are not equal:++ * Both are NULL++ * Both represent the same type and the encapsulated values are considered equal+ by applying (==) to them++ * The values of each, when converted to a string, are equal.++/STRING VERSIONS OF TIMES/++Default string representations are given as comments below where such are non-obvious.+These are used for 'fromSql' when a 'String' is desired. They are also defaults for+representing data to SQL backends, though individual backends may override them+when a different format is demanded by the underlying database. Date and time formats+use ISO8601 date format, with HH:MM:SS added for time, and -HHMM added for timezone+offsets.++/DEPRECATED CONSTRUCTORS/++'SqlEpochTime' and 'SqlTimeDiff' are no longer created automatically by any+'toSql' or 'fromSql' functions or database backends. They may still be manually+constructed, but are+expected to be removed in a future version. Although these two constructures will+be removed, support for marshalling to and from the old System.Time data will be+maintained as long as System.Time is, simply using the newer data types for conversion.+-}+data SqlValue = SqlString String + | SqlByteString B.ByteString+ | SqlWord32 Word32+ | SqlWord64 Word64+ | SqlInt32 Int32+ | SqlInt64 Int64+ | SqlInteger Integer+ | SqlChar Char+ | SqlBool Bool+ | SqlDouble Double+ | SqlRational Rational+ | SqlLocalDate Day -- ^ Local YYYY-MM-DD (no timezone)+ | SqlLocalTimeOfDay TimeOfDay -- ^ Local HH:MM:SS (no timezone)+ | SqlZonedLocalTimeOfDay TimeOfDay TimeZone -- ^ Local HH:MM:SS -HHMM. Converts to and from (TimeOfDay, TimeZone).+ | SqlLocalTime LocalTime -- ^ Local YYYY-MM-DD HH:MM:SS (no timezone)+ | SqlZonedTime ZonedTime -- ^ Local YYYY-MM-DD HH:MM:SS -HHMM. Considered equal if both convert to the same UTC time.+ | SqlUTCTime UTCTime -- ^ UTC YYYY-MM-DD HH:MM:SS+ | SqlDiffTime NominalDiffTime -- ^ Calendar diff between seconds. Rendered as Integer when converted to String, but greater precision may be preserved for other types or to underlying database.+ | SqlPOSIXTime POSIXTime -- ^ Time as seconds since midnight Jan 1 1970 UTC. Integer rendering as for 'SqlDiffTime'.+ | SqlEpochTime Integer -- ^ DEPRECATED Representation of ClockTime or CalendarTime. Use SqlPOSIXTime instead.+ | SqlTimeDiff Integer -- ^ DEPRECATED Representation of TimeDiff. Use SqlDiffTime instead.+ | SqlNull -- ^ NULL in SQL or Nothing in Haskell+ deriving (Show)++instance Typeable SqlValue where+ typeOf _ = mkTypeName "SqlValue"++instance Eq SqlValue where+ SqlString a == SqlString b = a == b+ SqlByteString a == SqlByteString b = a == b+ SqlWord32 a == SqlWord32 b = a == b+ SqlWord64 a == SqlWord64 b = a == b+ SqlInt32 a == SqlInt32 b = a == b+ SqlInt64 a == SqlInt64 b = a == b+ SqlInteger a == SqlInteger b = a == b+ SqlChar a == SqlChar b = a == b+ SqlBool a == SqlBool b = a == b+ SqlDouble a == SqlDouble b = a == b+ SqlRational a == SqlRational b = a == b+ SqlLocalTimeOfDay a == SqlLocalTimeOfDay b = a == b+ SqlZonedLocalTimeOfDay a b == SqlZonedLocalTimeOfDay c d = a == c && b == d+ SqlLocalTime a == SqlLocalTime b = a == b+ SqlLocalDate a == SqlLocalDate b = a == b+ SqlZonedTime a == SqlZonedTime b = zonedTimeToUTC a == zonedTimeToUTC b+ SqlUTCTime a == SqlUTCTime b = a == b+ SqlPOSIXTime a == SqlPOSIXTime b = a == b+ SqlDiffTime a == SqlDiffTime b = a == b+ SqlEpochTime a == SqlEpochTime b = a == b+ SqlTimeDiff a == SqlTimeDiff b = a == b+ SqlNull == SqlNull = True+ SqlNull == _ = False+ _ == SqlNull = False+ a == b = ((safeFromSql a)::ConvertResult String) == + ((safeFromSql b)::ConvertResult String)++instance Convertible String SqlValue where+ safeConvert = return . SqlString+instance Convertible SqlValue String where+ safeConvert (SqlString x) = return x+ safeConvert (SqlByteString x) = return . BUTF8.toString $ x+ safeConvert (SqlInt32 x) = return . show $ x+ safeConvert (SqlInt64 x) = return . show $ x+ safeConvert (SqlWord32 x) = return . show $ x+ safeConvert (SqlWord64 x) = return . show $ x+ safeConvert (SqlInteger x) = return . show $ x+ safeConvert (SqlChar x) = return [x]+ safeConvert (SqlBool x) = return . show $ x+ safeConvert (SqlDouble x) = return . show $ x+ safeConvert (SqlRational x) = return . show $ x+ safeConvert (SqlLocalDate x) = + return . formatTime defaultTimeLocale (iso8601DateFormat Nothing) $ x+ safeConvert (SqlLocalTimeOfDay x) = + return . formatTime defaultTimeLocale "%T" $ x+ safeConvert (SqlZonedLocalTimeOfDay tod tz) = + return $ formatTime defaultTimeLocale "%T " tod +++ formatTime defaultTimeLocale "%z" tz+ safeConvert (SqlLocalTime x) = + return . formatTime defaultTimeLocale (iso8601DateFormat (Just "%T")) $ x+ safeConvert (SqlZonedTime x) = + return . formatTime defaultTimeLocale (iso8601DateFormat (Just "%T %z")) $ x+ safeConvert (SqlUTCTime x) = + return . formatTime defaultTimeLocale (iso8601DateFormat (Just "%T")) $ x+ safeConvert (SqlDiffTime x) = return $ show ((truncate x)::Integer)+ safeConvert (SqlPOSIXTime x) = return $ show ((truncate x)::Integer)+ safeConvert (SqlEpochTime x) = return . show $ x+ safeConvert (SqlTimeDiff x) = return . show $ x+ safeConvert y@(SqlNull) = quickError y++#ifdef __HUGS__+instance Typeable B.ByteString where+ typeOf _ = mkTypeName "ByteString"+#endif++instance Convertible B.ByteString SqlValue where+ safeConvert = return . SqlByteString+instance Convertible SqlValue B.ByteString where+ safeConvert (SqlByteString x) = return x+ safeConvert y@(SqlNull) = quickError y+ safeConvert x = safeConvert x >>= return . BUTF8.fromString++instance Convertible BSL.ByteString SqlValue where+ safeConvert = return . SqlByteString . B.concat . BSL.toChunks+instance Convertible SqlValue BSL.ByteString where+ safeConvert x = do bs <- safeConvert x+ return (BSL.fromChunks [bs])++instance Convertible Int SqlValue where+ safeConvert x = + do i <- ((safeConvert x)::ConvertResult Int32)+ return $ SqlInt32 i+instance Convertible SqlValue Int where+ safeConvert (SqlString x) = read' x+ safeConvert (SqlByteString x) = (read' . BUTF8.toString) x+ safeConvert (SqlInt32 x) = safeConvert x+ safeConvert (SqlInt64 x) = safeConvert x+ safeConvert (SqlWord32 x) = safeConvert x+ safeConvert (SqlWord64 x) = safeConvert x+ safeConvert (SqlInteger x) = safeConvert x+ safeConvert (SqlChar x) = safeConvert x+ safeConvert (SqlBool x) = return (if x then 1 else 0)+ safeConvert (SqlDouble x) = safeConvert x+ safeConvert (SqlRational x) = safeConvert x+ safeConvert y@(SqlLocalDate _) = viaInteger y fromIntegral+ safeConvert y@(SqlLocalTimeOfDay _) = viaInteger y fromIntegral + safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = viaInteger y fromIntegral + safeConvert y@(SqlZonedTime _) = viaInteger y fromIntegral+ safeConvert (SqlUTCTime x) = safeConvert x+ safeConvert (SqlDiffTime x) = safeConvert x+ safeConvert (SqlPOSIXTime x) = safeConvert x+ safeConvert (SqlEpochTime x) = safeConvert x+ safeConvert (SqlTimeDiff x) = safeConvert x+ safeConvert y@(SqlNull) = quickError y++instance Convertible Int32 SqlValue where+ safeConvert = return . SqlInt32+instance Convertible SqlValue Int32 where+ safeConvert (SqlString x) = read' x+ safeConvert (SqlByteString x) = (read' . BUTF8.toString) x+ safeConvert (SqlInt32 x) = return x+ safeConvert (SqlInt64 x) = safeConvert x+ safeConvert (SqlWord32 x) = safeConvert x+ safeConvert (SqlWord64 x) = safeConvert x+ safeConvert (SqlInteger x) = safeConvert x+ safeConvert (SqlChar x) = safeConvert x+ safeConvert (SqlBool x) = return (if x then 1 else 0)+ safeConvert (SqlDouble x) = safeConvert x+ safeConvert (SqlRational x) = safeConvert x+ safeConvert y@(SqlLocalDate _) = viaInteger y fromIntegral+ safeConvert y@(SqlLocalTimeOfDay _) = viaInteger y fromIntegral+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlZonedTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlUTCTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlDiffTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlPOSIXTime _) = viaInteger y fromIntegral+ safeConvert (SqlEpochTime x) = safeConvert x+ safeConvert (SqlTimeDiff x) = safeConvert x+ safeConvert y@(SqlNull) = quickError y++instance Convertible Int64 SqlValue where+ safeConvert = return . SqlInt64+instance Convertible SqlValue Int64 where+ safeConvert (SqlString x) = read' x+ safeConvert (SqlByteString x) = (read' . BUTF8.toString) x+ safeConvert (SqlInt32 x) = safeConvert x+ safeConvert (SqlInt64 x) = return x+ safeConvert (SqlWord32 x) = safeConvert x+ safeConvert (SqlWord64 x) = safeConvert x+ safeConvert (SqlInteger x) = safeConvert x+ safeConvert (SqlChar x) = safeConvert x+ safeConvert (SqlBool x) = return (if x then 1 else 0)+ safeConvert (SqlDouble x) = safeConvert x+ safeConvert (SqlRational x) = safeConvert x+ safeConvert y@(SqlLocalDate _) = viaInteger y fromIntegral+ safeConvert y@(SqlLocalTimeOfDay _) = viaInteger y fromIntegral+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlZonedTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlUTCTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlDiffTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlPOSIXTime _) = viaInteger y fromIntegral+ safeConvert (SqlEpochTime x) = safeConvert x+ safeConvert (SqlTimeDiff x) = safeConvert x+ safeConvert y@(SqlNull) = quickError y++instance Convertible Word32 SqlValue where+ safeConvert = return . SqlWord32+instance Convertible SqlValue Word32 where+ safeConvert (SqlString x) = read' x+ safeConvert (SqlByteString x) = (read' . BUTF8.toString) x+ safeConvert (SqlInt32 x) = safeConvert x+ safeConvert (SqlInt64 x) = safeConvert x+ safeConvert (SqlWord32 x) = return x+ safeConvert (SqlWord64 x) = safeConvert x+ safeConvert (SqlInteger x) = safeConvert x+ safeConvert (SqlChar x) = safeConvert x+ safeConvert (SqlBool x) = return (if x then 1 else 0)+ safeConvert (SqlDouble x) = safeConvert x+ safeConvert (SqlRational x) = safeConvert x+ safeConvert y@(SqlLocalDate _) = viaInteger y fromIntegral+ safeConvert y@(SqlLocalTimeOfDay _) = viaInteger y fromIntegral+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlZonedTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlUTCTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlDiffTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlPOSIXTime _) = viaInteger y fromIntegral+ safeConvert (SqlEpochTime x) = safeConvert x+ safeConvert (SqlTimeDiff x) = safeConvert x+ safeConvert y@(SqlNull) = quickError y++instance Convertible Word64 SqlValue where+ safeConvert = return . SqlWord64+instance Convertible SqlValue Word64 where+ safeConvert (SqlString x) = read' x+ safeConvert (SqlByteString x) = (read' . BUTF8.toString) x+ safeConvert (SqlInt32 x) = safeConvert x+ safeConvert (SqlInt64 x) = safeConvert x+ safeConvert (SqlWord32 x) = safeConvert x+ safeConvert (SqlWord64 x) = return x+ safeConvert (SqlInteger x) = safeConvert x+ safeConvert (SqlChar x) = safeConvert x+ safeConvert (SqlBool x) = return (if x then 1 else 0)+ safeConvert (SqlDouble x) = safeConvert x+ safeConvert (SqlRational x) = safeConvert x+ safeConvert y@(SqlLocalDate _) = viaInteger y fromIntegral+ safeConvert y@(SqlLocalTimeOfDay _) = viaInteger y fromIntegral+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlZonedTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlUTCTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlDiffTime _) = viaInteger y fromIntegral+ safeConvert y@(SqlPOSIXTime _) = viaInteger y fromIntegral+ safeConvert (SqlEpochTime x) = safeConvert x+ safeConvert (SqlTimeDiff x) = safeConvert x+ safeConvert y@(SqlNull) = quickError y++instance Convertible Integer SqlValue where+ safeConvert = return . SqlInteger+instance Convertible SqlValue Integer where+ safeConvert (SqlString x) = read' x+ safeConvert (SqlByteString x) = (read' . BUTF8.toString) x+ safeConvert (SqlInt32 x) = safeConvert x+ safeConvert (SqlInt64 x) = safeConvert x+ safeConvert (SqlWord32 x) = safeConvert x+ safeConvert (SqlWord64 x) = safeConvert x+ safeConvert (SqlInteger x) = return x+ safeConvert (SqlChar x) = safeConvert x+ safeConvert (SqlBool x) = return (if x then 1 else 0)+ safeConvert (SqlDouble x) = safeConvert x+ safeConvert (SqlRational x) = safeConvert x+ safeConvert (SqlLocalDate x) = return . toModifiedJulianDay $ x+ safeConvert (SqlLocalTimeOfDay x) = + return . fromIntegral . fromEnum . timeOfDayToTime $ x+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = quickError y+ safeConvert (SqlZonedTime x) = + return . truncate . utcTimeToPOSIXSeconds . zonedTimeToUTC $ x+ safeConvert (SqlUTCTime x) = safeConvert x+ safeConvert (SqlDiffTime x) = safeConvert x+ safeConvert (SqlPOSIXTime x) = safeConvert x+ safeConvert (SqlEpochTime x) = return x+ safeConvert (SqlTimeDiff x) = return x+ safeConvert y@(SqlNull) = quickError y++instance Convertible Bool SqlValue where+ safeConvert = return . SqlBool+instance Convertible SqlValue Bool where+ safeConvert y@(SqlString x) = + case map toUpper x of+ "TRUE" -> Right True+ "T" -> Right True+ "FALSE" -> Right False+ "F" -> Right False+ "0" -> Right False+ "1" -> Right True+ _ -> convError "Cannot parse given String as Bool" y+ safeConvert (SqlByteString x) = (safeConvert . SqlString . BUTF8.toString) x+ safeConvert (SqlInt32 x) = numToBool x+ safeConvert (SqlInt64 x) = numToBool x+ safeConvert (SqlWord32 x) = numToBool x+ safeConvert (SqlWord64 x) = numToBool x+ safeConvert (SqlInteger x) = numToBool x+ safeConvert (SqlChar x) = numToBool (ord x)+ safeConvert (SqlBool x) = return x+ safeConvert (SqlDouble x) = numToBool x+ safeConvert (SqlRational x) = numToBool x+ safeConvert y@(SqlLocalDate _) = quickError y+ safeConvert y@(SqlLocalTimeOfDay _) = quickError y+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = quickError y+ safeConvert y@(SqlZonedTime _) = quickError y+ safeConvert y@(SqlUTCTime _) = quickError y+ safeConvert y@(SqlDiffTime _) = quickError y+ safeConvert y@(SqlPOSIXTime _) = quickError y+ safeConvert (SqlEpochTime x) = numToBool x+ safeConvert (SqlTimeDiff x) = numToBool x+ safeConvert y@(SqlNull) = quickError y++numToBool :: Num a => a -> ConvertResult Bool+numToBool x = Right (x /= 0)++instance Convertible Char SqlValue where+ safeConvert = return . SqlChar+instance Convertible SqlValue Char where+ safeConvert (SqlString [x]) = return x+ safeConvert y@(SqlString _) = convError "String length /= 1" y+ safeConvert y@(SqlByteString x) = + case B.length x of+ 1 -> safeConvert . SqlString . BUTF8.toString $ x+ _ -> convError "ByteString length /= 1" y+ safeConvert y@(SqlInt32 _) = quickError y+ safeConvert y@(SqlInt64 _) = quickError y+ safeConvert y@(SqlWord32 _) = quickError y+ safeConvert y@(SqlWord64 _) = quickError y+ safeConvert y@(SqlInteger _) = quickError y+ safeConvert (SqlChar x) = return x+ safeConvert (SqlBool x) = return (if x then '1' else '0')+ safeConvert y@(SqlDouble _) = quickError y+ safeConvert y@(SqlRational _) = quickError y+ safeConvert y@(SqlLocalDate _) = quickError y+ safeConvert y@(SqlLocalTimeOfDay _) = quickError y+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = quickError y+ safeConvert y@(SqlZonedTime _) = quickError y+ safeConvert y@(SqlUTCTime _) = quickError y+ safeConvert y@(SqlDiffTime _) = quickError y+ safeConvert y@(SqlPOSIXTime _) = quickError y+ safeConvert y@(SqlEpochTime _) = quickError y+ safeConvert y@(SqlTimeDiff _) = quickError y+ safeConvert y@(SqlNull) = quickError y++instance Convertible Double SqlValue where+ safeConvert = return . SqlDouble+instance Convertible SqlValue Double where+ safeConvert (SqlString x) = read' x+ safeConvert (SqlByteString x) = (read' . BUTF8.toString) x+ safeConvert (SqlInt32 x) = safeConvert x+ safeConvert (SqlInt64 x) = safeConvert x+ safeConvert (SqlWord32 x) = safeConvert x+ safeConvert (SqlWord64 x) = safeConvert x+ safeConvert (SqlInteger x) = safeConvert x+ safeConvert (SqlChar x) = return . fromIntegral . fromEnum $ x+ safeConvert (SqlBool x) = return (if x then 1.0 else 0.0)+ safeConvert (SqlDouble x) = return x+ safeConvert (SqlRational x) = safeConvert x+ safeConvert y@(SqlLocalDate _) = ((safeConvert y)::ConvertResult Integer) >>= + (return . fromIntegral)+ safeConvert (SqlLocalTimeOfDay x) = + return . fromRational . toRational . timeOfDayToTime $ x+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = quickError y+ safeConvert (SqlZonedTime x) = + safeConvert . SqlUTCTime . zonedTimeToUTC $ x+ safeConvert (SqlUTCTime x) = + return . fromRational . toRational . utcTimeToPOSIXSeconds $ x+ safeConvert (SqlDiffTime x) = safeConvert x+ safeConvert (SqlPOSIXTime x) = safeConvert x+ safeConvert (SqlEpochTime x) = safeConvert x+ safeConvert (SqlTimeDiff x) = safeConvert x+ safeConvert y@(SqlNull) = quickError y++instance Convertible Rational SqlValue where+ safeConvert = return . SqlRational+instance Convertible SqlValue Rational where+ safeConvert (SqlString x) = read' x+ safeConvert (SqlByteString x) = (read' . BUTF8.toString) x+ safeConvert (SqlInt32 x) = safeConvert x+ safeConvert (SqlInt64 x) = safeConvert x+ safeConvert (SqlWord32 x) = safeConvert x+ safeConvert (SqlWord64 x) = safeConvert x+ safeConvert (SqlInteger x) = safeConvert x+ safeConvert (SqlChar x) = return . fromIntegral . fromEnum $ x+ safeConvert (SqlBool x) = return $ if x then fromIntegral (1::Int) + else fromIntegral (0::Int)+ safeConvert (SqlDouble x) = safeConvert x+ safeConvert (SqlRational x) = return x+ safeConvert y@(SqlLocalDate _) = ((safeConvert y)::ConvertResult Integer) >>= + (return . fromIntegral)+ safeConvert (SqlLocalTimeOfDay x) = return . toRational . timeOfDayToTime $ x+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = quickError y+ safeConvert (SqlZonedTime x) = safeConvert . SqlUTCTime . zonedTimeToUTC $ x+ safeConvert (SqlUTCTime x) = safeConvert x+ safeConvert (SqlDiffTime x) = safeConvert x+ safeConvert (SqlPOSIXTime x) = safeConvert x+ safeConvert (SqlEpochTime x) = return . fromIntegral $ x+ safeConvert (SqlTimeDiff x) = return . fromIntegral $ x+ safeConvert y@(SqlNull) = quickError y++instance Typeable Day where+ typeOf _ = mkTypeName "Day"+instance Typeable TimeOfDay where+ typeOf _ = mkTypeName "TimeOfDay"+instance Typeable LocalTime where+ typeOf _ = mkTypeName "LocalTime"+instance Typeable ZonedTime where+ typeOf _ = mkTypeName "ZonedTime"+instance Typeable ST.ClockTime where+ typeOf _ = mkTypeName "ClockTime"+instance Typeable ST.TimeDiff where+ typeOf _ = mkTypeName "TimeDiff"+instance Typeable DiffTime where+ typeOf _ = mkTypeName "DiffTime"+instance Typeable TimeZone where+ typeOf _ = mkTypeName "TimeZone"++instance Convertible Day SqlValue where+ safeConvert = return . SqlLocalDate+instance Convertible SqlValue Day where+ safeConvert (SqlString x) = parseTime' (iso8601DateFormat Nothing) x+ safeConvert (SqlByteString x) = safeConvert (SqlString (BUTF8.toString x))+ safeConvert (SqlInt32 x) = + return $ ModifiedJulianDay {toModifiedJulianDay = fromIntegral x}+ safeConvert (SqlInt64 x) = + return $ ModifiedJulianDay {toModifiedJulianDay = fromIntegral x}+ safeConvert (SqlWord32 x) = + return $ ModifiedJulianDay {toModifiedJulianDay = fromIntegral x}+ safeConvert (SqlWord64 x) = + return $ ModifiedJulianDay {toModifiedJulianDay = fromIntegral x}+ safeConvert (SqlInteger x) = + return $ ModifiedJulianDay {toModifiedJulianDay = x}+ safeConvert y@(SqlChar _) = quickError y+ safeConvert y@(SqlBool _) = quickError y+ safeConvert (SqlDouble x) = + return $ ModifiedJulianDay {toModifiedJulianDay = truncate x}+ safeConvert (SqlRational x) = safeConvert . SqlDouble . fromRational $ x+ safeConvert (SqlLocalDate x) = return x+ safeConvert y@(SqlLocalTimeOfDay _) = quickError y+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert (SqlLocalTime x) = return . localDay $ x+ safeConvert y@(SqlZonedTime _) = safeConvert y >>= return . localDay+ safeConvert y@(SqlUTCTime _) = safeConvert y >>= return . localDay+ safeConvert y@(SqlDiffTime _) = quickError y+ safeConvert y@(SqlPOSIXTime _) = safeConvert y >>= return . localDay+ safeConvert y@(SqlEpochTime _) = safeConvert y >>= return . localDay+ safeConvert y@(SqlTimeDiff _) = quickError y+ safeConvert y@(SqlNull) = quickError y++instance Convertible TimeOfDay SqlValue where+ safeConvert = return . SqlLocalTimeOfDay+instance Convertible SqlValue TimeOfDay where+ safeConvert (SqlString x) = parseTime' "%T" x+ safeConvert (SqlByteString x) = safeConvert (SqlString (BUTF8.toString x))+ safeConvert (SqlInt32 x) = return . timeToTimeOfDay . fromIntegral $ x+ safeConvert (SqlInt64 x) = return . timeToTimeOfDay . fromIntegral $ x+ safeConvert (SqlWord32 x) = return . timeToTimeOfDay . fromIntegral $ x+ safeConvert (SqlWord64 x) = return . timeToTimeOfDay . fromIntegral $ x+ safeConvert (SqlInteger x) = return . timeToTimeOfDay . fromInteger $ x+ safeConvert y@(SqlChar _) = quickError y+ safeConvert y@(SqlBool _) = quickError y+ safeConvert (SqlDouble x) = + return . timeToTimeOfDay . fromIntegral $ ((truncate x)::Integer)+ safeConvert (SqlRational x) = safeConvert . SqlDouble . fromRational $ x+ safeConvert y@(SqlLocalDate _) = quickError y+ safeConvert (SqlLocalTimeOfDay x) = return x+ safeConvert (SqlZonedLocalTimeOfDay tod _) = return tod+ safeConvert (SqlLocalTime x) = return . localTimeOfDay $ x+ safeConvert y@(SqlZonedTime _) = safeConvert y >>= return . localTimeOfDay+ safeConvert y@(SqlUTCTime _) = safeConvert y >>= return . localTimeOfDay+ safeConvert y@(SqlDiffTime _) = quickError y+ safeConvert y@(SqlPOSIXTime _) = safeConvert y >>= return . localTimeOfDay+ safeConvert y@(SqlEpochTime _) = safeConvert y >>= return . localTimeOfDay+ safeConvert y@(SqlTimeDiff _) = quickError y+ safeConvert y@SqlNull = quickError y++instance Convertible (TimeOfDay, TimeZone) SqlValue where+ safeConvert (tod, tz) = return (SqlZonedLocalTimeOfDay tod tz)+instance Convertible SqlValue (TimeOfDay, TimeZone) where+ safeConvert (SqlString x) = + do tod <- parseTime' "%T %z" x+ tz <- case parseTime defaultTimeLocale "%T %z" x of+ Nothing -> convError "Couldn't extract timezone in" (SqlString x)+ Just y -> Right y+ return (tod, tz)+ safeConvert (SqlByteString x) = safeConvert (SqlString (BUTF8.toString x))+ safeConvert y@(SqlInt32 _) = quickError y+ safeConvert y@(SqlInt64 _) = quickError y+ safeConvert y@(SqlWord32 _) = quickError y+ safeConvert y@(SqlWord64 _) = quickError y+ safeConvert y@(SqlInteger _) = quickError y+ safeConvert y@(SqlChar _) = quickError y+ safeConvert y@(SqlBool _) = quickError y+ safeConvert y@(SqlDouble _) = quickError y+ safeConvert y@(SqlRational _) = quickError y+ safeConvert y@(SqlLocalDate _) = quickError y+ safeConvert y@(SqlLocalTimeOfDay _) = quickError y+ safeConvert (SqlZonedLocalTimeOfDay x y) = return (x, y)+ safeConvert y@(SqlLocalTime _) = quickError y+ safeConvert (SqlZonedTime x) = return (localTimeOfDay . zonedTimeToLocalTime $ x,+ zonedTimeZone x)+ safeConvert y@(SqlUTCTime _) = quickError y+ safeConvert y@(SqlDiffTime _) = quickError y+ safeConvert y@(SqlPOSIXTime _) = quickError y+ safeConvert y@(SqlEpochTime _) = quickError y+ safeConvert y@(SqlTimeDiff _) = quickError y+ safeConvert y@SqlNull = quickError y++instance Convertible LocalTime SqlValue where+ safeConvert = return . SqlLocalTime+instance Convertible SqlValue LocalTime where+ safeConvert (SqlString x) = parseTime' (iso8601DateFormat (Just "%T")) x+ safeConvert (SqlByteString x) = safeConvert (SqlString (BUTF8.toString x))+ safeConvert y@(SqlInt32 _) = quickError y+ safeConvert y@(SqlInt64 _) = quickError y+ safeConvert y@(SqlWord32 _) = quickError y+ safeConvert y@(SqlWord64 _) = quickError y+ safeConvert y@(SqlInteger _) = quickError y+ safeConvert y@(SqlChar _) = quickError y+ safeConvert y@(SqlBool _) = quickError y+ safeConvert y@(SqlDouble _) = quickError y+ safeConvert y@(SqlRational _) = quickError y+ safeConvert y@(SqlLocalDate _) = quickError y+ safeConvert y@(SqlLocalTimeOfDay _) = quickError y+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert (SqlLocalTime x) = return x+ safeConvert (SqlZonedTime x) = return . zonedTimeToLocalTime $ x+ safeConvert y@(SqlUTCTime _) = safeConvert y >>= return . zonedTimeToLocalTime+ safeConvert y@(SqlDiffTime _) = quickError y+ safeConvert y@(SqlPOSIXTime _) = safeConvert y >>= return . zonedTimeToLocalTime+ safeConvert y@(SqlEpochTime _) = safeConvert y >>= return . zonedTimeToLocalTime+ safeConvert y@(SqlTimeDiff _) = quickError y+ safeConvert y@SqlNull = quickError y++instance Convertible ZonedTime SqlValue where+ safeConvert = return . SqlZonedTime+instance Convertible SqlValue ZonedTime where+ safeConvert (SqlString x) = parseTime' (iso8601DateFormat (Just "%T %z")) x+ safeConvert (SqlByteString x) = safeConvert (SqlString (BUTF8.toString x))+ safeConvert (SqlInt32 x) = safeConvert (SqlInteger (fromIntegral x))+ safeConvert (SqlInt64 x) = safeConvert (SqlInteger (fromIntegral x))+ safeConvert (SqlWord32 x) = safeConvert (SqlInteger (fromIntegral x))+ safeConvert (SqlWord64 x) = safeConvert (SqlInteger (fromIntegral x))+ safeConvert y@(SqlInteger _) = safeConvert y >>= return . utcToZonedTime utc+ safeConvert y@(SqlChar _) = quickError y+ safeConvert y@(SqlBool _) = quickError y+ safeConvert y@(SqlDouble _) = safeConvert y >>= return . utcToZonedTime utc+ safeConvert y@(SqlRational _) = safeConvert y >>= return . utcToZonedTime utc+ safeConvert y@(SqlLocalDate _) = quickError y+ safeConvert y@(SqlLocalTime _) = quickError y+ safeConvert y@(SqlLocalTimeOfDay _) = quickError y+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert (SqlZonedTime x) = return x+ safeConvert (SqlUTCTime x) = return . utcToZonedTime utc $ x+ safeConvert y@(SqlDiffTime _) = quickError y+ safeConvert y@(SqlPOSIXTime _) = safeConvert y >>= return . utcToZonedTime utc+ safeConvert y@(SqlEpochTime _) = safeConvert y >>= return . utcToZonedTime utc+ safeConvert y@(SqlTimeDiff _) = quickError y+ safeConvert y@SqlNull = quickError y++instance Convertible UTCTime SqlValue where+ safeConvert = return . SqlUTCTime+instance Convertible SqlValue UTCTime where+ safeConvert (SqlString x) = parseTime' (iso8601DateFormat (Just "%T")) x+ safeConvert (SqlByteString x) = safeConvert (SqlString (BUTF8.toString x))+ safeConvert y@(SqlInt32 _) = safeConvert y >>= return . posixSecondsToUTCTime+ safeConvert y@(SqlInt64 _) = safeConvert y >>= return . posixSecondsToUTCTime+ safeConvert y@(SqlWord32 _) = safeConvert y >>= return . posixSecondsToUTCTime+ safeConvert y@(SqlWord64 _) = safeConvert y >>= return . posixSecondsToUTCTime+ safeConvert y@(SqlInteger _) = safeConvert y >>= return . posixSecondsToUTCTime+ safeConvert y@(SqlChar _) = quickError y+ safeConvert y@(SqlBool _) = quickError y+ safeConvert y@(SqlDouble _) = safeConvert y >>= return . posixSecondsToUTCTime+ safeConvert y@(SqlRational _) = safeConvert y >>= return . posixSecondsToUTCTime+ safeConvert y@(SqlLocalDate _) = quickError y+ safeConvert y@(SqlLocalTimeOfDay _) = quickError y+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = quickError y+ safeConvert (SqlZonedTime x) = return . zonedTimeToUTC $ x+ safeConvert (SqlUTCTime x) = return x+ safeConvert y@(SqlDiffTime _) = convError "incompatible types (did you mean SqlPOSIXTime?)" y+ safeConvert (SqlPOSIXTime x) = return . posixSecondsToUTCTime $ x+ safeConvert y@(SqlEpochTime _) = safeConvert y >>= return . posixSecondsToUTCTime+ safeConvert y@(SqlTimeDiff _) = convError "incompatible types (did you mean SqlPOSIXTime?)" y+ safeConvert y@SqlNull = quickError y++instance Convertible NominalDiffTime SqlValue where+ safeConvert = return . SqlDiffTime+instance Convertible SqlValue NominalDiffTime where+ safeConvert (SqlString x) = read' x >>= return . fromInteger+ safeConvert (SqlByteString x) = read' (BUTF8.toString x) >>= return . fromInteger+ safeConvert (SqlInt32 x) = return . fromIntegral $ x+ safeConvert (SqlInt64 x) = return . fromIntegral $ x+ safeConvert (SqlWord32 x) = return . fromIntegral $ x+ safeConvert (SqlWord64 x) = return . fromIntegral $ x+ safeConvert (SqlInteger x) = return . fromIntegral $ x+ safeConvert y@(SqlChar _) = quickError y+ safeConvert y@(SqlBool _) = quickError y+ safeConvert (SqlDouble x) = return . fromRational . toRational $ x+ safeConvert (SqlRational x) = return . fromRational $ x+ safeConvert (SqlLocalDate x) = return . fromIntegral . (\y -> y * 60 * 60 * 24) . + toModifiedJulianDay $ x+ safeConvert (SqlLocalTimeOfDay x) = + return . fromRational . toRational . timeOfDayToTime $ x+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = quickError y+ safeConvert (SqlZonedTime x) = return . utcTimeToPOSIXSeconds . zonedTimeToUTC $ x+ safeConvert (SqlUTCTime x) = return . utcTimeToPOSIXSeconds $ x+ safeConvert (SqlDiffTime x) = return x+ safeConvert (SqlPOSIXTime x) = return x+ safeConvert (SqlEpochTime x) = return . fromIntegral $ x+ safeConvert (SqlTimeDiff x) = return . fromIntegral $ x+ safeConvert y@SqlNull = quickError y++instance Convertible ST.ClockTime SqlValue where+ safeConvert x = safeConvert x >>= return . SqlPOSIXTime+instance Convertible SqlValue ST.ClockTime where+ safeConvert (SqlString x) = do r <- read' x+ return $ ST.TOD r 0+ safeConvert (SqlByteString x) = safeConvert . SqlString . BUTF8.toString $ x+ safeConvert (SqlInt32 x) = return $ ST.TOD (fromIntegral x) 0+ safeConvert (SqlInt64 x) = return $ ST.TOD (fromIntegral x) 0+ safeConvert (SqlWord32 x) = return $ ST.TOD (fromIntegral x) 0+ safeConvert (SqlWord64 x) = return $ ST.TOD (fromIntegral x) 0+ safeConvert (SqlInteger x) = return $ ST.TOD x 0+ safeConvert y@(SqlChar _) = quickError y+ safeConvert y@(SqlBool _) = quickError y+ safeConvert (SqlDouble x) = return $ ST.TOD (truncate x) 0+ safeConvert (SqlRational x) = return $ ST.TOD (truncate x) 0+ safeConvert y@(SqlLocalDate _) = quickError y+ safeConvert y@(SqlLocalTimeOfDay _) = quickError y+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = quickError y+ safeConvert y@(SqlZonedTime _) = safeConvert y >>= (\z -> return $ ST.TOD z 0)+ safeConvert y@(SqlUTCTime _) = safeConvert y >>= (\z -> return $ ST.TOD z 0)+ safeConvert y@(SqlDiffTime _) = quickError y+ safeConvert y@(SqlPOSIXTime _) = safeConvert y >>= (\z -> return $ ST.TOD z 0)+ safeConvert (SqlEpochTime x) = return $ ST.TOD x 0+ safeConvert y@(SqlTimeDiff _) = quickError y+ safeConvert y@SqlNull = quickError y++instance Convertible ST.TimeDiff SqlValue where+ safeConvert x = safeConvert x >>= return . SqlDiffTime+instance Convertible SqlValue ST.TimeDiff where+ safeConvert (SqlString x) = ((read' x)::ConvertResult Integer) >>= safeConvert+ safeConvert (SqlByteString x) = safeConvert . SqlString . BUTF8.toString $ x+ safeConvert (SqlInt32 x) = secs2td (fromIntegral x)+ safeConvert (SqlInt64 x) = secs2td (fromIntegral x)+ safeConvert (SqlWord32 x) = secs2td (fromIntegral x)+ safeConvert (SqlWord64 x) = secs2td (fromIntegral x)+ safeConvert (SqlInteger x) = secs2td x+ safeConvert y@(SqlChar _) = quickError y+ safeConvert y@(SqlBool _) = quickError y+ safeConvert (SqlDouble x) = secs2td (truncate x)+ safeConvert (SqlRational x) = secs2td (truncate x)+ safeConvert y@(SqlLocalDate _) = quickError y+ safeConvert y@(SqlLocalTimeOfDay _) = quickError y+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = quickError y+ safeConvert y@(SqlZonedTime _) = quickError y+ safeConvert y@(SqlUTCTime _) = quickError y+ safeConvert y@(SqlPOSIXTime _) = quickError y+ safeConvert (SqlDiffTime x) = safeConvert x+ safeConvert y@(SqlEpochTime _) = quickError y+ safeConvert (SqlTimeDiff x) = secs2td x+ safeConvert y@SqlNull = quickError y++instance Convertible DiffTime SqlValue where+ safeConvert = return . SqlDiffTime . fromRational . toRational+instance Convertible SqlValue DiffTime where+ safeConvert (SqlString x) = read' x >>= return . fromInteger+ safeConvert (SqlByteString x) = safeConvert . SqlString . BUTF8.toString $ x+ safeConvert (SqlInt32 x) = return . fromIntegral $ x+ safeConvert (SqlInt64 x) = return . fromIntegral $ x+ safeConvert (SqlWord32 x) = return . fromIntegral $ x+ safeConvert (SqlWord64 x) = return . fromIntegral $ x+ safeConvert (SqlInteger x) = return . fromIntegral $ x+ safeConvert y@(SqlChar _) = quickError y+ safeConvert y@(SqlBool _) = quickError y+ safeConvert (SqlDouble x) = return . fromRational . toRational $ x+ safeConvert (SqlRational x) = return . fromRational $ x+ safeConvert y@(SqlLocalDate _) = quickError y+ safeConvert y@(SqlLocalTimeOfDay _) = quickError y+ safeConvert y@(SqlZonedLocalTimeOfDay _ _) = quickError y+ safeConvert y@(SqlLocalTime _) = quickError y+ safeConvert y@(SqlZonedTime _) = quickError y+ safeConvert y@(SqlUTCTime _) = quickError y+ safeConvert (SqlDiffTime x) = return . fromRational . toRational $ x+ safeConvert y@(SqlPOSIXTime _) = quickError y+ safeConvert y@(SqlEpochTime _) = quickError y+ safeConvert (SqlTimeDiff x) = return . fromIntegral $ x+ safeConvert y@SqlNull = quickError y++instance Convertible ST.CalendarTime SqlValue where+ -- convert via ZonedTime+ safeConvert x = safeConvert x >>= return . SqlZonedTime+instance Convertible SqlValue ST.CalendarTime where+ -- convert via ZonedTime+ safeConvert = convertVia (undefined::ZonedTime)++instance (Convertible a SqlValue) => Convertible (Maybe a) SqlValue where+ safeConvert Nothing = return SqlNull+ safeConvert (Just a) = safeConvert a+instance (Convertible SqlValue a) => Convertible SqlValue (Maybe a) where+ safeConvert SqlNull = return Nothing+ safeConvert a = safeConvert a >>= (return . Just)++viaInteger' :: (Convertible SqlValue a, Bounded a, Show a, Convertible a Integer,+ Typeable a) => SqlValue -> (Integer -> ConvertResult a) -> ConvertResult a+viaInteger' sv func = + do i <- ((safeConvert sv)::ConvertResult Integer)+ boundedConversion func i++viaInteger :: (Convertible SqlValue a, Bounded a, Show a, Convertible a Integer,+ Typeable a) => SqlValue -> (Integer -> a) -> ConvertResult a+viaInteger sv func = viaInteger' sv (return . func)++secs2td :: Integer -> ConvertResult ST.TimeDiff+secs2td x = safeConvert x+++-- | Read a value from a string, and give an informative message+-- if it fails.+read' :: (Typeable a, Read a, Convertible SqlValue a) => String -> ConvertResult a+read' s = + case reads s of+ [(x,"")] -> Right x+ _ -> convError "Cannot read source value as dest type" (SqlString s)++#ifdef __HUGS__+parseTime' :: (Typeable t, Convertible SqlValue t) => String -> String -> ConvertResult t+parseTime' _ inpstr =+ convError "Hugs does not support time parsing" (SqlString inpstr)+#else+parseTime' :: (Typeable t, Convertible SqlValue t, ParseTime t) => String -> String -> ConvertResult t+parseTime' fmtstr inpstr = + case parseTime defaultTimeLocale fmtstr inpstr of+ Nothing -> convError ("Cannot parse using default format string " ++ show fmtstr)+ (SqlString inpstr)+ Just x -> Right x+#endif
Database/HDBC/Statement.hs view
@@ -2,18 +2,17 @@ ( Statement(..), SqlError(..),- SqlType(..), nToSql, iToSql,++ -- * Re-exported from "Database.HDBC.SqlValue"; this re-exporting is deprecated+ nToSql, iToSql, posixToSql, fromSql, safeFromSql, toSql, SqlValue(..) ) where import Data.Dynamic-import qualified Data.ByteString as B-import Data.Char(ord,toUpper)-import Data.Word-import Data.Int-import System.Time import Database.HDBC.ColTypes+import Database.HDBC.SqlValue+import Control.Exception data Statement = Statement {@@ -109,376 +108,12 @@ instance Typeable SqlError where typeOf _ = mkTyConApp sqlErrorTc [] -{- | Conversions to and from 'SqlValue's and standard Haskell types.--Conversions are powerful; for instance, you can call 'fromSql' on a SqlInt32-and get a String or a Double out of it. This class attempts to Do-The Right Thing whenever possible, and will raise an error when asked to-do something incorrect. In particular, when converting to any type-except a Maybe, 'SqlNull' as the input will cause an error to be raised.--Here are some notes about conversion:-- * Fractions of a second are not preserved on time values--See also 'nToSql', 'iToSql'.+#if __GLASGOW_HASKELL__ >= 610+--data SqlException+instance Exception SqlError where+{-+ toException = SomeException+ fromException (SomeException e) = Just e+ fromException _ = Nothing -}--class (Show a) => SqlType a where- toSql :: a -> SqlValue- fromSql :: SqlValue -> a--{- | Converts any Integral type to a 'SqlValue' by using toInteger. -}-nToSql :: Integral a => a -> SqlValue-nToSql n = SqlInteger (toInteger n)--{- | Convenience function for using numeric literals in your program. -}-iToSql :: Int -> SqlValue-iToSql = toSql--{- | The main type for expressing Haskell values to SQL databases.--This type is used to marshall Haskell data to and from database APIs.-HDBC driver interfaces will do their best to use the most accurate and-efficient way to send a particular value to the database server.--Values read back from the server are put in the most appropriate 'SqlValue'-type. 'fromSql' can then be used to convert them into whatever type-is needed locally in Haskell.--Most people will use 'toSql' and 'fromSql' instead of manipulating-'SqlValue's directly.--The default representation of time values is an integer number of seconds.-Databases such as PostgreSQL with builtin timestamp types can will see-automatic conversion between these Haskell types to local types. Other-databases can just use an int or a string. --This behavior also exists for other types. For instance, many databases don't-have a Rational type, so they'll just use Haskell's show function and-store a Rational as a string.--Two SqlValues are considered to be equal if one of these hold (first one that-is true holds; if none are true, they are not equal):- * Both are NULL- * Both represent the same type and the encapsulated values are equal- * The values of each, when converted to a string, are equal. -}-data SqlValue = SqlString String - | SqlByteString B.ByteString- | SqlWord32 Word32- | SqlWord64 Word64- | SqlInt32 Int32- | SqlInt64 Int64- | SqlInteger Integer- | SqlChar Char- | SqlBool Bool- | SqlDouble Double- | SqlRational Rational- | SqlEpochTime Integer -- ^ Representation of ClockTime or CalendarTime- | SqlTimeDiff Integer -- ^ Representation of TimeDiff- | SqlNull -- ^ NULL in SQL or Nothing in Haskell- deriving (Show)--instance Eq SqlValue where- SqlString a == SqlString b = a == b- SqlByteString a == SqlByteString b = a == b- SqlWord32 a == SqlWord32 b = a == b- SqlWord64 a == SqlWord64 b = a == b- SqlInt32 a == SqlInt32 b = a == b- SqlInt64 a == SqlInt64 b = a == b- SqlInteger a == SqlInteger b = a == b- SqlChar a == SqlChar b = a == b- SqlBool a == SqlBool b = a == b- SqlDouble a == SqlDouble b = a == b- SqlRational a == SqlRational b = a == b- SqlEpochTime a == SqlEpochTime b = a == b- SqlTimeDiff a == SqlTimeDiff b = a == b- SqlNull == SqlNull = True- SqlNull == _ = False- _ == SqlNull = False- a == b = ((fromSql a)::String) == ((fromSql b)::String)--instance SqlType String where- toSql = SqlString- fromSql (SqlString x) = x- fromSql (SqlByteString x) = byteString2String x- fromSql (SqlInt32 x) = show x- fromSql (SqlInt64 x) = show x- fromSql (SqlWord32 x) = show x- fromSql (SqlWord64 x) = show x- fromSql (SqlInteger x) = show x- fromSql (SqlChar x) = [x]- fromSql (SqlBool x) = show x- fromSql (SqlDouble x) = show x- fromSql (SqlRational x) = show x- fromSql (SqlEpochTime x) = show x- fromSql (SqlTimeDiff x) = show x- fromSql (SqlNull) = error "fromSql: cannot convert SqlNull to String"--instance SqlType B.ByteString where- toSql = SqlByteString- fromSql (SqlByteString x) = x- fromSql (SqlNull) = error "fromSql: cannot convert SqlNull to ByteString"- fromSql x = (string2ByteString . fromSql) x--string2ByteString :: String -> B.ByteString-string2ByteString = B.pack . map (toEnum . fromEnum)--instance SqlType Int where- toSql x = SqlInt32 (fromIntegral x)- fromSql (SqlString x) = read' x- fromSql (SqlByteString x) = (read' . byteString2String) x- fromSql (SqlInt32 x) = fromIntegral x- fromSql (SqlInt64 x) = fromIntegral x- fromSql (SqlWord32 x) = fromIntegral x- fromSql (SqlWord64 x) = fromIntegral x- fromSql (SqlInteger x) = fromIntegral x- fromSql (SqlChar x) = ord x- fromSql (SqlBool x) = if x then 1 else 0- fromSql (SqlDouble x) = truncate $ x- fromSql (SqlRational x) = truncate $ x- fromSql (SqlEpochTime x) = fromIntegral x- fromSql (SqlTimeDiff x) = fromIntegral x- fromSql (SqlNull) = error "fromSql: cannot convert SqlNull to Int"--instance SqlType Int32 where- toSql = SqlInt32- fromSql (SqlString x) = read' x- fromSql (SqlByteString x) = (read' . byteString2String) x- fromSql (SqlInt32 x) = x- fromSql (SqlInt64 x) = fromIntegral x- fromSql (SqlWord32 x) = fromIntegral x- fromSql (SqlWord64 x) = fromIntegral x- fromSql (SqlInteger x) = fromIntegral x- fromSql (SqlChar x) = fromIntegral $ ord x- fromSql (SqlBool x) = if x then 1 else 0- fromSql (SqlDouble x) = truncate $ x- fromSql (SqlRational x) = truncate $ x- fromSql (SqlEpochTime x) = fromIntegral x- fromSql (SqlTimeDiff x) = fromIntegral x- fromSql (SqlNull) = error "fromSql: cannot convert SqlNull to Int32"--instance SqlType Int64 where- toSql = SqlInt64- fromSql (SqlString x) = read' x- fromSql (SqlByteString x) = (read' . byteString2String) x- fromSql (SqlInt32 x) = fromIntegral x- fromSql (SqlInt64 x) = x- fromSql (SqlWord32 x) = fromIntegral x- fromSql (SqlWord64 x) = fromIntegral x- fromSql (SqlInteger x) = fromIntegral x- fromSql (SqlChar x) = fromIntegral $ ord x- fromSql (SqlBool x) = if x then 1 else 0- fromSql (SqlDouble x) = truncate $ x- fromSql (SqlRational x) = truncate $ x- fromSql (SqlEpochTime x) = fromIntegral x- fromSql (SqlTimeDiff x) = fromIntegral x- fromSql (SqlNull) = error "fromSql: cannot convert SqlNull to Int64"--instance SqlType Word32 where- toSql = SqlWord32- fromSql (SqlString x) = read' x- fromSql (SqlByteString x) = (read' . byteString2String) x- fromSql (SqlInt32 x) = fromIntegral x- fromSql (SqlInt64 x) = fromIntegral x- fromSql (SqlWord32 x) = x- fromSql (SqlWord64 x) = fromIntegral x- fromSql (SqlInteger x) = fromIntegral x- fromSql (SqlChar x) = fromIntegral $ ord x- fromSql (SqlBool x) = if x then 1 else 0- fromSql (SqlDouble x) = truncate $ x- fromSql (SqlRational x) = truncate $ x- fromSql (SqlEpochTime x) = fromIntegral x- fromSql (SqlTimeDiff x) = fromIntegral x- fromSql (SqlNull) = error "fromSql: cannot convert SqlNull to Word32"--instance SqlType Word64 where- toSql = SqlWord64- fromSql (SqlString x) = read' x- fromSql (SqlByteString x) = (read' . byteString2String) x- fromSql (SqlInt32 x) = fromIntegral x- fromSql (SqlInt64 x) = fromIntegral x- fromSql (SqlWord32 x) = fromIntegral x- fromSql (SqlWord64 x) = x- fromSql (SqlInteger x) = fromIntegral x- fromSql (SqlChar x) = fromIntegral (ord x)- fromSql (SqlBool x) = if x then 1 else 0- fromSql (SqlDouble x) = truncate $ x- fromSql (SqlRational x) = truncate $ x- fromSql (SqlEpochTime x) = fromIntegral x- fromSql (SqlTimeDiff x) = fromIntegral x- fromSql (SqlNull) = error "fromSql: cannot convert SqlNull to Int64"--instance SqlType Integer where- toSql = SqlInteger- fromSql (SqlString x) = read' x- fromSql (SqlByteString x) = (read' . byteString2String) x- fromSql (SqlInt32 x) = fromIntegral x- fromSql (SqlInt64 x) = fromIntegral x- fromSql (SqlWord32 x) = fromIntegral x- fromSql (SqlWord64 x) = fromIntegral x- fromSql (SqlInteger x) = x- fromSql (SqlChar x) = fromIntegral (ord x)- fromSql (SqlBool x) = if x then 1 else 0- fromSql (SqlDouble x) = truncate $ x- fromSql (SqlRational x) = truncate $ x- fromSql (SqlEpochTime x) = x- fromSql (SqlTimeDiff x) = x- fromSql (SqlNull) = error "fromSql: cannot convert SqlNull to Integer"--instance SqlType Bool where- toSql = SqlBool- fromSql (SqlString x) = - case map toUpper x of- "TRUE" -> True- "T" -> True- "FALSE" -> False- "F" -> False- "0" -> False- "1" -> True- _ -> error $ "fromSql: cannot convert SqlString " - ++ show x ++ " to Bool"- fromSql (SqlByteString x) = (fromSql . SqlString . byteString2String) x- fromSql (SqlInt32 x) = numToBool x- fromSql (SqlInt64 x) = numToBool x- fromSql (SqlWord32 x) = numToBool x- fromSql (SqlWord64 x) = numToBool x- fromSql (SqlInteger x) = numToBool x- fromSql (SqlChar x) = numToBool (ord x)- fromSql (SqlBool x) = x- fromSql (SqlDouble x) = numToBool x- fromSql (SqlRational x) = numToBool x- fromSql (SqlEpochTime x) = numToBool x- fromSql (SqlTimeDiff x) = numToBool x- fromSql (SqlNull) = error "fromSql: cannot convert SqlNull to Bool"--numToBool :: Num a => a -> Bool-numToBool x = x /= 0--instance SqlType Char where- toSql = SqlChar- fromSql (SqlString [x]) = x- fromSql (SqlByteString x) = (head . byteString2String) x- fromSql (SqlString _) = error "fromSql: cannot convert SqlString to Char"- fromSql (SqlInt32 _) = error "fromSql: cannot convert SqlInt32 to Char"- fromSql (SqlInt64 _) = error "fromSql: cannot convert SqlInt64 to Char"- fromSql (SqlWord32 _) = error "fromSql: cannot convert SqlWord32 to Char"- fromSql (SqlWord64 _) = error "fromSql: cannot convert SqlWord64 to Char"- fromSql (SqlInteger _) = error "fromSql: cannot convert SqlInt to Char"- fromSql (SqlChar x) = x- fromSql (SqlBool x) = if x then '1' else '0'- fromSql (SqlDouble _) = error "fromSql: cannot convert SqlDouble to Char"- fromSql (SqlRational _) = error "fromSql: cannot convert SqlRational to Char"- fromSql (SqlEpochTime _) = error "fromSql: cannot convert SqlEpochTime to Char"- fromSql (SqlTimeDiff _) = error "fromSql: cannot convert SqlTimeDiff to Char"- fromSql (SqlNull) = error "fromSql: cannot convert SqlNull to Char"--instance SqlType Double where- toSql = SqlDouble- fromSql (SqlString x) = read' x- fromSql (SqlByteString x) = (read' . byteString2String) x- fromSql (SqlInt32 x) = fromIntegral x- fromSql (SqlInt64 x) = fromIntegral x- fromSql (SqlWord32 x) = fromIntegral x- fromSql (SqlWord64 x) = fromIntegral x- fromSql (SqlInteger x) = fromIntegral x- fromSql (SqlChar x) = fromIntegral . ord $ x- fromSql (SqlBool x) = if x then 1.0 else 0.0- fromSql (SqlDouble x) = x- fromSql (SqlRational x) = fromRational x- fromSql (SqlEpochTime x) = fromIntegral x- fromSql (SqlTimeDiff x) = fromIntegral x- fromSql (SqlNull) = error "fromSql: cannot convert SqlNull to Double"--instance SqlType Rational where- toSql = SqlRational- fromSql (SqlString x) = read' x- fromSql (SqlByteString x) = (read' . byteString2String) x- fromSql (SqlInt32 x) = fromIntegral x- fromSql (SqlInt64 x) = fromIntegral x- fromSql (SqlWord32 x) = fromIntegral x- fromSql (SqlWord64 x) = fromIntegral x- fromSql (SqlInteger x) = fromIntegral x- fromSql (SqlChar x) = fromIntegral . ord $ x- fromSql (SqlBool x) = fromIntegral $ ((fromSql (SqlBool x))::Int)- fromSql (SqlDouble x) = toRational x- fromSql (SqlRational x) = x- fromSql (SqlEpochTime x) = fromIntegral x- fromSql (SqlTimeDiff x) = fromIntegral x- fromSql (SqlNull) = error "fromSql: cannot convert SqlNull to Double"--instance SqlType ClockTime where- toSql (TOD x _) = SqlEpochTime x- fromSql (SqlString x) = TOD (read' x) 0- fromSql (SqlByteString x) = TOD ((read' . byteString2String) x) 0- fromSql (SqlInt32 x) = TOD (fromIntegral x) 0- fromSql (SqlInt64 x) = TOD (fromIntegral x) 0- fromSql (SqlWord32 x) = TOD (fromIntegral x) 0- fromSql (SqlWord64 x) = TOD (fromIntegral x) 0- fromSql (SqlInteger x) = TOD x 0- fromSql (SqlChar _) = error "fromSql: cannot convert SqlChar to ClockTime"- fromSql (SqlBool _) = error "fromSql: cannot convert SqlBool to ClockTime"- fromSql (SqlDouble x) = TOD (truncate x) 0- fromSql (SqlRational x) = TOD (truncate x) 0- fromSql (SqlEpochTime x) = TOD x 0- fromSql (SqlTimeDiff _) = error "fromSql: cannot convert SqlTimeDiff to ClockTime"- fromSql SqlNull = error "fromSql: cannot convert SqlNull to ClockTime"--instance SqlType TimeDiff where- toSql x = SqlTimeDiff (timeDiffToSecs x)- fromSql (SqlString x) = secs2td (read' x)- fromSql (SqlByteString x) = secs2td ((read' . byteString2String) x)- fromSql (SqlInt32 x) = secs2td (fromIntegral x)- fromSql (SqlInt64 x) = secs2td (fromIntegral x)- fromSql (SqlWord32 x) = secs2td (fromIntegral x)- fromSql (SqlWord64 x) = secs2td (fromIntegral x)- fromSql (SqlInteger x) = secs2td x- fromSql (SqlChar _) = error "fromSql: cannot convert SqlChar to TimeDiff"- fromSql (SqlBool _) = error "fromSql: cannot convert SqlBool to TimeDiff"- fromSql (SqlDouble x) = secs2td (truncate x)- fromSql (SqlRational x) = secs2td (truncate x)- fromSql (SqlEpochTime _) = error "fromSql: cannot convert SqlEpochTime to TimeDiff"- fromSql (SqlTimeDiff x) = secs2td x- fromSql SqlNull = error "fromSql: cannot convert SqlNull to TimeDiff"--instance SqlType CalendarTime where- toSql x = toSql (toClockTime x)- fromSql = toUTCTime . fromSql--instance (SqlType a) => SqlType (Maybe a) where- toSql Nothing = SqlNull- toSql (Just a) = toSql a- fromSql SqlNull = Nothing- fromSql x = Just (fromSql x)--byteString2String :: B.ByteString -> String-byteString2String = map (toEnum . fromEnum) . B.unpack--secs2td :: Integer -> TimeDiff-secs2td x = diffClockTimes (TOD x 0) (TOD 0 0)----- | Read a value from a string, and give an informative message--- if it fails.-read' :: (Typeable a,Read a) => String -> a-read' s = ret- where ret = case reads s of- [(x,"")] -> x- _ -> error $ "fromSql: Cannot read " ++ show s - ++ " as " ++ t ++ "."- t = show (typeOf ret)------------------- The following function copied from MissingH.Time.hs--{- | Converts the given timeDiff to the number of seconds it represents.--Uses the same algorithm as normalizeTimeDiff in GHC. -}-timeDiffToSecs :: TimeDiff -> Integer-timeDiffToSecs td =- (fromIntegral $ tdSec td) +- 60 * ((fromIntegral $ tdMin td) +- 60 * ((fromIntegral $ tdHour td) +- 24 * ((fromIntegral $ tdDay td) +- 30 * ((fromIntegral $ tdMonth td) +- 365 * (fromIntegral $ tdYear td)))))+#endif
Database/HDBC/Types.hs view
@@ -1,5 +1,5 @@ {--Copyright (C) 2005-2007 John Goerzen <jgoerzen@complete.org>+Copyright (C) 2005-2009 John Goerzen <jgoerzen@complete.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public@@ -18,7 +18,7 @@ {- | Module : Database.HDBC.Types- Copyright : Copyright (C) 2005-2007 John Goerzen+ Copyright : Copyright (C) 2005-2009 John Goerzen License : GNU LGPL, version 2.1 or above Maintainer : John Goerzen <jgoerzen@complete.org>@@ -38,7 +38,7 @@ (IConnection(..), Statement(..), SqlError(..),- SqlType(..), nToSql, iToSql,+ nToSql, iToSql, posixToSql, fromSql, safeFromSql, toSql, SqlValue(..), ConnWrapper(..), withWConn@@ -46,6 +46,7 @@ where import Database.HDBC.Statement+import Database.HDBC.SqlValue import Database.HDBC.ColTypes {- | Main database handle object.
Database/HDBC/Utils.hs view
@@ -1,6 +1,7 @@+{-# LANGUAGE CPP #-} -- #hide {--Copyright (C) 2005 John Goerzen <jgoerzen@complete.org>+Copyright (C) 2005-2009 John Goerzen <jgoerzen@complete.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public@@ -19,7 +20,7 @@ {- | Module : Database.HDBC.Utils- Copyright : Copyright (C) 2005 John Goerzen+ Copyright : Copyright (C) 2005-2009 John Goerzen License : GNU LGPL, version 2.1 or above Maintainer : John Goerzen <jgoerzen@complete.org>@@ -39,15 +40,37 @@ import qualified Data.Map as Map import Control.Exception import Data.Char-import Data.Dynamic import System.IO.Unsafe import Data.List(genericLength) +-- import Data.Dynamic below for GHC < 6.10++#if __GLASGOW_HASKELL__ >= 610 {- | Execute the given IO action. If it raises a 'SqlError', then execute the supplied handler and return its return value. Otherwise, proceed as normal. -} catchSql :: IO a -> (SqlError -> IO a) -> IO a+catchSql action handler = + catchJust sqlExceptions action handler++{- | Like 'catchSql', with the order of arguments reversed. -}+handleSql :: (SqlError -> IO a) -> IO a -> IO a+handleSql h f = catchSql f h++{- | Given an Exception, return Just SqlError if it was an SqlError, or Nothing+otherwise. Useful with functions like catchJust. -}+sqlExceptions :: SqlError -> Maybe SqlError+sqlExceptions e = Just e++#else+import Data.Dynamic++{- | Execute the given IO action.++If it raises a 'SqlError', then execute the supplied handler and return its+return value. Otherwise, proceed as normal. -}+catchSql :: IO a -> (SqlError -> IO a) -> IO a catchSql = catchDyn {- | Like 'catchSql', with the order of arguments reversed. -}@@ -58,6 +81,7 @@ otherwise. Useful with functions like catchJust. -} sqlExceptions :: Exception -> Maybe SqlError sqlExceptions e = dynExceptions e >>= fromDynamic+#endif {- | Catches 'SqlError's, and re-raises them as IO errors with fail. Useful if you don't care to catch SQL errors, but want to see a sane@@ -119,6 +143,17 @@ -} withTransaction :: IConnection conn => conn -> (conn -> IO a) -> IO a withTransaction conn func =+#if __GLASGOW_HASKELL__ >= 610+ do r <- onException (func conn) doRollback+ commit conn+ return r+ where doRollback = + -- Discard any exception from (rollback conn) so original+ -- exception can be re-raised+ Control.Exception.catch (rollback conn) doRollbackHandler+ doRollbackHandler :: SomeException -> IO ()+ doRollbackHandler _ = return ()+#else do r <- try (func conn) case r of Right x -> do commit conn@@ -126,7 +161,7 @@ Left e -> do try (rollback conn) -- Discard any exception here throw e-+#endif {- | Lazily fetch all rows from an executed 'Statement'. You can think of this as hGetContents applied to a database result set.@@ -272,3 +307,15 @@ evalAll res return res +{- | A utility function to throw a 'SqlError'. The mechanics of throwing+such a thing differ between GHC 6.8.x, Hugs, and GHC 6.10. This function+takes care of the special cases to make it simpler.++With GHC 6.10, it is a type-restricted alias for throw. On all other systems,+it is a type-restricted alias for throwDyn. -}+throwSqlError :: SqlError -> IO a+#if __GLASGOW_HASKELL__ >= 610+throwSqlError = throw+#else+throwSqlError = throwDyn+#endif
HDBC.cabal view
@@ -1,9 +1,9 @@ Name: HDBC-Version: 1.1.6+Version: 2.0.0 License: LGPL Maintainer: John Goerzen <jgoerzen@complete.org> Author: John Goerzen-Copyright: Copyright (c) 2005-2008 John Goerzen+Copyright: Copyright (c) 2005-2009 John Goerzen license-file: COPYRIGHT extra-source-files: COPYING homepage: http://software.complete.org/hdbc@@ -16,22 +16,42 @@ Stability: Stable Build-Type: Simple -Cabal-Version: >=1.2+Cabal-Version: >=1.2.3 flag splitBase description: Choose the new smaller, split-up base package.+flag buildtests+ description: Build the executable to run unit tests+ default: False+ library if flag(splitBase)- Build-Depends: base>=3 && < 4, old-time, bytestring, containers+ Build-Depends: base>=3, old-time, time, bytestring, containers, old-locale else Build-Depends: base<3- Build-Depends: mtl+ Build-Depends: mtl, convertible >= 1.0.1, utf8-string - GHC-Options: -O2 -Wall -fglasgow-exts+ GHC-Options: -O2 -Wall -fno-warn-orphans Exposed-Modules: Database.HDBC, Database.HDBC.Types, Database.HDBC.DriverUtils,- Database.HDBC.ColTypes, Database.HDBC.Statement+ Database.HDBC.ColTypes, Database.HDBC.Statement, Database.HDBC.SqlValue Other-Modules: Database.HDBC.Utils- --Extensions: ExistentialQuantification, AllowOverlappingInstances,- -- AllowUndecidableInstances- Extensions: ExistentialQuantification+ Extensions: ExistentialQuantification, CPP, MultiParamTypeClasses,+ FlexibleContexts, TypeSynonymInstances, TypeOperators, RankNTypes,+ FlexibleInstances+ +Executable runtests+ if flag(buildtests)+ Buildable: True+ else+ Buildable: False+ Build-Depends: HUnit, QuickCheck, testpack+ Main-Is: runtests.hs+ Other-Modules: TestSqlValue+ TestInfrastructure+ Hs-Source-Dirs: ., testsrc+ GHC-Options: -O2+ Extensions: ExistentialQuantification, CPP, MultiParamTypeClasses,+ FlexibleContexts, TypeSynonymInstances, TypeOperators,+ RankNTypes, FlexibleInstances+