diff --git a/hasql.cabal b/hasql.cabal index 5392216..fca3b8c 100644 --- a/hasql.cabal +++ b/hasql.cabal @@ -106,6 +106,8 @@ library Hasql.PTI Hasql.Session.Core Hasql.Settings + Hasql.Statement.Function + Hasql.Statement.Function.SqlBuilder build-depends: , aeson >=2 && <3 diff --git a/library/Hasql/Statement.hs b/library/Hasql/Statement.hs index fe3b8df..9572958 100644 --- a/library/Hasql/Statement.hs +++ b/library/Hasql/Statement.hs @@ -1,5 +1,6 @@ module Hasql.Statement ( Statement (..), + function, refineResult, -- * Recipies @@ -16,6 +17,7 @@ import qualified Hasql.Decoders as Decoders import qualified Hasql.Decoders.All as Decoders import qualified Hasql.Encoders as Encoders import Hasql.Prelude +import qualified Hasql.Statement.Function as Function -- | -- Specification of a strictly single-statement query, which can be parameterized and prepared. @@ -117,3 +119,24 @@ refineResult refiner (Statement template encoder decoder preparable) = -- -- For details see -- . + +-- | +-- Utility for execution of stored procedures and functions, which automates the SQL generation. +-- +-- Produces SQL like the following: +-- +-- > SELECT function_name($1, $2, ..) +-- +-- with the amount of parameter placeholders derived from the encoder. +function :: + -- | Function name. + -- + -- Will get automatically escaped for injection-safety. + Text -> + Encoders.Params a -> + Decoders.Result b -> + -- | Whether the statement should be prepared. + Bool -> + Statement a b +function functionName encoders = + Statement (Function.sql functionName encoders) encoders diff --git a/library/Hasql/Statement/Function.hs b/library/Hasql/Statement/Function.hs new file mode 100644 index 0000000..7d8e774 --- /dev/null +++ b/library/Hasql/Statement/Function.hs @@ -0,0 +1,12 @@ +module Hasql.Statement.Function where + +import qualified ByteString.StrictBuilder as Builder +import qualified Hasql.Encoders.All as Encoders +import Hasql.Prelude +import qualified Hasql.Statement.Function.SqlBuilder as SqlBuilder + +sql :: Text -> Encoders.Params a -> ByteString +sql name encoders = + Builder.builderBytes + $ SqlBuilder.sql name + $ error "TODO: Get size" encoders diff --git a/library/Hasql/Statement/Function/SqlBuilder.hs b/library/Hasql/Statement/Function/SqlBuilder.hs new file mode 100644 index 0000000..1be6483 --- /dev/null +++ b/library/Hasql/Statement/Function/SqlBuilder.hs @@ -0,0 +1,25 @@ +module Hasql.Statement.Function.SqlBuilder where + +import ByteString.StrictBuilder +import qualified Data.Text as Text +import qualified Data.Text.Encoding as Text +import Hasql.Prelude + +sql :: Text -> Int -> Builder +sql name size = + "select " <> functionName name <> "(" <> arguments size <> ")" + +functionName :: Text -> Builder +functionName = + bytes . Text.encodeUtf8 . Text.replace "\"" "" + +arguments :: Int -> Builder +arguments size = + [1 .. size] + & fmap argument + & intersperse ", " + & mconcat + +argument :: Int -> Builder +argument num = + "$" <> asciiIntegral num