orville-postgresql-1.0.0.0: src/Orville/PostgreSQL/Expr/Insert.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{- |
Copyright : Flipstone Technology Partners 2023
License : MIT
Stability : Stable
@since 1.0.0.0
-}
module Orville.PostgreSQL.Expr.Insert
( InsertExpr
, insertExpr
, InsertColumnList
, insertColumnList
, InsertSource
, insertSqlValues
, RowValues
, rowValues
)
where
import Data.Maybe (catMaybes)
import Orville.PostgreSQL.Expr.Name (ColumnName, Qualified, TableName)
import Orville.PostgreSQL.Expr.ReturningExpr (ReturningExpr)
import qualified Orville.PostgreSQL.Raw.RawSql as RawSql
import Orville.PostgreSQL.Raw.SqlValue (SqlValue)
{- |
Type to represent a SQL "INSERT" statement. E.G.
> INSERT INTO foo (id) VALUES (1),(3),(3)
'InsertExpr' provides a 'RawSql.SqlExpression' instance. See
'RawSql.unsafeSqlExpression' for how to construct a value with your own custom
SQL.
@since 1.0.0.0
-}
newtype InsertExpr
= InsertExpr RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- | Create an 'InsertExpr' for the given 'TableName', limited to the specific columns if
given. Callers of this likely want to use a function to create the 'InsertSource' to ensure the
input values are correctly used as parameters. This function does not include that protection
itself.
@since 1.0.0.0
-}
insertExpr ::
Qualified TableName ->
Maybe InsertColumnList ->
InsertSource ->
Maybe ReturningExpr ->
InsertExpr
insertExpr target maybeInsertColumns source maybeReturning =
InsertExpr
. RawSql.intercalate RawSql.space
$ catMaybes
[ Just $ RawSql.fromString "INSERT INTO"
, Just $ RawSql.toRawSql target
, fmap RawSql.toRawSql maybeInsertColumns
, Just $ RawSql.toRawSql source
, fmap RawSql.toRawSql maybeReturning
]
{- |
Type to represent the SQL columns list for an insert statement. E.G.
> (foo,bar,baz)
'InsertColumnList' provides a 'RawSql.SqlExpression' instance. See
'RawSql.unsafeSqlExpression' for how to construct a value with your own custom
SQL.
@since 1.0.0.0
-}
newtype InsertColumnList
= InsertColumnList RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- | Create an 'InsertColumnList' for the given 'ColumnName's, making sure the columns are wrapped in
parens and commas are used to separate.
@since 1.0.0.0
-}
insertColumnList :: [ColumnName] -> InsertColumnList
insertColumnList columnNames =
InsertColumnList $
RawSql.leftParen
<> RawSql.intercalate RawSql.comma (fmap RawSql.toRawSql columnNames)
<> RawSql.rightParen
{- |
Type to represent the SQL for the source of data for an insert statement. E.G.
> VALUES ('Bob',32),('Cindy',33)
'InsertSource' provides a 'RawSql.SqlExpression' instance. See
'RawSql.unsafeSqlExpression' for how to construct a value with your own custom
SQL.
@since 1.0.0.0
-}
newtype InsertSource
= InsertSource RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- | Create an 'InsertSource' for the given 'RowValues'. This ensures that all input values are used
as parameters and comma-separated in the generated SQL.
@since 1.0.0.0
-}
insertRowValues :: [RowValues] -> InsertSource
insertRowValues rows =
InsertSource $
RawSql.fromString "VALUES "
<> RawSql.intercalate RawSql.comma (fmap RawSql.toRawSql rows)
{- | Create an 'InsertSource' for the given 'SqlValue's. This ensures that all input values are used
as parameters and comma-separated in the generated SQL.
@since 1.0.0.0
-}
insertSqlValues :: [[SqlValue]] -> InsertSource
insertSqlValues =
insertRowValues . fmap rowValues
{- |
Type to represent a SQL row literal. For example, a single row to insert
in a @VALUES@ clause. E.G.
> ('Cindy',33)
'RowValues' provides a 'RawSql.SqlExpression' instance. See
'RawSql.unsafeSqlExpression' for how to construct a value with your own custom
SQL.
@since 1.0.0.0
-}
newtype RowValues
= RowValues RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- | Create a 'RowValues' for the given 'SqlValue's. This ensures that all input values are used as
parameters and comma-separated in the generated SQL.
@since 1.0.0.0
-}
rowValues :: [SqlValue] -> RowValues
rowValues values =
RowValues $
mconcat
[ RawSql.leftParen
, RawSql.intercalate RawSql.comma (fmap RawSql.parameter values)
, RawSql.rightParen
]