Skip to content

Instantly share code, notes, and snippets.

@emonkak
Created September 2, 2019 16:48
Show Gist options
  • Save emonkak/e919d7a788a6fd2d55b469419e4690dc to your computer and use it in GitHub Desktop.
Save emonkak/e919d7a788a6fd2d55b469419e4690dc to your computer and use it in GitHub Desktop.
Sql.hs
{-# LANGUAGE FlexibleInstances, OverloadedLists, OverloadedStrings, TypeFamilies #-}
import Data.Monoid
import Data.String
import GHC.Exts
data Sql = Sql (DiffList Char) (DiffList SqlBinding)
deriving (Show)
data SqlBinding = SqlString String
| SqlInteger !Int
| SqlFloat !Double
| SqlNull
deriving (Show)
data DiffList a = DiffList ([a] -> [a])
instance (Show a) => Show (DiffList a) where
show = show . toList
instance IsList (DiffList a) where
type Item (DiffList a) = a
fromList xs = DiffList (xs++)
toList (DiffList f) = f []
instance IsString (DiffList Char) where
fromString = fromList
instance Semigroup (DiffList a) where
(<>) (DiffList f) (DiffList g) = DiffList (f . g)
instance Monoid (DiffList a) where
mempty = DiffList id
instance Semigroup Sql where
(<>) (Sql s1 bs1) (Sql s2 bs2) = Sql (s1 <> s2) (bs1 <> bs2)
instance Monoid Sql where
mempty = Sql mempty mempty
join :: String -> [Sql] -> Sql
join sep (x:xs) = step x xs
where
step acc (x:xs) = step (acc <> (Sql (fromList sep) []) <> x) xs
step acc [] = acc
join sep [] = Sql "" []
values :: [SqlBinding] -> Sql
values (b:bs) = step (Sql "(?" [b]) bs
where
step acc (b:bs) = step (acc <> (Sql ", ?" [b])) bs
step acc [] = acc <> (Sql ")" [])
values [] = Sql "()" []
main = do
print $ (Sql "SELECT * WHERE " []) <> join " AND "
[ (Sql "c1 = ?" [SqlInteger 123])
, (Sql "c2 = ?" [SqlInteger 456])
, (Sql "c3 IN " []) <> (values [SqlInteger 123, SqlInteger 456])
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment