module Database.HamSql.Internal.Stmt.Function where
import Data.Maybe
import qualified Data.Text as T
import Database.HamSql.Internal.Stmt.Basic
stmtsDropFunction' :: SqlId -> [SqlStmt]
stmtsDropFunction' x =
catMaybes [newSqlStmt SqlDropFunction x $ "DROP FUNCTION " <> toSqlCode x]
stmtsDropFunction :: SqlObj SQL_FUNCTION (SqlName, [SqlType]) -> [Maybe SqlStmt]
stmtsDropFunction x = map Just $ stmtsDropFunction' $ sqlId x
instance ToSqlStmts (SqlContext (Schema, Function)) where
toSqlStmts SetupContext {setupContextSetup = setup} obj@(SqlContext (s, f)) =
stmtCreateFunction :
sqlSetOwner (functionOwner f) :
stmtComment : maybeMap sqlStmtGrantExecute (functionPrivExecute f)
where
sqlStmtGrantExecute u = newSqlStmt SqlPriv obj $ sqlGrantExecute u
sqlGrantExecute u =
"GRANT EXECUTE ON FUNCTION \n" <> sqlIdCode obj <> "\nTO " <>
prefixedRole setup u
stmtCreateFunction =
newSqlStmt SqlCreateFunction obj $
"CREATE OR REPLACE FUNCTION " <> sqlFunctionIdentifierDef <> "\n" <>
"RETURNS" <->
toSqlCode (functionReturns f) <>
sqlReturnsColumns (functionReturnsColumns f) <>
"\nLANGUAGE " <>
sqlLanguage (functionLanguage f) <>
"\nSECURITY " <>
sqlSecurity (functionSecurityDefiner f) <>
"\nAS\n$BODY$\n" <>
sqlBody <>
"\n$BODY$\n"
stmtComment = stmtCommentOn obj $ toSqlCodeString (functionDescription f)
sqlSetOwner (Just o) =
newSqlStmt SqlPriv obj $
"ALTER FUNCTION " <> sqlIdCode obj <> "OWNER TO " <>
prefixedRole setup o
sqlSetOwner Nothing = Nothing
sqlFunctionIdentifierDef =
toSqlCode (schemaName s <.> functionName f) <> "(\n" <>
T.intercalate ",\n" (maybeMap sqlParameterDef (functionParameters f)) <>
"\n)"
sqlParameterDef p =
toSqlCode (variableName p) <-> toSqlCode (variableType p) <->
sqlParamDefault (variableDefault p)
where
sqlParamDefault Nothing = ""
sqlParamDefault (Just x) = "DEFAULT" <-> x
sqlReturnsColumns cs
| toSqlCode (functionReturns f) == "TABLE" =
" (" <\> T.intercalate ",\n" (maybeMap sqlReturnsColumn cs) <> ") "
| otherwise = ""
sqlReturnsColumn c =
toSqlCode (parameterName c) <> " " <> toSqlCode (parameterType c)
sqlBody
| isNothing (functionLanguage f) =
"DECLARE" <\> sqlVariables (functionVariables f) <> "BEGIN" <\> body <\>
"END;"
| otherwise = body
where
body =
T.intercalate "\n" preludes <> fromMaybe "" (functionBody f) <>
T.intercalate "\n" postludes
preludes :: [Text]
preludes =
catMaybes $maybeMap functiontplBodyPrelude (functionTemplateData f)
postludes :: [Text]
postludes =
catMaybes $maybeMap functiontplBodyPostlude (functionTemplateData f)
sqlVariables Nothing = ""
sqlVariables (Just vs) = T.concat (map sqlVariable vs)
sqlVariable v =
toSqlCode (variableName v) <-> toSqlCode (variableType v) <->
sqlVariableDefault (variableDefault v) <>
";\n"
sqlVariableDefault Nothing = ""
sqlVariableDefault (Just d) = ":=" <-> d
sqlSecurity (Just True) = "DEFINER"
sqlSecurity _ = "INVOKER"
sqlLanguage Nothing = "plpgsql"
sqlLanguage (Just lang) = lang