packages feed

opaleye 0.5.1.1 → 0.5.2.0

raw patch · 24 files changed

+414/−123 lines, 24 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Opaleye.Internal.Column: instance GHC.Show.Show (Opaleye.Internal.Column.Column a)
+ Opaleye.FunctionalJoin: fullJoinF :: (Default IfPP columnsResult columnsResult, Default Unpackspec columnsL columnsL, Default Unpackspec columnsR columnsR) => (columnsL -> columnsR -> columnsResult) -> (columnsL -> columnsResult) -> (columnsR -> columnsResult) -> (columnsL -> columnsR -> Column PGBool) -> Query columnsL -> Query columnsR -> Query columnsResult
+ Opaleye.FunctionalJoin: joinF :: (columnsL -> columnsR -> columnsResult) -> (columnsL -> columnsR -> Column PGBool) -> Query columnsL -> Query columnsR -> Query columnsResult
+ Opaleye.FunctionalJoin: leftJoinF :: (Default IfPP columnsResult columnsResult, Default Unpackspec columnsL columnsL, Default Unpackspec columnsR columnsR) => (columnsL -> columnsR -> columnsResult) -> (columnsL -> columnsResult) -> (columnsL -> columnsR -> Column PGBool) -> Query columnsL -> Query columnsR -> Query columnsResult
+ Opaleye.FunctionalJoin: rightJoinF :: (Default IfPP columnsResult columnsResult, Default Unpackspec columnsL columnsL, Default Unpackspec columnsR columnsR) => (columnsL -> columnsR -> columnsResult) -> (columnsR -> columnsResult) -> (columnsL -> columnsR -> Column PGBool) -> Query columnsL -> Query columnsR -> Query columnsResult
+ Opaleye.Internal.Column: instance GHC.Show.Show (Opaleye.Internal.Column.Column pgType)
+ Opaleye.Internal.HaskellDB.PrimQuery: OpILike :: BinOp
+ Opaleye.Internal.Join: extractLeftJoinFields :: Int -> Tag -> PrimExpr -> PM [(Symbol, PrimExpr)] PrimExpr
+ Opaleye.Internal.Operators: IfPP :: (Column PGBool -> a -> a -> b) -> IfPP a b
+ Opaleye.Internal.Operators: ifExplict :: IfPP columns columns' -> Column PGBool -> columns -> columns -> columns'
+ Opaleye.Internal.Operators: instance Data.Profunctor.Product.Class.ProductProfunctor Opaleye.Internal.Operators.IfPP
+ Opaleye.Internal.Operators: instance Data.Profunctor.Product.Default.Class.Default Opaleye.Internal.Operators.IfPP (Opaleye.Internal.Column.Column a) (Opaleye.Internal.Column.Column a)
+ Opaleye.Internal.Operators: instance Data.Profunctor.Unsafe.Profunctor Opaleye.Internal.Operators.IfPP
+ Opaleye.Internal.Operators: newtype IfPP a b
+ Opaleye.Internal.PrimQuery: type Bindings a = [(Symbol, a)]
+ Opaleye.Internal.Sql: SelectAttrsStar :: (NonEmpty (SqlExpr, Maybe SqlColumn)) -> SelectAttrs
+ Opaleye.Operators: ifThenElseMany :: Default IfPP columns columns => Column PGBool -> columns -> columns -> columns
+ Opaleye.Operators: ilike :: Column PGText -> Column PGText -> Column PGBool
- Opaleye.Column: data Column a
+ Opaleye.Column: data Column pgType
- Opaleye.Internal.Column: Column :: PrimExpr -> Column a
+ Opaleye.Internal.Column: Column :: PrimExpr -> Column pgType
- Opaleye.Internal.Column: newtype Column a
+ Opaleye.Internal.Column: newtype Column pgType
- Opaleye.Internal.HaskellDB.PrimQuery: ListExpr :: [PrimExpr] -> PrimExpr
+ Opaleye.Internal.HaskellDB.PrimQuery: ListExpr :: (NonEmpty PrimExpr) -> PrimExpr
- Opaleye.Internal.HaskellDB.Sql: ListSqlExpr :: [SqlExpr] -> SqlExpr
+ Opaleye.Internal.HaskellDB.Sql: ListSqlExpr :: (NonEmpty SqlExpr) -> SqlExpr
- Opaleye.Internal.Join: joinExplicit :: (columnsA -> returnedColumnsA) -> (columnsB -> returnedColumnsB) -> JoinType -> Query columnsA -> Query columnsB -> ((columnsA, columnsB) -> Column PGBool) -> Query (returnedColumnsA, returnedColumnsB)
+ Opaleye.Internal.Join: joinExplicit :: Unpackspec columnsA columnsA -> Unpackspec columnsB columnsB -> (columnsA -> returnedColumnsA) -> (columnsB -> returnedColumnsB) -> JoinType -> Query columnsA -> Query columnsB -> ((columnsA, columnsB) -> Column PGBool) -> Query (returnedColumnsA, returnedColumnsB)
- Opaleye.Internal.PrimQuery: Aggregate :: [(Symbol, (Maybe (AggrOp, [OrderExpr]), PrimExpr))] -> (PrimQuery' a) -> PrimQuery' a
+ Opaleye.Internal.PrimQuery: Aggregate :: (Bindings (Maybe (AggrOp, [OrderExpr]), PrimExpr)) -> (PrimQuery' a) -> PrimQuery' a
- Opaleye.Internal.PrimQuery: BaseTable :: TableIdentifier -> [(Symbol, PrimExpr)] -> PrimQuery' a
+ Opaleye.Internal.PrimQuery: BaseTable :: TableIdentifier -> (Bindings PrimExpr) -> PrimQuery' a
- Opaleye.Internal.PrimQuery: Binary :: BinOp -> [(Symbol, (PrimExpr, PrimExpr))] -> (PrimQuery' a, PrimQuery' a) -> PrimQuery' a
+ Opaleye.Internal.PrimQuery: Binary :: BinOp -> (Bindings (PrimExpr, PrimExpr)) -> (PrimQuery' a, PrimQuery' a) -> PrimQuery' a
- Opaleye.Internal.PrimQuery: Join :: JoinType -> PrimExpr -> (PrimQuery' a) -> (PrimQuery' a) -> PrimQuery' a
+ Opaleye.Internal.PrimQuery: Join :: JoinType -> PrimExpr -> (Bindings PrimExpr) -> (Bindings PrimExpr) -> (PrimQuery' a) -> (PrimQuery' a) -> PrimQuery' a
- Opaleye.Internal.PrimQuery: PrimQueryFold :: p -> (a -> p) -> (TableIdentifier -> [(Symbol, PrimExpr)] -> p) -> (NonEmpty p -> [PrimExpr] -> p) -> ([(Symbol, (Maybe (AggrOp, [OrderExpr]), PrimExpr))] -> p -> p) -> ([OrderExpr] -> p -> p) -> (LimitOp -> p -> p) -> (JoinType -> PrimExpr -> p -> p -> p) -> ([Symbol] -> (NonEmpty [PrimExpr]) -> p) -> (BinOp -> [(Symbol, (PrimExpr, PrimExpr))] -> (p, p) -> p) -> (String -> p -> p) -> (PrimExpr -> [(Symbol, PrimExpr)] -> p) -> PrimQueryFold' a p
+ Opaleye.Internal.PrimQuery: PrimQueryFold :: p -> (a -> p) -> (TableIdentifier -> (Bindings PrimExpr) -> p) -> (NonEmpty p -> [PrimExpr] -> p) -> ((Bindings (Maybe (AggrOp, [OrderExpr]), PrimExpr)) -> p -> p) -> ([OrderExpr] -> p -> p) -> (LimitOp -> p -> p) -> (JoinType -> PrimExpr -> (Bindings PrimExpr) -> (Bindings PrimExpr) -> p -> p -> p) -> ([Symbol] -> (NonEmpty [PrimExpr]) -> p) -> (BinOp -> (Bindings (PrimExpr, PrimExpr)) -> (p, p) -> p) -> (String -> p -> p) -> (PrimExpr -> (Bindings PrimExpr) -> p) -> PrimQueryFold' a p
- Opaleye.Internal.PrimQuery: RelExpr :: PrimExpr -> [(Symbol, PrimExpr)] -> PrimQuery' a
+ Opaleye.Internal.PrimQuery: RelExpr :: PrimExpr -> (Bindings PrimExpr) -> PrimQuery' a
- Opaleye.Internal.PrimQuery: [aggregate] :: PrimQueryFold' a p -> [(Symbol, (Maybe (AggrOp, [OrderExpr]), PrimExpr))] -> p -> p
+ Opaleye.Internal.PrimQuery: [aggregate] :: PrimQueryFold' a p -> (Bindings (Maybe (AggrOp, [OrderExpr]), PrimExpr)) -> p -> p
- Opaleye.Internal.PrimQuery: [baseTable] :: PrimQueryFold' a p -> TableIdentifier -> [(Symbol, PrimExpr)] -> p
+ Opaleye.Internal.PrimQuery: [baseTable] :: PrimQueryFold' a p -> TableIdentifier -> (Bindings PrimExpr) -> p
- Opaleye.Internal.PrimQuery: [binary] :: PrimQueryFold' a p -> BinOp -> [(Symbol, (PrimExpr, PrimExpr))] -> (p, p) -> p
+ Opaleye.Internal.PrimQuery: [binary] :: PrimQueryFold' a p -> BinOp -> (Bindings (PrimExpr, PrimExpr)) -> (p, p) -> p
- Opaleye.Internal.PrimQuery: [join] :: PrimQueryFold' a p -> JoinType -> PrimExpr -> p -> p -> p
+ Opaleye.Internal.PrimQuery: [join] :: PrimQueryFold' a p -> JoinType -> PrimExpr -> (Bindings PrimExpr) -> (Bindings PrimExpr) -> p -> p -> p
- Opaleye.Internal.PrimQuery: [relExpr] :: PrimQueryFold' a p -> PrimExpr -> [(Symbol, PrimExpr)] -> p
+ Opaleye.Internal.PrimQuery: [relExpr] :: PrimQueryFold' a p -> PrimExpr -> (Bindings PrimExpr) -> p
- Opaleye.Internal.Sql: join :: JoinType -> PrimExpr -> Select -> Select -> Select
+ Opaleye.Internal.Sql: join :: JoinType -> PrimExpr -> Bindings PrimExpr -> Bindings PrimExpr -> Select -> Select -> Select
- Opaleye.Join: fullJoin :: (Default Unpackspec columnsA columnsA, Default Unpackspec columnsB columnsB, Default NullMaker columnsA nullableColumnsA, Default NullMaker columnsB nullableColumnsB) => Query columnsA -> Query columnsB -> ((columnsA, columnsB) -> Column PGBool) -> Query (nullableColumnsA, nullableColumnsB)
+ Opaleye.Join: fullJoin :: (Default Unpackspec columnsL columnsL, Default Unpackspec columnsR columnsR, Default NullMaker columnsL nullableColumnsL, Default NullMaker columnsR nullableColumnsR) => Query columnsL -> Query columnsR -> ((columnsL, columnsR) -> Column PGBool) -> Query (nullableColumnsL, nullableColumnsR)
- Opaleye.Join: fullJoinExplicit :: Unpackspec columnsA columnsA -> Unpackspec columnsB columnsB -> NullMaker columnsA nullableColumnsA -> NullMaker columnsB nullableColumnsB -> Query columnsA -> Query columnsB -> ((columnsA, columnsB) -> Column PGBool) -> Query (nullableColumnsA, nullableColumnsB)
+ Opaleye.Join: fullJoinExplicit :: Unpackspec columnsL columnsL -> Unpackspec columnsR columnsR -> NullMaker columnsL nullableColumnsL -> NullMaker columnsR nullableColumnsR -> Query columnsL -> Query columnsR -> ((columnsL, columnsR) -> Column PGBool) -> Query (nullableColumnsL, nullableColumnsR)
- Opaleye.Join: leftJoin :: (Default Unpackspec columnsA columnsA, Default Unpackspec columnsB columnsB, Default NullMaker columnsB nullableColumnsB) => Query columnsA -> Query columnsB -> ((columnsA, columnsB) -> Column PGBool) -> Query (columnsA, nullableColumnsB)
+ Opaleye.Join: leftJoin :: (Default Unpackspec columnsL columnsL, Default Unpackspec columnsR columnsR, Default NullMaker columnsR nullableColumnsR) => Query columnsL -> Query columnsR -> ((columnsL, columnsR) -> Column PGBool) -> Query (columnsL, nullableColumnsR)
- Opaleye.Join: leftJoinExplicit :: Unpackspec columnsA columnsA -> Unpackspec columnsB columnsB -> NullMaker columnsB nullableColumnsB -> Query columnsA -> Query columnsB -> ((columnsA, columnsB) -> Column PGBool) -> Query (columnsA, nullableColumnsB)
+ Opaleye.Join: leftJoinExplicit :: Unpackspec columnsL columnsL -> Unpackspec columnsR columnsR -> NullMaker columnsR nullableColumnsR -> Query columnsL -> Query columnsR -> ((columnsL, columnsR) -> Column PGBool) -> Query (columnsL, nullableColumnsR)
- Opaleye.Join: rightJoin :: (Default Unpackspec columnsA columnsA, Default Unpackspec columnsB columnsB, Default NullMaker columnsA nullableColumnsA) => Query columnsA -> Query columnsB -> ((columnsA, columnsB) -> Column PGBool) -> Query (nullableColumnsA, columnsB)
+ Opaleye.Join: rightJoin :: (Default Unpackspec columnsL columnsL, Default Unpackspec columnsR columnsR, Default NullMaker columnsL nullableColumnsL) => Query columnsL -> Query columnsR -> ((columnsL, columnsR) -> Column PGBool) -> Query (nullableColumnsL, columnsR)
- Opaleye.Join: rightJoinExplicit :: Unpackspec columnsA columnsA -> Unpackspec columnsB columnsB -> NullMaker columnsA nullableColumnsA -> Query columnsA -> Query columnsB -> ((columnsA, columnsB) -> Column PGBool) -> Query (nullableColumnsA, columnsB)
+ Opaleye.Join: rightJoinExplicit :: Unpackspec columnsL columnsL -> Unpackspec columnsR columnsR -> NullMaker columnsL nullableColumnsL -> Query columnsL -> Query columnsR -> ((columnsL, columnsR) -> Column PGBool) -> Query (nullableColumnsL, columnsR)
- Opaleye.Manipulation: arrangeInsertManyReturning :: Unpackspec returned ignored -> Table columnsW columnsR -> NonEmpty columnsW -> (columnsR -> returned) -> Returning SqlInsert
+ Opaleye.Manipulation: arrangeInsertManyReturning :: Unpackspec columnsReturned ignored -> Table columnsW columnsR -> NonEmpty columnsW -> (columnsR -> columnsReturned) -> Returning SqlInsert
- Opaleye.Manipulation: arrangeInsertManyReturningSql :: Unpackspec returned ignored -> Table columnsW columnsR -> NonEmpty columnsW -> (columnsR -> returned) -> String
+ Opaleye.Manipulation: arrangeInsertManyReturningSql :: Unpackspec columnsReturned ignored -> Table columnsW columnsR -> NonEmpty columnsW -> (columnsR -> columnsReturned) -> String
- Opaleye.Manipulation: arrangeUpdateReturning :: Unpackspec returned ignored -> Table columnsW columnsR -> (columnsR -> columnsW) -> (columnsR -> Column PGBool) -> (columnsR -> returned) -> Returning SqlUpdate
+ Opaleye.Manipulation: arrangeUpdateReturning :: Unpackspec columnsReturned ignored -> Table columnsW columnsR -> (columnsR -> columnsW) -> (columnsR -> Column PGBool) -> (columnsR -> columnsReturned) -> Returning SqlUpdate
- Opaleye.Manipulation: arrangeUpdateReturningSql :: Unpackspec returned ignored -> Table columnsW columnsR -> (columnsR -> columnsW) -> (columnsR -> Column PGBool) -> (columnsR -> returned) -> String
+ Opaleye.Manipulation: arrangeUpdateReturningSql :: Unpackspec columnsReturned ignored -> Table columnsW columnsR -> (columnsR -> columnsW) -> (columnsR -> Column PGBool) -> (columnsR -> columnsReturned) -> String
- Opaleye.Manipulation: runInsertManyReturning :: (Default QueryRunner returned haskells) => Connection -> Table columnsW columnsR -> [columnsW] -> (columnsR -> returned) -> IO [haskells]
+ Opaleye.Manipulation: runInsertManyReturning :: (Default QueryRunner columnsReturned haskells) => Connection -> Table columnsW columnsR -> [columnsW] -> (columnsR -> columnsReturned) -> IO [haskells]
- Opaleye.Manipulation: runInsertManyReturningExplicit :: QueryRunner returned haskells -> Connection -> Table columnsW columnsR -> [columnsW] -> (columnsR -> returned) -> IO [haskells]
+ Opaleye.Manipulation: runInsertManyReturningExplicit :: QueryRunner columnsReturned haskells -> Connection -> Table columnsW columnsR -> [columnsW] -> (columnsR -> columnsReturned) -> IO [haskells]
- Opaleye.Manipulation: runInsertReturning :: (Default QueryRunner returned haskells) => Connection -> Table columnsW columnsR -> columnsW -> (columnsR -> returned) -> IO [haskells]
+ Opaleye.Manipulation: runInsertReturning :: (Default QueryRunner columnsReturned haskells) => Connection -> Table columnsW columnsR -> columnsW -> (columnsR -> columnsReturned) -> IO [haskells]
- Opaleye.Manipulation: runInsertReturningExplicit :: QueryRunner returned haskells -> Connection -> Table columnsW columnsR -> columnsW -> (columnsR -> returned) -> IO [haskells]
+ Opaleye.Manipulation: runInsertReturningExplicit :: QueryRunner columnsReturned haskells -> Connection -> Table columnsW columnsR -> columnsW -> (columnsR -> columnsReturned) -> IO [haskells]
- Opaleye.Manipulation: runUpdateReturning :: (Default QueryRunner returned haskells) => Connection -> Table columnsW columnsR -> (columnsR -> columnsW) -> (columnsR -> Column PGBool) -> (columnsR -> returned) -> IO [haskells]
+ Opaleye.Manipulation: runUpdateReturning :: (Default QueryRunner columnsReturned haskells) => Connection -> Table columnsW columnsR -> (columnsR -> columnsW) -> (columnsR -> Column PGBool) -> (columnsR -> columnsReturned) -> IO [haskells]
- Opaleye.Manipulation: runUpdateReturningExplicit :: QueryRunner returned haskells -> Connection -> Table columnsW columnsR -> (columnsR -> columnsW) -> (columnsR -> Column PGBool) -> (columnsR -> returned) -> IO [haskells]
+ Opaleye.Manipulation: runUpdateReturningExplicit :: QueryRunner columnsReturned haskells -> Connection -> Table columnsW columnsR -> (columnsR -> columnsW) -> (columnsR -> Column PGBool) -> (columnsR -> columnsReturned) -> IO [haskells]

Files

CHANGELOG.md view
@@ -1,3 +1,10 @@+## 0.5.2.0++* Added `Opaleye.FunctionalJoin`+* Fixed handling of `BinExpr OpIn _ (ListExpr _)` in `defaultSqlExpr`.+* `in_` now actually uses the SQL `IN` operator.+* Added support for `ILIKE`+ ## 0.5.1.0  * Added
Test/Test.hs view
@@ -346,6 +346,16 @@           O.restrict -< fst t .== 1           Arr.returnA -< t +testIn :: Test+testIn = testG query expected+  where query = proc () -> do+          t <- table1Q -< ()+          O.restrict -< O.in_ [O.pgInt4 100, O.pgInt4 200] (snd t)+          O.restrict -< O.not (O.in_ [] (fst t)) -- Making sure empty lists work.+          Arr.returnA -< t+        expected = \r ->+          filter (flip elem [100, 200] . snd) (L.sort table1data) == L.sort r+ testNum :: Test testNum = testG query expected   where query :: Query (Column O.PGInt4)@@ -596,6 +606,20 @@                    , ((1, 50), ((Just 1, Just 100), (Just 1, Just 50)))                    , ((1, 50), ((Just 1, Just 200), (Just 1, Just 50))) ] +testLeftJoinF :: Test+testLeftJoinF = testG q (== expected)+  where q = O.leftJoinF (,)+                        (\x -> (x, (-1, -2)))+                        (\l r -> fst l .== fst r)+                        table1Q+                        table3Q++        expected :: [((Int, Int), (Int, Int))]+        expected = [ ((1, 100), (1, 50))+                   , ((1, 100), (1, 50))+                   , ((1, 200), (1, 50))+                   , ((2, 300), (-1, -2)) ]+ testThreeWayProduct :: Test testThreeWayProduct = testG q (== expected)   where q = A.liftA3 (,,) table1Q table2Q table3Q@@ -835,10 +859,11 @@             testDistinct, testAggregate, testAggregate0, testAggregateFunction,             testAggregateProfunctor, testStringArrayAggregate, testStringAggregate,             testOrderBy, testOrderBy2, testOrderBySame, testLimit, testOffset,-            testLimitOffset, testOffsetLimit, testDistinctAndAggregate,+            testLimitOffset, testOffsetLimit, testDistinctAndAggregate, testIn,             testDoubleDistinct, testDoubleAggregate, testDoubleLeftJoin,             testDoubleValues, testDoubleUnionAll,             testLeftJoin, testLeftJoinNullable, testThreeWayProduct, testValues,+            testLeftJoinF,             testValuesEmpty, testUnionAll, testTableFunctor, testUpdate,             testKeywordColNames, testInsertSerial, testInQuery, testAtTimeZone,             testStringArrayAggregateOrdered, testMultipleAggregateOrdered,
opaleye.cabal view
@@ -1,6 +1,6 @@ name:            opaleye copyright:       Copyright (c) 2014-2016 Purely Agile Limited-version:         0.5.1.1+version:         0.5.2.0 synopsis:        An SQL-generating DSL targeting PostgreSQL description:     An SQL-generating DSL targeting PostgreSQL.  Allows                  Postgres queries to be written within Haskell in a@@ -13,10 +13,10 @@ maintainer:      Purely Agile category:        Database build-type:      Simple-cabal-version:   >= 1.10+cabal-version:   >= 1.18 extra-doc-files: *.md,                  Doc/*.md-tested-with:     GHC==7.10.1, GHC==7.8.4, GHC==7.6.3+tested-with:     GHC==8.0.1, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3  source-repository head   type:     git@@ -52,6 +52,7 @@                    Opaleye.Column,                    Opaleye.Constant,                    Opaleye.Distinct,+                   Opaleye.FunctionalJoin,                    Opaleye.Join,                    Opaleye.Label,                    Opaleye.Manipulation,@@ -99,7 +100,7 @@   other-modules: QuickCheck   hs-source-dirs: Test   build-depends:-    aeson >= 0.6 && < 0.12,+    aeson >= 0.6 && < 1.1,     base >= 4 && < 5,     containers,     contravariant,
src/Opaleye.hs view
@@ -1,8 +1,24 @@+-- | An SQL-generating DSL targeting PostgreSQL.  Allows Postgres+--   queries to be written within Haskell in a typesafe and composable+--   fashion.+--+-- You might like to look at+--+-- * <https://github.com/tomjaguarpaw/haskell-opaleye/blob/master/Doc/Tutorial/TutorialBasic.lhs Basic tutorial>+--+-- * <https://github.com/tomjaguarpaw/haskell-opaleye/blob/master/Doc/Tutorial/TutorialManipulation.lhs Manipulation tutorial>+--+-- * <https://github.com/tomjaguarpaw/haskell-opaleye/blob/master/Doc/Tutorial/TutorialAdvanced.lhs Advanced tutorial>+--+-- * If you are confused about the @Default@ typeclass, then+-- the <https://github.com/tomjaguarpaw/haskell-opaleye/blob/master/Doc/Tutorial/DefaultExplanation.lhs Default explanation>+ module Opaleye ( module Opaleye.Aggregate                , module Opaleye.Binary                , module Opaleye.Column                , module Opaleye.Constant                , module Opaleye.Distinct+               , module Opaleye.FunctionalJoin                , module Opaleye.Join                , module Opaleye.Label                , module Opaleye.Manipulation@@ -21,6 +37,7 @@ import Opaleye.Column import Opaleye.Constant import Opaleye.Distinct+import Opaleye.FunctionalJoin import Opaleye.Join import Opaleye.Label import Opaleye.Manipulation
src/Opaleye/Binary.hs view
@@ -23,7 +23,7 @@ -- functions would allow violation of SQL's scoping rules and lead to -- invalid queries. ----- `unionAll` is very close to being the @<|>@ operator of a+-- `unionAll` is very close to being the @\<|\>@ operator of a -- @Control.Applicative.Alternative@ instance but it fails to work -- only because of the typeclass constraint it has. 
src/Opaleye/Column.hs view
@@ -3,8 +3,8 @@ -- Please note that numeric 'Column' types are instances of 'Num', so -- you can use '*', '/', '+', '-' on them. -module Opaleye.Column (module Opaleye.Column,-                       Column,+module Opaleye.Column (Column,+                       module Opaleye.Column,                        Nullable,                        unsafeCast,                        unsafeCoerce,
+ src/Opaleye/FunctionalJoin.hs view
@@ -0,0 +1,141 @@+-- | Left, right, and full outer joins.+--+-- The interface in this module is much nicer than the standard \"make+-- missing rows NULL\" interface that SQL provides.  If you really+-- want the standard interface then use "Opaleye.Join".++{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE MultiParamTypeClasses #-}++module Opaleye.FunctionalJoin where++import           Control.Applicative             ((<$>), (<*>))+import           Control.Arrow                   ((<<<))++import qualified Data.Profunctor.Product.Default as D+import qualified Data.Profunctor.Product         as PP++import qualified Opaleye.Column                  as C+import           Opaleye.Internal.Column         (Column, Nullable)+import qualified Opaleye.Internal.Join           as IJ+import qualified Opaleye.Internal.Operators      as IO+import qualified Opaleye.Internal.Unpackspec     as IU+import qualified Opaleye.Join                    as J+import qualified Opaleye.PGTypes                 as T+import qualified Opaleye.Operators               as O+import           Opaleye.QueryArr                (Query)++joinF :: (columnsL -> columnsR -> columnsResult)+      -- ^ Calculate result columns from input columns+      -> (columnsL -> columnsR -> Column T.PGBool)+      -- ^ Condition on which to join+      -> Query columnsL+      -- ^ Left query+      -> Query columnsR+      -- ^ Right query+      -> Query columnsResult+joinF f cond l r =+  fmap (uncurry f) (O.keepWhen (uncurry cond) <<< ((,) <$> l <*> r))++leftJoinF :: (D.Default IO.IfPP columnsResult columnsResult,+              D.Default IU.Unpackspec columnsL columnsL,+              D.Default IU.Unpackspec columnsR columnsR)+          => (columnsL -> columnsR -> columnsResult)+          -- ^ Calculate result row from input rows for rows in the+          -- right query satisfying the join condition+          -> (columnsL -> columnsResult)+          -- ^ Calculate result row from input row when there are /no/+          -- rows in the right query satisfying the join condition+          -> (columnsL -> columnsR -> Column T.PGBool)+          -- ^ Condition on which to join+          -> Query columnsL+          -- ^ Left query+          -> Query columnsR+          -- ^ Right query+          -> Query columnsResult+leftJoinF f fL cond l r = fmap ret j+  where a1 = fmap (\x -> (x, T.pgBool True))+        j  = J.leftJoinExplicit D.def+                                D.def+                                (PP.p2 ((IJ.NullMaker id), nullmakerBool))+                                l+                                (a1 r)+                                (\(l', (r', _)) -> cond l' r')++        ret (lr, (rr, rc)) = O.ifThenElseMany (C.isNull rc) (fL lr) (f lr rr)++        nullmakerBool :: IJ.NullMaker (Column T.PGBool)+                                      (Column (Nullable T.PGBool))+        nullmakerBool = D.def++rightJoinF :: (D.Default IO.IfPP columnsResult columnsResult,+               D.Default IU.Unpackspec columnsL columnsL,+               D.Default IU.Unpackspec columnsR columnsR)+           => (columnsL -> columnsR -> columnsResult)+           -- ^ Calculate result row from input rows for rows in the+           -- left query satisfying the join condition+           -> (columnsR -> columnsResult)+           -- ^ Calculate result row from input row when there are /no/+           -- rows in the left query satisfying the join condition+           -> (columnsL -> columnsR -> Column T.PGBool)+           -- ^ Condition on which to join+           -> Query columnsL+           -- ^ Left query+           -> Query columnsR+           -- ^ Right query+           -> Query columnsResult+rightJoinF f fR cond l r = fmap ret j+  where a1 = fmap (\x -> (x, T.pgBool True))+        j  = J.rightJoinExplicit D.def+                                 D.def+                                 (PP.p2 ((IJ.NullMaker id), nullmakerBool))+                                 (a1 l)+                                 r+                                 (\((l', _), r') -> cond l' r')++        ret ((lr, lc), rr) = O.ifThenElseMany (C.isNull lc) (fR rr) (f lr rr)++        nullmakerBool :: IJ.NullMaker (Column T.PGBool)+                                      (Column (Nullable T.PGBool))+        nullmakerBool = D.def++fullJoinF :: (D.Default IO.IfPP columnsResult columnsResult,+              D.Default IU.Unpackspec columnsL columnsL,+              D.Default IU.Unpackspec columnsR columnsR)+          => (columnsL -> columnsR -> columnsResult)+           -- ^ Calculate result row from input rows for rows in the+           -- left and right query satisfying the join condition+          -> (columnsL -> columnsResult)+           -- ^ Calculate result row from left input row when there+           -- are /no/ rows in the right query satisfying the join+           -- condition+          -> (columnsR -> columnsResult)+           -- ^ Calculate result row from right input row when there+           -- are /no/ rows in the left query satisfying the join+           -- condition+          -> (columnsL -> columnsR -> Column T.PGBool)+          -- ^ Condition on which to join+          -> Query columnsL+          -- ^ Left query+          -> Query columnsR+          -- ^ Right query+          -> Query columnsResult+fullJoinF f fL fR cond l r = fmap ret j+  where a1 = fmap (\x -> (x, T.pgBool True))+        j  = J.fullJoinExplicit D.def+                                D.def+                                (PP.p2 ((IJ.NullMaker id), nullmakerBool))+                                (PP.p2 ((IJ.NullMaker id), nullmakerBool))+                                (a1 l)+                                (a1 r)+                                (\((l', _), (r', _)) -> cond l' r')++        ret ((lr, lc), (rr, rc)) = O.ifThenElseMany (C.isNull lc)+                                     (fR rr)+                                     (O.ifThenElseMany (C.isNull rc)+                                        (fL lr)+                                        (f lr rr))++        nullmakerBool :: IJ.NullMaker (Column T.PGBool)+                                      (Column (Nullable T.PGBool))+        nullmakerBool = D.def
src/Opaleye/Internal/Column.hs view
@@ -4,10 +4,14 @@  import qualified Opaleye.Internal.HaskellDB.PrimQuery as HPQ -newtype Column a = Column HPQ.PrimExpr deriving Show+-- | A column of a @Query@, of type @pgType@.  For example 'Column'+-- @PGInt4@ is an @int4@ column and a 'Column' @PGText@ is a @text@+-- column.+newtype Column pgType = Column HPQ.PrimExpr deriving Show --- | Only used within a 'Column', to indicate that it can take null--- values.+-- | Only used within a 'Column', to indicate that it can be @NULL@.+-- For example, a 'Column' ('Nullable' @PGText@) can be @NULL@ but a+-- 'Column' @PGText@ cannot. data Nullable a = Nullable  unColumn :: Column a -> HPQ.PrimExpr
src/Opaleye/Internal/HaskellDB/PrimQuery.hs view
@@ -6,6 +6,7 @@  import qualified Opaleye.Internal.Tag as T import Data.ByteString (ByteString)+import qualified Data.List.NonEmpty as NEL  type TableName  = String type Attribute  = String@@ -23,7 +24,7 @@                 | AggrExpr  AggrOp PrimExpr [OrderExpr]                 | ConstExpr Literal                 | CaseExpr [(PrimExpr,PrimExpr)] PrimExpr-                | ListExpr [PrimExpr]+                | ListExpr (NEL.NonEmpty PrimExpr)                 | ParamExpr (Maybe Name) PrimExpr                 | FunExpr Name [PrimExpr]                 | CastExpr Name PrimExpr -- ^ Cast an expression to a given type.@@ -47,7 +48,7 @@  data BinOp      = (:==) | (:<) | (:<=) | (:>) | (:>=) | (:<>)                 | OpAnd | OpOr-                | OpLike | OpIn+                | OpLike | OpILike | OpIn                 | OpOther String                  | (:||)
src/Opaleye/Internal/HaskellDB/Sql.hs view
@@ -41,7 +41,7 @@              | AggrFunSqlExpr String [SqlExpr] [(SqlExpr, SqlOrder)] -- ^ Aggregate functions separate from normal functions.              | ConstSqlExpr   String              | CaseSqlExpr    (NEL.NonEmpty (SqlExpr,SqlExpr)) SqlExpr-             | ListSqlExpr    [SqlExpr]+             | ListSqlExpr    (NEL.NonEmpty SqlExpr)              | ParamSqlExpr (Maybe SqlName) SqlExpr              | PlaceHolderSqlExpr              | ParensSqlExpr SqlExpr
src/Opaleye/Internal/HaskellDB/Sql/Default.hs view
@@ -100,6 +100,8 @@                 (paren leftE, rightE)               (OpOr, _, BinExpr OpAnd _ _) ->                 (leftE, paren rightE)+              (OpIn, _, ListExpr _) ->+                (leftE, rightE)               (_, ConstExpr _, ConstExpr _) ->                 (leftE, rightE)               (_, _, ConstExpr _) ->@@ -133,7 +135,7 @@                           in case NEL.nonEmpty cs' of                             Just nel -> CaseSqlExpr nel e'                             Nothing  -> e'-      ListExpr es      -> ListSqlExpr (map (sqlExpr gen) es)+      ListExpr es      -> ListSqlExpr (fmap (sqlExpr gen) es)       ParamExpr n _    -> ParamSqlExpr n PlaceHolderSqlExpr       FunExpr n exprs  -> FunSqlExpr n (map (sqlExpr gen) exprs)       CastExpr typ e1 -> CastSqlExpr typ (sqlExpr gen e1)@@ -150,6 +152,7 @@ showBinOp  OpAnd        = "AND" showBinOp  OpOr         = "OR" showBinOp  OpLike       = "LIKE"+showBinOp  OpILike      = "ILIKE" showBinOp  OpIn         = "IN" showBinOp  (OpOther s)  = s showBinOp  (:||)        = "||"
src/Opaleye/Internal/HaskellDB/Sql/Print.hs view
@@ -130,7 +130,7 @@                              <+> text "ELSE" <+> ppSqlExpr el <+> text "END"           where ppWhen (w,t) = text "WHEN" <+> ppSqlExpr w                                <+> text "THEN" <+> ppSqlExpr t-      ListSqlExpr es      -> parens (commaH ppSqlExpr es)+      ListSqlExpr es      -> parens (commaH ppSqlExpr (NEL.toList es))       ParamSqlExpr _ v -> ppSqlExpr v       PlaceHolderSqlExpr -> text "?"       CastSqlExpr typ e -> text "CAST" <> parens (ppSqlExpr e <+> text "AS" <+> text typ)
src/Opaleye/Internal/Join.hs view
@@ -2,7 +2,10 @@  module Opaleye.Internal.Join where -import qualified Opaleye.Internal.Tag as T+import qualified Opaleye.Internal.HaskellDB.PrimQuery as HPQ+import qualified Opaleye.Internal.PackMap             as PM+import qualified Opaleye.Internal.Tag                 as T+import qualified Opaleye.Internal.Unpackspec          as U import           Opaleye.Internal.Column (Column(Column), Nullable) import qualified Opaleye.Internal.QueryArr as Q import qualified Opaleye.Internal.PrimQuery as PQ@@ -21,29 +24,41 @@ toNullable (NullMaker f) = f  instance D.Default NullMaker (Column a) (Column (Nullable a)) where-  def = NullMaker C.unsafeCoerceColumn+  def = NullMaker C.toNullable  instance D.Default NullMaker (Column (Nullable a)) (Column (Nullable a)) where-  def = NullMaker C.unsafeCoerceColumn+  def = NullMaker id -joinExplicit :: (columnsA -> returnedColumnsA)+joinExplicit :: U.Unpackspec columnsA columnsA+             -> U.Unpackspec columnsB columnsB+             -> (columnsA -> returnedColumnsA)              -> (columnsB -> returnedColumnsB)              -> PQ.JoinType              -> Q.Query columnsA -> Q.Query columnsB              -> ((columnsA, columnsB) -> Column T.PGBool)              -> Q.Query (returnedColumnsA, returnedColumnsB)-joinExplicit returnColumnsA returnColumnsB joinType+joinExplicit uA uB returnColumnsA returnColumnsB joinType              qA qB cond = Q.simpleQueryArr q where   q ((), startTag) = ((nullableColumnsA, nullableColumnsB), primQueryR, T.next endTag)     where (columnsA, primQueryA, midTag) = Q.runSimpleQueryArr qA ((), startTag)           (columnsB, primQueryB, endTag) = Q.runSimpleQueryArr qB ((), midTag) -          nullableColumnsA = returnColumnsA columnsA-          nullableColumnsB = returnColumnsB columnsB+          (newColumnsA, ljPEsA) =+            PM.run (U.runUnpackspec uA (extractLeftJoinFields 1 endTag) columnsA)+          (newColumnsB, ljPEsB) =+            PM.run (U.runUnpackspec uB (extractLeftJoinFields 2 endTag) columnsB) +          nullableColumnsA = returnColumnsA newColumnsA+          nullableColumnsB = returnColumnsB newColumnsB+           Column cond' = cond (columnsA, columnsB)-          primQueryR = PQ.Join joinType cond' primQueryA primQueryB+          primQueryR = PQ.Join joinType cond' ljPEsA ljPEsB primQueryA primQueryB +extractLeftJoinFields :: Int+                      -> T.Tag+                      -> HPQ.PrimExpr+                      -> PM.PM [(HPQ.Symbol, HPQ.PrimExpr)] HPQ.PrimExpr+extractLeftJoinFields n = PM.extractAttr ("result" ++ show n ++ "_")  -- { Boilerplate instances 
src/Opaleye/Internal/Operators.hs view
@@ -39,6 +39,19 @@   def = EqPP C.unsafeEq  +newtype IfPP a b = IfPP (Column T.PGBool -> a -> a -> b)++ifExplict :: IfPP columns columns'+          -> Column T.PGBool+          -> columns+          -> columns+          -> columns'+ifExplict (IfPP f) = f++instance D.Default IfPP (Column a) (Column a) where+  def = IfPP C.unsafeIfThenElse++ -- This seems to be the only place we use ViewColumnMaker now. data RelExprMaker a b =   forall c. RelExprMaker {@@ -97,4 +110,13 @@                                     h vcmf vcmg cmf cmg     where h vcmg vcmf cmg cmf = RelExprMaker (vcmg ***! vcmf)                                              (cmg  ***! cmf)++instance Profunctor IfPP where+  dimap f g (IfPP h) = IfPP (\b a a' -> g (h b (f a) (f a')))++instance ProductProfunctor IfPP where+  empty = IfPP (\_ () () -> ())+  IfPP f ***! IfPP f' = IfPP (\b a a1 ->+                               (f b (fst a) (fst a1), f' b (snd a) (snd a1)))+ -- }
src/Opaleye/Internal/Optimize.hs view
@@ -43,7 +43,7 @@   , PQ.aggregate = fmap . PQ.Aggregate   , PQ.order     = fmap . PQ.Order   , PQ.limit     = fmap . PQ.Limit-  , PQ.join      = \jt pe pq1 pq2 -> PQ.Join jt pe <$> pq1 <*> pq2+  , PQ.join      = \jt pe pes1 pes2 pq1 pq2 -> PQ.Join jt pe pes1 pes2 <$> pq1 <*> pq2   , PQ.values    = return .: PQ.Values   , PQ.binary    = \case       -- Some unfortunate duplication here
src/Opaleye/Internal/PrimQuery.hs view
@@ -29,9 +29,7 @@ tiToSqlTable ti = HSql.SqlTable { HSql.sqlTableSchemaName = tiSchemaName ti                                 , HSql.sqlTableName       = tiTableName ti } ---- In the future it may make sense to introduce this datatype--- type Bindings a = [(Symbol, a)]+type Bindings a = [(Symbol, a)]  -- We use a 'NEL.NonEmpty' for Product because otherwise we'd have to check -- for emptiness explicity in the SQL generation phase.@@ -43,19 +41,24 @@ -- SQL so we remove it in 'Optimize' and set 'a = Void'. data PrimQuery' a = Unit                   | Empty     a-                  | BaseTable TableIdentifier [(Symbol, HPQ.PrimExpr)]+                  | BaseTable TableIdentifier (Bindings HPQ.PrimExpr)                   | Product   (NEL.NonEmpty (PrimQuery' a)) [HPQ.PrimExpr]-                  | Aggregate [(Symbol, (Maybe (HPQ.AggrOp, [HPQ.OrderExpr]), HPQ.PrimExpr))]+                  | Aggregate (Bindings (Maybe (HPQ.AggrOp, [HPQ.OrderExpr]), HPQ.PrimExpr))                               (PrimQuery' a)                   | Order     [HPQ.OrderExpr] (PrimQuery' a)                   | Limit     LimitOp (PrimQuery' a)-                  | Join      JoinType HPQ.PrimExpr (PrimQuery' a) (PrimQuery' a)+                  | Join      JoinType+                              HPQ.PrimExpr+                              (Bindings HPQ.PrimExpr)+                              (Bindings HPQ.PrimExpr)+                              (PrimQuery' a)+                              (PrimQuery' a)                   | Values    [Symbol] (NEL.NonEmpty [HPQ.PrimExpr])                   | Binary    BinOp-                              [(Symbol, (HPQ.PrimExpr, HPQ.PrimExpr))]+                              (Bindings (HPQ.PrimExpr, HPQ.PrimExpr))                               (PrimQuery' a, PrimQuery' a)                   | Label     String (PrimQuery' a)-                  | RelExpr   HPQ.PrimExpr [(Symbol, HPQ.PrimExpr)]+                  | RelExpr   HPQ.PrimExpr (Bindings HPQ.PrimExpr)                  deriving Show  type PrimQuery = PrimQuery' ()@@ -64,16 +67,22 @@ data PrimQueryFold' a p = PrimQueryFold   { unit      :: p   , empty     :: a -> p-  , baseTable :: TableIdentifier -> [(Symbol, HPQ.PrimExpr)] -> p+  , baseTable :: TableIdentifier -> (Bindings HPQ.PrimExpr) -> p   , product   :: NEL.NonEmpty p -> [HPQ.PrimExpr] -> p-  , aggregate :: [(Symbol, (Maybe (HPQ.AggrOp, [HPQ.OrderExpr]), HPQ.PrimExpr))] -> p -> p+  , aggregate :: (Bindings (Maybe (HPQ.AggrOp, [HPQ.OrderExpr]), HPQ.PrimExpr)) -> p -> p   , order     :: [HPQ.OrderExpr] -> p -> p   , limit     :: LimitOp -> p -> p-  , join      :: JoinType -> HPQ.PrimExpr -> p -> p -> p+  , join      :: JoinType+              -> HPQ.PrimExpr+              -> (Bindings HPQ.PrimExpr)+              -> (Bindings HPQ.PrimExpr)+              -> p+              -> p+              -> p   , values    :: [Symbol] -> (NEL.NonEmpty [HPQ.PrimExpr]) -> p-  , binary    :: BinOp -> [(Symbol, (HPQ.PrimExpr, HPQ.PrimExpr))] -> (p, p) -> p+  , binary    :: BinOp -> (Bindings (HPQ.PrimExpr, HPQ.PrimExpr)) -> (p, p) -> p   , label     :: String -> p -> p-  , relExpr   :: HPQ.PrimExpr -> [(Symbol, HPQ.PrimExpr)] -> p+  , relExpr   :: HPQ.PrimExpr -> (Bindings HPQ.PrimExpr) -> p     -- ^ A relation-valued expression   } @@ -104,7 +113,7 @@           Aggregate aggrs q         -> aggregate f aggrs (self q)           Order pes q               -> order     f pes (self q)           Limit op q                -> limit     f op (self q)-          Join j cond q1 q2         -> join      f j cond (self q1) (self q2)+          Join j cond pe1 pe2 q1 q2 -> join      f j cond pe1 pe2 (self q1) (self q2)           Values ss pes             -> values    f ss pes           Binary binop pes (q1, q2) -> binary    f binop pes (self q1, self q2)           Label l pq                -> label     f l (self pq)
src/Opaleye/Internal/Print.hs view
@@ -25,6 +25,7 @@ ppSql :: Select -> Doc ppSql (SelectFrom s)   = ppSelectFrom s ppSql (Table table)    = HPrint.ppTable table+ppSql (RelExpr expr)   = HPrint.ppSqlExpr expr ppSql (SelectJoin j)   = ppSelectJoin j ppSql (SelectValues v) = ppSelectValues v ppSql (SelectBinary v) = ppSelectBinary v@@ -78,8 +79,10 @@ ppJoinType Sql.FullJoin = text "FULL OUTER JOIN"  ppAttrs :: Sql.SelectAttrs -> Doc-ppAttrs Sql.Star             = text "*"-ppAttrs (Sql.SelectAttrs xs) = (HPrint.commaV nameAs . NEL.toList) xs+ppAttrs Sql.Star                 = text "*"+ppAttrs (Sql.SelectAttrs xs)     = (HPrint.commaV nameAs . NEL.toList) xs+ppAttrs (Sql.SelectAttrsStar xs) =+  HPrint.commaV id ((map nameAs . NEL.toList) xs ++ [text "*"])  -- This is pretty much just nameAs from HaskellDB nameAs :: (HSql.SqlExpr, Maybe HSql.SqlColumn) -> Doc
src/Opaleye/Internal/RunQuery.hs view
@@ -72,6 +72,10 @@ instance Functor (QueryRunnerColumn u) where   fmap f ~(QueryRunnerColumn u fp) = QueryRunnerColumn u ((fmap . fmap . fmap) f fp) +-- | A 'QueryRunner' specifies how to convert Postgres values (@columns@)+--   into Haskell values (@haskells@).  Most likely you will never need+--   to create on of these or handle one directly.  It will be provided+--   for you by the 'D.Default' 'QueryRunner' instance. data QueryRunner columns haskells =   QueryRunner (U.Unpackspec columns ())               (columns -> RowParser haskells)
src/Opaleye/Internal/Sql.hs view
@@ -31,6 +31,7 @@ data SelectAttrs =     Star   | SelectAttrs (NEL.NonEmpty (HSql.SqlExpr, Maybe HSql.SqlColumn))+  | SelectAttrsStar (NEL.NonEmpty (HSql.SqlExpr, Maybe HSql.SqlColumn))   deriving Show  data From = From {@@ -155,10 +156,21 @@           PQ.OffsetOp n        -> (Nothing, Just n)           PQ.LimitOffsetOp l o -> (Just l, Just o) -join :: PQ.JoinType -> HPQ.PrimExpr -> Select -> Select -> Select-join j cond s1 s2 = SelectJoin Join { jJoinType = joinType j-                                    , jTables = (s1, s2)-                                    , jCond = sqlExpr cond }+join :: PQ.JoinType+     -> HPQ.PrimExpr+     -> PQ.Bindings HPQ.PrimExpr+     -> PQ.Bindings HPQ.PrimExpr+     -> Select+     -> Select+     -> Select+join j cond pes1 pes2 s1 s2 =+  SelectJoin Join { jJoinType = joinType j+                  , jTables   = (selectFrom pes1 s1, selectFrom pes2 s2)+                  , jCond     = sqlExpr cond }+  where selectFrom pes s = SelectFrom $ newSelect {+            attrs  = SelectAttrsStar (ensureColumns (map sqlBinding pes))+          , tables = [s]+          }  -- Postgres seems to name columns of VALUES clauses "column1", -- "column2", ... . I'm not sure to what extent it is customisable or
src/Opaleye/Join.hs view
@@ -1,5 +1,11 @@--- | Left, right, and full outer joins.  If you want inner joins, just use 'restrict' instead.+-- | Left, right, and full outer joins. --+-- "Opaleye.FunctionalJoin" provides a much nicer, Haskelly, interface+-- to joins than this module, which sticks to the (horrible) standard+-- \"make missing rows NULL\" interface that SQL provides.+--+-- If you want inner joins, just use 'restrict' instead.+-- -- The use of the 'D.Default' typeclass means that the compiler will -- have trouble inferring types.  It is strongly recommended that you -- provide full type signatures when using the join functions.@@ -13,7 +19,9 @@ --          -> Query ((Column a, Column b), (Column (Nullable c), Column (Nullable d))) -- @ -{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}  module Opaleye.Join where @@ -26,63 +34,60 @@  import qualified Data.Profunctor.Product.Default as D -leftJoin  :: (D.Default U.Unpackspec columnsA columnsA,-              D.Default U.Unpackspec columnsB columnsB,-              D.Default J.NullMaker columnsB nullableColumnsB)-          => Query columnsA  -- ^ Left query-          -> Query columnsB  -- ^ Right query-          -> ((columnsA, columnsB) -> Column T.PGBool) -- ^ Condition on which to join-          -> Query (columnsA, nullableColumnsB) -- ^ Left join+leftJoin  :: (D.Default U.Unpackspec columnsL columnsL,+              D.Default U.Unpackspec columnsR columnsR,+              D.Default J.NullMaker columnsR nullableColumnsR)+          => Query columnsL  -- ^ Left query+          -> Query columnsR  -- ^ Right query+          -> ((columnsL, columnsR) -> Column T.PGBool) -- ^ Condition on which to join+          -> Query (columnsL, nullableColumnsR) -- ^ Left join leftJoin = leftJoinExplicit D.def D.def D.def -rightJoin  :: (D.Default U.Unpackspec columnsA columnsA,-               D.Default U.Unpackspec columnsB columnsB,-               D.Default J.NullMaker columnsA nullableColumnsA)-           => Query columnsA -- ^ Left query-           -> Query columnsB -- ^ Right query-           -> ((columnsA, columnsB) -> Column T.PGBool) -- ^ Condition on which to join-           -> Query (nullableColumnsA, columnsB) -- ^ Right join+rightJoin  :: (D.Default U.Unpackspec columnsL columnsL,+               D.Default U.Unpackspec columnsR columnsR,+               D.Default J.NullMaker columnsL nullableColumnsL)+           => Query columnsL -- ^ Left query+           -> Query columnsR -- ^ Right query+           -> ((columnsL, columnsR) -> Column T.PGBool) -- ^ Condition on which to join+           -> Query (nullableColumnsL, columnsR) -- ^ Right join rightJoin = rightJoinExplicit D.def D.def D.def  -fullJoin  :: (D.Default U.Unpackspec columnsA columnsA,-              D.Default U.Unpackspec columnsB columnsB,-              D.Default J.NullMaker columnsA nullableColumnsA,-              D.Default J.NullMaker columnsB nullableColumnsB)-          => Query columnsA -- ^ Left query-          -> Query columnsB -- ^ Right query-          -> ((columnsA, columnsB) -> Column T.PGBool) -- ^ Condition on which to join-          -> Query (nullableColumnsA, nullableColumnsB) -- ^ Full outer join+fullJoin  :: (D.Default U.Unpackspec columnsL columnsL,+              D.Default U.Unpackspec columnsR columnsR,+              D.Default J.NullMaker columnsL nullableColumnsL,+              D.Default J.NullMaker columnsR nullableColumnsR)+          => Query columnsL -- ^ Left query+          -> Query columnsR -- ^ Right query+          -> ((columnsL, columnsR) -> Column T.PGBool) -- ^ Condition on which to join+          -> Query (nullableColumnsL, nullableColumnsR) -- ^ Full outer join fullJoin = fullJoinExplicit D.def D.def D.def D.def --- We don't actually need the Unpackspecs any more, but I'm going to--- leave them here in case they're ever needed again.  I don't want to--- have to break the API to add them back.-leftJoinExplicit :: U.Unpackspec columnsA columnsA-                 -> U.Unpackspec columnsB columnsB-                 -> J.NullMaker columnsB nullableColumnsB-                 -> Query columnsA -> Query columnsB-                 -> ((columnsA, columnsB) -> Column T.PGBool)-                 -> Query (columnsA, nullableColumnsB)-leftJoinExplicit _ _ nullmaker =-  J.joinExplicit id (J.toNullable nullmaker) PQ.LeftJoin+leftJoinExplicit :: U.Unpackspec columnsL columnsL+                 -> U.Unpackspec columnsR columnsR+                 -> J.NullMaker columnsR nullableColumnsR+                 -> Query columnsL -> Query columnsR+                 -> ((columnsL, columnsR) -> Column T.PGBool)+                 -> Query (columnsL, nullableColumnsR)+leftJoinExplicit uA uB nullmaker =+  J.joinExplicit uA uB id (J.toNullable nullmaker) PQ.LeftJoin -rightJoinExplicit :: U.Unpackspec columnsA columnsA-                  -> U.Unpackspec columnsB columnsB-                  -> J.NullMaker columnsA nullableColumnsA-                  -> Query columnsA -> Query columnsB-                  -> ((columnsA, columnsB) -> Column T.PGBool)-                  -> Query (nullableColumnsA, columnsB)-rightJoinExplicit _ _ nullmaker =-  J.joinExplicit (J.toNullable nullmaker) id PQ.RightJoin+rightJoinExplicit :: U.Unpackspec columnsL columnsL+                  -> U.Unpackspec columnsR columnsR+                  -> J.NullMaker columnsL nullableColumnsL+                  -> Query columnsL -> Query columnsR+                  -> ((columnsL, columnsR) -> Column T.PGBool)+                  -> Query (nullableColumnsL, columnsR)+rightJoinExplicit uA uB nullmaker =+  J.joinExplicit uA uB (J.toNullable nullmaker) id PQ.RightJoin  -fullJoinExplicit :: U.Unpackspec columnsA columnsA-                 -> U.Unpackspec columnsB columnsB-                 -> J.NullMaker columnsA nullableColumnsA-                 -> J.NullMaker columnsB nullableColumnsB-                 -> Query columnsA -> Query columnsB-                 -> ((columnsA, columnsB) -> Column T.PGBool)-                 -> Query (nullableColumnsA, nullableColumnsB)-fullJoinExplicit _ _ nullmakerA nullmakerB =-  J.joinExplicit (J.toNullable nullmakerA) (J.toNullable nullmakerB) PQ.FullJoin+fullJoinExplicit :: U.Unpackspec columnsL columnsL+                 -> U.Unpackspec columnsR columnsR+                 -> J.NullMaker columnsL nullableColumnsL+                 -> J.NullMaker columnsR nullableColumnsR+                 -> Query columnsL -> Query columnsR+                 -> ((columnsL, columnsR) -> Column T.PGBool)+                 -> Query (nullableColumnsL, nullableColumnsR)+fullJoinExplicit uA uB nullmakerA nullmakerB =+  J.joinExplicit uA uB (J.toNullable nullmakerA) (J.toNullable nullmakerB) PQ.FullJoin
src/Opaleye/Manipulation.hs view
@@ -66,14 +66,14 @@ -- compiler will have trouble inferring types.  It is strongly -- recommended that you provide full type signatures when using -- @runInsertManyReturning@.-runInsertManyReturning :: (D.Default RQ.QueryRunner returned haskells)+runInsertManyReturning :: (D.Default RQ.QueryRunner columnsReturned haskells)                        => PGS.Connection                        -- ^                        -> T.Table columnsW columnsR                        -- ^ Table to insert into                        -> [columnsW]                        -- ^ Rows to insert-                       -> (columnsR -> returned)+                       -> (columnsR -> columnsReturned)                        -- ^ Function @f@ to apply to the inserted rows                        -> IO [haskells]                        -- ^ Returned rows after @f@ has been applied@@ -90,7 +90,7 @@           -- 'runUpdate' will update rows for which @f@ returns @TRUE@           -- and leave unchanged rows for which @f@ returns @FALSE@.           -> IO Int64-          -- ^ The number of updated rows+          -- ^ The number of rows updated runUpdate conn = PGS.execute_ conn . fromString .:. arrangeUpdateSql  @@ -100,7 +100,7 @@ -- that the compiler will have trouble inferring types.  It is -- strongly recommended that you provide full type signatures when -- using @runInsertReturning@.-runUpdateReturning :: (D.Default RQ.QueryRunner returned haskells)+runUpdateReturning :: (D.Default RQ.QueryRunner columnsReturned haskells)                    => PGS.Connection                    -- ^                    -> T.Table columnsW columnsR@@ -112,7 +112,7 @@                    -- update.  'runUpdate' will update rows for which                    -- @f@ returns @TRUE@ and leave unchanged rows for                    -- which @f@ returns @FALSE@.-                   -> (columnsR -> returned)+                   -> (columnsR -> columnsReturned)                    -- ^ Functon @g@ to apply to the updated rows                    -> IO [haskells]                    -- ^ Returned rows after @g@ has been applied@@ -128,18 +128,18 @@           -- 'runDelete' will delete rows for which @f@ returns @TRUE@           -- and leave unchanged rows for which @f@ returns @FALSE@.           -> IO Int64-          -- ^ The number of deleted rows+          -- ^ The number of rows deleted runDelete conn = PGS.execute_ conn . fromString .: arrangeDeleteSql  -- | You probably don't need this, but can just use -- 'runInsertReturning' instead.  You only need it if you want to run -- an INSERT RETURNING statement but need to be explicit about the -- 'QueryRunner'.-runInsertReturningExplicit :: RQ.QueryRunner returned haskells+runInsertReturningExplicit :: RQ.QueryRunner columnsReturned haskells                            -> PGS.Connection                            -> T.Table columnsW columnsR                            -> columnsW-                           -> (columnsR -> returned)+                           -> (columnsR -> columnsReturned)                            -> IO [haskells] runInsertReturningExplicit qr conn t =   runInsertManyReturningExplicit qr conn t . return@@ -148,11 +148,11 @@ -- 'runInsertManyReturning' instead.  You only need it if you want to -- run an UPDATE RETURNING statement but need to be explicit about the -- 'QueryRunner'.-runInsertManyReturningExplicit :: RQ.QueryRunner returned haskells+runInsertManyReturningExplicit :: RQ.QueryRunner columnsReturned haskells                                -> PGS.Connection                                -> T.Table columnsW columnsR                                -> [columnsW]-                               -> (columnsR -> returned)+                               -> (columnsR -> columnsReturned)                                -> IO [haskells] runInsertManyReturningExplicit qr conn t columns r =   case NEL.nonEmpty columns of@@ -170,12 +170,12 @@ -- 'runUpdateReturning' instead.  You only need it if you want to run -- an UPDATE RETURNING statement but need to be explicit about the -- 'QueryRunner'.-runUpdateReturningExplicit :: RQ.QueryRunner returned haskells+runUpdateReturningExplicit :: RQ.QueryRunner columnsReturned haskells                            -> PGS.Connection                            -> T.Table columnsW columnsR                            -> (columnsR -> columnsW)                            -> (columnsR -> Column PGBool)-                           -> (columnsR -> returned)+                           -> (columnsR -> columnsReturned)                            -> IO [haskells] runUpdateReturningExplicit qr conn t update cond r =   PGS.queryWith_ parser conn@@ -197,11 +197,11 @@ -- -- This will be deprecated in a future release.  Use -- 'runInsertManyReturning' instead.-runInsertReturning :: (D.Default RQ.QueryRunner returned haskells)+runInsertReturning :: (D.Default RQ.QueryRunner columnsReturned haskells)                    => PGS.Connection                    -> T.Table columnsW columnsR                    -> columnsW-                   -> (columnsR -> returned)+                   -> (columnsR -> columnsReturned)                    -> IO [haskells] runInsertReturning = runInsertReturningExplicit D.def @@ -265,10 +265,10 @@  -- | For internal use only.  Do not use.  Will be removed in a -- subsequent release.-arrangeInsertManyReturning :: U.Unpackspec returned ignored+arrangeInsertManyReturning :: U.Unpackspec columnsReturned ignored                            -> T.Table columnsW columnsR                            -> NEL.NonEmpty columnsW-                           -> (columnsR -> returned)+                           -> (columnsR -> columnsReturned)                            -> Sql.Returning HSql.SqlInsert arrangeInsertManyReturning unpackspec table columns returningf =   Sql.Returning insert returningSEs@@ -279,21 +279,21 @@  -- | For internal use only.  Do not use.  Will be removed in a -- subsequent release.-arrangeInsertManyReturningSql :: U.Unpackspec returned ignored+arrangeInsertManyReturningSql :: U.Unpackspec columnsReturned ignored                               -> T.Table columnsW columnsR                               -> NEL.NonEmpty columnsW-                              -> (columnsR -> returned)+                              -> (columnsR -> columnsReturned)                               -> String arrangeInsertManyReturningSql =   show . Print.ppInsertReturning .:: arrangeInsertManyReturning  -- | For internal use only.  Do not use.  Will be removed in a -- subsequent release.-arrangeUpdateReturning :: U.Unpackspec returned ignored+arrangeUpdateReturning :: U.Unpackspec columnsReturned ignored                        -> T.Table columnsW columnsR                        -> (columnsR -> columnsW)                        -> (columnsR -> Column PGBool)-                       -> (columnsR -> returned)+                       -> (columnsR -> columnsReturned)                        -> Sql.Returning HSql.SqlUpdate arrangeUpdateReturning unpackspec table updatef cond returningf =   Sql.Returning update returningSEs@@ -304,11 +304,11 @@  -- | For internal use only.  Do not use.  Will be removed in a -- subsequent release.-arrangeUpdateReturningSql :: U.Unpackspec returned ignored+arrangeUpdateReturningSql :: U.Unpackspec columnsReturned ignored                           -> T.Table columnsW columnsR                           -> (columnsR -> columnsW)                           -> (columnsR -> Column PGBool)-                          -> (columnsR -> returned)+                          -> (columnsR -> columnsReturned)                           -> String arrangeUpdateReturningSql =   show . Print.ppUpdateReturning .::. arrangeUpdateReturning
src/Opaleye/Operators.hs view
@@ -9,6 +9,7 @@  import qualified Control.Arrow as A import qualified Data.Foldable as F+import qualified Data.List.NonEmpty as NEL  import           Opaleye.Internal.Column (Column(Column), unsafeCase_,                                           unsafeIfThenElse, unsafeGt)@@ -91,9 +92,20 @@ case_ :: [(Column T.PGBool, Column a)] -> Column a -> Column a case_ = unsafeCase_ +-- | Monomorphic if\/then\/else.+--+-- This may be replaced by 'ifThenElseMany' in a future version. ifThenElse :: Column T.PGBool -> Column a -> Column a -> Column a ifThenElse = unsafeIfThenElse +-- | Polymorphic if\/then\/else.+ifThenElseMany :: D.Default O.IfPP columns columns+               => Column T.PGBool+               -> columns+               -> columns+               -> columns+ifThenElseMany = O.ifExplict D.def+ infixr 2 .||  -- | Boolean or@@ -119,6 +131,10 @@ like :: Column T.PGText -> Column T.PGText -> Column T.PGBool like = C.binOp HPQ.OpLike +-- | Postgres @ILIKE@ operator+ilike :: Column T.PGText -> Column T.PGText -> Column T.PGBool+ilike = C.binOp HPQ.OpILike+ charLength :: C.PGString a => Column a -> Column Int charLength (Column e) = Column (HPQ.FunExpr "char_length" [e]) @@ -132,7 +148,9 @@ -- product.  'in_' @validProducts@ is a function which checks whether -- a product is a valid product. in_ :: (Functor f, F.Foldable f) => f (Column a) -> Column a -> Column T.PGBool-in_ hs w = ors . fmap (w .==) $ hs+in_ fcas (Column a) = Column $ case NEL.nonEmpty (F.toList fcas) of+   Nothing -> HPQ.ConstExpr (HPQ.BoolLit False)+   Just xs -> HPQ.BinExpr HPQ.OpIn a (HPQ.ListExpr (fmap C.unColumn xs))  -- | True if the first argument occurs amongst the rows of the second, -- false otherwise.@@ -156,7 +174,7 @@         qj = Join.leftJoin (A.arr (const 1))                            (Distinct.distinct q')                            (uncurry (.==))-                          +         -- Check whether it is 'NULL'         qj' :: Query (Column T.PGBool)         qj' = A.arr (Opaleye.Operators.not
src/Opaleye/RunQuery.hs view
@@ -29,14 +29,14 @@ -- Example type specialization: -- -- @--- runQuery :: Query (Column 'Opaleye.PGTypes.PGInt4', Column 'Opaleye.PGTypes.PGText') -> IO [(Column Int, Column String)]+-- runQuery :: Query (Column 'Opaleye.PGTypes.PGInt4', Column 'Opaleye.PGTypes.PGText') -> IO [(Int, String)] -- @ -- -- Assuming the @makeAdaptorAndInstance@ splice has been run for the product type @Foo@: -- -- @ -- runQuery :: Query (Foo (Column 'Opaleye.PGTypes.PGInt4') (Column 'Opaleye.PGTypes.PGText') (Column 'Opaleye.PGTypes.PGBool')---          -> IO [(Foo (Column Int) (Column String) (Column Bool)]+--          -> IO [Foo Int String Bool] -- @ -- -- Opaleye types are converted to Haskell types based on instances of
src/Opaleye/Table.hs view
@@ -40,11 +40,15 @@   f ((), t0) = (retwires, primQ, Tag.next t0) where     (retwires, primQ) = T.queryTable cm table t0 +-- | 'required' is for columns which are not 'optional'.  You must+-- provide them on writes. required :: String -> TableProperties (Column a) (Column a) required columnName = T.TableProperties   (T.required columnName)   (View (Column (HPQ.BaseTableAttrExpr columnName))) +-- | 'optional' is for columns that you can omit on writes, such as+--  columns which have defaults or which are SERIAL. optional :: String -> TableProperties (Maybe (Column a)) (Column a) optional columnName = T.TableProperties   (T.optional columnName)