{-# LANGUAGE OverloadedStrings, FlexibleInstances, UndecidableInstances #-}
{-# LANGUAGE ScopedTypeVariables, TypeOperators, GADTs, FlexibleContexts #-}
{-# LANGUAGE DeriveGeneric, GeneralizedNewtypeDeriving, TypeFamilies, CPP #-}
{-# LANGUAGE DataKinds #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
-- | Selda is not LINQ, but they're definitely related.
--
--   Selda is a high-level EDSL for interacting with relational databases.
--   All database computations are performed within some monad implementing
--   the 'MonadSelda' type class. The 'SeldaT' monad over any @MonadIO@ is the
--   only pre-defined instance of @MonadSelda@.
--   'SeldaM' is provided as a convenient short-hand for @SeldaT IO@.
--
--   To actually execute a database computation, you need one of the database
--   backends: @selda-sqlite@ or @selda-postgresql@.
--
--   All Selda functions may throw 'SeldaError' when something goes wrong.
--   This includes database connection errors, uniqueness constraint errors,
--   etc.
--
--   See <https://selda.link/tutorial> for a tutorial covering the language
--   basics.
module Database.Selda
  ( -- * Running queries
    MonadSelda, Backend
  , SeldaError (..), ValidationError
  , SeldaT, SeldaM
  , Relational, Only (..), The (..)
  , Table (tableName), Query, Row, Col, Res, Result
  , query, queryInto
  , transaction, withoutForeignKeyEnforcement
  , newUuid

    -- * Constructing queries
  , SqlType (..), SqlRow (..), GSqlRow, SqlEnum (..)
  , Columns, Same
  , Order (..)
  , (:*:)(..)
  , select, selectValues, from, distinct
  , restrict, limit
  , order, ascending, descending
  , orderRandom
  , union, unionAll, inner, suchThat

    -- * Working with selectors
  , Selector, Coalesce
  , HasField, FieldType, IsLabel
  , (!), (?), Assignment ((:=)), with
  , (+=), (-=), (*=), (||=), (&&=), ($=)

    -- * Expressions over columns
  , Set (..), Monoid (..), Semigroup (..)
  , ID, invalidId, isInvalidId, untyped, fromId, toId
  , IsUUID (..), UUID', typedUuid, untypedUuid
  , RowID, invalidRowId, isInvalidRowId, fromRowId, toRowId
  , (.==), (./=), (.>), (.<), (.>=), (.<=), like
  , (.&&), (.||), not_
  , literal, is, int, float, text, true, false, null_
  , roundTo, length_, isNull, ifThenElse, ifNull, matchNull
  , toUpper, toLower
  , new, row, only
  , Mappable (..)

    -- * Converting between column types
  , round_, just, fromBool, fromInt, toString

    -- * Inner queries
  , Aggr, Aggregates, OuterCols, AggrCols, LeftCols, Inner, SqlOrd
  , innerJoin, leftJoin
  , aggregate, groupBy
  , count, avg, sum_, max_, min_

    -- * Modifying tables
  , insert, insert_, insertWithPK, tryInsert, insertUnless, insertWhen, def
  , update, update_, upsert
  , deleteFrom, deleteFrom_

    -- * Prepared statements
  , Preparable, Prepare
  , prepared

    -- * Defining schemas
  , Generic
  , TableName, ColName, Attr (..), Attribute
  , ForeignKey (..)
  , SelectorLike, Group (..), sel
  , table, tableFieldMod
  , primary, autoPrimary, weakAutoPrimary
  , untypedAutoPrimary, weakUntypedAutoPrimary
  , unique
  , IndexMethod (..), index, indexUsing

    -- * Creating and dropping tables
  , createTable, tryCreateTable
  , dropTable, tryDropTable

    -- * Tuple convenience functions
  , Tup, Head
  , first, second, third, fourth, fifth

    -- * Useful re-exports
  , MonadIO, MonadMask, liftIO
  , Text, Day, TimeOfDay, UTCTime, UUID
  ) where
import Control.Monad.Catch (MonadMask)
import Data.Typeable ( Typeable, eqT, (:~:)(..) )
import Database.Selda.Backend.Internal
    ( SqlType(..),
      SeldaM,
      SeldaT,
      MonadSelda(Backend),
      SeldaError(..) )
import Database.Selda.SqlType
    ( UUID,
      UUID'(..),
      ID(..),
      RowID,
      SqlEnum(..),
      invalidRowId,
      isInvalidRowId,
      toRowId,
      fromRowId,
      typedUuid,
      toId,
      fromId,
      invalidId,
      isInvalidId )
import Database.Selda.Table.Type ( IndexMethod(..) )
import Database.Selda.Types
    ( TableName,
      ColName,
      Tup,
      Head,
      type (:*:)(..),
      first,
      second,
      third,
      fourth,
      fifth )
import Database.Selda.Column
    ( BinOp(Like, Eq, Neq, Gt, Lt, Gte, Lte, And, Or),
      UnOp(Not, IsNull),
      Exp(If, InQuery, InList, BinOp, UnOp),
      UntypedCol(Untyped),
      Same(..),
      Row(..),
      Col(..),
      Columns,
      literal,
      liftC3,
      liftC )
import Database.Selda.Compile
    ( Result, Res, compQueryWithFreshScope )
import Database.Selda.FieldSelectors
    ( IsLabel, HasField, FieldType )
import Database.Selda.Frontend
    ( MonadIO(..),
      query,
      queryInto,
      insert,
      tryInsert,
      upsert,
      insertUnless,
      insertWhen,
      insert_,
      insertWithPK,
      update,
      update_,
      deleteFrom,
      deleteFrom_,
      createTable,
      tryCreateTable,
      dropTable,
      tryDropTable,
      transaction,
      withoutForeignKeyEnforcement )
import Database.Selda.Generic
    ( Generic, gRow, gNew, Relational, def )
import Database.Selda.Inner
    ( Aggregates,
      LeftCols,
      AggrCols,
      OuterCols,
      Inner,
      Aggr,
      liftAggr,
      aggr )
import Database.Selda.Prepared ( Prepare, Preparable, prepared )
import Database.Selda.Query
    ( select,
      selectValues,
      union,
      unionAll,
      restrict,
      aggregate,
      leftJoin,
      innerJoin,
      groupBy,
      limit,
      order,
      orderRandom,
      distinct )
import Database.Selda.Query.Type ( Query )
import Database.Selda.Selectors
    ( Selector, Assignment(..), Coalesce, (!), (?), ($=), with )
import Database.Selda.SQL ( Order(..) )
import Database.Selda.SqlRow ( GSqlRow, SqlRow(..) )
import Database.Selda.Table
    ( Table(tableName),
      ForeignKey(..),
      Attribute,
      SelectorLike,
      Attr(..),
      Group(..),
      table,
      tableFieldMod,
      primary,
      index,
      indexUsing,
      autoPrimary,
      weakAutoPrimary,
      untypedAutoPrimary,
      weakUntypedAutoPrimary,
      unique )
import Database.Selda.Table.Validation ( ValidationError )
import Database.Selda.Unsafe ( cast, fun, fun2, operator )
import Data.Proxy ( Proxy(..) )
import Data.String (IsString)
import Data.Text (Text)
import Data.Time (Day, TimeOfDay, UTCTime)
import GHC.Generics (Rep)
import qualified GHC.Generics as G (from)
import Unsafe.Coerce ( unsafeCoerce )
import System.Random (randomIO)
import GHC.TypeLits as TL
    ( TypeError, ErrorMessage(Text, (:<>:), ShowType, (:$$:)) )

-- | Any column type that can be used with the 'min_' and 'max_' functions.
class SqlType a => SqlOrd a
instance {-# OVERLAPPABLE #-} (SqlType a, Num a) => SqlOrd a
instance SqlOrd RowID
instance SqlOrd Text
instance SqlOrd Day
instance SqlOrd UTCTime
instance SqlOrd TimeOfDay
instance SqlOrd a => SqlOrd (Maybe a)
instance Typeable a => SqlOrd (ID a)

-- | Wrapper for single column tables.
--   Use this when you need a table with only a single column, with 'table' or
--   'selectValues'.
newtype Only a = Only a
  deriving
    ( forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Only a) x -> Only a
forall a x. Only a -> Rep (Only a) x
$cto :: forall a x. Rep (Only a) x -> Only a
$cfrom :: forall a x. Only a -> Rep (Only a) x
Generic
    , Int -> Only a -> ShowS
forall a. Show a => Int -> Only a -> ShowS
forall a. Show a => [Only a] -> ShowS
forall a. Show a => Only a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Only a] -> ShowS
$cshowList :: forall a. Show a => [Only a] -> ShowS
show :: Only a -> String
$cshow :: forall a. Show a => Only a -> String
showsPrec :: Int -> Only a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Only a -> ShowS
Show
    , ReadPrec [Only a]
ReadPrec (Only a)
ReadS [Only a]
forall a. Read a => ReadPrec [Only a]
forall a. Read a => ReadPrec (Only a)
forall a. Read a => Int -> ReadS (Only a)
forall a. Read a => ReadS [Only a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Only a]
$creadListPrec :: forall a. Read a => ReadPrec [Only a]
readPrec :: ReadPrec (Only a)
$creadPrec :: forall a. Read a => ReadPrec (Only a)
readList :: ReadS [Only a]
$creadList :: forall a. Read a => ReadS [Only a]
readsPrec :: Int -> ReadS (Only a)
$creadsPrec :: forall a. Read a => Int -> ReadS (Only a)
Read
    , Only a -> Only a -> Bool
forall a. Eq a => Only a -> Only a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Only a -> Only a -> Bool
$c/= :: forall a. Eq a => Only a -> Only a -> Bool
== :: Only a -> Only a -> Bool
$c== :: forall a. Eq a => Only a -> Only a -> Bool
Eq
    , Only a -> Only a -> Bool
Only a -> Only a -> Ordering
Only a -> Only a -> Only a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (Only a)
forall a. Ord a => Only a -> Only a -> Bool
forall a. Ord a => Only a -> Only a -> Ordering
forall a. Ord a => Only a -> Only a -> Only a
min :: Only a -> Only a -> Only a
$cmin :: forall a. Ord a => Only a -> Only a -> Only a
max :: Only a -> Only a -> Only a
$cmax :: forall a. Ord a => Only a -> Only a -> Only a
>= :: Only a -> Only a -> Bool
$c>= :: forall a. Ord a => Only a -> Only a -> Bool
> :: Only a -> Only a -> Bool
$c> :: forall a. Ord a => Only a -> Only a -> Bool
<= :: Only a -> Only a -> Bool
$c<= :: forall a. Ord a => Only a -> Only a -> Bool
< :: Only a -> Only a -> Bool
$c< :: forall a. Ord a => Only a -> Only a -> Bool
compare :: Only a -> Only a -> Ordering
$ccompare :: forall a. Ord a => Only a -> Only a -> Ordering
Ord
    , Int -> Only a
Only a -> Int
Only a -> [Only a]
Only a -> Only a
Only a -> Only a -> [Only a]
Only a -> Only a -> Only a -> [Only a]
forall a. Enum a => Int -> Only a
forall a. Enum a => Only a -> Int
forall a. Enum a => Only a -> [Only a]
forall a. Enum a => Only a -> Only a
forall a. Enum a => Only a -> Only a -> [Only a]
forall a. Enum a => Only a -> Only a -> Only a -> [Only a]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Only a -> Only a -> Only a -> [Only a]
$cenumFromThenTo :: forall a. Enum a => Only a -> Only a -> Only a -> [Only a]
enumFromTo :: Only a -> Only a -> [Only a]
$cenumFromTo :: forall a. Enum a => Only a -> Only a -> [Only a]
enumFromThen :: Only a -> Only a -> [Only a]
$cenumFromThen :: forall a. Enum a => Only a -> Only a -> [Only a]
enumFrom :: Only a -> [Only a]
$cenumFrom :: forall a. Enum a => Only a -> [Only a]
fromEnum :: Only a -> Int
$cfromEnum :: forall a. Enum a => Only a -> Int
toEnum :: Int -> Only a
$ctoEnum :: forall a. Enum a => Int -> Only a
pred :: Only a -> Only a
$cpred :: forall a. Enum a => Only a -> Only a
succ :: Only a -> Only a
$csucc :: forall a. Enum a => Only a -> Only a
Enum
    , Integer -> Only a
Only a -> Only a
Only a -> Only a -> Only a
forall a. Num a => Integer -> Only a
forall a. Num a => Only a -> Only a
forall a. Num a => Only a -> Only a -> Only a
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> Only a
$cfromInteger :: forall a. Num a => Integer -> Only a
signum :: Only a -> Only a
$csignum :: forall a. Num a => Only a -> Only a
abs :: Only a -> Only a
$cabs :: forall a. Num a => Only a -> Only a
negate :: Only a -> Only a
$cnegate :: forall a. Num a => Only a -> Only a
* :: Only a -> Only a -> Only a
$c* :: forall a. Num a => Only a -> Only a -> Only a
- :: Only a -> Only a -> Only a
$c- :: forall a. Num a => Only a -> Only a -> Only a
+ :: Only a -> Only a -> Only a
$c+ :: forall a. Num a => Only a -> Only a -> Only a
Num
    , Only a -> Integer
Only a -> Only a -> (Only a, Only a)
Only a -> Only a -> Only a
forall {a}. Integral a => Enum (Only a)
forall {a}. Integral a => Real (Only a)
forall a. Integral a => Only a -> Integer
forall a. Integral a => Only a -> Only a -> (Only a, Only a)
forall a. Integral a => Only a -> Only a -> Only a
forall a.
Real a
-> Enum a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
toInteger :: Only a -> Integer
$ctoInteger :: forall a. Integral a => Only a -> Integer
divMod :: Only a -> Only a -> (Only a, Only a)
$cdivMod :: forall a. Integral a => Only a -> Only a -> (Only a, Only a)
quotRem :: Only a -> Only a -> (Only a, Only a)
$cquotRem :: forall a. Integral a => Only a -> Only a -> (Only a, Only a)
mod :: Only a -> Only a -> Only a
$cmod :: forall a. Integral a => Only a -> Only a -> Only a
div :: Only a -> Only a -> Only a
$cdiv :: forall a. Integral a => Only a -> Only a -> Only a
rem :: Only a -> Only a -> Only a
$crem :: forall a. Integral a => Only a -> Only a -> Only a
quot :: Only a -> Only a -> Only a
$cquot :: forall a. Integral a => Only a -> Only a -> Only a
Integral
    , Rational -> Only a
Only a -> Only a
Only a -> Only a -> Only a
forall {a}. Fractional a => Num (Only a)
forall a. Fractional a => Rational -> Only a
forall a. Fractional a => Only a -> Only a
forall a. Fractional a => Only a -> Only a -> Only a
forall a.
Num a
-> (a -> a -> a) -> (a -> a) -> (Rational -> a) -> Fractional a
fromRational :: Rational -> Only a
$cfromRational :: forall a. Fractional a => Rational -> Only a
recip :: Only a -> Only a
$crecip :: forall a. Fractional a => Only a -> Only a
/ :: Only a -> Only a -> Only a
$c/ :: forall a. Fractional a => Only a -> Only a -> Only a
Fractional
    , Only a -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
forall {a}. Real a => Num (Only a)
forall {a}. Real a => Ord (Only a)
forall a. Real a => Only a -> Rational
toRational :: Only a -> Rational
$ctoRational :: forall a. Real a => Only a -> Rational
Real
    , String -> Only a
forall a. IsString a => String -> Only a
forall a. (String -> a) -> IsString a
fromString :: String -> Only a
$cfromString :: forall a. IsString a => String -> Only a
IsString
    )
instance SqlType a => SqlRow (Only a)

instance (TypeError
  ( 'TL.Text "'Only " ':<>: 'ShowType a ':<>: 'TL.Text "' is not a proper SQL type."
    ':$$: 'TL.Text "Use 'the' to access the value of the column."
  ), Typeable a) => SqlType (Only a) where
  mkLit :: Only a -> Lit (Only a)
mkLit = forall a. HasCallStack => String -> a
error String
"unreachable"
  sqlType :: Proxy (Only a) -> SqlTypeRep
sqlType = forall a. HasCallStack => String -> a
error String
"unreachable"
  fromSql :: SqlValue -> Only a
fromSql = forall a. HasCallStack => String -> a
error String
"unreachable"
  defaultValue :: Lit (Only a)
defaultValue = forall a. HasCallStack => String -> a
error String
"unreachable"

-- | Any type which is backed by an UUID.
class IsUUID a where
  uuid :: UUID -> a
instance IsUUID UUID where
  uuid :: UUID -> UUID
uuid = forall a. a -> a
id
instance IsUUID (UUID' a) where
  uuid :: UUID -> UUID' a
uuid = forall a. UUID -> UUID' a
typedUuid

-- | Generate a new random UUID using the system's random number generator.
--   UUIDs generated this way are (astronomically likely to be) unique,
--   but not necessarily unpredictable.
--
--   For applications where unpredictability is crucial, take care to use a
--   proper cryptographic PRNG to generate your UUIDs.
newUuid :: (MonadIO m, IsUUID uuid) => m uuid
newUuid :: forall (m :: * -> *) uuid. (MonadIO m, IsUUID uuid) => m uuid
newUuid = forall a. IsUUID a => UUID -> a
uuid forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a (m :: * -> *). (Random a, MonadIO m) => m a
randomIO

-- | Annotation to force the type of a polymorphic label (i.e. @#foo@) to
--   be a selector. This is useful, for instance, when defining unique
--   constraints: @sel #foo :- unique@.
sel :: Selector t a -> Selector t a
sel :: forall t a. Selector t a -> Selector t a
sel = forall a. a -> a
id

-- | Add the given column to the column pointed to by the given selector.
(+=) :: (SqlType a, Num (Col s a)) => Selector t a -> Col s a -> Assignment s t
Selector t a
s += :: forall a s t.
(SqlType a, Num (Col s a)) =>
Selector t a -> Col s a -> Assignment s t
+= Col s a
c = Selector t a
s forall t a s.
Selector t a -> (Col s a -> Col s a) -> Assignment s t
$= (forall a. Num a => a -> a -> a
+ Col s a
c)
infixl 2 +=

-- | Subtract the given column from the column pointed to by the given selector.
(-=) :: (SqlType a, Num (Col s a)) => Selector t a -> Col s a -> Assignment s t
Selector t a
s -= :: forall a s t.
(SqlType a, Num (Col s a)) =>
Selector t a -> Col s a -> Assignment s t
-= Col s a
c = Selector t a
s forall t a s.
Selector t a -> (Col s a -> Col s a) -> Assignment s t
$= (\Col s a
x -> Col s a
x forall a. Num a => a -> a -> a
- Col s a
c)
infixl 2 -=

-- | Multiply the column pointed to by the given selector, by the given column.
(*=) :: (SqlType a, Num (Col s a)) => Selector t a -> Col s a -> Assignment s t
Selector t a
s *= :: forall a s t.
(SqlType a, Num (Col s a)) =>
Selector t a -> Col s a -> Assignment s t
*= Col s a
c = Selector t a
s forall t a s.
Selector t a -> (Col s a -> Col s a) -> Assignment s t
$= (forall a. Num a => a -> a -> a
* Col s a
c)
infixl 2 *=

-- | Logically @OR@ the column pointed to by the given selector with
--   the given column.
(||=) :: Selector t Bool -> Col s Bool -> Assignment s t
Selector t Bool
s ||= :: forall t s. Selector t Bool -> Col s Bool -> Assignment s t
||= Col s Bool
c = Selector t Bool
s forall t a s.
Selector t a -> (Col s a -> Col s a) -> Assignment s t
$= (forall s t. Same s t => Col s Bool -> Col t Bool -> Col s Bool
.|| Col s Bool
c)
infixl 2 ||=

-- | Logically @AND@ the column pointed to by the given selector with
--   the given column.
(&&=) :: Selector t Bool -> Col s Bool -> Assignment s t
Selector t Bool
s &&= :: forall t s. Selector t Bool -> Col s Bool -> Assignment s t
&&= Col s Bool
c = Selector t Bool
s forall t a s.
Selector t a -> (Col s a -> Col s a) -> Assignment s t
$= (forall s t. Same s t => Col s Bool -> Col t Bool -> Col s Bool
.&& Col s Bool
c)
infixl 2 &&=

class The a where
  type TheOnly a
  -- | Extract the value of a row from a singleton table.
  the :: a -> TheOnly a

instance The (Only a) where
  type TheOnly (Only a) = a
  the :: Only a -> TheOnly (Only a)
the (Only a
x) = a
x

instance The (Row s (Only a)) where
  type TheOnly (Row s (Only a)) = Col s a
  the :: Row s (Only a) -> TheOnly (Row s (Only a))
the (Many [Untyped Exp SQL a
x]) = forall {k} (s :: k) a. Exp SQL a -> Col s a
One (forall a b. a -> b
unsafeCoerce Exp SQL a
x)
  the (Many [UntypedCol SQL]
_)           = forall a. HasCallStack => String -> a
error String
"BUG: non-singleton Only-column"

-- | Create a singleton table column from an appropriate value.
only :: SqlType a => Col s a -> Row s (Only a)
only :: forall a s. SqlType a => Col s a -> Row s (Only a)
only (One Exp SQL a
x)  = forall {k} {k} (s :: k) (a :: k). [UntypedCol SQL] -> Row s a
Many [forall sql a. Exp sql a -> UntypedCol sql
Untyped Exp SQL a
x]

-- | Create a new row with the given fields.
--   Any unassigned fields will contain their default values.
new :: forall s a. Relational a => [Assignment s a] -> Row s a
new :: forall s a. Relational a => [Assignment s a] -> Row s a
new [Assignment s a]
fields = forall {k} {k} (s :: k) (a :: k). [UntypedCol SQL] -> Row s a
Many (forall (f :: * -> *) sql.
GRelation f =>
Proxy f -> [UntypedCol sql]
gNew (forall {k} (t :: k). Proxy t
Proxy :: Proxy (Rep a))) forall s a. Row s a -> [Assignment s a] -> Row s a
`with` [Assignment s a]
fields

-- | Create a new row from the given value.
--   This can be useful when you want to update all or most of a row:
--
-- > update users (#uid `is` user_id)
-- >              (\old -> row user_info `with` [...])
row :: forall s a. Relational a => a -> Row s a
row :: forall s a. Relational a => a -> Row s a
row a
x = forall {k} {k} (s :: k) (a :: k). [UntypedCol SQL] -> Row s a
Many (forall (f :: * -> *) a sql. GRelation f => f a -> [UntypedCol sql]
gRow (forall a x. Generic a => a -> Rep a x
G.from a
x))

-- | Convenient shorthand for @fmap (! sel) q@.
--   The following two queries are quivalent:
--
-- > q1 = name `from` select people
-- > q2 = do
-- >   person <- select people
-- >   return (person ! name)
from :: (Typeable t, SqlType a)
     => Selector t a
     -> Query s (Row s t)
     -> Query s (Col s a)
from :: forall t a s.
(Typeable t, SqlType a) =>
Selector t a -> Query s (Row s t) -> Query s (Col s a)
from Selector t a
s Query s (Row s t)
q = (forall a s t. SqlType a => Row s t -> Selector t a -> Col s a
! Selector t a
s) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Query s (Row s t)
q
infixr 7 `from`

-- | Explicitly create an inner query. Equivalent to @innerJoin (const true)@.
--
--   Sometimes it's handy, for performance
--   reasons and otherwise, to perform a subquery and restrict only that query
--   before adding the result of the query to the result set, instead of first
--   adding the query to the result set and restricting the whole result set
--   afterwards.
inner :: (Columns a, Columns (OuterCols a))
      => Query (Inner s) a
      -> Query s (OuterCols a)
inner :: forall a s.
(Columns a, Columns (OuterCols a)) =>
Query (Inner s) a -> Query s (OuterCols a)
inner = forall a s.
(Columns a, Columns (OuterCols a)) =>
(OuterCols a -> Col s Bool)
-> Query (Inner s) a -> Query s (OuterCols a)
innerJoin (forall a b. a -> b -> a
const forall s. Col s Bool
true)

-- | Create and filter an inner query, before adding it to the current result
--   set.
--
--   @q `suchThat` p@ is generally more efficient than
--   @select q >>= \x -> restrict (p x) >> pure x@.
suchThat :: (Columns a, Columns (OuterCols a))
         => Query (Inner s) a
         -> (a -> Col (Inner s) Bool)
         -> Query s (OuterCols a)
suchThat :: forall a s.
(Columns a, Columns (OuterCols a)) =>
Query (Inner s) a
-> (a -> Col (Inner s) Bool) -> Query s (OuterCols a)
suchThat Query (Inner s) a
q a -> Col (Inner s) Bool
p = forall a s.
(Columns a, Columns (OuterCols a)) =>
Query (Inner s) a -> Query s (OuterCols a)
inner forall a b. (a -> b) -> a -> b
$ do
  a
x <- Query (Inner s) a
q
  forall s t. Same s t => Col s Bool -> Query t ()
restrict (a -> Col (Inner s) Bool
p a
x)
  forall (m :: * -> *) a. Monad m => a -> m a
return a
x
infixr 7 `suchThat`

-- | Comparisons over columns.
--   Note that when comparing nullable (i.e. @Maybe@) columns, SQL @NULL@
--   semantics are used. This means that comparing to a @NULL@ field will remove
--   the row in question from the current set.
--   To test for @NULL@, use 'isNull' instead of @.== literal Nothing@.
(.==), (./=) :: (Same s t, SqlType a) => Col s a -> Col t a -> Col s Bool
(.>), (.<), (.>=), (.<=) :: (Same s t, SqlOrd a) => Col s a -> Col t a -> Col s Bool
.== :: forall s t a.
(Same s t, SqlType a) =>
Col s a -> Col t a -> Col s Bool
(.==) = forall {k} (s :: k) (t :: k) a b c.
Same s t =>
(Exp SQL a -> Exp SQL b -> Exp SQL c)
-> Col s a -> Col t b -> Col s c
liftC2 forall a b. (a -> b) -> a -> b
$ forall a b c sql.
BinOp a b c -> Exp sql a -> Exp sql b -> Exp sql c
BinOp forall a. BinOp a a Bool
Eq
./= :: forall s t a.
(Same s t, SqlType a) =>
Col s a -> Col t a -> Col s Bool
(./=) = forall {k} (s :: k) (t :: k) a b c.
Same s t =>
(Exp SQL a -> Exp SQL b -> Exp SQL c)
-> Col s a -> Col t b -> Col s c
liftC2 forall a b. (a -> b) -> a -> b
$ forall a b c sql.
BinOp a b c -> Exp sql a -> Exp sql b -> Exp sql c
BinOp forall a. BinOp a a Bool
Neq
.> :: forall s t a.
(Same s t, SqlOrd a) =>
Col s a -> Col t a -> Col s Bool
(.>)  = forall {k} (s :: k) (t :: k) a b c.
Same s t =>
(Exp SQL a -> Exp SQL b -> Exp SQL c)
-> Col s a -> Col t b -> Col s c
liftC2 forall a b. (a -> b) -> a -> b
$ forall a b c sql.
BinOp a b c -> Exp sql a -> Exp sql b -> Exp sql c
BinOp forall a. BinOp a a Bool
Gt
.< :: forall s t a.
(Same s t, SqlOrd a) =>
Col s a -> Col t a -> Col s Bool
(.<)  = forall {k} (s :: k) (t :: k) a b c.
Same s t =>
(Exp SQL a -> Exp SQL b -> Exp SQL c)
-> Col s a -> Col t b -> Col s c
liftC2 forall a b. (a -> b) -> a -> b
$ forall a b c sql.
BinOp a b c -> Exp sql a -> Exp sql b -> Exp sql c
BinOp forall a. BinOp a a Bool
Lt
.>= :: forall s t a.
(Same s t, SqlOrd a) =>
Col s a -> Col t a -> Col s Bool
(.>=) = forall {k} (s :: k) (t :: k) a b c.
Same s t =>
(Exp SQL a -> Exp SQL b -> Exp SQL c)
-> Col s a -> Col t b -> Col s c
liftC2 forall a b. (a -> b) -> a -> b
$ forall a b c sql.
BinOp a b c -> Exp sql a -> Exp sql b -> Exp sql c
BinOp forall a. BinOp a a Bool
Gte
.<= :: forall s t a.
(Same s t, SqlOrd a) =>
Col s a -> Col t a -> Col s Bool
(.<=) = forall {k} (s :: k) (t :: k) a b c.
Same s t =>
(Exp SQL a -> Exp SQL b -> Exp SQL c)
-> Col s a -> Col t b -> Col s c
liftC2 forall a b. (a -> b) -> a -> b
$ forall a b c sql.
BinOp a b c -> Exp sql a -> Exp sql b -> Exp sql c
BinOp forall a. BinOp a a Bool
Lte
infixl 4 .==
infixl 4 ./=
infixl 4 .>
infixl 4 .<
infixl 4 .>=
infixl 4 .<=

-- | Is the given column null?
isNull :: SqlType a => Col s (Maybe a) -> Col s Bool
isNull :: forall a s. SqlType a => Col s (Maybe a) -> Col s Bool
isNull = forall {k} a b (s :: k).
(Exp SQL a -> Exp SQL b) -> Col s a -> Col s b
liftC forall a b. (a -> b) -> a -> b
$ forall a b sql. UnOp a b -> Exp sql a -> Exp sql b
UnOp forall a. UnOp (Maybe a) Bool
IsNull

-- | Applies the given function to the given nullable column where it isn't null,
--   and returns the given default value where it is.
--
--   This is the Selda equivalent of 'maybe'.
matchNull :: (SqlType a, SqlType b, Same s t)
          => Col s b
          -> (Col s a -> Col s b)
          -> Col t (Maybe a)
          -> Col s b
matchNull :: forall a b s t.
(SqlType a, SqlType b, Same s t) =>
Col s b -> (Col s a -> Col s b) -> Col t (Maybe a) -> Col s b
matchNull Col s b
nullvalue Col s a -> Col s b
f Col t (Maybe a)
x = forall s t u a.
(Same s t, Same t u, SqlType a) =>
Col s Bool -> Col t a -> Col u a -> Col s a
ifThenElse (forall a s. SqlType a => Col s (Maybe a) -> Col s Bool
isNull Col t (Maybe a)
x) Col s b
nullvalue (Col s a -> Col s b
f (forall s a b. SqlType b => Col s a -> Col s b
cast Col t (Maybe a)
x))

-- | If the second value is Nothing, return the first value. Otherwise return
--   the second value.
ifNull :: (Same s t, SqlType a) => Col s a -> Col t (Maybe a) -> Col s a
ifNull :: forall s t a.
(Same s t, SqlType a) =>
Col s a -> Col t (Maybe a) -> Col s a
ifNull Col s a
nullvalue Col t (Maybe a)
x = forall s t u a.
(Same s t, Same t u, SqlType a) =>
Col s Bool -> Col t a -> Col u a -> Col s a
ifThenElse (forall a s. SqlType a => Col s (Maybe a) -> Col s Bool
isNull Col t (Maybe a)
x) Col s a
nullvalue (forall s a b. SqlType b => Col s a -> Col s b
cast Col t (Maybe a)
x)

-- | Any container type which can be mapped over.
--   Sort of like 'Functor', if you squint a bit.
class Mappable f where
  type Container f a
  (.<$>) :: (SqlType a, SqlType b)
         => (Col s a -> Col s b)
         -> f s (Container f a)
         -> f s (Container f b)
infixl 4 .<$>

instance Mappable Aggr where
  type Container Aggr a = a
  .<$> :: forall a b s.
(SqlType a, SqlType b) =>
(Col s a -> Col s b)
-> Aggr s (Container Aggr a) -> Aggr s (Container Aggr b)
(.<$>) = forall s a b. (Col s a -> Col s b) -> Aggr s a -> Aggr s b
liftAggr

instance Mappable Col where
  type Container Col a = Maybe a
  Col s a -> Col s b
f .<$> :: forall a b s.
(SqlType a, SqlType b) =>
(Col s a -> Col s b)
-> Col s (Container Col a) -> Col s (Container Col b)
.<$> Col s (Container Col a)
mx = forall s a b. SqlType b => Col s a -> Col s b
cast (Col s a -> Col s b
f (forall s a b. SqlType b => Col s a -> Col s b
cast Col s (Container Col a)
mx))

-- | Any container type for which we can check object membership.
class Set set where
  -- | Is the given column contained in the given set?
  isIn :: (Same s t, SqlType a) => Col s a -> set (Col t a) -> Col s Bool
infixl 4 `isIn`

instance Set [] where
  isIn :: forall s t a.
(Same s t, SqlType a) =>
Col s a -> [Col t a] -> Col s Bool
isIn Col s a
_ []     = forall s. Col s Bool
false
  isIn (One Exp SQL a
x) [Col t a]
xs = forall {k} (s :: k) a. Exp SQL a -> Col s a
One forall a b. (a -> b) -> a -> b
$ forall sql a. Exp sql a -> [Exp sql a] -> Exp sql Bool
InList Exp SQL a
x [Exp SQL a
c | One Exp SQL a
c <- [Col t a]
xs]

instance Set (Query s) where
  isIn :: forall s t a.
(Same s t, SqlType a) =>
Col s a -> Query s (Col t a) -> Col s Bool
isIn (One Exp SQL a
x) = forall {k} (s :: k) a. Exp SQL a -> Col s a
One forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall sql a. Exp sql a -> sql -> Exp sql Bool
InQuery Exp SQL a
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a s. Result a => Query s a -> (Int, SQL)
compQueryWithFreshScope

(.&&), (.||) :: Same s t => Col s Bool -> Col t Bool -> Col s Bool
.&& :: forall s t. Same s t => Col s Bool -> Col t Bool -> Col s Bool
(.&&) = forall {k} (s :: k) (t :: k) a b c.
Same s t =>
(Exp SQL a -> Exp SQL b -> Exp SQL c)
-> Col s a -> Col t b -> Col s c
liftC2 forall a b. (a -> b) -> a -> b
$ forall a b c sql.
BinOp a b c -> Exp sql a -> Exp sql b -> Exp sql c
BinOp BinOp Bool Bool Bool
And
.|| :: forall s t. Same s t => Col s Bool -> Col t Bool -> Col s Bool
(.||) = forall {k} (s :: k) (t :: k) a b c.
Same s t =>
(Exp SQL a -> Exp SQL b -> Exp SQL c)
-> Col s a -> Col t b -> Col s c
liftC2 forall a b. (a -> b) -> a -> b
$ forall a b c sql.
BinOp a b c -> Exp sql a -> Exp sql b -> Exp sql c
BinOp BinOp Bool Bool Bool
Or
infixr 3 .&&
infixr 2 .||

-- | Ordering for 'order'.
ascending, descending :: Order
ascending :: Order
ascending = Order
Asc
descending :: Order
descending = Order
Desc

-- | Lift a non-nullable column to a nullable one.
--   Useful for creating expressions over optional columns:
--
-- > data Person = Person {name :: Text, age :: Int, pet :: Maybe Text}
-- >   deriving Generic
-- > instance SqlRow Person
-- >
-- > people :: Table Person
-- > people = table "people" []
-- >
-- > peopleWithCats = do
-- >   person <- select people
-- >   restrict (person ! #pet .== just "cat")
-- >   return (person ! #name)
just :: SqlType a => Col s a -> Col s (Maybe a)
just :: forall a s. SqlType a => Col s a -> Col s (Maybe a)
just = forall s a b. SqlType b => Col s a -> Col s b
cast

-- | Returns 'true' if the given field in the given row is equal to the given
--   literal.
is :: forall r s c. SqlType c => Selector r c -> c -> Row s r -> Col s Bool
is :: forall r s c.
SqlType c =>
Selector r c -> c -> Row s r -> Col s Bool
is Selector r c
s c
x Row s r
r = Row s r
r forall a s t. SqlType a => Row s t -> Selector t a -> Col s a
! Selector r c
s forall s t a.
(Same s t, SqlType a) =>
Col s a -> Col t a -> Col s Bool
.== (forall {k} a (s :: k). SqlType a => a -> Col s a
literal c
x :: Col s c)

-- | SQL NULL, at any type you like.
null_ :: SqlType a => Col s (Maybe a)
null_ :: forall a s. SqlType a => Col s (Maybe a)
null_ = forall {k} a (s :: k). SqlType a => a -> Col s a
literal forall a. Maybe a
Nothing

-- | Specialization of 'literal' for integers.
int :: Int -> Col s Int
int :: forall s. Int -> Col s Int
int = forall {k} a (s :: k). SqlType a => a -> Col s a
literal

-- | Specialization of 'literal' for doubles.
float :: Double -> Col s Double
float :: forall s. Double -> Col s Double
float = forall {k} a (s :: k). SqlType a => a -> Col s a
literal

-- | Specialization of 'literal' for text.
text :: Text -> Col s Text
text :: forall s. Text -> Col s Text
text = forall {k} a (s :: k). SqlType a => a -> Col s a
literal

-- | True and false boolean literals.
true, false :: Col s Bool
true :: forall s. Col s Bool
true = forall {k} a (s :: k). SqlType a => a -> Col s a
literal Bool
True
false :: forall s. Col s Bool
false = forall {k} a (s :: k). SqlType a => a -> Col s a
literal Bool
False

-- | The SQL @LIKE@ operator; matches strings with @%@ wildcards.
--   For instance:
--
-- > "%gon" `like` "dragon" .== true
like :: Same s t => Col s Text -> Col t Text -> Col s Bool
like :: forall s t. Same s t => Col s Text -> Col t Text -> Col s Bool
like = forall {k} (s :: k) (t :: k) a b c.
Same s t =>
(Exp SQL a -> Exp SQL b -> Exp SQL c)
-> Col s a -> Col t b -> Col s c
liftC2 forall a b. (a -> b) -> a -> b
$ forall a b c sql.
BinOp a b c -> Exp sql a -> Exp sql b -> Exp sql c
BinOp BinOp Text Text Bool
Like
infixl 4 `like`

-- | The number of non-null values in the given column.
count :: SqlType a => Col s a -> Aggr s Int
count :: forall a s. SqlType a => Col s a -> Aggr s Int
count = forall a s b. SqlType a => Text -> Col s a -> Aggr s b
aggr Text
"COUNT"

-- | The average of all values in the given column.
avg :: (SqlType a, Num a) => Col s a -> Aggr s (Maybe a)
avg :: forall a s. (SqlType a, Num a) => Col s a -> Aggr s (Maybe a)
avg = forall a s b. SqlType a => Text -> Col s a -> Aggr s b
aggr Text
"AVG"

-- | The greatest value in the given column. Texts are compared lexically.
max_ :: SqlOrd a => Col s a -> Aggr s (Maybe a)
max_ :: forall a s. SqlOrd a => Col s a -> Aggr s (Maybe a)
max_ = forall a s b. SqlType a => Text -> Col s a -> Aggr s b
aggr Text
"MAX"

-- | The smallest value in the given column. Texts are compared lexically.
min_ :: SqlOrd a => Col s a -> Aggr s (Maybe a)
min_ :: forall a s. SqlOrd a => Col s a -> Aggr s (Maybe a)
min_ = forall a s b. SqlType a => Text -> Col s a -> Aggr s b
aggr Text
"MIN"

-- | Sum all values in the given column.
sum_ :: forall a b s. (SqlType a, SqlType b, Num a, Num b) => Col s a -> Aggr s b
sum_ :: forall a b s.
(SqlType a, SqlType b, Num a, Num b) =>
Col s a -> Aggr s b
sum_ = forall s a b. (Col s a -> Col s b) -> Aggr s a -> Aggr s b
liftAggr (forall s t a.
(Same s t, SqlType a) =>
Col s a -> Col t (Maybe a) -> Col s a
ifNull (Col s b
0::Col s b) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s a b. SqlType b => Col s a -> Col s b
cast) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a s b. SqlType a => Text -> Col s a -> Aggr s b
aggr Text
"SUM"

-- | Round a value to the nearest integer. Equivalent to @roundTo 0@.
round_ :: forall s a. (SqlType a, Num a) => Col s Double -> Col s a
round_ :: forall s a. (SqlType a, Num a) => Col s Double -> Col s a
round_ =
  case forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (a :~: Double) of
    Just a :~: Double
Refl -> forall s a b. Text -> Col s a -> Col s b
fun Text
"ROUND"
    Maybe (a :~: Double)
_         -> forall s a b. SqlType b => Col s a -> Col s b
cast forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s a b. Text -> Col s a -> Col s b
fun Text
"ROUND"

-- | Round a column to the given number of decimals places.
roundTo :: Col s Int -> Col s Double -> Col s Double
roundTo :: forall s. Col s Int -> Col s Double -> Col s Double
roundTo = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a b. (a -> b) -> a -> b
$ forall s a b c. Text -> Col s a -> Col s b -> Col s c
fun2 Text
"ROUND"

-- | Calculate the length of a string column.
length_ :: Col s Text -> Col s Int
length_ :: forall s. Col s Text -> Col s Int
length_ = forall s a b. Text -> Col s a -> Col s b
fun Text
"LENGTH"

-- | Boolean negation.
not_ :: Col s Bool -> Col s Bool
not_ :: forall s. Col s Bool -> Col s Bool
not_ = forall {k} a b (s :: k).
(Exp SQL a -> Exp SQL b) -> Col s a -> Col s b
liftC forall a b. (a -> b) -> a -> b
$ forall a b sql. UnOp a b -> Exp sql a -> Exp sql b
UnOp UnOp Bool Bool
Not

-- | Convert a boolean column to any numeric type.
fromBool :: (SqlType a, Num a) => Col s Bool -> Col s a
fromBool :: forall a s. (SqlType a, Num a) => Col s Bool -> Col s a
fromBool = forall s a b. SqlType b => Col s a -> Col s b
cast

-- | Convert an integer column to any numeric type.
fromInt :: (SqlType a, Num a) => Col s Int -> Col s a
fromInt :: forall a s. (SqlType a, Num a) => Col s Int -> Col s a
fromInt = forall s a b. SqlType b => Col s a -> Col s b
cast

-- | Convert any SQL type to a string.
toString :: SqlType a => Col s a -> Col s Text
toString :: forall a s. SqlType a => Col s a -> Col s Text
toString = forall s a b. SqlType b => Col s a -> Col s b
cast

-- | Convert the given string to uppercase.
toUpper :: Col s Text -> Col s Text
toUpper :: forall s. Col s Text -> Col s Text
toUpper = forall s a b. Text -> Col s a -> Col s b
fun Text
"UPPER"

-- | Convert the given string to lowercase.
toLower :: Col s Text -> Col s Text
toLower :: forall s. Col s Text -> Col s Text
toLower = forall s a b. Text -> Col s a -> Col s b
fun Text
"LOWER"

instance Semigroup (Col s Text) where
  <> :: Col s Text -> Col s Text -> Col s Text
(<>) = forall s a b c. Text -> Col s a -> Col s b -> Col s c
operator Text
"||"
instance Monoid (Col s Text) where
  mempty :: Col s Text
mempty = Col s Text
""




-- | Perform a conditional on a column
ifThenElse :: (Same s t, Same t u, SqlType a) => Col s Bool -> Col t a -> Col u a -> Col s a
ifThenElse :: forall s t u a.
(Same s t, Same t u, SqlType a) =>
Col s Bool -> Col t a -> Col u a -> Col s a
ifThenElse = forall {k} a b c d (s :: k).
(Exp SQL a -> Exp SQL b -> Exp SQL c -> Exp SQL d)
-> Col s a -> Col s b -> Col s c -> Col s d
liftC3 forall sql a. Exp sql Bool -> Exp sql a -> Exp sql a -> Exp sql a
If