module Opaleye.SQLite.Internal.Column where

import qualified Opaleye.SQLite.Internal.HaskellDB.PrimQuery as HPQ

-- | The 'Num' and 'Fractional' instances for 'Column' 'a' are too
-- general.  For example, they allow you to add two 'Column'
-- 'String's.  This will be fixed in a subsequent release.
newtype Column a = Column HPQ.PrimExpr deriving Int -> Column a -> ShowS
[Column a] -> ShowS
Column a -> String
(Int -> Column a -> ShowS)
-> (Column a -> String) -> ([Column a] -> ShowS) -> Show (Column a)
forall a. Int -> Column a -> ShowS
forall a. [Column a] -> ShowS
forall a. Column a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Column a] -> ShowS
$cshowList :: forall a. [Column a] -> ShowS
show :: Column a -> String
$cshow :: forall a. Column a -> String
showsPrec :: Int -> Column a -> ShowS
$cshowsPrec :: forall a. Int -> Column a -> ShowS
Show

data Nullable a = Nullable

unColumn :: Column a -> HPQ.PrimExpr
unColumn :: Column a -> PrimExpr
unColumn (Column PrimExpr
e) = PrimExpr
e

{-# DEPRECATED unsafeCoerce "Use unsafeCoerceColumn instead" #-}
unsafeCoerce :: Column a -> Column b
unsafeCoerce :: Column a -> Column b
unsafeCoerce = Column a -> Column b
forall a b. Column a -> Column b
unsafeCoerceColumn

unsafeCoerceColumn :: Column a -> Column b
unsafeCoerceColumn :: Column a -> Column b
unsafeCoerceColumn (Column PrimExpr
e) = PrimExpr -> Column b
forall a. PrimExpr -> Column a
Column PrimExpr
e

binOp :: HPQ.BinOp -> Column a -> Column b -> Column c
binOp :: BinOp -> Column a -> Column b -> Column c
binOp BinOp
op (Column PrimExpr
e) (Column PrimExpr
e') = PrimExpr -> Column c
forall a. PrimExpr -> Column a
Column (BinOp -> PrimExpr -> PrimExpr -> PrimExpr
HPQ.BinExpr BinOp
op PrimExpr
e PrimExpr
e')

unOp :: HPQ.UnOp -> Column a -> Column b
unOp :: UnOp -> Column a -> Column b
unOp UnOp
op (Column PrimExpr
e) = PrimExpr -> Column b
forall a. PrimExpr -> Column a
Column (UnOp -> PrimExpr -> PrimExpr
HPQ.UnExpr UnOp
op PrimExpr
e)

-- For import order reasons we can't make the return type PGBool
unsafeCase_ :: [(Column pgBool, Column a)] -> Column a -> Column a
unsafeCase_ :: [(Column pgBool, Column a)] -> Column a -> Column a
unsafeCase_ [(Column pgBool, Column a)]
alts (Column PrimExpr
otherwise_) = PrimExpr -> Column a
forall a. PrimExpr -> Column a
Column ([(PrimExpr, PrimExpr)] -> PrimExpr -> PrimExpr
HPQ.CaseExpr ([(Column pgBool, Column a)] -> [(PrimExpr, PrimExpr)]
forall a a. [(Column a, Column a)] -> [(PrimExpr, PrimExpr)]
unColumns [(Column pgBool, Column a)]
alts) PrimExpr
otherwise_)
  where unColumns :: [(Column a, Column a)] -> [(PrimExpr, PrimExpr)]
unColumns = ((Column a, Column a) -> (PrimExpr, PrimExpr))
-> [(Column a, Column a)] -> [(PrimExpr, PrimExpr)]
forall a b. (a -> b) -> [a] -> [b]
map (\(Column PrimExpr
e, Column PrimExpr
e') -> (PrimExpr
e, PrimExpr
e'))

unsafeIfThenElse :: Column pgBool -> Column a -> Column a -> Column a
unsafeIfThenElse :: Column pgBool -> Column a -> Column a -> Column a
unsafeIfThenElse Column pgBool
cond Column a
t Column a
f = [(Column pgBool, Column a)] -> Column a -> Column a
forall pgBool a.
[(Column pgBool, Column a)] -> Column a -> Column a
unsafeCase_ [(Column pgBool
cond, Column a
t)] Column a
f

unsafeGt :: Column a -> Column a -> Column pgBool
unsafeGt :: Column a -> Column a -> Column pgBool
unsafeGt = BinOp -> Column a -> Column a -> Column pgBool
forall a b c. BinOp -> Column a -> Column b -> Column c
binOp BinOp
HPQ.OpGt

unsafeEq :: Column a -> Column a -> Column pgBool
unsafeEq :: Column a -> Column a -> Column pgBool
unsafeEq = BinOp -> Column a -> Column a -> Column pgBool
forall a b c. BinOp -> Column a -> Column b -> Column c
binOp BinOp
HPQ.OpEq

class PGNum a where
  pgFromInteger :: Integer -> Column a

instance PGNum a => Num (Column a) where
  fromInteger :: Integer -> Column a
fromInteger = Integer -> Column a
forall a. PGNum a => Integer -> Column a
pgFromInteger
  * :: Column a -> Column a -> Column a
(*) = BinOp -> Column a -> Column a -> Column a
forall a b c. BinOp -> Column a -> Column b -> Column c
binOp BinOp
HPQ.OpMul
  + :: Column a -> Column a -> Column a
(+) = BinOp -> Column a -> Column a -> Column a
forall a b c. BinOp -> Column a -> Column b -> Column c
binOp BinOp
HPQ.OpPlus
  (-) = BinOp -> Column a -> Column a -> Column a
forall a b c. BinOp -> Column a -> Column b -> Column c
binOp BinOp
HPQ.OpMinus

  abs :: Column a -> Column a
abs = UnOp -> Column a -> Column a
forall a b. UnOp -> Column a -> Column b
unOp UnOp
HPQ.OpAbs
  negate :: Column a -> Column a
negate = UnOp -> Column a -> Column a
forall a b. UnOp -> Column a -> Column b
unOp UnOp
HPQ.OpNegate

  -- We can't use Postgres's 'sign' function because it returns only a
  -- numeric or a double
  signum :: Column a -> Column a
signum Column a
c = [(Column Any, Column a)] -> Column a -> Column a
forall pgBool a.
[(Column pgBool, Column a)] -> Column a -> Column a
unsafeCase_ [(Column a
c Column a -> Column a -> Column Any
forall a pgBool. Column a -> Column a -> Column pgBool
`unsafeGt` Column a
0, Column a
1), (Column a
c Column a -> Column a -> Column Any
forall a pgBool. Column a -> Column a -> Column pgBool
`unsafeEq` Column a
0, Column a
0)] (-Column a
1)

class PGFractional a where
  pgFromRational :: Rational -> Column a

instance (PGNum a, PGFractional a) => Fractional (Column a) where
  fromRational :: Rational -> Column a
fromRational = Rational -> Column a
forall a. PGFractional a => Rational -> Column a
pgFromRational
  / :: Column a -> Column a -> Column a
(/) = BinOp -> Column a -> Column a -> Column a
forall a b c. BinOp -> Column a -> Column b -> Column c
binOp BinOp
HPQ.OpDiv

unsafeCast :: String -> Column a -> Column b
unsafeCast :: String -> Column a -> Column b
unsafeCast = (PrimExpr -> PrimExpr) -> Column a -> Column b
forall c a. (PrimExpr -> PrimExpr) -> Column c -> Column a
mapColumn ((PrimExpr -> PrimExpr) -> Column a -> Column b)
-> (String -> PrimExpr -> PrimExpr)
-> String
-> Column a
-> Column b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> PrimExpr -> PrimExpr
HPQ.CastExpr
  where
    mapColumn :: (HPQ.PrimExpr -> HPQ.PrimExpr) -> Column c -> Column a
    mapColumn :: (PrimExpr -> PrimExpr) -> Column c -> Column a
mapColumn PrimExpr -> PrimExpr
primExpr = PrimExpr -> Column a
forall a. PrimExpr -> Column a
Column (PrimExpr -> Column a)
-> (Column c -> PrimExpr) -> Column c -> Column a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PrimExpr -> PrimExpr
primExpr (PrimExpr -> PrimExpr)
-> (Column c -> PrimExpr) -> Column c -> PrimExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Column c -> PrimExpr
forall a. Column a -> PrimExpr
unColumn