mirror of https://github.com/voidlizard/hbs2
79 lines
2.4 KiB
Haskell
79 lines
2.4 KiB
Haskell
{-# LANGUAGE AllowAmbiguousTypes #-}
|
||
{-# LANGUAGE UndecidableInstances #-}
|
||
{-# LANGUAGE DefaultSignatures #-}
|
||
module DBPipe.SQLite.Generic where
|
||
|
||
import GHC.Generics
|
||
import Data.Text qualified as Text
|
||
import Data.Text (Text)
|
||
import Data.String (IsString(..))
|
||
import Text.InterpolatedString.Perl6 (qc)
|
||
import Data.Coerce
|
||
|
||
newtype SQLName = SQLName Text
|
||
deriving stock (Eq,Ord,Show)
|
||
deriving newtype (IsString,Monoid,Semigroup)
|
||
|
||
newtype SQLPart = SQLPart Text
|
||
deriving stock (Eq,Ord,Show)
|
||
deriving newtype (IsString,Monoid,Semigroup)
|
||
|
||
class ToSQL a where
|
||
toSQL :: a -> SQLPart
|
||
|
||
instance ToSQL SQLName where
|
||
toSQL (SQLName a) = SQLPart a
|
||
|
||
class GHasColumnNames f where
|
||
gColumnNames :: f p -> [SQLName]
|
||
|
||
class HasColumnNames a where
|
||
columnNames :: a -> [SQLName]
|
||
default columnNames :: (Generic a, GHasColumnNames (Rep a)) => a -> [SQLName]
|
||
columnNames = gColumnNames . from
|
||
|
||
class HasTableName t where
|
||
tableName :: SQLName
|
||
|
||
class HasColumnName a where
|
||
columnName :: SQLName
|
||
|
||
instance HasColumnNames [SQLName] where
|
||
columnNames = id
|
||
|
||
instance HasColumnNames SQLName where
|
||
columnNames n = [n]
|
||
|
||
instance (Generic a, GHasColumnNames (Rep a)) => HasColumnNames a
|
||
|
||
instance GHasColumnNames U1 where
|
||
gColumnNames U1 = []
|
||
|
||
instance (GHasColumnNames a, GHasColumnNames b) => GHasColumnNames (a :*: b) where
|
||
gColumnNames (a :*: b) = gColumnNames a <> gColumnNames b
|
||
|
||
instance (GHasColumnNames a, GHasColumnNames b) => GHasColumnNames (a :+: b) where
|
||
gColumnNames _ = [] -- Не используется для нашего случая.
|
||
|
||
instance HasColumnName c => GHasColumnNames (K1 i c) where
|
||
gColumnNames (K1 c) = [columnName @c]
|
||
|
||
instance GHasColumnNames a => GHasColumnNames (M1 i t a) where
|
||
gColumnNames (M1 a) = gColumnNames a
|
||
|
||
columnListPart :: forall a . HasColumnNames a => a -> SQLPart
|
||
columnListPart w = SQLPart $ Text.intercalate "," [ coerce @_ @Text x | x <- columnNames w ]
|
||
|
||
bindListPart :: forall a . HasColumnNames a => a -> SQLPart
|
||
bindListPart w = SQLPart $ Text.intercalate "," [ "?" | _ <- columnNames w ]
|
||
|
||
class (HasTableName t, HasColumnNames b) => Insert t b where
|
||
insert :: b -> SQLPart
|
||
|
||
instance (HasTableName t, HasColumnNames b) => Insert t b where
|
||
insert values = [qc|insert into {tableName @t} values({v}) ({n})|]
|
||
where
|
||
n = bindListPart values
|
||
v = columnListPart values
|
||
|