opaleye 0.7.6.0 → 0.7.6.1
raw patch · 12 files changed
+38/−438 lines, 12 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +4/−0
- Doc/Tutorial/Main.hs +0/−1
- Doc/Tutorial/TutorialBasicTypeFamilies.lhs +0/−399
- Test/Opaleye/Test/Arbitrary.hs +2/−2
- Test/Test.hs +8/−8
- opaleye.cabal +2/−3
- src/Opaleye/FunctionalJoin.hs +5/−8
- src/Opaleye/Internal/Constant.hs +1/−1
- src/Opaleye/Internal/Unpackspec.hs +1/−1
- src/Opaleye/Join.hs +8/−11
- src/Opaleye/RunSelect.hs +5/−4
- src/Opaleye/TypeFamilies.hs +2/−0
CHANGELOG.md view
@@ -1,3 +1,7 @@+## 0.7.6.1++No user-visible changes+ ## 0.7.6.0 * Added `matchMaybe`
Doc/Tutorial/Main.hs view
@@ -1,6 +1,5 @@ import TutorialBasic () import TutorialBasicMonomorphic ()-import TutorialBasicTypeFamilies () import TutorialManipulation () import TutorialAdvanced () import DefaultExplanation ()
− Doc/Tutorial/TutorialBasicTypeFamilies.lhs
@@ -1,399 +0,0 @@-> {-# LANGUAGE FlexibleContexts #-}-> {-# LANGUAGE FlexibleInstances #-}-> {-# LANGUAGE MultiParamTypeClasses #-}-> {-# LANGUAGE UndecidableInstances #-}->-> {-# LANGUAGE TypeFamilies #-}-> {-# LANGUAGE EmptyDataDecls #-}-> {-# LANGUAGE FunctionalDependencies #-}-> {-# LANGUAGE NoMonomorphismRestriction #-}-> {-# LANGUAGE DataKinds #-}-> {-# LANGUAGE TypeOperators #-}->-> module TutorialBasicTypeFamilies where->-> import Prelude hiding (sum)->-> import Opaleye (Field,-> Table, table, tableField, selectTable,-> Select, (.==), aggregate, groupBy,-> count, avg, sum, leftJoin, runSelect, runSelectTF,-> showSql, Unpackspec,-> SqlInt4, SqlInt8, SqlText, SqlDate, SqlFloat8)->-> import qualified Opaleye as O-> import qualified Opaleye.Map as M-> import Opaleye.TypeFamilies (O, H, NN, Req, Nulls, W,-> TableRecordField, IMap, F,-> (:<$>), (:<*>))->-> import qualified Data.Profunctor as P-> import qualified Data.Profunctor.Product as PP-> import Data.Profunctor.Product (p3)-> import Data.Profunctor.Product.Default (Default)-> import qualified Data.Profunctor.Product.Default as D->-> import Data.Time.Calendar (Day)->-> import qualified Database.PostgreSQL.Simple as PGS--Introduction-============--In this example file I'll give you a brief introduction to the Opaleye-relational query EDSL. I'll show you how to define tables in Opaleye;-use them to generate selects, joins and filters; use the API of-Opaleye to make your queries more composable; and finally run the-queries on Postgres.--Schema-======--Opaleye assumes that a Postgres database already exists. Currently-there is no support for creating databases or tables, though these-features may be added later according to demand.--A table is defined with the `table` function. The syntax is-simple. You specify the types of the fields, the name of the table-and the names of the fields in the underlying database.--(Note: This simple syntax is supported by an extra combinator that-describes the shape of the container that you are storing the fields-in. In the first example we are using a tuple of size 3 and the-combinator is called `p3`. We'll see examples of others later.)--The `Table` type constructor has two arguments. The first one tells-us what fields we can write to the table and the second what fields-we can read from the table. In this case all fields are required, so-the write and read types will be the same.--> personTable :: Table (Field SqlText, Field SqlInt4, Field SqlText)-> (Field SqlText, Field SqlInt4, Field SqlText)-> personTable = table "personTable" (p3 ( tableField "name"-> , tableField "age"-> , tableField "address" ))--By default, the table `"personTable"` is looked up in PostgreSQL's-default `"public"` schema. If we wanted to specify a different schema we-could have used the `tableWithSchema` function instead of `table`.--To select from a table we use `selectTable`.--(Here and in a few other places in Opaleye there is some typeclass-magic going on behind the scenes to reduce boilerplate. However, you-never *have* to use typeclasses. All the magic that typeclasses do is-also available by explicitly passing in the "typeclass dictionary".-For this example file we will always use the typeclass versions-because they are simpler to read and the typeclass magic is-essentially invisible.)--> personSelect :: Select (Field SqlText, Field SqlInt4, Field SqlText)-> personSelect = selectTable personTable--A `Select` corresponds to an SQL SELECT that we can run. Here is the-SQL generated for `personSelect`. (`printSQL` is just a convenient-utility function for the purposes of this example file. See below for-its definition.)-- ghci> printSql personSelect- SELECT name0_1 as result1,- age1_1 as result2,- address2_1 as result3- FROM (SELECT *- FROM (SELECT name as name0_1,- age as age1_1,- address as address2_1- FROM personTable as T1) as T1) as T1--This SQL is functionally equivalent to the following "idealized" SQL.-In this document every example of SQL generated by Opaleye will be-followed by an "idealized" equivalent version. This will give you-some idea of how readable the SQL generated by Opaleye is. Eventually-Opaleye should generate SQL closer to the "idealized" version, but-that is an ongoing project. Since Postgres has a sensible query-optimization engine there should be little difference in performance-between Opaleye's version and the ideal. Please submit any-differences encountered in practice as an Opaleye bug.-- SELECT name,- age- address- FROM personTable---Record types---------------Opaleye can use user defined types such as record types in queries.--Contrary to popular belief, you don't have to define your data types-to be polymorphic in all their fields. In fact there's a nice scheme-using type families that reduces boiler plate and has always been-compatible with Opaleye!--> data Birthday f = Birthday { bdName :: TableRecordField f String SqlText NN Req-> , bdDay :: TableRecordField f Day SqlDate NN Req-> }--This instance, adaptor and type family are fully derivable by Template-Haskell or generics but I haven't got round to writing that yet.-Please volunteer to do that if you can.--> instance ( PP.ProductProfunctor p-> , Default p (TableRecordField a String SqlText NN Req)-> (TableRecordField b String SqlText NN Req)-> , Default p (TableRecordField a Day SqlDate NN Req)-> (TableRecordField b Day SqlDate NN Req)) =>-> Default p (Birthday a) (Birthday b) where-> def = pBirthday (Birthday D.def D.def)->-> pBirthday :: PP.ProductProfunctor p-> => Birthday (p :<$> a :<*> b)-> -> p (Birthday a) (Birthday b)-> pBirthday b = Birthday PP.***$ P.lmap bdName (bdName b)-> PP.**** P.lmap bdDay (bdDay b)->-> type instance M.Map g (Birthday (F f)) = Birthday (F (IMap g f))--Then we can use 'table' to make a table on our record type in exactly-the same way as before.--> birthdayTable :: Table (Birthday W) (Birthday O)-> birthdayTable = table "birthdayTable" $ pBirthday $ Birthday {-> bdName = tableField "name"-> , bdDay = tableField "birthday"-> }->-> birthdaySelect :: Select (Birthday O)-> birthdaySelect = selectTable birthdayTable-- ghci> printSql birthdaySelect- SELECT name0_1 as result1,- birthday1_1 as result2- FROM (SELECT *- FROM (SELECT name as name0_1,- birthday as birthday1_1- FROM birthdayTable as T1) as T1) as T1--Idealized SQL:-- SELECT name,- birthday- FROM birthdayTable---Aggregation-===========--Type safe aggregation is the jewel in the crown of Opaleye. Even SQL-generating APIs which are otherwise type safe often fall down when it-comes to aggregation. If you want to find holes in the type system of-an SQL generating language, aggregation is the best place to look! By-contrast, Opaleye aggregations always generate meaningful SQL.--By way of example, suppose we have a widget table which contains the-style, color, location, quantity and radius of widgets. We can model-this information with the following datatype.--> data Widget f = Widget { style :: TableRecordField f String SqlText NN Req-> , color :: TableRecordField f String SqlText NN Req-> , location :: TableRecordField f String SqlText NN Req-> , quantity :: TableRecordField f Int SqlInt4 NN Req-> , radius :: TableRecordField f Double SqlFloat8 NN Req-> }--This instance, adaptor and type family are fully derivable but no-one's implemented the Template Haskell or generics to do that yet.--> instance ( PP.ProductProfunctor p-> , Default p (TableRecordField a String SqlText NN Req)-> (TableRecordField b String SqlText NN Req)-> , Default p (TableRecordField a Int SqlInt4 NN Req)-> (TableRecordField b Int SqlInt4 NN Req)-> , Default p (TableRecordField a Double SqlFloat8 NN Req)-> (TableRecordField b Double SqlFloat8 NN Req)) =>-> Default p (Widget a) (Widget b) where-> def = pWidget (Widget D.def D.def D.def D.def D.def)->-> pWidget :: PP.ProductProfunctor p-> => Widget (p :<$> a :<*> b)-> -> p (Widget a) (Widget b)-> pWidget w = Widget PP.***$ P.lmap style (style w)-> PP.**** P.lmap color (color w)-> PP.**** P.lmap location (location w)-> PP.**** P.lmap quantity (quantity w)-> PP.**** P.lmap radius (radius w)->-> type instance M.Map g (Widget (F f)) = Widget (F (IMap g f))--For the purposes of this example the style, color and location will be-strings, but in practice they might have been a different data type.--> widgetTable :: Table (Widget W) (Widget O)-> widgetTable = table "widgetTable" $ pWidget $ Widget {-> style = tableField "style"-> , color = tableField "color"-> , location = tableField "location"-> , quantity = tableField "quantity"-> , radius = tableField "radius"-> }--Say we want to group by the style and color of widgets, calculating-how many (possibly duplicated) locations there are, the total number-of such widgets and their average radius. `aggregateWidgets` shows us-how to do this.--> aggregateWidgets :: Select (Field SqlText, Field SqlText, Field SqlInt8,-> Field SqlInt4, Field SqlFloat8)-> aggregateWidgets = aggregate ((,,,,) <$> P.lmap style groupBy-> <*> P.lmap color groupBy-> <*> P.lmap location count-> <*> P.lmap quantity sum-> <*> P.lmap radius avg)-> (selectTable widgetTable)--The generated SQL is-- ghci> printSql aggregateWidgets- SELECT result0_2 as result1,- result1_2 as result2,- result2_2 as result3,- result3_2 as result4,- result4_2 as result5- FROM (SELECT *- FROM (SELECT style0_1 as result0_2,- color1_1 as result1_2,- COUNT(location2_1) as result2_2,- SUM(quantity3_1) as result3_2,- AVG(radius4_1) as result4_2- FROM (SELECT *- FROM (SELECT style as style0_1,- color as color1_1,- location as location2_1,- quantity as quantity3_1,- radius as radius4_1- FROM widgetTable as T1) as T1) as T1- GROUP BY style0_1,- color1_1) as T1) as T1--Idealized SQL:-- SELECT style,- color,- COUNT(location),- SUM(quantity),- AVG(radius)- FROM widgetTable- GROUP BY style, color--Note: In `widgetTable` and `aggregateWidgets` we see more explicit-uses of our Template Haskell derived code. We use the 'pWidget'-"adaptor" to specify how fields are aggregated.--Outer join-==========--Opaleye supports outer joins (i.e. left joins, right joins and full-outer joins). An outer join is expressed by specifying the two tables-to join and the join condition.--> personBirthdayLeftJoin :: Select ((Field SqlText, Field SqlInt4, Field SqlText),-> Birthday Nulls)-> personBirthdayLeftJoin = leftJoin personSelect birthdaySelect eqName-> where eqName ((name, _, _), birthdayRow) = name .== bdName birthdayRow--The generated SQL is-- ghci> printSql personBirthdayLeftJoin- SELECT result1_0_3 as result1,- result1_1_3 as result2,- result1_2_3 as result3,- result2_0_3 as result4,- result2_1_3 as result5- FROM (SELECT *- FROM (SELECT name0_1 as result1_0_3,- age1_1 as result1_1_3,- address2_1 as result1_2_3,- name0_2 as result2_0_3,- birthday1_2 as result2_1_3- FROM- (SELECT *- FROM (SELECT name as name0_1,- age as age1_1,- address as address2_1- FROM personTable as T1) as T1) as T1- LEFT OUTER JOIN- (SELECT *- FROM (SELECT name as name0_2,- birthday as birthday1_2- FROM birthdayTable as T1) as T1) as T2- ON- (name0_1) = (name0_2)) as T1) as T1--Idealized SQL:-- SELECT name0,- age0,- address0,- name1,- birthday1- FROM (SELECT name as name0,- age as age0,- address as address0- FROM personTable) as T1- LEFT OUTER JOIN- (SELECT name as name1,- birthday as birthday1- FROM birthdayTable) as T1- ON name0 = name1--Types of joins are inferrable in new versions of Opaleye. Here is a-(rather silly) example.--> typeInferred =-> O.fullJoinInferrable (O.fullJoinInferrable-> birthdaySelect-> (selectTable widgetTable)-> (const (O.sqlBool True)))-> birthdaySelect-> (const (O.sqlBool True))--Running queries on Postgres-===========================---Opaleye provides simple facilities for running queries on Postgres.-`runSelect` is a typeclass polymorphic function that effectively has-the following type--> -- runSelect :: Database.PostgreSQL.Simple.Connection-> -- -> Select fields -> IO [haskells]--It converts a "record" of Opaleye fields to a list of "records" of-Haskell values. Like `leftJoin` this particular formulation uses-typeclasses so please put type signatures on everything in sight to-minimize the number of confusing error messages!--> runBirthdaySelect :: PGS.Connection-> -> Select (Birthday O)-> -> IO [Birthday H]-> runBirthdaySelect = runSelect--The type of selects can be inferred if you use the `runSelectTF`-function.--> -- printNames :: PGS.Connection -> Select (Birthday O) -> IO ()-> printNames conn select = mapM_ (print . bdName) =<< runSelectTF conn select--Conclusion-==========--There ends the Opaleye introductions module. Please send me your questions!--Utilities-=========--This is a little utility function to help with printing generated SQL.--> printSql :: Default Unpackspec a a => Select a -> IO ()-> printSql = putStrLn . maybe "Empty select" id . showSql
Test/Opaleye/Test/Arbitrary.hs view
@@ -54,7 +54,7 @@ twoIntTable :: String -> O.Table (O.Field O.SqlInt4, O.Field O.SqlInt4) (O.Field O.SqlInt4, O.Field O.SqlInt4)-twoIntTable n = O.Table n (PP.p2 (O.requiredTableField "column1",+twoIntTable n = O.table n (PP.p2 (O.requiredTableField "column1", O.requiredTableField "column2")) table1 :: O.Table (O.Field O.SqlInt4, O.Field O.SqlInt4)@@ -421,7 +421,7 @@ arbitrarySelectArrMaybeRecurse0 = arbitraryG ArbitrarySelectArrMaybe [ fmap (\fg -> fg <*> TQ.arbitrary)- [ pure (Arrow.arr . fmap . unArbitraryFunction) ]+ [ pure (Arrow.arr . fmap . (\x -> unArbitraryFunction x)) ] ] arbitrarySelectArrMaybeRecurse1 :: [Int -> TQ.Gen ArbitrarySelectArrMaybe]
Test/Test.hs view
@@ -93,7 +93,7 @@ twoIntTable :: String -> O.Table (Field O.SqlInt4, Field O.SqlInt4) (Field O.SqlInt4, Field O.SqlInt4)-twoIntTable n = O.Table n (PP.p2 (required "column1", required "column2"))+twoIntTable n = O.table n (PP.p2 (required "column1", required "column2")) table1 :: O.Table (Field O.SqlInt4, Field O.SqlInt4) (Field O.SqlInt4, Field O.SqlInt4)@@ -119,29 +119,29 @@ table5 :: O.Table (Maybe (Field O.SqlInt4), Maybe (Field O.SqlInt4)) (Field O.SqlInt4, Field O.SqlInt4)-table5 = O.TableWithSchema "public" "table5"+table5 = O.tableWithSchema "public" "table5" (PP.p2 (O.optionalTableField "column1", O.optionalTableField "column2")) table6 :: O.Table (Field O.SqlText, Field O.SqlText) (Field O.SqlText, Field O.SqlText)-table6 = O.Table "table6" (PP.p2 (required "column1", required "column2"))+table6 = O.table "table6" (PP.p2 (required "column1", required "column2")) table7 :: O.Table (Field O.SqlText, Field O.SqlText) (Field O.SqlText, Field O.SqlText)-table7 = O.Table "table7" (PP.p2 (required "column1", required "column2"))+table7 = O.table "table7" (PP.p2 (required "column1", required "column2")) table8 :: O.Table (Field O.SqlJson) (Field O.SqlJson)-table8 = O.Table "table8" (required "column1")+table8 = O.table "table8" (required "column1") table9 :: O.Table (Field O.SqlJsonb) (Field O.SqlJsonb)-table9 = O.Table "table9" (required "column1")+table9 = O.table "table9" (required "column1") table10 :: O.Table (Field O.SqlInt4) (Field O.SqlInt4)-table10 = O.Table "table10" (required "column1")+table10 = O.table "table10" (required "column1") tableKeywordColNames :: O.Table (Field O.SqlInt4, Field O.SqlInt4) (Field O.SqlInt4, Field O.SqlInt4)-tableKeywordColNames = O.Table "keywordtable"+tableKeywordColNames = O.table "keywordtable" (PP.p2 (required "column", required "where")) table1Q :: Select (Field O.SqlInt4, Field O.SqlInt4)
opaleye.cabal view
@@ -1,6 +1,6 @@ name: opaleye copyright: Copyright (c) 2014-2018 Purely Agile Limited; 2019-2021 Tom Ellis-version: 0.7.6.0+version: 0.7.6.1 synopsis: An SQL-generating DSL targeting PostgreSQL description: An SQL-generating DSL targeting PostgreSQL. Allows Postgres queries to be written within Haskell in a@@ -17,7 +17,7 @@ extra-doc-files: README.md CHANGELOG.md *.md-tested-with: GHC==8.10, GHC==8.8, GHC==8.6, GHC==8.4, GHC==8.2, GHC==8.0+tested-with: GHC==9.0, GHC==8.10, GHC==8.8, GHC==8.6, GHC==8.4, GHC==8.2, GHC==8.0 source-repository head type: git@@ -157,7 +157,6 @@ TutorialBasic, TutorialManipulation, TutorialBasicMonomorphic,- TutorialBasicTypeFamilies, DefaultExplanation hs-source-dirs: Doc/Tutorial build-depends:
src/Opaleye/FunctionalJoin.hs view
@@ -8,15 +8,8 @@ module Opaleye.FunctionalJoin ( -- * Full outer join fullJoinF,- -- * Other joins- -- ** Inner join- -- | It is recommended that instead of @joinF@ you use- -- 'Opaleye.Operators.restrict' directly (along with @do@- -- notatation, 'Control.Applicative.<*>', or arrow notation).+ -- ** Deprecated joinF,- -- ** Left/right joins- -- | It is recommended that instead of @leftJoinF@ and @rightJoinF@- -- you use 'Opaleye.Join.optional'. leftJoinF, rightJoinF, ) where@@ -37,6 +30,8 @@ import qualified Opaleye.SqlTypes as T import qualified Opaleye.Operators as O +-- | Use 'Opaleye.Operators.where_' and @do@ notation instead. Will+-- be deprecated in 0.8. joinF :: (fieldsL -> fieldsR -> fieldsResult) -- ^ Calculate result fields from input fields -> (fieldsL -> fieldsR -> F.Field T.SqlBool)@@ -49,6 +44,7 @@ joinF f cond l r = fmap (uncurry f) (O.keepWhen (uncurry cond) <<< ((,) <$> l <*> r)) +-- | Use 'Opaleye.Join.optional' instead. Will be deprecated in 0.8. leftJoinF :: (D.Default IO.IfPP fieldsResult fieldsResult, D.Default IU.Unpackspec fieldsL fieldsL, D.Default IU.Unpackspec fieldsR fieldsR)@@ -80,6 +76,7 @@ (F.FieldNullable T.SqlBool) nullmakerBool = D.def +-- | Use 'Opaleye.Join.optional' instead. Will be deprecated in 0.8. rightJoinF :: (D.Default IO.IfPP fieldsResult fieldsResult, D.Default IU.Unpackspec fieldsL fieldsL, D.Default IU.Unpackspec fieldsR fieldsR)
src/Opaleye/Internal/Constant.hs view
@@ -141,7 +141,7 @@ def = toToFields T.sqlValueJSONB instance D.Default ToFields haskell (Column sql) => D.Default ToFields (Maybe haskell) (Maybe (Column sql)) where- def = toToFields (constant <$>)+ def = toToFields (toFields <$>) instance (D.Default ToFields a (Column b), T.IsSqlType b) => D.Default ToFields [a] (Column (T.SqlArray b)) where
src/Opaleye/Internal/Unpackspec.hs view
@@ -56,7 +56,7 @@ where f pe = ([pe], pe) instance D.Default Unpackspec (C.Column a) (C.Column a) where- def = unpackspecColumn+ def = unpackspecField -- {
src/Opaleye/Join.hs view
@@ -27,8 +27,9 @@ -- which provide APIs that are more familiar to a Haskell programmer -- and more composable: ----- - Inner joins: use 'Opaleye.Operators.restrict' directly (along--- with @do@ notatation, 'Control.Applicative.<*>', or arrow notation)+-- - Inner joins: use 'Opaleye.Operators.where_' directly, along with+-- @do@ notatation (or use 'Opaleye.Operators.restrict' directly,+-- along with arrow notation) -- -- - Left/right joins: use 'optional' --@@ -40,11 +41,7 @@ -- -- - Left/right joins which really must not use @LATERAL@: use 'optionalRestrict' ----- - Full outer joins: use 'Opaleye.FunctionalJoin.fullJoinF' (If you--- have a real-world use case for full outer joins then we'd love to--- hear about it. Please [open a new issue on the Opaleye--- project](http://github.com/tomjaguarpaw/haskell-opaleye/issues/new)--- and tell us about it.)+-- - Full outer joins: use 'Opaleye.FunctionalJoin.fullJoinF' -- | NB Opaleye exports @Opaleye.Table.'Opaleye.Table.optional'@ from -- the top level. If you want this @optional@ you will have to import@@ -68,11 +65,11 @@ -- -- @ -- > let l1 = ["one", "two", "three"] :: [Field SqlText]--- > 'Opaleye.RunSelect.runSelect' conn ('optional' ('Opaleye.Values.valuesSafe' l1)) :: IO [Maybe String]+-- > 'Opaleye.RunSelect.runSelectI' conn ('optional' ('Opaleye.Values.values' l1)) -- [Just "one", Just "two", Just "three"] -- -- > let l2 = [] :: [Field SqlText]--- > 'Opaleye.RunSelect.runSelect' conn ('optional' ('Opaleye.Values.valuesSafe' l2)) :: IO [Maybe String]+-- > 'Opaleye.RunSelect.runSelectI' conn ('optional' ('Opaleye.Values.values' l2)) -- [Nothing] -- @ --@@ -111,10 +108,10 @@ -- -- @ -- > let l = [1, 10, 100, 1000] :: [Field SqlInt4]--- > 'Opaleye.RunSelect.runSelect' conn (proc () -> optionalRestrict ('Opaleye.Values.valuesSafe' l) -\< (.> 100000)) :: IO [Maybe Int]+-- > 'Opaleye.RunSelect.runSelectI' conn (proc () -> optionalRestrict ('Opaleye.Values.values' l) -\< (.> 100000)) -- [Nothing] ----- > 'Opaleye.RunSelect.runSelect' conn (proc () -> optionalRestrict ('Opaleye.Values.valuesSafe' l) -\< (.> 15)) :: IO [Maybe Int]+-- > 'Opaleye.RunSelect.runSelectI' conn (proc () -> optionalRestrict ('Opaleye.Values.values' l) -\< (.> 15)) -- [Just 100,Just 1000] -- @ --
src/Opaleye/RunSelect.hs view
@@ -6,7 +6,6 @@ (-- * Running 'S.Select's runSelect, runSelectI,- runSelectTF, runSelectFold, -- * Cursor interface declareCursor,@@ -25,7 +24,10 @@ IRQ.DefaultFromField(defaultFromField), -- * Helper functions IRQ.fromPGSFromField,- IRQ.fromPGSFieldParser) where+ IRQ.fromPGSFieldParser,+ -- * Deprecated+ runSelectTF,+ ) where import qualified Data.Profunctor as P import qualified Database.PostgreSQL.Simple as PGS@@ -66,8 +68,7 @@ -> IO [haskells] runSelect = RQ.runQuery --- | 'runSelectTF' has better type inference than 'runSelect' but only--- works with "higher-kinded data" types.+-- | Will be deprecated in 0.8. Use 'runSelectI' instead. runSelectTF :: D.Default FromFields (rec TF.O) (rec TF.H) => PGS.Connection -- ^
src/Opaleye/TypeFamilies.hs view
@@ -1,3 +1,5 @@+-- | Will be deprecated in 0.8.+ module Opaleye.TypeFamilies ( TF.TableRecordField , TF.RecordField