packages feed

persistable-record 0.5.0.1 → 0.5.0.2

raw patch · 5 files changed

+175/−84 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

ChangeLog.md view
@@ -1,5 +1,9 @@ <!-- -*- Markdown -*- --> +## 0.5.0.2++- add tested-with 8.2.1.+ ## 0.5.0.1  - Use Haskell implementation test instead of flag test in .cabal
persistable-record.cabal view
@@ -1,5 +1,5 @@ name:                persistable-record-version:             0.5.0.1+version:             0.5.0.2 synopsis:            Binding between SQL database values and haskell records. description:         This package contiains types to represent table constraints and                      interfaces to bind between SQL database values and Haskell records.@@ -12,7 +12,8 @@ category:            Database build-type:          Simple cabal-version:       >=1.10-tested-with:           GHC == 8.0.1, GHC == 8.0.2+tested-with:           GHC == 8.2.1+                     , GHC == 8.0.1, GHC == 8.0.2                      , GHC == 7.10.1, GHC == 7.10.2, GHC == 7.10.3                      , GHC == 7.8.1, GHC == 7.8.2, GHC == 7.8.3, GHC == 7.8.4                      , GHC == 7.6.1, GHC == 7.6.2, GHC == 7.6.3
src/Database/Record/FromSql.hs view
@@ -14,17 +14,17 @@ -- Portability : unknown -- -- This module defines interfaces--- from list of SQL type into Haskell type.+-- from list of database value type into Haskell type.+ module Database.Record.FromSql (-  -- * Conversion from list of SQL type into record type-  -- $recordFromSql+  -- * Conversion from list of database value type into record type   RecordFromSql, runTakeRecord, runToRecord,   createRecordFromSql,    (<&>),   maybeRecord, -  -- * Inference rules of 'RecordFromSql' conversion+  -- * Derivation rules of 'RecordFromSql' conversion   FromSql (recordFromSql),   takeRecord, toRecord, @@ -40,11 +40,13 @@ import Database.Record.KeyConstraint   (HasColumnConstraint(columnConstraint), ColumnConstraint, NotNull, index) +{- |+'RecordFromSql' 'q' 'a' is data-type wrapping function+to convert from list of database value type (to receive from database) ['q'] into Haskell type 'a' -{- $recordFromSql-Structure of 'RecordFromSql' 'q' 'a' is similar to parser.-While running 'RecordFromSql' behavior is the same as parser-which parse list of SQL type ['q'] stream.+This structure is similar to parser.+While running 'RecordFromSql' behavior is the same as non-fail-able parser+which parse list of database value type ['q'] stream.  So, 'RecordFromSql' 'q' is 'Monad' and 'Applicative' instance like parser monad. When, you have data constructor and objects like below.@@ -69,25 +71,23 @@   myRecord =  MyRecord \<$\> foo \<*\> bar \<*\> baz @ -}---- | Proof object type to convert from sql value type 'q' list into Haskell type 'a'. newtype RecordFromSql q a = RecordFromSql ([q] -> (a, [q])) --- | Run 'RecordFromSql' proof object.---   Convert from list of SQL type ['q'] into Haskell type 'a' and rest of list ['q'].-runTakeRecord :: RecordFromSql q a -- ^ Proof object which has capability to convert-              -> [q]               -- ^ list of SQL type+-- | Run 'RecordFromSql' parser function object.+--   Convert from list of database value type ['q'] into Haskell type 'a' and rest of list ['q'].+runTakeRecord :: RecordFromSql q a -- ^ parser function object which has capability to convert+              -> [q]               -- ^ list of database value type               -> (a, [q])          -- ^ Haskell type and rest of list runTakeRecord (RecordFromSql f) = f --- | Axiom of 'RecordFromSql' for SQL type 'q' and Haskell type 'a'+-- | Axiom of 'RecordFromSql' for database value type 'q' and Haskell type 'a' createRecordFromSql :: ([q] -> (a, [q])) -- ^ Convert function body-                    -> RecordFromSql q a -- ^ Result proof object+                    -> RecordFromSql q a -- ^ Result parser function object createRecordFromSql =  RecordFromSql --- | Run 'RecordFromSql' proof object. Convert from list of SQL type ['q'] into  Haskell type 'a'.-runToRecord :: RecordFromSql q a -- ^ Proof object which has capability to convert-            -> [q]               -- ^ list of SQL type+-- | Run 'RecordFromSql' parser function object. Convert from list of database value type ['q'] into  Haskell type 'a'.+runToRecord :: RecordFromSql q a -- ^ parser function object which has capability to convert+            -> [q]               -- ^ list of database value type             -> a                 -- ^ Haskell type runToRecord r = fst . runTakeRecord r @@ -108,14 +108,14 @@   pure  = return   (<*>) = ap --- | Derivation rule of 'RecordFromSql' proof object for Haskell tuple (,) type.+-- | Derivation rule of 'RecordFromSql' parser function object for Haskell tuple (,) type. (<&>) :: RecordFromSql q a -> RecordFromSql q b -> RecordFromSql q (a, b) a <&> b = (,) <$> a <*> b  infixl 4 <&>  --- | Derivation rule of 'RecordFromSql' proof object for Haskell 'Maybe' type.+-- | Derivation rule of 'RecordFromSql' parser function object for Haskell 'Maybe' type. maybeRecord :: PersistableType q             => RecordFromSql q a             -> ColumnConstraint NotNull a@@ -126,10 +126,25 @@     | otherwise                         = (Nothing, vals')  where       (a, vals') = runTakeRecord rec vals +{- |+'FromSql' 'q' 'a' is implicit rule to derive 'RecordFromSql' 'q' 'a' record parser function against type 'a'. --- | Inference rule interface for 'RecordFromSql' proof object.+Generic programming (<https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#generic-programming>)+with default signature is available for 'FromSql' class,+so you can make instance like below:++@+  \{\-\# LANGUAGE DeriveGeneric \#\-\}+  import GHC.Generics (Generic)+  import Database.HDBC (SqlValue)+  --+  data Foo = Foo { ... } deriving Generic+  instance FromSql SqlValue Foo+@++-} class FromSql q a where-  -- | 'RecordFromSql' proof object.+  -- | 'RecordFromSql' 'q' 'a' record parser function.   recordFromSql :: RecordFromSql q a    default recordFromSql :: (Generic a, GFromSql q (Rep a)) => RecordFromSql q a@@ -152,26 +167,26 @@   gFromSql = K1 <$> recordFromSql  --- | Inference rule of 'RecordFromSql' proof object which can convert---   from list of SQL type ['q'] into Haskell 'Maybe' type.+-- | Implicit derivation rule of 'RecordFromSql' parser function object which can convert+--   from list of database value type ['q'] into Haskell 'Maybe' type. instance (HasColumnConstraint NotNull a, FromSql q a, PersistableType q)          => FromSql q (Maybe a)  where   recordFromSql = maybeRecord recordFromSql columnConstraint --- | Inference rule of 'RecordFromSql' proof object which can convert---   from /empty/ list of SQL type ['q'] into Haskell unit () type.+-- | Implicit derivation rule of 'RecordFromSql' parser function object which can convert+--   from /empty/ list of database value type ['q'] into Haskell unit () type. instance FromSql q ()  -- default generic instance --- | Run inferred 'RecordFromSql' proof object.---   Convert from list of SQL type ['q'] into haskell type 'a' and rest of list ['q'].+-- | Run implicit 'RecordFromSql' parser function object.+--   Convert from list of database value type ['q'] into haskell type 'a' and rest of list ['q']. takeRecord :: FromSql q a => [q] -> (a, [q]) takeRecord =  runTakeRecord recordFromSql --- | Run inferred 'RecordFromSql' proof object.---   Convert from list of SQL type ['q'] into haskell type 'a'.+-- | Run implicit 'RecordFromSql' parser function object.+--   Convert from list of database value type ['q'] into haskell type 'a'. toRecord :: FromSql q a => [q] -> a toRecord =  runToRecord recordFromSql --- | Derivation rule of 'RecordFromSql' proof object for value convert function.+-- | Derivation rule of 'RecordFromSql' parser function object for value convert function. valueRecordFromSql :: (q -> a) -> RecordFromSql q a valueRecordFromSql d = createRecordFromSql $ \qs -> (d $ head qs, tail qs)
src/Database/Record/Persistable.hs view
@@ -13,17 +13,17 @@ -- Stability   : experimental -- Portability : unknown ----- This module defines interfaces--- between Haskell type and list of SQL type.+-- This module defines proposition interfaces+-- for database value type and record type width. module Database.Record.Persistable (-  -- * Specify SQL type+  -- * Specify database value type   PersistableSqlType, runPersistableNullValue, unsafePersistableSqlTypeFromNull,    -- * Specify record width   PersistableRecordWidth, runPersistableRecordWidth,   unsafePersistableRecordWidth, unsafeValueWidth, (<&>), maybeWidth, -  -- * Inference rules for proof objects+  -- * Implicit derivation rules, database value type and record type width   PersistableType(..), sqlNullValue,   PersistableWidth (..), derivedWidth, @@ -41,15 +41,15 @@ import qualified Data.DList as DList  --- | Proof object to specify type 'q' is SQL type+-- | Proposition to specify type 'q' is database value type, contains null value newtype PersistableSqlType q = PersistableSqlType q --- | Null value of SQL type 'q'.+-- | Null value of database value type 'q'. runPersistableNullValue :: PersistableSqlType q -> q runPersistableNullValue (PersistableSqlType q) = q --- | Unsafely generate 'PersistableSqlType' proof object from specified SQL null value which type is 'q'.-unsafePersistableSqlTypeFromNull :: q                    -- ^ SQL null value of SQL type 'q'+-- | Unsafely specify 'PersistableSqlType' axiom from specified database null value which type is 'q'.+unsafePersistableSqlTypeFromNull :: q                    -- ^ null value of database value type 'q'                                  -> PersistableSqlType q -- ^ Result proof object unsafePersistableSqlTypeFromNull =  PersistableSqlType @@ -63,8 +63,8 @@ getProductConst = getConst . unPC {-# INLINE getProductConst #-} --- | Proof object to specify width of Haskell type 'a'---   when converting to SQL type list.+-- | Proposition to specify width of Haskell type 'a'.+--   The width is length of database value list which is converted from Haskell type 'a'. type PersistableRecordWidth a = ProductConst (Sum Int) a  -- unsafely map PersistableRecordWidth@@ -84,13 +84,13 @@ instance Show a => Show (ProductConst a b) where   show = ("PC " ++) . show . getConst . unPC --- | Unsafely generate 'PersistableRecordWidth' proof object from specified width of Haskell type 'a'.+-- | Unsafely specify 'PersistableRecordWidth' axiom from specified width of Haskell type 'a'. unsafePersistableRecordWidth :: Int                      -- ^ Specify width of Haskell type 'a'                              -> PersistableRecordWidth a -- ^ Result proof object unsafePersistableRecordWidth = ProductConst . Const . Sum {-# INLINE unsafePersistableRecordWidth #-} --- | Unsafely generate 'PersistableRecordWidth' proof object for Haskell type 'a' which is single column type.+-- | Unsafely specify 'PersistableRecordWidth' axiom for Haskell type 'a' which is single column type. unsafeValueWidth :: PersistableRecordWidth a unsafeValueWidth =  unsafePersistableRecordWidth 1 {-# INLINE unsafeValueWidth #-}@@ -104,16 +104,31 @@ maybeWidth = pmap Just  --- | Interface of inference rule for 'PersistableSqlType' proof object+-- | Interface of derivation rule for 'PersistableSqlType'. class Eq q => PersistableType q where   persistableType :: PersistableSqlType q --- | Inferred Null value of SQL type.+-- | Implicitly derived null value of database value type. sqlNullValue :: PersistableType q => q sqlNullValue =  runPersistableNullValue persistableType  --- | Interface of inference rule for 'PersistableRecordWidth' proof object+{- |+'PersistableWidth' 'a' is implicit rule to derive 'PersistableRecordWidth' 'a' width proposition for type 'a'.++Generic programming (<https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#generic-programming>)+with default signature is available for 'PersistableWidth' class,+so you can make instance like below:++@+  \{\-\# LANGUAGE DeriveGeneric \#\-\}+  import GHC.Generics (Generic)+  --+  data Foo = Foo { ... } deriving Generic+  instance PersistableWidth Foo+@++-} class PersistableWidth a where   persistableWidth :: PersistableRecordWidth a 
src/Database/Record/ToSql.hs view
@@ -14,24 +14,24 @@ -- Portability : unknown -- -- This module defines interfaces--- from Haskell type into list of SQL type.+-- from Haskell type into list of database value type. module Database.Record.ToSql (-  -- * Conversion from record type into list of SQL type+  -- * Conversion from record type into list of database value type   ToSqlM, RecordToSql, runFromRecord,   createRecordToSql,    (<&>), -  -- * Inference rules of 'RecordToSql' conversion+  -- * Derivation rules of 'RecordToSql' conversion   ToSql (recordToSql),   putRecord, putEmpty, fromRecord, wrapToSql,    valueRecordToSql,    -- * Make parameter list for updating with key-  updateValuesByUnique',   updateValuesByUnique,   updateValuesByPrimary,+  updateValuesByUnique',    untypedUpdateValuesIndex,   unsafeUpdateValuesWithIndexes@@ -51,13 +51,20 @@   (Primary, Unique, KeyConstraint, HasKeyConstraint(keyConstraint), unique, indexes)  --- | Context type to convert SQL type list.+-- | Context type to convert into database value list. type ToSqlM q a = Writer (DList q) a  runToSqlM :: ToSqlM q a -> [q] runToSqlM =  DList.toList . execWriter --- | Proof object type to convert from Haskell type 'a' into list of SQL type ['q'].+{- |+'RecordToSql' 'q' 'a' is data-type wrapping function+to convert from Haskell type 'a' into list of database value type (to send to database) ['q'].++This structure is similar to printer.+While running 'RecordToSql' behavior is the same as list printer.+which appends list of database value type ['q'] stream.+-} newtype RecordToSql q a = RecordToSql (a -> ToSqlM q ())  runRecordToSql :: RecordToSql q a -> a -> ToSqlM q ()@@ -67,15 +74,15 @@ wrapToSql :: (a -> ToSqlM q ()) -> RecordToSql q a wrapToSql =  RecordToSql --- | Run 'RecordToSql' proof object. Convert from Haskell type 'a' into list of SQL type ['q'].-runFromRecord :: RecordToSql q a -- ^ Proof object which has capability to convert+-- | Run 'RecordToSql' printer function object. Convert from Haskell type 'a' into list of database value type ['q'].+runFromRecord :: RecordToSql q a -- ^ printer function object which has capability to convert               -> a               -- ^ Haskell type-              -> [q]             -- ^ list of SQL type+              -> [q]             -- ^ list of database value runFromRecord r = runToSqlM . runRecordToSql r --- | Axiom of 'RecordToSql' for SQL type 'q' and Haksell type 'a'.+-- | Axiom of 'RecordToSql' for database value type 'q' and Haksell type 'a'. createRecordToSql :: (a -> [q])      -- ^ Convert function body-                  -> RecordToSql q a -- ^ Result proof object+                  -> RecordToSql q a -- ^ Result printer function object createRecordToSql f =  wrapToSql $ tell . DList.fromList . f  -- unsafely map record@@ -89,11 +96,11 @@   runRecordToSql ra a   runRecordToSql rb b --- | Derivation rule of 'RecordToSql' proof object for Haskell tuple (,) type.+-- | Derivation rule of 'RecordToSql' printer function object for Haskell tuple (,) type. (<&>) :: RecordToSql q a -> RecordToSql q b -> RecordToSql q (a, b) (<&>) = productToSql $ flip uncurry --- | Derivation rule of 'RecordToSql' proof object for Haskell 'Maybe' type.+-- | Derivation rule of 'RecordToSql' printer function object for Haskell 'Maybe' type. maybeRecord :: PersistableSqlType q -> PersistableRecordWidth a -> RecordToSql q a -> RecordToSql q (Maybe a) maybeRecord qt w ra =  wrapToSql d  where   d (Just r) = runRecordToSql ra r@@ -101,10 +108,53 @@  infixl 4 <&> +{- |+'ToSql' 'q' 'a' is implicit rule to derive 'RecordToSql' 'q' 'a' record printer function for type 'a'. --- | Inference rule interface for 'RecordToSql' proof object.+Generic programming (<https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#generic-programming>)+with default signature is available for 'ToSql' class,+so you can make instance like below:++@+  \{\-\# LANGUAGE DeriveGeneric \#\-\}+  import GHC.Generics (Generic)+  import Database.HDBC (SqlValue)+  --+  data Foo = Foo { ... } deriving Generic+  instance ToSql SqlValue Foo+@++To make instances of 'ToSql' manually,+'ToSql' 'q' 'a' and 'RecordToSql' 'q 'a' are composable with monadic context.+When, you have data constructor and objects like below.++@+  data MyRecord = MyRecord Foo Bar Baz+@++@+  instance ToSql SqlValue Foo where+    ...+  instance ToSql SqlValue Bar where+    ...+  instance ToSql SqlValue Baz where+    ...+@++You can get composed 'ToSql' implicit rule like below.++@+  instance ToSql SqlValue MyRecord where+    recordToSql =+    recordToSql = wrapToSql $ \\ (MyRecord x y z) -> do+      putRecord x+      putRecord y+      putRecord z+@++-} class ToSql q a where-  -- | Infer 'RecordToSql' proof object.+  -- | Derived 'RecordToSql' printer function object.   recordToSql :: RecordToSql q a    default recordToSql :: (Generic a, GToSql q (Rep a)) => RecordToSql q a@@ -126,17 +176,17 @@   gToSql = (\(K1 a) -> a) `mapToSql` recordToSql  --- | Inference rule of 'RecordToSql' proof object which can convert---   from Haskell 'Maybe' type into list of SQL type ['q'].+-- | Implicit derivation rule of 'RecordToSql' printer function object which can convert+--   from Haskell 'Maybe' type into list of database value type ['q']. instance (PersistableType q, PersistableWidth a, ToSql q a) => ToSql q (Maybe a)  where   recordToSql = maybeRecord persistableType persistableWidth recordToSql --- | Inference rule of 'RecordToSql' proof object which can convert---   from Haskell unit () type into /empty/ list of SQL type ['q'].+-- | Implicit derivation rule of 'RecordToSql' printer function object which can convert+--   from Haskell unit () type into /empty/ list of database value type ['q']. instance ToSql q ()  -- default generic instance --- | Run inferred 'RecordToSql' proof object.---   Context to convert haskell record type 'a' into SQL type 'q' list.+-- | Run implicit 'RecordToSql' printer function object.+--   Context to convert haskell record type 'a' into lib of database value type ['q']. putRecord :: ToSql q a => a -> ToSqlM q () putRecord =  runRecordToSql recordToSql @@ -144,19 +194,21 @@ putEmpty :: () -> ToSqlM q () putEmpty =  putRecord --- | Run inferred 'RecordToSql' proof object.---   Convert from haskell type 'a' into list of SQL type ['q'].+-- | Run implicit 'RecordToSql' printer function object.+--   Convert from haskell type 'a' into list of database value type ['q']. fromRecord :: ToSql q a => a -> [q] fromRecord =  runToSqlM . putRecord --- | Derivation rule of 'RecordToSql' proof object for value convert function.+-- | Derivation rule of 'RecordToSql' printer function object for value convert function. valueRecordToSql :: (a -> q) -> RecordToSql q a valueRecordToSql = createRecordToSql . ((:[]) .)  -- | Make untyped indexes to update column from key indexes and record width. --   Expected by update form like ----- /UPDATE <table> SET c0 = ?, c1 = ?, ..., cn = ? WHERE key0 = ? AND key1 = ? AND key2 = ? ... /+--  @+--   UPDATE /table/ SET /c0/ = ?, /c1/ = ?, /c2/ = ? ... WHERE /key0/ = ? AND /key1/ = ? AND key2 = ? ...+--  @ untypedUpdateValuesIndex :: [Int] -- ^ Key indexes                          -> Int   -- ^ Record width                          -> [Int] -- ^ Indexes to update other than key@@ -165,11 +217,13 @@     otherThanKey = toList $ fromList [0 .. maxIx] \\ fromList key  -- | Unsafely specify key indexes to convert from Haskell type `ra`---   into SQL value `q` list expected by update form like+--   into database value `q` list expected by update form like ----- /UPDATE <table> SET c0 = ?, c1 = ?, ..., cn = ? WHERE key0 = ? AND key1 = ? AND key2 = ? ... /+-- @+--   UPDATE /table/ SET /c0/ = ?, /c1/ = ?, /c2/ = ? ... WHERE /key0/ = ? AND /key1/ = ? AND /key2/ = ? ...+-- @ -----   using 'RecordToSql' proof object.+--   using 'RecordToSql' printer function object. unsafeUpdateValuesWithIndexes :: RecordToSql q ra                               -> [Int]                               -> ra@@ -181,25 +235,27 @@     valsA = listArray (0, width - 1) vals     otherThanKey = untypedUpdateValuesIndex key width --- | Convert from Haskell type `ra` into SQL value `q` list expected by update form like+-- | Convert from Haskell type `ra` into database value `q` list expected by update form like ----- /UPDATE <table> SET c0 = ?, c1 = ?, ..., cn = ? WHERE key0 = ? AND key1 = ? AND key2 = ? ... /+-- @+--   UPDATE /table/ SET /c0/ = ?, /c1/ = ?, /c2/ = ? ... WHERE /key0/ = ? AND /key1/ = ? AND /key2/ = ? ...+-- @ -----   using 'RecordToSql' proof object.+--   using 'RecordToSql' printer function object. updateValuesByUnique' :: RecordToSql q ra-                      -> KeyConstraint Unique ra -- ^ Unique key table constraint proof object.+                      -> KeyConstraint Unique ra -- ^ Unique key table constraint printer function object.                       -> ra                       -> [q] updateValuesByUnique' pr uk = unsafeUpdateValuesWithIndexes pr (indexes uk) --- | Convert like 'updateValuesByUnique'' using inferred 'RecordToSql' proof object.+-- | Convert like 'updateValuesByUnique'' using implicit 'RecordToSql' printer function object. updateValuesByUnique :: ToSql q ra-                     => KeyConstraint Unique ra -- ^ Unique key table constraint proof object.+                     => KeyConstraint Unique ra -- ^ Unique key table constraint printer function object.                      -> ra                      -> [q] updateValuesByUnique = updateValuesByUnique' recordToSql --- | Convert like 'updateValuesByUnique'' using inferred 'RecordToSql' and 'ColumnConstraint' proof objects.+-- | Convert like 'updateValuesByUnique'' using implicit 'RecordToSql' and 'ColumnConstraint'. updateValuesByPrimary :: (HasKeyConstraint Primary ra, ToSql q ra)                       => ra -> [q] updateValuesByPrimary =  updateValuesByUnique (unique keyConstraint)