{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE CPP #-}
module Database.Beam.Query.CustomSQL
(
IsCustomExprFn(..)
, valueExpr_, agg_
, IsCustomSqlSyntax(..) ) where
import Database.Beam.Query.Internal
import Database.Beam.Backend.SQL
import Database.Beam.Backend.SQL.Builder
import Data.ByteString (ByteString)
import Data.ByteString.Builder (byteString, toLazyByteString)
import Data.ByteString.Lazy (toStrict)
import Data.Kind (Type)
import Data.String
import qualified Data.Text as T
class (Monoid (CustomSqlSyntax syntax), Semigroup (CustomSqlSyntax syntax), IsString (CustomSqlSyntax syntax)) =>
IsCustomSqlSyntax syntax where
data CustomSqlSyntax syntax :: Type
customExprSyntax :: CustomSqlSyntax syntax -> syntax
renderSyntax :: syntax -> CustomSqlSyntax syntax
instance IsCustomSqlSyntax SqlSyntaxBuilder where
newtype CustomSqlSyntax SqlSyntaxBuilder = SqlSyntaxBuilderCustom ByteString
deriving (IsString, Monoid, Semigroup)
customExprSyntax (SqlSyntaxBuilderCustom bs) = SqlSyntaxBuilder (byteString bs)
renderSyntax = SqlSyntaxBuilderCustom . toStrict . toLazyByteString . buildSql
newtype CustomSqlSnippet be = CustomSqlSnippet (T.Text -> CustomSqlSyntax (BeamSqlBackendExpressionSyntax be))
instance IsCustomSqlSyntax (BeamSqlBackendExpressionSyntax be) => Semigroup (CustomSqlSnippet be) where
CustomSqlSnippet a <> CustomSqlSnippet b =
CustomSqlSnippet $ \pfx -> a pfx <> b pfx
instance IsCustomSqlSyntax (BeamSqlBackendExpressionSyntax be) => Monoid (CustomSqlSnippet be) where
mempty = CustomSqlSnippet (pure mempty)
mappend = (<>)
instance IsCustomSqlSyntax (BeamSqlBackendExpressionSyntax be) => IsString (CustomSqlSnippet be) where
fromString s = CustomSqlSnippet $ \_ -> fromString s
class IsCustomExprFn fn res | res -> fn where
customExpr_ :: fn -> res
type BeamSqlBackendHasCustomSyntax be = IsCustomSqlSyntax (BeamSqlBackendExpressionSyntax be)
instance BeamSqlBackendHasCustomSyntax be => IsCustomExprFn (CustomSqlSnippet be) (QGenExpr ctxt be s res) where
customExpr_ (CustomSqlSnippet mkSyntax) = QExpr (customExprSyntax . mkSyntax)
instance (IsCustomExprFn a res, BeamSqlBackendHasCustomSyntax be) =>
IsCustomExprFn (CustomSqlSnippet be -> a) (QGenExpr ctxt be s r -> res) where
customExpr_ fn (QExpr e) = customExpr_ $ fn (CustomSqlSnippet (renderSyntax . e))
valueExpr_ :: QExpr be s a -> QExpr be s a
valueExpr_ = id
agg_ :: QAgg be s a -> QAgg be s a
agg_ = id