{-# LANGUAGE BlockArguments #-} ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- | module Sqlite.Query.Types ( Null (..), Solo (..), Sql (..), (:.) (..), ) where import Control.Arrow (first) import Data.String (IsString (..)) import Data.Text qualified as T import Data.Tuple (Solo (..)) -- | A placeholder for the Sql @NULL@ value. data Null = Null deriving (Read, Show) instance Eq Null where _ == _ = False _ /= _ = False -- | A query string. This type is intended to make it difficult to -- construct a Sql query by concatenating string fragments, as that is -- an extremely common way to accidentally introduce Sql injection -- vulnerabilities into an application. -- -- This type is an instance of 'IsString', so the easiest way to -- construct a query is to enable the @OverloadedStrings@ language -- extension and then simply write the query in double quotes. -- -- > {-# LANGUAGE OverloadedStrings #-} -- > -- > import Database.Sqlite.Simple -- > -- > q :: Query -- > q = "select ?" -- -- The underlying type is a 'Text', and literal Haskell strings that -- contain Unicode characters will be correctly transformed to UTF-8. newtype Sql = Sql { sqlText :: T.Text } deriving (Eq, Ord) instance Show Sql where show = show . sqlText instance Read Sql where readsPrec i = fmap (first Sql) . readsPrec i instance IsString Sql where fromString = Sql . T.pack instance Semigroup Sql where Sql a <> Sql b = Sql (T.append a b) {-# INLINE (<>) #-} instance Monoid Sql where mempty = Sql T.empty mappend = (<>) {-# INLINE mappend #-} -- | A composite type to parse your custom data structures without -- having to define dummy newtype wrappers every time. -- -- -- > instance FromRow MyData where ... -- -- > instance FromRow MyData2 where ... -- -- -- then I can do the following for free: -- -- @ -- res <- query' c "..." -- forM res $ \\(MyData{..} :. MyData2{..}) -> do -- .... -- @ data h :. t = h :. t deriving (Eq, Ord, Show, Read) infixr 3 :.