orville-postgresql-1.1.0.0: src/Orville/PostgreSQL/Schema/SequenceDefinition.hs
{- |
Copyright : Flipstone Technology Partners 2023
License : MIT
Stability : Stable
@since 1.0.0.0
-}
module Orville.PostgreSQL.Schema.SequenceDefinition
( SequenceDefinition
, mkSequenceDefinition
, setSequenceSchema
, sequenceIdentifier
, sequenceName
, sequenceIncrement
, setSequenceIncrement
, sequenceMinValue
, setSequenceMinValue
, sequenceMaxValue
, setSequenceMaxValue
, sequenceStart
, setSequenceStart
, sequenceCache
, setSequenceCache
, sequenceCycle
, setSequenceCycle
, mkCreateSequenceExpr
)
where
import Data.Int (Int64)
import qualified Orville.PostgreSQL.Expr as Expr
import Orville.PostgreSQL.Schema.SequenceIdentifier (SequenceIdentifier, sequenceIdQualifiedName, setSequenceIdSchema, unqualifiedNameToSequenceId)
{- | Contains the definition of a SQL sequence for Orville to use when creating
the sequence and fetching values from it. You can create a
'SequenceDefinition' with default values via 'mkSequenceDefinition' and then
use the various set functions that are provided if you need to set specific
attributes on the sequence.
@since 1.0.0.0
-}
data SequenceDefinition = SequenceDefinition
{ i_sequenceIdentifier :: SequenceIdentifier
, i_sequenceIncrement :: Int64
, i_sequenceMinValue :: Maybe Int64
, i_sequenceMaxValue :: Maybe Int64
, i_sequenceStart :: Maybe Int64
, i_sequenceCache :: Int64
, i_sequenceCycle :: Bool
}
deriving
( -- | @since 1.0.0.0
Eq
, -- | @since 1.0.0.0
Show
)
{- | Constructs an ascending 'SequenceDefinition' with increment 1 and cache
1 that does not cycle. The sequence will start at 1 and count to the
largest 'Int64' value.
@since 1.0.0.0
-}
mkSequenceDefinition :: String -> SequenceDefinition
mkSequenceDefinition name =
SequenceDefinition
{ i_sequenceIdentifier = unqualifiedNameToSequenceId name
, i_sequenceIncrement = 1
, i_sequenceMinValue = Nothing
, i_sequenceMaxValue = Nothing
, i_sequenceStart = Nothing
, i_sequenceCache = 1
, i_sequenceCycle = False
}
{- | Sets the sequence's schema to the name in the given 'String', which will be
treated as a SQL identifier. If a sequence has a schema name set, it will be
included as a qualifier on the sequence name for all queries involving the
sequence.
@since 1.0.0.0
-}
setSequenceSchema ::
String ->
SequenceDefinition ->
SequenceDefinition
setSequenceSchema schemaName sequenceDef =
sequenceDef
{ i_sequenceIdentifier = setSequenceIdSchema schemaName (i_sequenceIdentifier sequenceDef)
}
{- | Retrieves the 'SequenceIdentifier' for this sequence, which is set by the
name provided to 'mkSequenceDefinition' and any calls made to
'setSequenceSchema' thereafter.
@since 1.0.0.0
-}
sequenceIdentifier :: SequenceDefinition -> SequenceIdentifier
sequenceIdentifier = i_sequenceIdentifier
{- | Retrieves the 'Expr.Qualified' 'Expr.SequenceName' for the sequence that
should be used to build SQL expressions involving it.
@since 1.0.0.0
-}
sequenceName :: SequenceDefinition -> Expr.QualifiedOrUnqualified Expr.SequenceName
sequenceName =
sequenceIdQualifiedName . i_sequenceIdentifier
{- | Retrieves the increment value for the sequence.
@since 1.0.0.0
-}
sequenceIncrement :: SequenceDefinition -> Int64
sequenceIncrement = i_sequenceIncrement
{- | Sets the increment value for the sequence. The increment cannot be set to
@0@ (PostgreSQL will raise an error when trying to create or modify the
sequence in this case).
If the increment is negative, the sequence will be descending. When no
explicit start is set, a descending sequence begins at the max value.
@since 1.0.0.0
-}
setSequenceIncrement :: Int64 -> SequenceDefinition -> SequenceDefinition
setSequenceIncrement n sequenceDef =
sequenceDef {i_sequenceIncrement = n}
{- | Retrieves the min value of the sequence. If no explicit minimum has been set,
this returns @1@ for ascending sequences and 'minBound' for 'Int64' for
descending sequences.
@since 1.0.0.0
-}
sequenceMinValue :: SequenceDefinition -> Int64
sequenceMinValue sequenceDef =
case i_sequenceMinValue sequenceDef of
Just minValue -> minValue
Nothing ->
if sequenceIncrement sequenceDef >= 0
then 1
else minBound
{- | Sets the min value for the sequence.
@since 1.0.0.0
-}
setSequenceMinValue :: Int64 -> SequenceDefinition -> SequenceDefinition
setSequenceMinValue n sequenceDef =
sequenceDef {i_sequenceMinValue = Just n}
{- | Retrieves the max value of the sequence. If no explicit maximum has been set,
this returns 'maxBound' for 'Int64' for ascending sequences and @-1@ for
descending sequences.
@since 1.0.0.0
-}
sequenceMaxValue :: SequenceDefinition -> Int64
sequenceMaxValue sequenceDef =
case i_sequenceMaxValue sequenceDef of
Just maxValue -> maxValue
Nothing ->
if sequenceIncrement sequenceDef >= 0
then maxBound
else -1
{- | Sets the max value for the sequence.
@since 1.0.0.0
-}
setSequenceMaxValue :: Int64 -> SequenceDefinition -> SequenceDefinition
setSequenceMaxValue n sequenceDef =
sequenceDef {i_sequenceMaxValue = Just n}
{- | Retrieves the start value for the sequence. If no explicit start value has
been set, this returns 'sequenceMinValue' for ascending sequences and
'sequenceMaxValue' for descending sequences.
@since 1.0.0.0
-}
sequenceStart :: SequenceDefinition -> Int64
sequenceStart sequenceDef =
case i_sequenceStart sequenceDef of
Just start -> start
Nothing ->
if sequenceIncrement sequenceDef >= 0
then sequenceMinValue sequenceDef
else sequenceMaxValue sequenceDef
{- | Sets the sequence start value. The start value must be at least the
minimum value and no greater than the maximum value.
@since 1.0.0.0
-}
setSequenceStart :: Int64 -> SequenceDefinition -> SequenceDefinition
setSequenceStart n sequenceDef =
sequenceDef {i_sequenceStart = Just n}
{- | Retrieves the number of sequence values that will be pre-allocated by
PostgreSQL.
@since 1.0.0.0
-}
sequenceCache :: SequenceDefinition -> Int64
sequenceCache = i_sequenceCache
{- | Sets the number of sequence values that will be pre-allocated by PostgreSQL.
@since 1.0.0.0
-}
setSequenceCache :: Int64 -> SequenceDefinition -> SequenceDefinition
setSequenceCache n sequenceDef =
sequenceDef {i_sequenceCache = n}
{- | Indicates whether the sequence will wrap around when it reaches the maximum
value (for ascending sequences) or minimum value (for descending sequences).
When 'False', any attempts to get the next value of the sequence while at the
limit will result in an error.
@since 1.0.0.0
-}
sequenceCycle :: SequenceDefinition -> Bool
sequenceCycle = i_sequenceCycle
{- | Sets the 'sequenceCycle' value for the sequence. 'True' indicates that the
sequence will cycle. 'False' will cause an error to be raised if the next
sequence value is requested while already at the limit.
@since 1.0.0.0
-}
setSequenceCycle :: Bool -> SequenceDefinition -> SequenceDefinition
setSequenceCycle b sequenceDef =
sequenceDef {i_sequenceCycle = b}
{- | Builds a 'Expr.CreateSequenceExpr' that will create a SQL sequence matching
the given 'SequenceDefinition' when it is executed.
@since 1.0.0.0
-}
mkCreateSequenceExpr :: SequenceDefinition -> Expr.CreateSequenceExpr
mkCreateSequenceExpr sequenceDef =
Expr.createSequenceExpr
(sequenceName sequenceDef)
(Just . Expr.incrementBy . sequenceIncrement $ sequenceDef)
(Just . Expr.minValue . sequenceMinValue $ sequenceDef)
(Just . Expr.maxValue . sequenceMaxValue $ sequenceDef)
(Just . Expr.startWith . sequenceStart $ sequenceDef)
(Just . Expr.cache . sequenceCache $ sequenceDef)
(Just . Expr.cycleIfTrue . sequenceCycle $ sequenceDef)