selda 0.3.0.0 → 0.3.1.0
raw patch · 6 files changed
+23/−39 lines, 6 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Database.Selda.Unsafe: unsafeSelector :: SqlRow a => Int -> Selector a b
- Database.Selda: [:-] :: (a -> b) -> Attribute a b -> Attr a
+ Database.Selda: [:-] :: Selector a b -> Attribute a b -> Attr a
Files
- ChangeLog.md +5/−0
- selda.cabal +1/−1
- src/Database/Selda/Generic.hs +1/−31
- src/Database/Selda/Selectors.hs +9/−1
- src/Database/Selda/Table.hs +5/−6
- src/Database/Selda/Unsafe.hs +2/−0
ChangeLog.md view
@@ -1,6 +1,11 @@ # Revision history for Selda +## 0.3.1.0 -- 2018-08-06++* Minor API fix when defining table attributes.++ ## 0.3.0.0 -- 2018-08-05 * Support for Stack and GHC 8.4.
selda.cabal view
@@ -1,5 +1,5 @@ name: selda-version: 0.3.0.0+version: 0.3.1.0 synopsis: Multi-backend, high-level EDSL for interacting with SQL 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/Generic.hs view
@@ -6,7 +6,7 @@ -- | Generics utilities. module Database.Selda.Generic ( Relational, Generic- , tblCols, mkDummy, identify, params, def, gNew+ , tblCols, params, def, gNew ) where import Control.Monad.State import Data.Dynamic@@ -20,7 +20,6 @@ import qualified GHC.TypeLits as TL import qualified GHC.Generics as G ((:+:)(..)) #endif-import Unsafe.Coerce import Control.Exception (Exception (..), try, throw) import System.IO.Unsafe import Database.Selda.Types@@ -49,18 +48,6 @@ , GSelectors a (Rep a) ) --- | A dummy of some type. Encapsulated to avoid improper use, since all of--- its fields are 'unsafeCoerce'd ints.-newtype Dummy a = Dummy a---- | Create a dummy of the given type.-mkDummy :: (Generic a, GRelation (Rep a)) => Dummy a-mkDummy = Dummy $ to $ evalState gMkDummy 0---- | Get the selector identifier of the given selector for the given dummy.-identify :: Dummy a -> (a -> b) -> Int-identify (Dummy d) f = unsafeCoerce $ f d- -- | Extract all insert parameters from a generic value. params :: Relational a => a -> [Either Param Param] params = unsafePerformIO . gParams . from@@ -99,17 +86,12 @@ -> (Int -> Maybe ColName -> ColName) -> State Int [ColInfo] - -- | Create a dummy value where all fields are replaced by @unsafeCoerce@'d- -- ints. See 'mkDummy' and 'identify' for more information.- gMkDummy :: State Int (f a)- -- | Create a new value with all default fields. gNew :: Proxy f -> [UntypedCol sql] instance {-# OVERLAPPABLE #-} GRelation a => GRelation (M1 t c a) where gParams (M1 x) = gParams x gTblCols _ = gTblCols (Proxy :: Proxy a)- gMkDummy = M1 <$> gMkDummy gNew _ = gNew (Proxy :: Proxy a) instance {-# OVERLAPPING #-} (G.Selector c, GRelation a) =>@@ -121,7 +103,6 @@ case selName ((M1 undefined) :: M1 S c a b) of "" -> Nothing s -> Just (mkColName $ pack s)- gMkDummy = M1 <$> gMkDummy gNew _ = gNew (Proxy :: Proxy a) instance (Typeable a, SqlType a) => GRelation (K1 i a) where@@ -151,11 +132,6 @@ | typeRepTyCon (typeRep (Proxy :: Proxy a)) == maybeTyCon = [Optional] | otherwise = [Required] - gMkDummy = do- n <- get- put (n+1)- return $ unsafeCoerce n- gNew _ = [Untyped (Lit (defaultValue :: Lit a))] instance (GRelation a, GRelation b) => GRelation (a G.:*: b) where@@ -167,10 +143,6 @@ where a = Proxy :: Proxy a b = Proxy :: Proxy b- gMkDummy = do- a <- gMkDummy :: State Int (a x)- b <- gMkDummy :: State Int (b x)- return (a G.:*: b) gNew _ = gNew (Proxy :: Proxy a) ++ gNew (Proxy :: Proxy b) #if MIN_VERSION_base(4, 9, 0)@@ -182,7 +154,6 @@ )) => GRelation (a G.:+: b) where gParams = error "unreachable" gTblCols = error "unreachable"- gMkDummy = error "unreachable" gNew = error "unreachable" instance {-# OVERLAPS #-}@@ -193,6 +164,5 @@ )) => GRelation (K1 i (C.Col s a)) where gParams = error "unreachable" gTblCols = error "unreachable"- gMkDummy = error "unreachable" gNew = error "unreachable" #endif
src/Database/Selda/Selectors.hs view
@@ -5,9 +5,10 @@ module Database.Selda.Selectors ( Assignment ((:=)), Selected, Selector, Source, Selectors, GSelectors , (!), with, ($=)- , selectorsFor, selectorIndex+ , selectorsFor, selectorIndex, unsafeSelector ) where import Control.Monad.State.Strict+import Database.Selda.SqlRow (SqlRow) import Database.Selda.SqlType import Database.Selda.Types import Database.Selda.Column@@ -29,6 +30,13 @@ type family Source a where Source (Maybe a) = a Source a = a++-- | A selector indicating the nth (zero-based) column of a table.+--+-- Will cause errors in queries during compilation, execution, or both,+-- unless handled with extreme care. You really shouldn't use it at all.+unsafeSelector :: SqlRow a => Int -> Selector a b+unsafeSelector = Selector -- | Extract the given column from the given row. -- Extracting a value from a nullable column will yield a nullable value.
src/Database/Selda/Table.hs view
@@ -30,7 +30,7 @@ -- Essentially a pair or a record selector over the type @a@ and a column -- attribute. data Attr a where- (:-) :: (a -> b) -> Attribute a b -> Attr a+ (:-) :: Selector a b -> Attribute a b -> Attr a -- | Generate a table from the given table name and list of column attributes. -- All @Maybe@ fields in the table's type will be represented by nullable@@ -90,19 +90,18 @@ , tableHasAutoPK = apk } where- dummy = mkDummy cols = zipWith addAttrs [0..] (tblCols (Proxy :: Proxy a) fieldMod) apk = or [AutoIncrement `elem` as | _ :- Attribute as <- attrs] addAttrs n ci = ci { colAttrs = colAttrs ci ++ concat [ as- | f :- Attribute as <- attrs- , identify dummy f == n+ | sel :- Attribute as <- attrs+ , selectorIndex sel == n ] , colFKs = colFKs ci ++ [ thefk- | f :- ForeignKey thefk <- attrs- , identify dummy f == n+ | sel :- ForeignKey thefk <- attrs+ , selectorIndex sel == n ] }
src/Database/Selda/Unsafe.hs view
@@ -6,9 +6,11 @@ , aggr , cast , castAggr+ , unsafeSelector ) where import Database.Selda.Column import Database.Selda.Inner (Aggr, aggr, liftAggr)+import Database.Selda.Selectors (unsafeSelector) import Database.Selda.SqlType import Data.Text (Text) import Data.Proxy