{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}

-- |
-- Module      : Database.Relational.Projectable
-- Copyright   : 2013-2018 Kei Hibino
-- License     : BSD3
--
-- Maintainer  : ex8k.hibino@gmail.com
-- Stability   : experimental
-- Portability : unknown
--
-- This module defines operators on various projected records.
module Database.Relational.Projectable (
  -- * Projectable from SQL strings
  SqlContext (unsafeProjectSqlTerms), unsafeProjectSql',
  unsafeProjectSql,

  -- * Records of values
  value,
  valueTrue, valueFalse,
  values,
  nothing,

  -- * Placeholders
  PlaceHolders, unsafeAddPlaceHolders, unsafePlaceHolders,
  pwPlaceholder, placeholder', placeholder, unitPlaceHolder, unitPH,

  -- * Projectable into SQL strings
  unsafeShowSql', unsafeShowSql,

  -- * Operators
  (.=.), (.<.), (.<=.), (.>.), (.>=.), (.<>.),

  and', or', in',

  (.||.), (?||?), like, likeMaybe, like', likeMaybe',
  (.+.), (.-.), (.*.), (./.),
  (?+?), (?-?), (?*?), (?/?),

  isNothing, isJust, fromMaybe,
  not', exists,

  negate', fromIntegral', showNum,
  negateMaybe, fromIntegralMaybe, showNumMaybe,

  casesOrElse, casesOrElse',
  caseSearch, caseSearchMaybe, case', caseMaybe,

  SqlBinOp, unsafeBinOp, unsafeUniOp,

  -- * Terms for Window function types
  rank, denseRank, rowNumber, percentRank, cumeDist,

  -- * Zipping projections
  projectZip, (><),

  -- * 'Maybe' type projecitoins
  ProjectableMaybe (just, flattenMaybe),

  -- * Projection for nested 'Maybe's
  ProjectableFlattenMaybe (flatten),

  flattenPiMaybe,

  -- * Get narrower records
  (!), (?), (??), (?!), (?!?), (!??),

  -- * Aggregate functions
  unsafeAggregateOp,
  count,
  sum', sumMaybe, avg, avgMaybe,
  max', maxMaybe, min', minMaybe,
  every, any', some',
  ) where

import Prelude hiding (pi)

import Data.String (IsString)
import Data.Functor.ProductIsomorphic
  ((|$|), ProductIsoApplicative, pureP, (|*|), )

import Language.SQL.Keyword (Keyword)
import qualified Language.SQL.Keyword as SQL

import Database.Record
  (PersistableWidth, persistableWidth, PersistableRecordWidth,
   HasColumnConstraint, NotNull)
import Database.Record.Persistable (runPersistableRecordWidth)

import Database.Relational.Internal.ContextType (Flat, Exists, OverWindow)
import Database.Relational.Internal.String (StringSQL, stringSQL, showStringSQL)
import Database.Relational.SqlSyntax (Record, Predicate)
import qualified Database.Relational.SqlSyntax as Syntax

import Database.Relational.Pure ()
import Database.Relational.TupleInstances ()
import Database.Relational.Pi (Pi)
import Database.Relational.ProjectableClass
  (LiteralSQL, showLiteral, )
import Database.Relational.Record (RecordList)
import qualified Database.Relational.Record as Record
import Database.Relational.Projectable.Unsafe
  (SqlContext (..), OperatorContext, AggregatedContext, PlaceHolders (..))
import Database.Relational.Projectable.Instances ()


-- | Unsafely Project single SQL term.
unsafeProjectSql' :: SqlContext c => StringSQL -> Record c t
unsafeProjectSql' :: StringSQL -> Record c t
unsafeProjectSql' = [StringSQL] -> Record c t
forall c t. SqlContext c => [StringSQL] -> Record c t
unsafeProjectSqlTerms ([StringSQL] -> Record c t)
-> (StringSQL -> [StringSQL]) -> StringSQL -> Record c t
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (StringSQL -> [StringSQL] -> [StringSQL]
forall a. a -> [a] -> [a]
:[])

-- | Unsafely Project single SQL string. String interface of 'unsafeProjectSql'''.
unsafeProjectSql :: SqlContext c => String -> Record c t
unsafeProjectSql :: String -> Record c t
unsafeProjectSql = StringSQL -> Record c t
forall c t. SqlContext c => StringSQL -> Record c t
unsafeProjectSql' (StringSQL -> Record c t)
-> (String -> StringSQL) -> String -> Record c t
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> StringSQL
stringSQL

-- | Record with polymorphic phantom type of SQL null value. Semantics of comparing is unsafe.
nothing :: (OperatorContext c, SqlContext c, PersistableWidth a)
        => Record c (Maybe a)
nothing :: Record c (Maybe a)
nothing = PersistableRecordWidth a -> Record c (Maybe a)
forall c a.
SqlContext c =>
PersistableRecordWidth a -> Record c (Maybe a)
proxyWidth PersistableRecordWidth a
forall a. PersistableWidth a => PersistableRecordWidth a
persistableWidth
  where
    proxyWidth :: SqlContext c => PersistableRecordWidth a -> Record c (Maybe a)
    proxyWidth :: PersistableRecordWidth a -> Record c (Maybe a)
proxyWidth PersistableRecordWidth a
w = [StringSQL] -> Record c (Maybe a)
forall c t. SqlContext c => [StringSQL] -> Record c t
unsafeProjectSqlTerms ([StringSQL] -> Record c (Maybe a))
-> [StringSQL] -> Record c (Maybe a)
forall a b. (a -> b) -> a -> b
$ Int -> StringSQL -> [StringSQL]
forall a. Int -> a -> [a]
replicate (PersistableRecordWidth a -> Int
forall a. PersistableRecordWidth a -> Int
runPersistableRecordWidth PersistableRecordWidth a
w) StringSQL
SQL.NULL

-- | Generate record with polymorphic type of SQL constant values from Haskell value.
value :: (LiteralSQL t, OperatorContext c) => t -> Record c t
value :: t -> Record c t
value = [StringSQL] -> Record c t
forall c t. SqlContext c => [StringSQL] -> Record c t
unsafeProjectSqlTerms ([StringSQL] -> Record c t)
-> (t -> [StringSQL]) -> t -> Record c t
forall b c a. (b -> c) -> (a -> b) -> a -> c
. t -> [StringSQL]
forall a. LiteralSQL a => a -> [StringSQL]
showLiteral

-- | Record with polymorphic type of SQL true value.
valueTrue  :: OperatorContext c => Record c (Maybe Bool)
valueTrue :: Record c (Maybe Bool)
valueTrue  =  Record c Bool -> Record c (Maybe Bool)
forall (p :: * -> *) a. ProjectableMaybe p => p a -> p (Maybe a)
just (Record c Bool -> Record c (Maybe Bool))
-> Record c Bool -> Record c (Maybe Bool)
forall a b. (a -> b) -> a -> b
$ Bool -> Record c Bool
forall t c. (LiteralSQL t, OperatorContext c) => t -> Record c t
value Bool
True

-- | Record with polymorphic type of SQL false value.
valueFalse :: OperatorContext c => Record c (Maybe Bool)
valueFalse :: Record c (Maybe Bool)
valueFalse =  Record c Bool -> Record c (Maybe Bool)
forall (p :: * -> *) a. ProjectableMaybe p => p a -> p (Maybe a)
just (Record c Bool -> Record c (Maybe Bool))
-> Record c Bool -> Record c (Maybe Bool)
forall a b. (a -> b) -> a -> b
$ Bool -> Record c Bool
forall t c. (LiteralSQL t, OperatorContext c) => t -> Record c t
value Bool
False

-- | RecordList with polymorphic type of SQL set value from Haskell list.
values :: (LiteralSQL t, OperatorContext c) => [t] -> RecordList (Record c) t
values :: [t] -> RecordList (Record c) t
values =  [Record c t] -> RecordList (Record c) t
forall (p :: * -> *) t. [p t] -> RecordList p t
Record.list ([Record c t] -> RecordList (Record c) t)
-> ([t] -> [Record c t]) -> [t] -> RecordList (Record c) t
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (t -> Record c t) -> [t] -> [Record c t]
forall a b. (a -> b) -> [a] -> [b]
map t -> Record c t
forall t c. (LiteralSQL t, OperatorContext c) => t -> Record c t
value


-- | Unsafely generate SQL expression term from record object.
unsafeShowSql' :: Record c a -> StringSQL
unsafeShowSql' :: Record c a -> StringSQL
unsafeShowSql' = Record c a -> StringSQL
forall c r. Record c r -> StringSQL
Record.unsafeStringSql

-- | Unsafely generate SQL expression string from record object.
--   String interface of 'unsafeShowSql''.
unsafeShowSql :: Record c a    -- ^ Source record object
              -> String -- ^ Result SQL expression string.
unsafeShowSql :: Record c a -> String
unsafeShowSql =  StringSQL -> String
showStringSQL (StringSQL -> String)
-> (Record c a -> StringSQL) -> Record c a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Record c a -> StringSQL
forall c r. Record c r -> StringSQL
unsafeShowSql'


-- | Binary operator type for SQL String.
type SqlBinOp = Keyword -> Keyword -> Keyword

-- | Unsafely make unary operator for records from SQL keyword.
unsafeUniOp :: SqlContext c2
            => (Keyword -> Keyword) -> Record c1 a -> Record c2 b
unsafeUniOp :: (StringSQL -> StringSQL) -> Record c1 a -> Record c2 b
unsafeUniOp StringSQL -> StringSQL
u = StringSQL -> Record c2 b
forall c t. SqlContext c => StringSQL -> Record c t
unsafeProjectSql' (StringSQL -> Record c2 b)
-> (Record c1 a -> StringSQL) -> Record c1 a -> Record c2 b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StringSQL -> StringSQL
u (StringSQL -> StringSQL)
-> (Record c1 a -> StringSQL) -> Record c1 a -> StringSQL
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Record c1 a -> StringSQL
forall c r. Record c r -> StringSQL
unsafeShowSql'

unsafeFlatUniOp :: SqlContext c
                => Keyword -> Record c a -> Record c b
unsafeFlatUniOp :: StringSQL -> Record c a -> Record c b
unsafeFlatUniOp StringSQL
kw = (StringSQL -> StringSQL) -> Record c a -> Record c b
forall c2 c1 a b.
SqlContext c2 =>
(StringSQL -> StringSQL) -> Record c1 a -> Record c2 b
unsafeUniOp (StringSQL -> StringSQL
SQL.paren (StringSQL -> StringSQL)
-> (StringSQL -> StringSQL) -> StringSQL -> StringSQL
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StringSQL -> StringSQL -> StringSQL
SQL.defineUniOp StringSQL
kw)

-- | Unsafely make binary operator for records from string binary operator.
unsafeBinOp :: SqlContext k
            => SqlBinOp
            -> Record k a -> Record k b -> Record k c
unsafeBinOp :: (StringSQL -> StringSQL -> StringSQL)
-> Record k a -> Record k b -> Record k c
unsafeBinOp StringSQL -> StringSQL -> StringSQL
op Record k a
a Record k b
b = StringSQL -> Record k c
forall c t. SqlContext c => StringSQL -> Record c t
unsafeProjectSql' (StringSQL -> Record k c)
-> (StringSQL -> StringSQL) -> StringSQL -> Record k c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StringSQL -> StringSQL
SQL.paren (StringSQL -> Record k c) -> StringSQL -> Record k c
forall a b. (a -> b) -> a -> b
$
                     StringSQL -> StringSQL -> StringSQL
op (Record k a -> StringSQL
forall c r. Record c r -> StringSQL
unsafeShowSql' Record k a
a) (Record k b -> StringSQL
forall c r. Record c r -> StringSQL
unsafeShowSql' Record k b
b)

-- | Unsafely make binary operator to compare records from string binary operator.
compareBinOp :: SqlContext c
             => SqlBinOp
             -> Record c a -> Record c a -> Record c (Maybe Bool)
compareBinOp :: (StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c (Maybe Bool)
compareBinOp =  (StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c (Maybe Bool)
forall k a b c.
SqlContext k =>
(StringSQL -> StringSQL -> StringSQL)
-> Record k a -> Record k b -> Record k c
unsafeBinOp

-- | Unsafely make numrical binary operator for records from string binary operator.
monoBinOp :: SqlContext c
          => SqlBinOp
          -> Record c a -> Record c a -> Record c a
monoBinOp :: (StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c a
monoBinOp =  (StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c a
forall k a b c.
SqlContext k =>
(StringSQL -> StringSQL -> StringSQL)
-> Record k a -> Record k b -> Record k c
unsafeBinOp


-- | Compare operator corresponding SQL /=/ .
(.=.)  :: OperatorContext c
       => Record c ft -> Record c ft -> Record c (Maybe Bool)
.=. :: Record c ft -> Record c ft -> Record c (Maybe Bool)
(.=.)  =  (StringSQL -> StringSQL -> StringSQL)
-> Record c ft -> Record c ft -> Record c (Maybe Bool)
forall c a.
SqlContext c =>
(StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c (Maybe Bool)
compareBinOp StringSQL -> StringSQL -> StringSQL
(SQL..=.)

-- | Compare operator corresponding SQL /</ .
(.<.)  :: OperatorContext c
       => Record c ft -> Record c ft -> Record c (Maybe Bool)
.<. :: Record c ft -> Record c ft -> Record c (Maybe Bool)
(.<.)  =  (StringSQL -> StringSQL -> StringSQL)
-> Record c ft -> Record c ft -> Record c (Maybe Bool)
forall c a.
SqlContext c =>
(StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c (Maybe Bool)
compareBinOp StringSQL -> StringSQL -> StringSQL
(SQL..<.)

-- | Compare operator corresponding SQL /<=/ .
(.<=.)  :: OperatorContext c
        => Record c ft -> Record c ft -> Record c (Maybe Bool)
.<=. :: Record c ft -> Record c ft -> Record c (Maybe Bool)
(.<=.)  =  (StringSQL -> StringSQL -> StringSQL)
-> Record c ft -> Record c ft -> Record c (Maybe Bool)
forall c a.
SqlContext c =>
(StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c (Maybe Bool)
compareBinOp StringSQL -> StringSQL -> StringSQL
(SQL..<=.)

-- | Compare operator corresponding SQL />/ .
(.>.)  :: OperatorContext c
       => Record c ft -> Record c ft -> Record c (Maybe Bool)
.>. :: Record c ft -> Record c ft -> Record c (Maybe Bool)
(.>.)  =  (StringSQL -> StringSQL -> StringSQL)
-> Record c ft -> Record c ft -> Record c (Maybe Bool)
forall c a.
SqlContext c =>
(StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c (Maybe Bool)
compareBinOp StringSQL -> StringSQL -> StringSQL
(SQL..>.)

-- | Compare operator corresponding SQL />=/ .
(.>=.)  :: OperatorContext c
        => Record c ft -> Record c ft -> Record c (Maybe Bool)
.>=. :: Record c ft -> Record c ft -> Record c (Maybe Bool)
(.>=.)  =  (StringSQL -> StringSQL -> StringSQL)
-> Record c ft -> Record c ft -> Record c (Maybe Bool)
forall c a.
SqlContext c =>
(StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c (Maybe Bool)
compareBinOp StringSQL -> StringSQL -> StringSQL
(SQL..>=.)

-- | Compare operator corresponding SQL /<>/ .
(.<>.) :: OperatorContext c
       => Record c ft -> Record c ft -> Record c (Maybe Bool)
.<>. :: Record c ft -> Record c ft -> Record c (Maybe Bool)
(.<>.) =  (StringSQL -> StringSQL -> StringSQL)
-> Record c ft -> Record c ft -> Record c (Maybe Bool)
forall c a.
SqlContext c =>
(StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c (Maybe Bool)
compareBinOp StringSQL -> StringSQL -> StringSQL
(SQL..<>.)

-- | Logical operator corresponding SQL /AND/ .
and' :: OperatorContext c
     => Record c (Maybe Bool) -> Record c (Maybe Bool) -> Record c (Maybe Bool)
and' :: Record c (Maybe Bool)
-> Record c (Maybe Bool) -> Record c (Maybe Bool)
and' = (StringSQL -> StringSQL -> StringSQL)
-> Record c (Maybe Bool)
-> Record c (Maybe Bool)
-> Record c (Maybe Bool)
forall c a.
SqlContext c =>
(StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c a
monoBinOp StringSQL -> StringSQL -> StringSQL
SQL.and

-- | Logical operator corresponding SQL /OR/ .
or' :: OperatorContext c
    => Record c (Maybe Bool) -> Record c (Maybe Bool) -> Record c (Maybe Bool)
or' :: Record c (Maybe Bool)
-> Record c (Maybe Bool) -> Record c (Maybe Bool)
or'  = (StringSQL -> StringSQL -> StringSQL)
-> Record c (Maybe Bool)
-> Record c (Maybe Bool)
-> Record c (Maybe Bool)
forall c a.
SqlContext c =>
(StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c a
monoBinOp StringSQL -> StringSQL -> StringSQL
SQL.or

-- | Logical operator corresponding SQL /NOT/ .
not' :: OperatorContext c
     => Record c (Maybe Bool) -> Record c (Maybe Bool)
not' :: Record c (Maybe Bool) -> Record c (Maybe Bool)
not' =  StringSQL -> Record c (Maybe Bool) -> Record c (Maybe Bool)
forall c a b. SqlContext c => StringSQL -> Record c a -> Record c b
unsafeFlatUniOp StringSQL
SQL.NOT

-- | Logical operator corresponding SQL /EXISTS/ .
exists :: OperatorContext c
       => RecordList (Record Exists) r -> Record c (Maybe Bool)
exists :: RecordList (Record Exists) r -> Record c (Maybe Bool)
exists =  StringSQL -> Record c (Maybe Bool)
forall c t. SqlContext c => StringSQL -> Record c t
unsafeProjectSql' (StringSQL -> Record c (Maybe Bool))
-> (RecordList (Record Exists) r -> StringSQL)
-> RecordList (Record Exists) r
-> Record c (Maybe Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StringSQL -> StringSQL
SQL.paren (StringSQL -> StringSQL)
-> (RecordList (Record Exists) r -> StringSQL)
-> RecordList (Record Exists) r
-> StringSQL
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StringSQL -> StringSQL -> StringSQL
SQL.defineUniOp StringSQL
SQL.EXISTS
          (StringSQL -> StringSQL)
-> (RecordList (Record Exists) r -> StringSQL)
-> RecordList (Record Exists) r
-> StringSQL
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Record Exists r -> StringSQL)
-> RecordList (Record Exists) r -> StringSQL
forall (p :: * -> *) t.
(p t -> StringSQL) -> RecordList p t -> StringSQL
Record.unsafeStringSqlList Record Exists r -> StringSQL
forall c r. Record c r -> StringSQL
unsafeShowSql'

-- | Concatinate operator corresponding SQL /||/ .
(.||.) :: OperatorContext c
       => Record c a -> Record c a -> Record c a
.||. :: Record c a -> Record c a -> Record c a
(.||.) =  (StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c a
forall k a b c.
SqlContext k =>
(StringSQL -> StringSQL -> StringSQL)
-> Record k a -> Record k b -> Record k c
unsafeBinOp StringSQL -> StringSQL -> StringSQL
(SQL..||.)

-- | Concatinate operator corresponding SQL /||/ . Maybe type version.
(?||?) :: (OperatorContext c, IsString a)
       => Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
?||? :: Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
(?||?) =  (StringSQL -> StringSQL -> StringSQL)
-> Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
forall k a b c.
SqlContext k =>
(StringSQL -> StringSQL -> StringSQL)
-> Record k a -> Record k b -> Record k c
unsafeBinOp StringSQL -> StringSQL -> StringSQL
(SQL..||.)

unsafeLike :: OperatorContext c
           => Record c a -> Record c b -> Record c (Maybe Bool)
unsafeLike :: Record c a -> Record c b -> Record c (Maybe Bool)
unsafeLike = (StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c b -> Record c (Maybe Bool)
forall k a b c.
SqlContext k =>
(StringSQL -> StringSQL -> StringSQL)
-> Record k a -> Record k b -> Record k c
unsafeBinOp (StringSQL -> StringSQL -> StringSQL -> StringSQL
SQL.defineBinOp StringSQL
SQL.LIKE)

-- | String-compare operator corresponding SQL /LIKE/ .
like' :: (OperatorContext c, IsString a)
      => Record c a -> Record c a -> Record c (Maybe Bool)
Record c a
x like' :: Record c a -> Record c a -> Record c (Maybe Bool)
`like'` Record c a
y = Record c a
x Record c a -> Record c a -> Record c (Maybe Bool)
forall c a b.
OperatorContext c =>
Record c a -> Record c b -> Record c (Maybe Bool)
`unsafeLike` Record c a
y

-- | String-compare operator corresponding SQL /LIKE/ .
likeMaybe' :: (OperatorContext c, IsString a)
           => Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe Bool)
Record c (Maybe a)
x likeMaybe' :: Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe Bool)
`likeMaybe'` Record c (Maybe a)
y = Record c (Maybe a)
x Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe Bool)
forall c a b.
OperatorContext c =>
Record c a -> Record c b -> Record c (Maybe Bool)
`unsafeLike` Record c (Maybe a)
y

-- | String-compare operator corresponding SQL /LIKE/ .
like :: (OperatorContext c, IsString a, LiteralSQL a)
       => Record c a -> a -> Record c (Maybe Bool)
Record c a
x like :: Record c a -> a -> Record c (Maybe Bool)
`like` a
a = Record c a
x Record c a -> Record c a -> Record c (Maybe Bool)
forall c a.
(OperatorContext c, IsString a) =>
Record c a -> Record c a -> Record c (Maybe Bool)
`like'` a -> Record c a
forall t c. (LiteralSQL t, OperatorContext c) => t -> Record c t
value a
a

-- | String-compare operator corresponding SQL /LIKE/ . Maybe type version.
likeMaybe :: (OperatorContext c, IsString a, LiteralSQL a)
          => Record c (Maybe a) -> a -> Record c (Maybe Bool)
Record c (Maybe a)
x likeMaybe :: Record c (Maybe a) -> a -> Record c (Maybe Bool)
`likeMaybe` a
a = Record c (Maybe a)
x Record c (Maybe a) -> Record c a -> Record c (Maybe Bool)
forall c a b.
OperatorContext c =>
Record c a -> Record c b -> Record c (Maybe Bool)
`unsafeLike` a -> Record c a
forall t c. (LiteralSQL t, OperatorContext c) => t -> Record c t
value a
a

-- | Unsafely make number binary operator for records from SQL operator string.
monoBinOp' :: SqlContext c
           => Keyword -> Record c a -> Record c a -> Record c a
monoBinOp' :: StringSQL -> Record c a -> Record c a -> Record c a
monoBinOp' = (StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c a
forall c a.
SqlContext c =>
(StringSQL -> StringSQL -> StringSQL)
-> Record c a -> Record c a -> Record c a
monoBinOp ((StringSQL -> StringSQL -> StringSQL)
 -> Record c a -> Record c a -> Record c a)
-> (StringSQL -> StringSQL -> StringSQL -> StringSQL)
-> StringSQL
-> Record c a
-> Record c a
-> Record c a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StringSQL -> StringSQL -> StringSQL -> StringSQL
SQL.defineBinOp

-- | Number operator corresponding SQL /+/ .
(.+.) :: (OperatorContext c, Num a)
      => Record c a -> Record c a -> Record c a
.+. :: Record c a -> Record c a -> Record c a
(.+.) =  StringSQL -> Record c a -> Record c a -> Record c a
forall c a.
SqlContext c =>
StringSQL -> Record c a -> Record c a -> Record c a
monoBinOp' StringSQL
"+"

-- | Number operator corresponding SQL /-/ .
(.-.) :: (OperatorContext c, Num a)
      => Record c a -> Record c a -> Record c a
.-. :: Record c a -> Record c a -> Record c a
(.-.) =  StringSQL -> Record c a -> Record c a -> Record c a
forall c a.
SqlContext c =>
StringSQL -> Record c a -> Record c a -> Record c a
monoBinOp' StringSQL
"-"

-- | Number operator corresponding SQL /// .
(./.) :: (OperatorContext c, Num a)
      => Record c a -> Record c a -> Record c a
./. :: Record c a -> Record c a -> Record c a
(./.) =  StringSQL -> Record c a -> Record c a -> Record c a
forall c a.
SqlContext c =>
StringSQL -> Record c a -> Record c a -> Record c a
monoBinOp' StringSQL
"/"

-- | Number operator corresponding SQL /*/ .
(.*.) :: (OperatorContext c, Num a)
      => Record c a -> Record c a -> Record c a
.*. :: Record c a -> Record c a -> Record c a
(.*.) =  StringSQL -> Record c a -> Record c a -> Record c a
forall c a.
SqlContext c =>
StringSQL -> Record c a -> Record c a -> Record c a
monoBinOp' StringSQL
"*"

-- | Number negate uni-operator corresponding SQL /-/.
negate' :: (OperatorContext c, Num a)
        => Record c a -> Record c a
negate' :: Record c a -> Record c a
negate' =  StringSQL -> Record c a -> Record c a
forall c a b. SqlContext c => StringSQL -> Record c a -> Record c b
unsafeFlatUniOp (StringSQL -> Record c a -> Record c a)
-> StringSQL -> Record c a -> Record c a
forall a b. (a -> b) -> a -> b
$ String -> StringSQL
SQL.word String
"-"

unsafeCastProjectable :: SqlContext c
                      => Record c a -> Record c b
unsafeCastProjectable :: Record c a -> Record c b
unsafeCastProjectable = Tuple -> Record c b
forall c t. Tuple -> Record c t
Syntax.record (Tuple -> Record c b)
-> (Record c a -> Tuple) -> Record c a -> Record c b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Record c a -> Tuple
forall c t. Record c t -> Tuple
Syntax.untypeRecord

-- | Number fromIntegral uni-operator.
fromIntegral' :: (SqlContext c, Integral a, Num b)
              => Record c a -> Record c b
fromIntegral' :: Record c a -> Record c b
fromIntegral' =  Record c a -> Record c b
forall c a b. SqlContext c => Record c a -> Record c b
unsafeCastProjectable

-- | Unsafely show number into string-like type in records.
showNum :: (SqlContext c, Num a, IsString b)
        => Record c a -> Record c b
showNum :: Record c a -> Record c b
showNum =  Record c a -> Record c b
forall c a b. SqlContext c => Record c a -> Record c b
unsafeCastProjectable

-- | Number operator corresponding SQL /+/ .
(?+?) :: (OperatorContext c, Num a)
      => Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
?+? :: Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
(?+?) =  StringSQL
-> Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
forall c a.
SqlContext c =>
StringSQL -> Record c a -> Record c a -> Record c a
monoBinOp' StringSQL
"+"

-- | Number operator corresponding SQL /-/ .
(?-?) :: (OperatorContext c, Num a)
      => Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
?-? :: Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
(?-?) =  StringSQL
-> Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
forall c a.
SqlContext c =>
StringSQL -> Record c a -> Record c a -> Record c a
monoBinOp' StringSQL
"-"

-- | Number operator corresponding SQL /// .
(?/?) :: (OperatorContext c, Num a)
      => Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
?/? :: Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
(?/?) =  StringSQL
-> Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
forall c a.
SqlContext c =>
StringSQL -> Record c a -> Record c a -> Record c a
monoBinOp' StringSQL
"/"

-- | Number operator corresponding SQL /*/ .
(?*?) :: (OperatorContext c, Num a)
      => Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
?*? :: Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
(?*?) =  StringSQL
-> Record c (Maybe a) -> Record c (Maybe a) -> Record c (Maybe a)
forall c a.
SqlContext c =>
StringSQL -> Record c a -> Record c a -> Record c a
monoBinOp' StringSQL
"*"

-- | Number negate uni-operator corresponding SQL /-/.
negateMaybe :: (OperatorContext c, Num a)
            => Record c (Maybe a) -> Record c (Maybe a)
negateMaybe :: Record c (Maybe a) -> Record c (Maybe a)
negateMaybe =  StringSQL -> Record c (Maybe a) -> Record c (Maybe a)
forall c a b. SqlContext c => StringSQL -> Record c a -> Record c b
unsafeFlatUniOp (StringSQL -> Record c (Maybe a) -> Record c (Maybe a))
-> StringSQL -> Record c (Maybe a) -> Record c (Maybe a)
forall a b. (a -> b) -> a -> b
$ String -> StringSQL
SQL.word String
"-"

-- | Number fromIntegral uni-operator.
fromIntegralMaybe :: (SqlContext c, Integral a, Num b)
                  => Record c (Maybe a) -> Record c (Maybe b)
fromIntegralMaybe :: Record c (Maybe a) -> Record c (Maybe b)
fromIntegralMaybe =  Record c (Maybe a) -> Record c (Maybe b)
forall c a b. SqlContext c => Record c a -> Record c b
unsafeCastProjectable

-- | Unsafely show number into string-like type in records.
showNumMaybe :: (SqlContext c, Num a, IsString b)
             => Record c (Maybe a) -> Record c (Maybe b)
showNumMaybe :: Record c (Maybe a) -> Record c (Maybe b)
showNumMaybe = Record c (Maybe a) -> Record c (Maybe b)
forall c a b. SqlContext c => Record c a -> Record c b
unsafeCastProjectable

-- | Search case operator correnponding SQL search /CASE/.
--   Like, /CASE WHEN p0 THEN a WHEN p1 THEN b ... ELSE c END/
caseSearch :: OperatorContext c
           => [(Predicate c, Record c a)] -- ^ Each when clauses
           -> Record c a                            -- ^ Else result record
           -> Record c a                            -- ^ Result record
caseSearch :: [(Predicate c, Record c a)] -> Record c a -> Record c a
caseSearch = [(Predicate c, Record c a)] -> Record c a -> Record c a
forall c a. [(Predicate c, Record c a)] -> Record c a -> Record c a
Syntax.caseSearch

-- | Same as 'caseSearch', but you can write like <when list> `casesOrElse` <else clause>.
casesOrElse :: OperatorContext c
            => [(Predicate c, Record c a)] -- ^ Each when clauses
            -> Record c a                            -- ^ Else result record
            -> Record c a                            -- ^ Result record
casesOrElse :: [(Predicate c, Record c a)] -> Record c a -> Record c a
casesOrElse = [(Predicate c, Record c a)] -> Record c a -> Record c a
forall c a.
OperatorContext c =>
[(Predicate c, Record c a)] -> Record c a -> Record c a
caseSearch

-- | Null default version of 'caseSearch'.
caseSearchMaybe :: (OperatorContext c {- (Record c) is always ProjectableMaybe -}, PersistableWidth a)
                => [(Predicate c, Record c (Maybe a))] -- ^ Each when clauses
                -> Record c (Maybe a)                            -- ^ Result record
caseSearchMaybe :: [(Predicate c, Record c (Maybe a))] -> Record c (Maybe a)
caseSearchMaybe [(Predicate c, Record c (Maybe a))]
cs = [(Predicate c, Record c (Maybe a))]
-> Record c (Maybe a) -> Record c (Maybe a)
forall c a.
OperatorContext c =>
[(Predicate c, Record c a)] -> Record c a -> Record c a
caseSearch [(Predicate c, Record c (Maybe a))]
cs Record c (Maybe a)
forall c a.
(OperatorContext c, SqlContext c, PersistableWidth a) =>
Record c (Maybe a)
nothing

-- | Simple case operator correnponding SQL simple /CASE/.
--   Like, /CASE x WHEN v THEN a WHEN w THEN b ... ELSE c END/
case' :: OperatorContext c
      => Record c a                 -- ^ Record value to match
      -> [(Record c a, Record c b)] -- ^ Each when clauses
      -> Record c b                 -- ^ Else result record
      -> Record c b                 -- ^ Result record
case' :: Record c a
-> [(Record c a, Record c b)] -> Record c b -> Record c b
case' = Record c a
-> [(Record c a, Record c b)] -> Record c b -> Record c b
forall c a b.
Record c a
-> [(Record c a, Record c b)] -> Record c b -> Record c b
Syntax.case'

-- | Uncurry version of 'case'', and you can write like ... `casesOrElse'` <else clause>.
casesOrElse' :: OperatorContext c
             => (Record c a, [(Record c a, Record c b)]) -- ^ Record value to match and each when clauses list
             -> Record c b                               -- ^ Else result record
             -> Record c b                               -- ^ Result record
casesOrElse' :: (Record c a, [(Record c a, Record c b)])
-> Record c b -> Record c b
casesOrElse' =  (Record c a
 -> [(Record c a, Record c b)] -> Record c b -> Record c b)
-> (Record c a, [(Record c a, Record c b)])
-> Record c b
-> Record c b
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Record c a
-> [(Record c a, Record c b)] -> Record c b -> Record c b
forall c a b.
OperatorContext c =>
Record c a
-> [(Record c a, Record c b)] -> Record c b -> Record c b
case'

-- | Null default version of 'case''.
caseMaybe :: (OperatorContext c {- (Record c) is always ProjectableMaybe -}, PersistableWidth b)
          => Record c a                         -- ^ Record value to match
          -> [(Record c a, Record c (Maybe b))] -- ^ Each when clauses
          -> Record c (Maybe b)                 -- ^ Result record
caseMaybe :: Record c a
-> [(Record c a, Record c (Maybe b))] -> Record c (Maybe b)
caseMaybe Record c a
v [(Record c a, Record c (Maybe b))]
cs = Record c a
-> [(Record c a, Record c (Maybe b))]
-> Record c (Maybe b)
-> Record c (Maybe b)
forall c a b.
OperatorContext c =>
Record c a
-> [(Record c a, Record c b)] -> Record c b -> Record c b
case' Record c a
v [(Record c a, Record c (Maybe b))]
cs Record c (Maybe b)
forall c a.
(OperatorContext c, SqlContext c, PersistableWidth a) =>
Record c (Maybe a)
nothing

-- | Binary operator corresponding SQL /IN/ .
in' :: OperatorContext c
    => Record c t -> RecordList (Record c) t -> Record c (Maybe Bool)
in' :: Record c t -> RecordList (Record c) t -> Record c (Maybe Bool)
in' Record c t
a RecordList (Record c) t
lp = StringSQL -> Record c (Maybe Bool)
forall c t. SqlContext c => StringSQL -> Record c t
unsafeProjectSql' (StringSQL -> Record c (Maybe Bool))
-> (StringSQL -> StringSQL) -> StringSQL -> Record c (Maybe Bool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StringSQL -> StringSQL
SQL.paren
           (StringSQL -> Record c (Maybe Bool))
-> StringSQL -> Record c (Maybe Bool)
forall a b. (a -> b) -> a -> b
$ StringSQL -> StringSQL -> StringSQL
SQL.in' (Record c t -> StringSQL
forall c r. Record c r -> StringSQL
unsafeShowSql' Record c t
a) ((Record c t -> StringSQL) -> RecordList (Record c) t -> StringSQL
forall (p :: * -> *) t.
(p t -> StringSQL) -> RecordList p t -> StringSQL
Record.unsafeStringSqlList Record c t -> StringSQL
forall c r. Record c r -> StringSQL
unsafeShowSql' RecordList (Record c) t
lp)

-- | Operator corresponding SQL /IS NULL/ , and extended against record types.
isNothing :: (OperatorContext c, HasColumnConstraint NotNull r)
          => Record c (Maybe r) -> Predicate c
isNothing :: Record c (Maybe r) -> Predicate c
isNothing Record c (Maybe r)
mr = StringSQL -> Predicate c
forall c t. SqlContext c => StringSQL -> Record c t
unsafeProjectSql' (StringSQL -> Predicate c) -> StringSQL -> Predicate c
forall a b. (a -> b) -> a -> b
$
               StringSQL -> StringSQL
SQL.paren (StringSQL -> StringSQL) -> StringSQL -> StringSQL
forall a b. (a -> b) -> a -> b
$ (StringSQL -> StringSQL -> StringSQL -> StringSQL
SQL.defineBinOp StringSQL
SQL.IS)
               (Record c (Maybe r) -> StringSQL
forall r c.
HasColumnConstraint NotNull r =>
Record c (Maybe r) -> StringSQL
Record.unsafeStringSqlNotNullMaybe Record c (Maybe r)
mr) StringSQL
SQL.NULL

-- | Operator corresponding SQL /NOT (... IS NULL)/ , and extended against record type.
isJust :: (OperatorContext c, HasColumnConstraint NotNull r)
          => Record c (Maybe r) -> Predicate c
isJust :: Record c (Maybe r) -> Predicate c
isJust =  Predicate c -> Predicate c
forall c.
OperatorContext c =>
Record c (Maybe Bool) -> Record c (Maybe Bool)
not' (Predicate c -> Predicate c)
-> (Record c (Maybe r) -> Predicate c)
-> Record c (Maybe r)
-> Predicate c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Record c (Maybe r) -> Predicate c
forall c r.
(OperatorContext c, HasColumnConstraint NotNull r) =>
Record c (Maybe r) -> Predicate c
isNothing

-- | Operator from maybe type using record extended 'isNull'.
fromMaybe :: (OperatorContext c, HasColumnConstraint NotNull r)
          => Record c r -> Record c (Maybe r) -> Record c r
fromMaybe :: Record c r -> Record c (Maybe r) -> Record c r
fromMaybe Record c r
d Record c (Maybe r)
p = [ (Record c (Maybe r) -> Predicate c
forall c r.
(OperatorContext c, HasColumnConstraint NotNull r) =>
Record c (Maybe r) -> Predicate c
isNothing Record c (Maybe r)
p, Record c r
d) ] [(Predicate c, Record c r)] -> Record c r -> Record c r
forall c a.
OperatorContext c =>
[(Predicate c, Record c a)] -> Record c a -> Record c a
`casesOrElse` Record c (Maybe r) -> Record c r
forall c a b. SqlContext c => Record c a -> Record c b
unsafeCastProjectable Record c (Maybe r)
p

unsafeUniTermFunction :: SqlContext c => Keyword -> Record c t
unsafeUniTermFunction :: StringSQL -> Record c t
unsafeUniTermFunction =  StringSQL -> Record c t
forall c t. SqlContext c => StringSQL -> Record c t
unsafeProjectSql' (StringSQL -> Record c t)
-> (StringSQL -> StringSQL) -> StringSQL -> Record c t
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (StringSQL -> StringSQL -> StringSQL
SQL.<++> String -> StringSQL
stringSQL String
"()")

-- | /RANK()/ term.
rank :: Integral a => Record OverWindow a
rank :: Record OverWindow a
rank =  StringSQL -> Record OverWindow a
forall c t. SqlContext c => StringSQL -> Record c t
unsafeUniTermFunction StringSQL
SQL.RANK

-- | /DENSE_RANK()/ term.
denseRank :: Integral a => Record OverWindow a
denseRank :: Record OverWindow a
denseRank =  StringSQL -> Record OverWindow a
forall c t. SqlContext c => StringSQL -> Record c t
unsafeUniTermFunction StringSQL
SQL.DENSE_RANK

-- | /ROW_NUMBER()/ term.
rowNumber :: Integral a => Record OverWindow a
rowNumber :: Record OverWindow a
rowNumber =  StringSQL -> Record OverWindow a
forall c t. SqlContext c => StringSQL -> Record c t
unsafeUniTermFunction StringSQL
SQL.ROW_NUMBER

-- | /PERCENT_RANK()/ term.
percentRank :: Record OverWindow Double
percentRank :: Record OverWindow Double
percentRank =  StringSQL -> Record OverWindow Double
forall c t. SqlContext c => StringSQL -> Record c t
unsafeUniTermFunction StringSQL
SQL.PERCENT_RANK

-- | /CUME_DIST()/ term.
cumeDist :: Record OverWindow Double
cumeDist :: Record OverWindow Double
cumeDist =  StringSQL -> Record OverWindow Double
forall c t. SqlContext c => StringSQL -> Record c t
unsafeUniTermFunction StringSQL
SQL.CUME_DIST

-- | Unsafely add placeholder parameter to queries.
unsafeAddPlaceHolders :: Functor f => f a -> f (PlaceHolders p, a)
unsafeAddPlaceHolders :: f a -> f (PlaceHolders p, a)
unsafeAddPlaceHolders =  (a -> (PlaceHolders p, a)) -> f a -> f (PlaceHolders p, a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((,) PlaceHolders p
forall p. PlaceHolders p
PlaceHolders)

-- | Unsafely get placeholder parameter
unsafePlaceHolders :: PlaceHolders p
unsafePlaceHolders :: PlaceHolders p
unsafePlaceHolders =  PlaceHolders p
forall p. PlaceHolders p
PlaceHolders

-- | No placeholder semantics
unitPlaceHolder :: PlaceHolders ()
unitPlaceHolder :: PlaceHolders ()
unitPlaceHolder = () -> PlaceHolders ()
forall (f :: * -> *) a.
(ProductIsoApplicative f, ProductConstructor a) =>
a -> f a
pureP ()

-- | No placeholder semantics. Same as `unitPlaceHolder`
unitPH :: PlaceHolders ()
unitPH :: PlaceHolders ()
unitPH = () -> PlaceHolders ()
forall (f :: * -> *) a.
(ProductIsoApplicative f, ProductConstructor a) =>
a -> f a
pureP ()

-- | Unsafely cast placeholder parameter type.
unsafeCastPlaceHolders :: PlaceHolders a -> PlaceHolders b
unsafeCastPlaceHolders :: PlaceHolders a -> PlaceHolders b
unsafeCastPlaceHolders PlaceHolders a
PlaceHolders = PlaceHolders b
forall p. PlaceHolders p
PlaceHolders

-- | Provide scoped placeholder from width and return its parameter object.
pwPlaceholder :: SqlContext c
              => PersistableRecordWidth a
              -> (Record c a -> b)
              -> (PlaceHolders a, b)
pwPlaceholder :: PersistableRecordWidth a
-> (Record c a -> b) -> (PlaceHolders a, b)
pwPlaceholder PersistableRecordWidth a
pw Record c a -> b
f = (PlaceHolders a
forall p. PlaceHolders p
PlaceHolders, Record c a -> b
f (Record c a -> b) -> Record c a -> b
forall a b. (a -> b) -> a -> b
$ PersistableRecordWidth a -> Record c a
forall c a. SqlContext c => PersistableRecordWidth a -> Record c a
projectPlaceHolder PersistableRecordWidth a
pw)
  where
    projectPlaceHolder :: SqlContext c
                       => PersistableRecordWidth a
                       -> Record c a
    projectPlaceHolder :: PersistableRecordWidth a -> Record c a
projectPlaceHolder = [StringSQL] -> Record c a
forall c t. SqlContext c => [StringSQL] -> Record c t
unsafeProjectSqlTerms ([StringSQL] -> Record c a)
-> (PersistableRecordWidth a -> [StringSQL])
-> PersistableRecordWidth a
-> Record c a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> StringSQL -> [StringSQL]
forall a. Int -> a -> [a]
`replicate` StringSQL
"?") (Int -> [StringSQL])
-> (PersistableRecordWidth a -> Int)
-> PersistableRecordWidth a
-> [StringSQL]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PersistableRecordWidth a -> Int
forall a. PersistableRecordWidth a -> Int
runPersistableRecordWidth

-- | Provide scoped placeholder and return its parameter object.
placeholder' :: (PersistableWidth t, SqlContext c) => (Record c t -> a) ->  (PlaceHolders t, a)
placeholder' :: (Record c t -> a) -> (PlaceHolders t, a)
placeholder' = PersistableRecordWidth t
-> (Record c t -> a) -> (PlaceHolders t, a)
forall c a b.
SqlContext c =>
PersistableRecordWidth a
-> (Record c a -> b) -> (PlaceHolders a, b)
pwPlaceholder PersistableRecordWidth t
forall a. PersistableWidth a => PersistableRecordWidth a
persistableWidth

-- | Provide scoped placeholder and return its parameter object. Monadic version.
placeholder :: (PersistableWidth t, SqlContext c, Monad m) => (Record c t -> m a) -> m (PlaceHolders t, a)
placeholder :: (Record c t -> m a) -> m (PlaceHolders t, a)
placeholder Record c t -> m a
f = do
  let (PlaceHolders t
ph, m a
ma) = (Record c t -> m a) -> (PlaceHolders t, m a)
forall t c a.
(PersistableWidth t, SqlContext c) =>
(Record c t -> a) -> (PlaceHolders t, a)
placeholder' Record c t -> m a
f
  a
a <- m a
ma
  (PlaceHolders t, a) -> m (PlaceHolders t, a)
forall (m :: * -> *) a. Monad m => a -> m a
return (PlaceHolders t
ph, a
a)


-- | Zipping projections.
projectZip :: ProductIsoApplicative p => p a -> p b -> p (a, b)
projectZip :: p a -> p b -> p (a, b)
projectZip p a
pa p b
pb = (,) (a -> b -> (a, b)) -> p a -> p (b -> (a, b))
forall (f :: * -> *) a b.
(ProductIsoFunctor f, ProductConstructor (a -> b)) =>
(a -> b) -> f a -> f b
|$| p a
pa p (b -> (a, b)) -> p b -> p (a, b)
forall (f :: * -> *) a b.
ProductIsoApplicative f =>
f (a -> b) -> f a -> f b
|*| p b
pb

-- | Binary operator the same as 'projectZip'.
(><) :: ProductIsoApplicative p => p a -> p b -> p (a, b)
>< :: p a -> p b -> p (a, b)
(><) = p a -> p b -> p (a, b)
forall (p :: * -> *) a b.
ProductIsoApplicative p =>
p a -> p b -> p (a, b)
projectZip

-- | Interface to control 'Maybe' of phantom type in records.
class ProjectableMaybe p where
  -- | Cast record phantom type into 'Maybe'.
  just :: p a -> p (Maybe a)
  -- | Compose nested 'Maybe' phantom type on record.
  flattenMaybe :: p (Maybe (Maybe a)) -> p (Maybe a)

-- | Control phantom 'Maybe' type in placeholder parameters.
instance ProjectableMaybe PlaceHolders where
  just :: PlaceHolders a -> PlaceHolders (Maybe a)
just         = PlaceHolders a -> PlaceHolders (Maybe a)
forall a b. PlaceHolders a -> PlaceHolders b
unsafeCastPlaceHolders
  flattenMaybe :: PlaceHolders (Maybe (Maybe a)) -> PlaceHolders (Maybe a)
flattenMaybe = PlaceHolders (Maybe (Maybe a)) -> PlaceHolders (Maybe a)
forall a b. PlaceHolders a -> PlaceHolders b
unsafeCastPlaceHolders

-- | Control phantom 'Maybe' type in record type 'Record'.
instance ProjectableMaybe (Record c) where
  just :: Record c a -> Record c (Maybe a)
just         = Record c a -> Record c (Maybe a)
forall c a. Record c a -> Record c (Maybe a)
Record.just
  flattenMaybe :: Record c (Maybe (Maybe a)) -> Record c (Maybe a)
flattenMaybe = Record c (Maybe (Maybe a)) -> Record c (Maybe a)
forall c a. Record c (Maybe (Maybe a)) -> Record c (Maybe a)
Record.flattenMaybe


-- | Unsafely make aggregation uni-operator from SQL keyword.
unsafeAggregateOp :: (AggregatedContext ac, SqlContext ac)
                  => SQL.Keyword -> Record Flat a -> Record ac b
unsafeAggregateOp :: StringSQL -> Record Flat a -> Record ac b
unsafeAggregateOp StringSQL
op = (StringSQL -> StringSQL) -> Record Flat a -> Record ac b
forall c2 c1 a b.
SqlContext c2 =>
(StringSQL -> StringSQL) -> Record c1 a -> Record c2 b
unsafeUniOp ((StringSQL
op StringSQL -> StringSQL -> StringSQL
SQL.<++>) (StringSQL -> StringSQL)
-> (StringSQL -> StringSQL) -> StringSQL -> StringSQL
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StringSQL -> StringSQL
SQL.paren)

-- | Aggregation function COUNT.
count :: (Integral b, AggregatedContext ac, SqlContext ac)
      => Record Flat a -> Record ac b
count :: Record Flat a -> Record ac b
count =  StringSQL -> Record Flat a -> Record ac b
forall ac a b.
(AggregatedContext ac, SqlContext ac) =>
StringSQL -> Record Flat a -> Record ac b
unsafeAggregateOp StringSQL
SQL.COUNT

-- | Aggregation function SUM.
sumMaybe :: (Num a, AggregatedContext ac, SqlContext ac)
         => Record Flat (Maybe a) -> Record ac (Maybe a)
sumMaybe :: Record Flat (Maybe a) -> Record ac (Maybe a)
sumMaybe  =  StringSQL -> Record Flat (Maybe a) -> Record ac (Maybe a)
forall ac a b.
(AggregatedContext ac, SqlContext ac) =>
StringSQL -> Record Flat a -> Record ac b
unsafeAggregateOp StringSQL
SQL.SUM

-- | Aggregation function SUM.
sum' :: (Num a, AggregatedContext ac, SqlContext ac)
     => Record Flat a -> Record ac (Maybe a)
sum' :: Record Flat a -> Record ac (Maybe a)
sum'  =  Record Flat (Maybe a) -> Record ac (Maybe a)
forall a ac.
(Num a, AggregatedContext ac, SqlContext ac) =>
Record Flat (Maybe a) -> Record ac (Maybe a)
sumMaybe (Record Flat (Maybe a) -> Record ac (Maybe a))
-> (Record Flat a -> Record Flat (Maybe a))
-> Record Flat a
-> Record ac (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Record Flat a -> Record Flat (Maybe a)
forall c a. Record c a -> Record c (Maybe a)
Record.just

-- | Aggregation function AVG.
avgMaybe :: (Num a, Fractional b, AggregatedContext ac, SqlContext ac)
         => Record Flat (Maybe a) -> Record ac (Maybe b)
avgMaybe :: Record Flat (Maybe a) -> Record ac (Maybe b)
avgMaybe   =  StringSQL -> Record Flat (Maybe a) -> Record ac (Maybe b)
forall ac a b.
(AggregatedContext ac, SqlContext ac) =>
StringSQL -> Record Flat a -> Record ac b
unsafeAggregateOp StringSQL
SQL.AVG

-- | Aggregation function AVG.
avg :: (Num a, Fractional b, AggregatedContext ac, SqlContext ac)
    => Record Flat a -> Record ac (Maybe b)
avg :: Record Flat a -> Record ac (Maybe b)
avg =  Record Flat (Maybe a) -> Record ac (Maybe b)
forall a b ac.
(Num a, Fractional b, AggregatedContext ac, SqlContext ac) =>
Record Flat (Maybe a) -> Record ac (Maybe b)
avgMaybe (Record Flat (Maybe a) -> Record ac (Maybe b))
-> (Record Flat a -> Record Flat (Maybe a))
-> Record Flat a
-> Record ac (Maybe b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Record Flat a -> Record Flat (Maybe a)
forall c a. Record c a -> Record c (Maybe a)
Record.just

-- | Aggregation function MAX.
maxMaybe :: (Ord a, AggregatedContext ac, SqlContext ac)
         => Record Flat (Maybe a) -> Record ac (Maybe a)
maxMaybe :: Record Flat (Maybe a) -> Record ac (Maybe a)
maxMaybe  =  StringSQL -> Record Flat (Maybe a) -> Record ac (Maybe a)
forall ac a b.
(AggregatedContext ac, SqlContext ac) =>
StringSQL -> Record Flat a -> Record ac b
unsafeAggregateOp StringSQL
SQL.MAX

-- | Aggregation function MAX.
max' :: (Ord a, AggregatedContext ac, SqlContext ac)
     => Record Flat a -> Record ac (Maybe a)
max' :: Record Flat a -> Record ac (Maybe a)
max' =  Record Flat (Maybe a) -> Record ac (Maybe a)
forall a ac.
(Ord a, AggregatedContext ac, SqlContext ac) =>
Record Flat (Maybe a) -> Record ac (Maybe a)
maxMaybe (Record Flat (Maybe a) -> Record ac (Maybe a))
-> (Record Flat a -> Record Flat (Maybe a))
-> Record Flat a
-> Record ac (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Record Flat a -> Record Flat (Maybe a)
forall c a. Record c a -> Record c (Maybe a)
Record.just

-- | Aggregation function MIN.
minMaybe :: (Ord a, AggregatedContext ac, SqlContext ac)
         => Record Flat (Maybe a) -> Record ac (Maybe a)
minMaybe :: Record Flat (Maybe a) -> Record ac (Maybe a)
minMaybe  =  StringSQL -> Record Flat (Maybe a) -> Record ac (Maybe a)
forall ac a b.
(AggregatedContext ac, SqlContext ac) =>
StringSQL -> Record Flat a -> Record ac b
unsafeAggregateOp StringSQL
SQL.MIN

-- | Aggregation function MIN.
min' :: (Ord a, AggregatedContext ac, SqlContext ac)
     => Record Flat a -> Record ac (Maybe a)
min' :: Record Flat a -> Record ac (Maybe a)
min' =  Record Flat (Maybe a) -> Record ac (Maybe a)
forall a ac.
(Ord a, AggregatedContext ac, SqlContext ac) =>
Record Flat (Maybe a) -> Record ac (Maybe a)
minMaybe (Record Flat (Maybe a) -> Record ac (Maybe a))
-> (Record Flat a -> Record Flat (Maybe a))
-> Record Flat a
-> Record ac (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Record Flat a -> Record Flat (Maybe a)
forall c a. Record c a -> Record c (Maybe a)
Record.just

-- | Aggregation function EVERY.
every :: (AggregatedContext ac, SqlContext ac)
      => Predicate Flat -> Record ac (Maybe Bool)
every :: Predicate Flat -> Record ac (Maybe Bool)
every =  StringSQL -> Predicate Flat -> Record ac (Maybe Bool)
forall ac a b.
(AggregatedContext ac, SqlContext ac) =>
StringSQL -> Record Flat a -> Record ac b
unsafeAggregateOp StringSQL
SQL.EVERY

-- | Aggregation function ANY.
any' :: (AggregatedContext ac, SqlContext ac)
     => Predicate Flat -> Record ac (Maybe Bool)
any' :: Predicate Flat -> Record ac (Maybe Bool)
any'  =  StringSQL -> Predicate Flat -> Record ac (Maybe Bool)
forall ac a b.
(AggregatedContext ac, SqlContext ac) =>
StringSQL -> Record Flat a -> Record ac b
unsafeAggregateOp StringSQL
SQL.ANY

-- | Aggregation function SOME.
some' :: (AggregatedContext ac, SqlContext ac)
      => Predicate Flat -> Record ac (Maybe Bool)
some' :: Predicate Flat -> Record ac (Maybe Bool)
some' =  StringSQL -> Predicate Flat -> Record ac (Maybe Bool)
forall ac a b.
(AggregatedContext ac, SqlContext ac) =>
StringSQL -> Record Flat a -> Record ac b
unsafeAggregateOp StringSQL
SQL.SOME

-- | Get narrower record along with projection path.
(!) :: PersistableWidth a
    => Record c a -- ^ Source 'Record'
    -> Pi a b     -- ^ Record path
    -> Record c b -- ^ Narrower projected object
(!) = Record c a -> Pi a b -> Record c b
forall a c b.
PersistableWidth a =>
Record c a -> Pi a b -> Record c b
Record.pi

-- | Get narrower record along with projection path
--   'Maybe' phantom functor is 'map'-ed.
(?!) :: PersistableWidth a
     => Record c (Maybe a) -- ^ Source 'Record'. 'Maybe' type
     -> Pi a b             -- ^ Record path
     -> Record c (Maybe b) -- ^ Narrower projected object. 'Maybe' type result
?! :: Record c (Maybe a) -> Pi a b -> Record c (Maybe b)
(?!) = Record c (Maybe a) -> Pi a b -> Record c (Maybe b)
forall a c b.
PersistableWidth a =>
Record c (Maybe a) -> Pi a b -> Record c (Maybe b)
Record.piMaybe

-- | Get narrower record along with projection path
--   and project into result record type.
--   Source record 'Maybe' phantom functor and projection path leaf 'Maybe' functor are 'join'-ed.
(?!?) :: PersistableWidth a
      => Record c (Maybe a) -- ^ Source 'Record'. 'Maybe' phantom type
      -> Pi a (Maybe b)     -- ^ Record path. 'Maybe' type leaf
      -> Record c (Maybe b) -- ^ Narrower projected object. 'Maybe' phantom type result
?!? :: Record c (Maybe a) -> Pi a (Maybe b) -> Record c (Maybe b)
(?!?) = Record c (Maybe a) -> Pi a (Maybe b) -> Record c (Maybe b)
forall a c b.
PersistableWidth a =>
Record c (Maybe a) -> Pi a (Maybe b) -> Record c (Maybe b)
Record.piMaybe'


-- | Interface to compose phantom 'Maybe' nested type.
class ProjectableFlattenMaybe a b where
  flatten :: ProjectableMaybe p => p a -> p b

-- | Compose 'Maybe' type in record phantom type.
instance ProjectableFlattenMaybe (Maybe a) b
         => ProjectableFlattenMaybe (Maybe (Maybe a)) b where
  flatten :: p (Maybe (Maybe a)) -> p b
flatten = p (Maybe a) -> p b
forall a b (p :: * -> *).
(ProjectableFlattenMaybe a b, ProjectableMaybe p) =>
p a -> p b
flatten (p (Maybe a) -> p b)
-> (p (Maybe (Maybe a)) -> p (Maybe a))
-> p (Maybe (Maybe a))
-> p b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. p (Maybe (Maybe a)) -> p (Maybe a)
forall (p :: * -> *) a.
ProjectableMaybe p =>
p (Maybe (Maybe a)) -> p (Maybe a)
flattenMaybe

-- | Not 'Maybe' type is not processed.
instance ProjectableFlattenMaybe (Maybe a) (Maybe a) where
  flatten :: p (Maybe a) -> p (Maybe a)
flatten = p (Maybe a) -> p (Maybe a)
forall a. a -> a
id

-- | Get narrower record with flatten leaf phantom Maybe types along with projection path.
flattenPiMaybe :: (PersistableWidth a, ProjectableFlattenMaybe (Maybe b) c)
               => Record cont (Maybe a) -- ^ Source 'Record'. 'Maybe' phantom type
               -> Pi a b                -- ^ Projection path
               -> Record cont c         -- ^ Narrower 'Record'. Flatten 'Maybe' phantom type
flattenPiMaybe :: Record cont (Maybe a) -> Pi a b -> Record cont c
flattenPiMaybe Record cont (Maybe a)
p = Record cont (Maybe b) -> Record cont c
forall a b (p :: * -> *).
(ProjectableFlattenMaybe a b, ProjectableMaybe p) =>
p a -> p b
flatten (Record cont (Maybe b) -> Record cont c)
-> (Pi a b -> Record cont (Maybe b)) -> Pi a b -> Record cont c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Record cont (Maybe a) -> Pi a b -> Record cont (Maybe b)
forall a c b.
PersistableWidth a =>
Record c (Maybe a) -> Pi a b -> Record c (Maybe b)
Record.piMaybe Record cont (Maybe a)
p

-- | Get narrower record with flatten leaf phantom Maybe types along with projection path.
(!??) :: (PersistableWidth a, ProjectableFlattenMaybe (Maybe b) c)
      => Record cont (Maybe a) -- ^ Source 'Record'. 'Maybe' phantom type
      -> Pi a b                -- ^ Projection path
      -> Record cont c         -- ^ Narrower flatten and projected object.
!?? :: Record cont (Maybe a) -> Pi a b -> Record cont c
(!??) = Record cont (Maybe a) -> Pi a b -> Record cont c
forall a b c cont.
(PersistableWidth a, ProjectableFlattenMaybe (Maybe b) c) =>
Record cont (Maybe a) -> Pi a b -> Record cont c
flattenPiMaybe

-- | Same as '(?!)'. Use this operator like '(? #foo) mayX'.
(?) :: PersistableWidth a
    => Record c (Maybe a) -- ^ Source 'Record'. 'Maybe' type
    -> Pi a b             -- ^ Record path
    -> Record c (Maybe b) -- ^ Narrower projected object. 'Maybe' type result
? :: Record c (Maybe a) -> Pi a b -> Record c (Maybe b)
(?) = Record c (Maybe a) -> Pi a b -> Record c (Maybe b)
forall a c b.
PersistableWidth a =>
Record c (Maybe a) -> Pi a b -> Record c (Maybe b)
(?!)

-- | Same as '(?!?)'. Use this operator like '(?? #foo) mayX'.
(??) :: PersistableWidth a
     => Record c (Maybe a) -- ^ Source 'Record'. 'Maybe' phantom type
     -> Pi a (Maybe b)     -- ^ Record path. 'Maybe' type leaf
     -> Record c (Maybe b) -- ^ Narrower projected object. 'Maybe' phantom type result
?? :: Record c (Maybe a) -> Pi a (Maybe b) -> Record c (Maybe b)
(??) = Record c (Maybe a) -> Pi a (Maybe b) -> Record c (Maybe b)
forall a c b.
PersistableWidth a =>
Record c (Maybe a) -> Pi a (Maybe b) -> Record c (Maybe b)
(?!?)

infixl 8 !, ?, ??, ?!, ?!?, !??
infixl 7 .*., ./., ?*?, ?/?
infixl 6 .+., .-., ?+?, ?-?
infixl 5 .||., ?||?
infix  4 .=., .<>., .>., .>=., .<., .<=., `in'`, `like`, `likeMaybe`, `like'`, `likeMaybe'`
infixr 3 `and'`
infixr 2 `or'`
infixl 1  ><