selda 0.1.1.1 → 0.1.2.0
raw patch · 8 files changed
+56/−87 lines, 8 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Database.Selda: (+++) :: ComposeSpec t a b => t a -> t b -> ColSpec (a :+++: b)
- Database.Selda: (¤) :: ColSpec a -> ColSpec b -> ColSpec (a :*: b)
- Database.Selda: class ComposeSpec t a b
- Database.Selda: infixr 1 ¤
- Database.Selda.Generic: instance (Database.Selda.Generic.Append (Database.Selda.Generic.Rel a) (Database.Selda.Generic.Rel b), Database.Selda.Generic.GRelation a, Database.Selda.Generic.GRelation b) => Database.Selda.Generic.GRelation (a GHC.Generics.:*: b)
- Database.Selda.Generic: instance (a Database.Selda.Types.:*: b) ~ (a Database.Selda.Generic.:++: b) => Database.Selda.Generic.Append a b
- Database.Selda.Generic: instance Database.Selda.Generic.Append b c => Database.Selda.Generic.Append (a Database.Selda.Types.:*: b) c
+ Database.Selda: app :: Append a b => a -> b -> a :++: b
+ Database.Selda: class Append a b
+ Database.Selda: class TableSpec a
+ Database.Selda.Generic: instance (Database.Selda.Types.Append (Database.Selda.Generic.Rel a) (Database.Selda.Generic.Rel b), Database.Selda.Generic.GRelation a, Database.Selda.Generic.GRelation b) => Database.Selda.Generic.GRelation (a GHC.Generics.:*: b)
- Database.Selda: table :: TableName -> ColSpec a -> Table a
+ Database.Selda: table :: forall a. TableSpec a => TableName -> ColSpecs a -> Table a
Files
- ChangeLog.md +5/−0
- README.md +8/−8
- selda.cabal +1/−1
- src/Database/Selda.hs +4/−4
- src/Database/Selda/Caching.hs +4/−8
- src/Database/Selda/Generic.hs +0/−15
- src/Database/Selda/Table.hs +18/−50
- src/Database/Selda/Types.hs +16/−1
ChangeLog.md view
@@ -1,5 +1,10 @@ # Revision history for selda +## 0.1.2.0 -- 2017-04-20++* Replace `¤` with `:*:` in table definitions.++ ## 0.1.1.1 -- 2017-04-20 * Generic tables, queries and mutation.
README.md view
@@ -56,17 +56,17 @@ `OverloadedStrings` extensions. Table schemas are defined as the product of one or more columns, stitched-together using the `¤` operator.+together using the `:*:` operator. A table is parameterized over the types of its columns, with the column types-separated by the `:*:` operator. This, by the way, is why you need+also separated by the `:*:` operator. This, by the way, is why you need `TypeOperators`. ``` people :: Table (Text :*: Int :*: Maybe Text)-people = table "people" $ primary "name" ¤ required "age" ¤ optional "pet"+people = table "people" $ primary "name" :*: required "age" :*: optional "pet" addresses :: Table (Text :*: Text)-addresses = table "addresses" $ required "name" ¤ required "city"+addresses = table "addresses" $ required "name" :*: required "city" ``` Columns may be either `required` or `optional`.@@ -181,10 +181,10 @@ ``` people' :: Table (Int :*: Text :*: Int :*: Maybe Text) people' = table "people_with_ids"- $ autoPrimary "id"- ¤ required "name"- ¤ required "age"- ¤ optional "pet"+ $ autoPrimary "id"+ :*: required "name"+ :*: required "age"+ :*: optional "pet" populate' :: SeldaT IO () populate' = do
selda.cabal view
@@ -1,5 +1,5 @@ name: selda-version: 0.1.1.1+version: 0.1.2.0 synopsis: Type-safe, high-level EDSL for interacting with relational databases. description: This package provides an EDSL for writing portable, type-safe, high-level database code. Its feature set includes querying and modifying databases,
src/Database/Selda.hs view
@@ -34,12 +34,11 @@ , update, update_ , deleteFrom, deleteFrom_ -- * Defining schemas- , ColSpec, TableName, ColName+ , TableSpec, ColSpecs, ColSpec, TableName, ColName , NonNull, IsNullable, Nullable, NotNullable- , table, (¤), required, optional+ , Append (..), (:++:)+ , table, required, optional , primary, autoPrimary- -- * Combining schemas- , ComposeSpec, (:+++:), (+++) -- * Creating and dropping tables , createTable, tryCreateTable , dropTable, tryDropTable@@ -82,6 +81,7 @@ (.>=) = liftC2 $ BinOp Gte (.<=) = liftC2 $ BinOp Lte infixl 4 .==+infixl 4 ./= infixl 4 .> infixl 4 .< infixl 4 .>=
src/Database/Selda/Caching.hs view
@@ -139,13 +139,9 @@ -- | Set the maximum number of items allowed in the cache. setMaxItems :: Int -> IO ()-setMaxItems n = atomicModifyIORef' theCache $ \c -> (setMaxItems' n c, ())---- | The the maximum number of items for the cache.-getMaxItems :: IO Int-getMaxItems = maxItems <$> readIORef theCache+setMaxItems n = atomicModifyIORef' theCache $ \_ -> (setMaxItems' n, ()) -setMaxItems' :: Int -> ResultCache -> ResultCache-setMaxItems' 0 _ = emptyCache-setMaxItems' n rc = emptyCache {maxItems = n}+setMaxItems' :: Int -> ResultCache+setMaxItems' 0 = emptyCache+setMaxItems' n = emptyCache {maxItems = n} #endif
src/Database/Selda/Generic.hs view
@@ -247,21 +247,6 @@ isMaybeType _ = True instance {-# OVERLAPPABLE #-} Traits a --- | Normalized append of two inductive tuples.--- Note that this will flatten any nested inductive tuples.-type family a :++: b where- (a :*: b) :++: c = a :*: (b :++: c)- a :++: b = a :*: b--class Append a b where- app :: a -> b -> a :++: b--instance {-# OVERLAPPING #-} Append b c => Append (a :*: b) c where- app (a :*: b) c = a :*: app b c--instance ((a :*: b) ~ (a :++: b)) => Append a b where- app a b = a :*: b- -- | The relation corresponding to the given type. type family Rel (rep :: * -> *) where Rel (M1 t c a) = Rel a
src/Database/Selda/Table.hs view
@@ -1,5 +1,4 @@-{-# LANGUAGE GADTs, TypeOperators, OverloadedStrings #-}-{-# LANGUAGE MultiParamTypeClasses, TypeFamilies, RankNTypes #-}+{-# LANGUAGE TypeOperators, TypeFamilies, OverloadedStrings #-} {-# LANGUAGE UndecidableInstances, FlexibleInstances, ScopedTypeVariables #-} -- | Selda table definition language. module Database.Selda.Table where@@ -10,38 +9,6 @@ import Data.List (sort, group) import Data.Monoid -type family a :+++: b where- (a :*: b) :+++: c = a :*: (b :+++: c)- a :+++: b = a :*: b-infixr 5 :+++:-infixr 5 +++--class ComposeSpec t a b where- -- | Combine the given tables or column specifications into a new- -- column specification which can be used to create a new table.- -- Useful for building composable table specifications.- --- -- Note that this function is only suitable for combining specifications- -- which have a concrete type. To build a column specification from scratch,- -- use '(¤)' instead.- (+++) :: t a -> t b -> ColSpec (a :+++: b)--instance (ComposeSpec Table a b, ComposeSpec Table b c) =>- ComposeSpec Table (a :*: b) c where- a +++ b = ColSpec $ tableCols a ++ tableCols b--instance {-# OVERLAPPABLE #-} ((a :+++: b) ~ (a :*: b)) =>- ComposeSpec Table a b where- a +++ b = ColSpec $ tableCols a ++ tableCols b--instance (ComposeSpec ColSpec a b, ComposeSpec ColSpec b c) =>- ComposeSpec ColSpec (a :*: b) c where- ColSpec a +++ ColSpec b = ColSpec $ a ++ b--instance {-# OVERLAPPABLE #-} ((a :+++: b) ~ (a :*: b)) =>- ComposeSpec ColSpec a b where- ColSpec a +++ ColSpec b = ColSpec $ a ++ b- -- | A database table. -- Tables are parameterized over their column types. For instance, a table -- containing one string and one integer, in that order, would have the type@@ -70,19 +37,7 @@ }] -- | A table column specification.-newtype ColSpec a = ColSpec [ColInfo]---- | Combine two column specifications.--- Table descriptions are built by chaining columns using this operator:------ > people :: Table (Text :*: Int :*: Maybe Text)--- > people = table "people" $ required "name" ¤ required "age" ¤ optional "pet"------ To combine two pre-built tables into a table comprised of both tables'--- fields, see '(+++)'.-(¤) :: ColSpec a -> ColSpec b -> ColSpec (a :*: b)-ColSpec a ¤ ColSpec b = ColSpec (a ++ b)-infixr 1 ¤+newtype ColSpec a = ColSpec {unCS :: [ColInfo]} -- | Used by 'IsNullable' to indicate a nullable type. data Nullable@@ -131,11 +86,24 @@ addAttr attr (ColSpec [ci]) = ColSpec [ci {colAttrs = attr : colAttrs ci}] addAttr _ _ = error "impossible: SqlType ColSpec with several columns" +-- | An inductive tuple where each element is a column specification.+type family ColSpecs a where+ ColSpecs (a :*: b) = ColSpec a :*: ColSpecs b+ ColSpecs a = ColSpec a++-- | An inductive tuple forming a table specification.+class TableSpec a where+ mergeSpecs :: Proxy a -> ColSpecs a -> [ColInfo]+instance TableSpec b => TableSpec (a :*: b) where+ mergeSpecs _ (ColSpec a :*: b) = a ++ mergeSpecs (Proxy :: Proxy b) b+instance {-# OVERLAPPABLE #-} ColSpecs a ~ ColSpec a => TableSpec a where+ mergeSpecs _ (ColSpec a) = a+ -- | A table with the given name and columns.-table :: TableName -> ColSpec a -> Table a-table name (ColSpec cs) = Table+table :: forall a. TableSpec a => TableName -> ColSpecs a -> Table a+table name cs = Table { tableName = name- , tableCols = validate name $ map tidy cs+ , tableCols = validate name $ map tidy $ mergeSpecs (Proxy :: Proxy a) cs } -- | Remove duplicate attributes.
src/Database/Selda/Types.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE GADTs, TypeOperators, TypeFamilies, FlexibleInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses #-} -- | Basic Selda types. module Database.Selda.Types where import Data.Text (Text)@@ -82,3 +82,18 @@ tenth :: Tup j => (a :*: b :*: c :*: d :*: e :*: f :*: g :*: h :*: i :*: j) -> Head j tenth (_ :*: _ :*: _ :*: _ :*: _ :*: _ :*: _ :*: _ :*: _ :*: j) = tupHead j++-- | Normalized append of two inductive tuples.+-- Note that this will flatten any nested inductive tuples.+type family a :++: b where+ (a :*: b) :++: c = a :*: (b :++: c)+ a :++: b = a :*: b++class Append a b where+ app :: a -> b -> a :++: b++instance {-# OVERLAPPING #-} Append b c => Append (a :*: b) c where+ app (a :*: b) c = a :*: app b c++instance ((a :*: b) ~ (a :++: b)) => Append a b where+ app a b = a :*: b