orville-postgresql-1.1.0.0: src/Orville/PostgreSQL/Expr/TableConstraint.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{- |
Copyright : Flipstone Technology Partners 2023
License : MIT
Stability : Stable
@since 1.0.0.0
-}
module Orville.PostgreSQL.Expr.TableConstraint
( TableConstraint
, uniqueConstraint
, foreignKeyConstraint
, ForeignKeyActionExpr
, restrictExpr
, cascadeExpr
, setNullExpr
, setDefaultExpr
, ForeignKeyDeleteActionExpr
, foreignKeyDeleteActionExpr
, ForeignKeyUpdateActionExpr
, foreignKeyUpdateActionExpr
)
where
import Data.List.NonEmpty (NonEmpty)
import Orville.PostgreSQL.Expr.Name (ColumnName, QualifiedOrUnqualified, TableName)
import qualified Orville.PostgreSQL.Raw.RawSql as RawSql
{- | Type to represent a table constraint that would be part of a @CREATE TABLE@ or
@ALTER TABLE@ statement. For instance, the @UNIQUE@ constraint in
> CREATE TABLE FOO
> ( id integer
> , UNIQUE id
> )
>
'TableConstraint' 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 TableConstraint
= TableConstraint RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- | Constructs a 'TableConstraint' will create a @UNIQUE@ constraint on the
given columns.
@since 1.0.0.0
-}
uniqueConstraint :: NonEmpty ColumnName -> TableConstraint
uniqueConstraint columnNames =
TableConstraint $
RawSql.fromString "UNIQUE "
<> RawSql.leftParen
<> RawSql.intercalate RawSql.comma columnNames
<> RawSql.rightParen
{- | Type to represent a foreign key action on a @FOREIGN KEY@ constraint. E.G.
the @CASCADE@ in
> FOREIGN KEY (foo_id) REFERENCES foo (id) ON DELETE CASCADE
'ForeignKeyActionExpr' 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 ForeignKeyActionExpr
= ForeignKeyActionExpr RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- | The foreign key action @RESTRICT@.
@since 1.0.0.0
-}
restrictExpr :: ForeignKeyActionExpr
restrictExpr = ForeignKeyActionExpr $ RawSql.fromString "RESTRICT"
{- | The foreign key action @CASCADE@.
@since 1.0.0.0
-}
cascadeExpr :: ForeignKeyActionExpr
cascadeExpr = ForeignKeyActionExpr $ RawSql.fromString "CASCADE"
{- | The foreign key action @SET NULL@.
@since 1.0.0.0
-}
setNullExpr :: ForeignKeyActionExpr
setNullExpr = ForeignKeyActionExpr $ RawSql.fromString "SET NULL"
{- | The foreign key action @SET DEFAULT@.
@since 1.0.0.0
-}
setDefaultExpr :: ForeignKeyActionExpr
setDefaultExpr = ForeignKeyActionExpr $ RawSql.fromString "SET DEFAULT"
{- | Type to represent a foreign key update action on a @FOREIGN KEY@ constraint. E.G.
the @ON UPDATE RESTRICT@ in
> FOREIGN KEY (foo_id) REFERENCES foo (id) ON UPDATE RESTRICT
'ForeignKeyUpdateActionExpr' 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 ForeignKeyUpdateActionExpr
= ForeignKeyUpdateActionExpr RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- | Constructs a 'ForeignKeyActionExpr' that uses the given 'ForeignKeyActionExpr'
in an @ON UPDATE@ clause for a foreign key.
@since 1.0.0.0
-}
foreignKeyUpdateActionExpr :: ForeignKeyActionExpr -> ForeignKeyUpdateActionExpr
foreignKeyUpdateActionExpr action =
ForeignKeyUpdateActionExpr $
RawSql.fromString "ON UPDATE"
<> RawSql.space
<> RawSql.toRawSql action
{- | Type to represent a foreign key update action on a @FOREIGN KEY@ constraint. E.G.
the @ON DELETE RESTRICT@ in
> FOREIGN KEY (foo_id) REFERENCES foo (id) ON DELETE RESTRICT
'ForeignKeyDeleteActionExpr' 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 ForeignKeyDeleteActionExpr
= ForeignKeyDeleteActionExpr RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- | Constructs a 'ForeignKeyActionExpr' that uses the given 'ForeignKeyActionExpr'
in an @ON UPDATE@ clause for a foreign key.
@since 1.0.0.0
-}
foreignKeyDeleteActionExpr :: ForeignKeyActionExpr -> ForeignKeyDeleteActionExpr
foreignKeyDeleteActionExpr action =
ForeignKeyDeleteActionExpr $
RawSql.fromString "ON DELETE"
<> RawSql.space
<> RawSql.toRawSql action
{- | Constructs a 'TableConstraint' that represent a @FOREIGN KEY@ constraint
@since 1.0.0.0
-}
foreignKeyConstraint ::
-- | The names of the columns in the source table that form the foreign key.
NonEmpty ColumnName ->
-- | The name of the table that the foreign key references.
QualifiedOrUnqualified TableName ->
-- | The names of the columns in the foreign table that the foreign key references.
NonEmpty ColumnName ->
-- | An optional @ON UPDATE@ foreign key action to perform.
Maybe ForeignKeyUpdateActionExpr ->
-- | An optional @ON DELETE@ foreign key action to perform.
Maybe ForeignKeyDeleteActionExpr ->
TableConstraint
foreignKeyConstraint columnNames foreignTableName foreignColumnNames mbUpdateAction mbDeleteAction =
TableConstraint $
RawSql.fromString "FOREIGN KEY "
<> RawSql.leftParen
<> RawSql.intercalate RawSql.comma columnNames
<> RawSql.rightParen
<> RawSql.fromString " REFERENCES "
<> RawSql.toRawSql foreignTableName
<> RawSql.space
<> RawSql.leftParen
<> RawSql.intercalate RawSql.comma foreignColumnNames
<> RawSql.rightParen
<> maybe mempty (\updateAction -> RawSql.space <> RawSql.toRawSql updateAction) mbUpdateAction
<> maybe mempty (\deleteAction -> RawSql.space <> RawSql.toRawSql deleteAction) mbDeleteAction