module Spark.Core.Internal.RowGenericsFrom(
FromSQL,
cellToValue,
) where
import GHC.Generics
import Data.Text(Text, pack)
import Control.Monad.Except
import Formatting
import qualified Data.Vector as V
import Spark.Core.Internal.RowStructures
import Spark.Core.Internal.Utilities
cellToValue :: (FromSQL a) => Cell -> Either Text a
cellToValue = _cellToValue
type TryS = Either Text
data Decode2 =
D2Cons ![Cell]
| D2Normal !Cell
deriving (Eq, Show)
class FromSQL a where
_cellToValue :: Cell -> TryS a
default _cellToValue :: (Generic a, GFromSQL (Rep a)) => Cell -> TryS a
_cellToValue cell = let
x1r = _gFcell (D2Normal cell) :: TryS (Rep a a)
x1t = to <$> x1r
in x1t
instance FromSQL a => FromSQL (Maybe a) where
_cellToValue Empty = pure Nothing
_cellToValue x = pure <$> _cellToValue x
instance FromSQL Int where
_cellToValue (IntElement x) = pure x
_cellToValue x = throwError $ sformat ("FromSQL: Decoding an int from "%shown) x
instance FromSQL Cell where
_cellToValue = pure
instance FromSQL a => FromSQL [a] where
_cellToValue (RowArray xs) = sequence (_cellToValue <$> V.toList xs)
_cellToValue x = throwError $ sformat ("FromSQL: Decoding array from "%shown) x
class GFromSQL r where
_gFcell :: Decode2 -> TryS (r a)
instance GFromSQL U1 where
_gFcell x = failure $ pack $ "GFromSQL UI called" ++ show x
instance (GFromSQL a, GFromSQL b) => GFromSQL (a :*: b) where
_gFcell (D2Normal (RowArray arr)) | not (V.null arr) =
let (cell : l) = V.toList arr
x1t = _gFcell (D2Normal cell)
x2t = _gFcell (D2Cons l)
x = do
x1 <- x1t
x2 <- x2t
return (x1 :*: x2)
in x
_gFcell (D2Cons (cell : l)) =
let x1t = _gFcell (D2Cons [cell])
x2t = _gFcell (D2Cons l)
x = do
x1 <- x1t
x2 <- x2t
return (x1 :*: x2)
in x
_gFcell x = failure $ pack ("GFromSQL (a :*: b) " ++ show x)
instance (GFromSQL a, GFromSQL b) => GFromSQL (a :+: b) where
_gFcell x = failure $ pack $ "GFromSQL (a :+: b)" ++ show x
_m1 :: GFromSQL f1 => String -> Decode2 -> TryS (M1 i1 c1 f1 p1)
_m1 msg (D2Cons x) = failure $ pack (msg ++ " FAILED CONS: " ++ show x)
_m1 _ (D2Normal cell) =
let xt = _gFcell (D2Normal cell) in
M1 <$> xt
instance (GFromSQL a, Constructor c) => GFromSQL (M1 C c a) where
_gFcell = _m1 "GFromSQL (M1 C c a)"
instance (GFromSQL a, Selector c) => GFromSQL (M1 S c a) where
_gFcell (D2Normal (RowArray arr)) | V.length arr == 1 =
M1 <$> _gFcell (D2Cons [cell]) where
cell = V.head arr
_gFcell z @ (D2Cons [_]) =
M1 <$> _gFcell z
_gFcell x = _m1 "GFromSQL (M1 S c a)" x
instance (GFromSQL a, Datatype c) => GFromSQL (M1 D c a) where
_gFcell z @ (D2Normal (RowArray _)) =
let xt = _gFcell z in
M1 <$> xt
_gFcell x = failure $ pack $ "FAIL GFromSQL (M1 D c a)" ++ show x
instance (FromSQL a) => GFromSQL (K1 i a) where
_gFcell (D2Normal cell) =
let xt = _cellToValue cell :: TryS a in
K1 <$> xt
_gFcell (D2Cons [cell]) =
let xt = _cellToValue cell in
K1 <$> xt
_gFcell x = failure $ pack ("GFromSQLK FAIL " ++ show x)