persistent 1.1.0.1 → 1.1.2
raw patch · 6 files changed
+102/−8 lines, 6 files
Files
- Database/Persist/EntityDef.hs +1/−0
- Database/Persist/GenericSql.hs +73/−0
- Database/Persist/GenericSql/Internal.hs +2/−2
- Database/Persist/Quasi.hs +3/−1
- Database/Persist/Util.hs +22/−4
- persistent.cabal +1/−1
Database/Persist/EntityDef.hs view
@@ -56,6 +56,7 @@ { uniqueHaskell :: HaskellName , uniqueDBName :: DBName , uniqueFields :: [(HaskellName, DBName)]+ , uniqueAttrs :: [Attr] } deriving (Show, Eq, Read, Ord)
Database/Persist/GenericSql.hs view
@@ -19,6 +19,9 @@ , runSqlPool , Key + -- * Useful data types+ , Checkmark(..)+ -- * Raw SQL queries -- $rawSql , rawSql@@ -268,6 +271,76 @@ show :: Show a => a -> Text show = pack . P.show+++-- | A 'Checkmark' should be used as a field type whenever a+-- uniqueness constraint should guarantee that a certain kind of+-- record may appear at most once, but other kinds of records may+-- appear any number of times.+--+-- /NOTE:/ You need to mark any @Checkmark@ fields as @nullable@+-- (see the following example).+--+-- For example, suppose there's a @Location@ entity that+-- represents where a user has lived:+--+-- @+-- Location+-- user UserId+-- name Text+-- current Checkmark nullable+--+-- UniqueLocation user current+-- @+--+-- The @UniqueLocation@ constraint allows any number of+-- 'Inactive' @Location@s to be @current@. However, there may be+-- at most one @current@ @Location@ per user (i.e., either zero+-- or one per user).+--+-- This data type works because of the way that SQL treats+-- @NULL@able fields within uniqueness constraints. The SQL+-- standard says that @NULL@ values should be considered+-- different, so we represent 'Inactive' as SQL @NULL@, thus+-- allowing any number of 'Inactive' records. On the other hand,+-- we represent 'Active' as @TRUE@, so the uniqueness constraint+-- will disallow more than one 'Active' record.+--+-- /Note:/ There may be DBMSs that do not respect the SQL+-- standard's treatment of @NULL@ values on uniqueness+-- constraints, please check if this data type works before+-- relying on it.+--+-- The SQL @BOOLEAN@ type is used because it's the smallest data+-- type available. Note that we never use @FALSE@, just @TRUE@+-- and @NULL@. Provides the same behavior @Maybe ()@ would if+-- @()@ was a valid 'PersistField'.+data Checkmark = Active+ -- ^ When used on a uniqueness constraint, there+ -- may be at most one 'Active' record.+ | Inactive+ -- ^ When used on a uniqueness constraint, there+ -- may be any number of 'Inactive' records.+ deriving (Eq, Ord, Read, Show, Enum, Bounded)++instance PersistField Checkmark where+ toPersistValue Active = PersistBool True+ toPersistValue Inactive = PersistNull+ fromPersistValue PersistNull = Right Inactive+ fromPersistValue (PersistBool True) = Right Active+ fromPersistValue (PersistBool False) =+ Left "PersistField Checkmark: found unexpected FALSE value"+ fromPersistValue other =+ Left $ "PersistField Checkmark: unknown value " ++ show other+ sqlType _ = SqlBool+ isNullable _ = True++instance PathPiece Checkmark where+ toPathPiece = show+ fromPathPiece txt =+ case reads (T.unpack txt) of+ [(a, "")] -> Just a+ _ -> Nothing -- $rawSql
Database/Persist/GenericSql/Internal.hs view
@@ -26,7 +26,7 @@ import Database.Persist.Store import Control.Exception.Lifted (bracket) import Control.Monad.Trans.Control (MonadBaseControl)-import Database.Persist.Util (nullable)+import Database.Persist.Util (nullable, IsNullable(NotNullable)) import Data.Text (Text) import qualified Data.Text as T import Data.Monoid (Monoid, mappend, mconcat)@@ -115,7 +115,7 @@ go fd p = Column (fieldDB fd)- (nullable (fieldAttrs fd) || entitySum t)+ (nullable (fieldAttrs fd) /= NotNullable || entitySum t) (maybe (sqlType p) SqlOther $ listToMaybe $ mapMaybe (T.stripPrefix "sqltype=") $ fieldAttrs fd) (def $ fieldAttrs fd) (maxLen $ fieldAttrs fd)
Database/Persist/Quasi.hs view
@@ -248,8 +248,10 @@ = Just $ UniqueDef (HaskellName n) (DBName $ psToDBName ps n)- (map (HaskellName &&& getDBName defs) rest)+ (map (HaskellName &&& getDBName defs) fields)+ attrs where+ (fields,attrs) = break ("!" `T.isPrefixOf`) rest getDBName [] t = error $ "Unknown column in unique constraint: " ++ show t getDBName (d:ds) t | fieldHaskell d == HaskellName t = fieldDB d
Database/Persist/Util.hs view
@@ -1,17 +1,35 @@ {-# LANGUAGE OverloadedStrings #-} module Database.Persist.Util ( nullable+ , IsNullable(..)+ , WhyNullable(..) , deprecate ) where import System.IO.Unsafe (unsafePerformIO) import Data.Text -nullable :: [Text] -> Bool+nullable :: [Text] -> IsNullable nullable s- | "Maybe" `elem` s = True- | "null" `elem` s = deprecate "Please replace null with Maybe" True- | otherwise = False+ | "Maybe" `elem` s = Nullable ByMaybeAttr+ | "nullable" `elem` s = Nullable ByNullableAttr+ | "null" `elem` s = deprecate "Please replace null with Maybe" (Nullable ByMaybeAttr)+ | otherwise = NotNullable+++data IsNullable = Nullable !WhyNullable+ | NotNullable+ deriving (Eq, Show)++-- | The reason why a field is 'nullable' is very important. A+-- field that is nullable because of a @Maybe@ tag will have its+-- type changed from @A@ to @Maybe A@. OTOH, a field that is+-- nullable because of a @nullable@ tag will remain with the same+-- type.+data WhyNullable = ByMaybeAttr+ | ByNullableAttr+ deriving (Eq, Show)+ deprecate :: String -> a -> a deprecate s x = unsafePerformIO $ do
persistent.cabal view
@@ -1,5 +1,5 @@ name: persistent-version: 1.1.0.1+version: 1.1.2 license: MIT license-file: LICENSE author: Michael Snoyman <michael@snoyman.com>