each working

This commit is contained in:
Ollie Charles 2020-01-17 15:27:14 +00:00
parent a69a9cb56d
commit 3408791b3f
11 changed files with 208 additions and 26 deletions

1
.envrc Normal file
View File

@ -0,0 +1 @@
eval "$(lorri direnv)"

28
opaleye.nix Normal file
View File

@ -0,0 +1,28 @@
{ mkDerivation, aeson, base, base16-bytestring, bytestring
, case-insensitive, containers, contravariant, dotenv, hspec
, hspec-discover, multiset, postgresql-simple, pretty
, product-profunctors, profunctors, QuickCheck, scientific
, semigroups, stdenv, text, time, time-locale-compat, transformers
, uuid, void
}:
mkDerivation {
pname = "opaleye";
version = "0.6.7004.1";
sha256 = "e12d1fdf762524997713db4538fe4b9477ff0c48e939d0c712e842c4276e4f26";
libraryHaskellDepends = [
aeson base base16-bytestring bytestring case-insensitive
contravariant postgresql-simple pretty product-profunctors
profunctors scientific semigroups text time time-locale-compat
transformers uuid void
];
testHaskellDepends = [
aeson base containers contravariant dotenv hspec hspec-discover
multiset postgresql-simple product-profunctors profunctors
QuickCheck semigroups text time transformers uuid
];
testToolDepends = [ hspec-discover ];
doCheck = false;
homepage = "https://github.com/tomjaguarpaw/haskell-opaleye";
description = "An SQL-generating DSL targeting PostgreSQL";
license = stdenv.lib.licenses.bsd3;
}

View File

@ -8,11 +8,17 @@ build-type: Simple
extra-source-files: CHANGELOG.md
library
build-depends: base >=4.12 && <4.13
default-language: Haskell2010
ghc-options: -Wall
hs-source-dirs: src
exposed-modules: Rel8.PublicFacing
build-depends:
base >=4.12 && <4.13
, opaleye
default-language:
Haskell2010
ghc-options:
-Wall
hs-source-dirs:
src
exposed-modules:
Rel8.PublicFacing
other-modules:
Rel8.Column
Rel8.ColumnSchema

33
shell.nix Normal file
View File

@ -0,0 +1,33 @@
{ nixpkgs ? import <nixpkgs> {}, compiler ? "default", doBenchmark ? false }:
let
inherit (nixpkgs) pkgs;
f = { mkDerivation, base, opaleye, stdenv }:
mkDerivation {
pname = "rel8";
version = "0.1.0.0";
src = ./.;
libraryHaskellDepends = [ base opaleye ];
license = "unknown";
hydraPlatforms = stdenv.lib.platforms.none;
};
haskellPackages = (if compiler == "default"
then pkgs.haskellPackages
else pkgs.haskell.packages.${compiler}).override { inherit overrides; };
overrides = self: super: {
beam-core = self.callPackage ./beam-core.nix {};
beam-postgres = self.callPackage ./beam-postgres.nix {};
opaleye = self.callPackage ./opaleye.nix {};
};
variant = if doBenchmark then pkgs.haskell.lib.doBenchmark else pkgs.lib.id;
drv = variant (haskellPackages.callPackage f {});
in
if pkgs.lib.inNixShell then drv.env else drv

View File

@ -4,14 +4,16 @@
{-# language TypeFamilies #-}
{-# language UndecidableInstances #-}
module Rel8.Expr ( Expr ) where
module Rel8.Expr where
import Data.Kind
import Rel8.Table
import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye
-- | Typed SQL expressions
data Expr ( m :: Type -> Type ) a
data Expr ( m :: Type -> Type ) a =
Expr { toPrimExpr :: Opaleye.PrimExpr }
type role Expr representational nominal

View File

@ -8,7 +8,7 @@ module Rel8.FromRow ( FromRow ) where
import Data.Functor.Identity
import Rel8.Expr
import Rel8.MaybeTable
import {-# source #-} Rel8.Query
import Rel8.Query
-- | @FromRow@ witnesses the one-to-one correspondence between the type @sql@,

View File

@ -1,34 +1,110 @@
{-# language BlockArguments #-}
{-# language DeriveGeneric #-}
{-# language FlexibleContexts #-}
{-# language KindSignatures #-}
{-# language LambdaCase #-}
{-# language MultiParamTypeClasses #-}
{-# language NamedFieldPuns #-}
{-# language ScopedTypeVariables #-}
{-# language TypeApplications #-}
module Rel8.MonadQuery where
import Data.Proxy
import Numeric.Natural
import Rel8.Column
import Rel8.ColumnSchema
import Rel8.Expr
import Rel8.MaybeTable
import Rel8.Nest
import Rel8.Rewrite
import Rel8.TableSchema
import Rel8.ZipLeaves
import Rel8.Top
import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye
import qualified Opaleye.Internal.QueryArr as Opaleye
import qualified Opaleye.Internal.Table as Opaleye
import qualified Opaleye.Internal.Unpackspec as Opaleye
import qualified Opaleye.Internal.PackMap as Opaleye
import qualified Opaleye.Table as Opaleye
-- | The class of monads that can form SQL queries, along with the corresponding
-- expression type.
class Monad m => MonadQuery m
class Monad m => MonadQuery m where
liftOpaleye :: Opaleye.Query a -> m a
instance MonadQuery m => MonadQuery ( Nest m ) where
liftOpaleye =
Nest . liftOpaleye
-- | Exists checks if a query returns at least one row.
--
-- @exists q@ is the same as the SQL expression @EXISTS ( q )@
exists :: m a -> m ( Expr m Bool )
exists = undefined
exists =
undefined
-- | Select each row from a table definition.
--
-- This is equivalent to @FROM table@.
each :: ( MonadQuery m, Rewrite ColumnSchema ( Expr m ) schema row ) => TableSchema schema -> m row
each =
undefined
each
:: forall m schema row
. ( MonadQuery m
, Rewrite ColumnSchema ( Expr m ) schema row
, ZipLeaves row row ( Expr m ) ( Expr m )
, CanZipLeaves row row Top
)
=> TableSchema schema -> m row
each schema =
liftOpaleye ( Opaleye.selectTableExplicit unpackspec table )
where
unpackspec :: Opaleye.Unpackspec row row
unpackspec =
Opaleye.Unpackspec $ Opaleye.PackMap \f row ->
zipLeaves
( Proxy @Top )
( \( C expr ) _ -> fmap ( C . Expr ) ( f ( toPrimExpr expr ) ) )
row
row
table :: Opaleye.Table () row
table =
case tableSchema schema of
Nothing ->
Opaleye.Table ( tableName schema ) tableFields
Just s ->
Opaleye.TableWithSchema s ( tableName schema ) tableFields
tableFields :: Opaleye.TableFields () row
tableFields =
Opaleye.TableProperties writer view
writer :: Opaleye.Writer () row
writer =
Opaleye.Writer ( Opaleye.PackMap \_ _ -> pure () )
view :: Opaleye.View row
view =
Opaleye.View
( rewrite
( \( C ColumnSchema{ columnName } ) ->
C ( Expr ( Opaleye.BaseTableAttrExpr columnName ) )
)
( tableColumns schema )
)
-- | Select all rows from another table that match a given predicate. If the

View File

@ -1,3 +0,0 @@
module Rel8.MonadQuery where
class Monad m => MonadQuery m

View File

@ -2,8 +2,6 @@
module Rel8.Nest where
import {-# source #-} Rel8.MonadQuery
newtype Nest m a = Nest ( m a )
deriving ( Functor, Applicative, Monad, MonadQuery )
deriving ( Functor, Applicative, Monad )

View File

@ -1,19 +1,63 @@
{-# language BlockArguments #-}
{-# language FlexibleContexts #-}
{-# language GeneralizedNewtypeDeriving #-}
{-# language ScopedTypeVariables #-}
{-# language TypeApplications #-}
module Rel8.Query where
import Rel8.FromRow
import Data.Proxy
import qualified Opaleye
import qualified Opaleye.Internal.PackMap as Opaleye
import qualified Opaleye.Internal.QueryArr as Opaleye
import qualified Opaleye.Internal.Unpackspec as Opaleye
import Rel8.Column
import Rel8.Expr
import Rel8.MonadQuery
import Rel8.Top
import Rel8.ZipLeaves
import {-# source #-} Rel8.FromRow
newtype Query a = Query ( IO a )
deriving ( Functor, Applicative, Monad )
newtype Query a = Query ( Opaleye.Query a )
deriving ( Functor, Applicative )
instance MonadQuery Query
instance Monad Query where
return = pure
Query ( Opaleye.QueryArr f ) >>= g = Query $ Opaleye.QueryArr \input ->
case ( f input ) of
( a, primQuery, tag ) ->
case g a of
Query ( Opaleye.QueryArr h ) ->
h ( (), primQuery, tag )
instance MonadQuery Query where
liftOpaleye =
Query
-- | Run a @SELECT@ query, returning all rows.
select :: FromRow row haskell => Query row -> m [ haskell ]
select _ =
undefined
showSQL
:: forall a
. ( CanZipLeaves a a Top, ZipLeaves a a ( Expr Query ) ( Expr Query ) )
=> Query a -> Maybe String
showSQL ( Query opaleye ) =
Opaleye.showSqlExplicit unpackspec opaleye
where
unpackspec :: Opaleye.Unpackspec a a
unpackspec =
Opaleye.Unpackspec $ Opaleye.PackMap \f row ->
zipLeaves
( Proxy @Top )
( \( C expr ) _ -> C . Expr <$> f ( toPrimExpr expr ) )
row
row

View File

@ -1,3 +0,0 @@
module Rel8.Query where
data Query a