orville-postgresql-1.1.0.0: src/Orville/PostgreSQL/Expr/ColumnDefinition.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{- |
Copyright : Flipstone Technology Partners 2023-2025
License : MIT
Stability : Stable
@since 1.0.0.0
-}
module Orville.PostgreSQL.Expr.ColumnDefinition
( ColumnDefinition
, columnDefinition
, ColumnConstraint
, notNullConstraint
, nullConstraint
, ColumnDefault
, columnDefault
, identityColumnConstraint
, ColumnIdentityGeneration
, alwaysColumnIdentityGeneration
, byDefaultColumnIdentityGeneration
)
where
import Orville.PostgreSQL.Expr.DataType (DataType)
import Orville.PostgreSQL.Expr.Name (ColumnName)
import Orville.PostgreSQL.Expr.ValueExpression (ValueExpression)
import qualified Orville.PostgreSQL.Raw.RawSql as RawSql
{- | Represent a complete definition of a column. E.G.
> foo INTEGER
'ColumnDefinition' 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 ColumnDefinition
= ColumnDefinition RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- | Smart constructor for ensuring a 'ColumnDefinition' is set up correctly.
@since 1.0.0.0
-}
columnDefinition ::
-- | The name the resulting column should have.
ColumnName ->
-- | The SQL type of the column.
DataType ->
-- | The constraints on the column, if any.
[ColumnConstraint] ->
-- | The default value for the column, if any.
Maybe ColumnDefault ->
ColumnDefinition
columnDefinition columnName dataType columnConstraints maybeColumnDefault =
let
constraintRawSql =
RawSql.intercalate RawSql.space columnConstraints
in
ColumnDefinition $
RawSql.toRawSql columnName
<> RawSql.space
<> RawSql.toRawSql dataType
<> RawSql.space
<> constraintRawSql
<> case maybeColumnDefault of
Nothing -> mempty
Just colDefault ->
RawSql.space <> RawSql.toRawSql colDefault
{- | Represent constraints, such as nullability, on a column. E.G.
> NOT NULL
'ColumnConstraint' 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 ColumnConstraint
= ColumnConstraint RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- | Express that a column may not contain NULL.
@since 1.0.0.0
-}
notNullConstraint :: ColumnConstraint
notNullConstraint =
ColumnConstraint (RawSql.fromString "NOT NULL")
{- | Express that a column may contain NULL.
@since 1.0.0.0
-}
nullConstraint :: ColumnConstraint
nullConstraint =
ColumnConstraint (RawSql.fromString "NULL")
{- | Represent the generation definition of an identity column. E.G.
> ALWAYS
'ColumnIdentityGeneration' provides a 'RawSql.SqlExpression' instance. See
'RawSql.unsafeSqlExpression' for how to construct a value with your own custom
SQL.
@since 1.1.0.0
-}
newtype ColumnIdentityGeneration
= ColumnIdentityGeneration RawSql.RawSql
deriving
( -- | @since 1.1.0.0
RawSql.SqlExpression
)
{- | Express that a column is an identity column.
@since 1.1.0.0
-}
identityColumnConstraint ::
ColumnIdentityGeneration ->
ColumnConstraint
identityColumnConstraint identityGeneration =
ColumnConstraint $
RawSql.fromString "GENERATED "
<> RawSql.toRawSql identityGeneration
<> RawSql.fromString " AS IDENTITY"
{- | The @ALWAYS@ generation for an identity column
@since 1.1.0.0
-}
alwaysColumnIdentityGeneration :: ColumnIdentityGeneration
alwaysColumnIdentityGeneration = ColumnIdentityGeneration $ RawSql.fromString "ALWAYS"
{- | The @BY DEFAULT@ generation for an identity column
@since 1.1.0.0
-}
byDefaultColumnIdentityGeneration :: ColumnIdentityGeneration
byDefaultColumnIdentityGeneration = ColumnIdentityGeneration $ RawSql.fromString "BY DEFAULT"
{- | Represents the default value of a column. E.G.
> now()
'ColumnDefault' 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 ColumnDefault
= ColumnDefault RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- | Given a 'ValueExpression', use that as a 'ColumnDefault'. This is the preferred path to creating a
column default. Note that it is up to the caller to ensure the 'ValueExpression' makes sense for
the resulting 'ColumnDefinition' this will be a part of.
@since 1.0.0.0
-}
columnDefault ::
ValueExpression ->
ColumnDefault
columnDefault defaultValue =
ColumnDefault (RawSql.fromString "DEFAULT " <> RawSql.toRawSql defaultValue)