orville-postgresql-1.0.0.0: src/Orville/PostgreSQL/Expr/Index.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{- |
Copyright : Flipstone Technology Partners 2023
License : MIT
Stability : Stable
@since 1.0.0.0
-}
module Orville.PostgreSQL.Expr.Index
( CreateIndexExpr
, createIndexExpr
, IndexUniqueness (UniqueIndex, NonUniqueIndex)
, IndexBodyExpr
, indexBodyColumns
, ConcurrentlyExpr
, concurrently
, DropIndexExpr
, dropIndexExpr
, createNamedIndexExpr
)
where
import Data.List.NonEmpty (NonEmpty)
import Orville.PostgreSQL.Expr.Name (ColumnName, IndexName, Qualified, TableName)
import qualified Orville.PostgreSQL.Raw.RawSql as RawSql
{- |
Type to represent a SQL "CREATE INDEX" statement. E.G.
> CREATE INDEX ON table (foo, bar, baz)
'CreateIndexExpr' 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 CreateIndexExpr
= CreateIndexExpr RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- |
Construct a SQL CREATE INDEX from an indicator of if the index should be
unique, a table, and corresponding collection of 'ColumnName's.
@since 1.0.0.0
-}
createIndexExpr ::
IndexUniqueness ->
Maybe ConcurrentlyExpr ->
Qualified TableName ->
NonEmpty ColumnName ->
CreateIndexExpr
createIndexExpr uniqueness mbConcurrently tableName columns =
CreateIndexExpr $
RawSql.fromString "CREATE "
<> uniquenessToSql uniqueness
<> RawSql.fromString "INDEX "
<> maybe mempty (<> RawSql.space) (fmap RawSql.toRawSql mbConcurrently)
<> RawSql.fromString "ON "
<> RawSql.toRawSql tableName
<> RawSql.space
<> RawSql.toRawSql (indexBodyColumns columns)
{- |
Construct a SQL CREATE INDEX from an indicator of if the index should be
unique, a table, a name for the index, and some SQL representing the rest of
the index creation.
@since 1.0.0.0
-}
createNamedIndexExpr ::
IndexUniqueness ->
Maybe ConcurrentlyExpr ->
Qualified TableName ->
IndexName ->
IndexBodyExpr ->
CreateIndexExpr
createNamedIndexExpr uniqueness mbConcurrently tableName indexName bodyExpr =
CreateIndexExpr $
RawSql.fromString "CREATE "
<> uniquenessToSql uniqueness
<> RawSql.fromString "INDEX "
<> maybe mempty (<> RawSql.space) (fmap RawSql.toRawSql mbConcurrently)
<> RawSql.toRawSql indexName
<> RawSql.fromString " ON "
<> RawSql.toRawSql tableName
<> RawSql.space
<> RawSql.toRawSql bodyExpr
{- |
Type to represent the @CONCURRENTLY@ keyword for index creation. E.G.
> CONCURRENTLY
'ConcurrentlyExpr' 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 ConcurrentlyExpr
= ConcurrentlyExpr RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- |
The @CONCURRENTLY@ keyword indicates to PostgreSQL that an index should be
created concurrently.
@since 1.0.0.0
-}
concurrently :: ConcurrentlyExpr
concurrently =
RawSql.unsafeSqlExpression "CONCURRENTLY"
{- |
Type to represent the body of an index definition E.G.
> (foo, bar)
in
> CREATE some_index ON some_table (foo, bar)
'IndexBodyExpr' 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 IndexBodyExpr
= IndexBodyExpr RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- |
Creates an 'IndexBodyExpr' for the given column names. The resulting
SQL looks like @(column1, column2, ...)@.
@since 1.0.0.0
-}
indexBodyColumns ::
NonEmpty ColumnName ->
IndexBodyExpr
indexBodyColumns columns =
IndexBodyExpr $
RawSql.leftParen
<> RawSql.intercalate RawSql.comma columns
<> RawSql.rightParen
{- |
Type to represent if an index should be unique.
@since 1.0.0.0
-}
data IndexUniqueness
= UniqueIndex
| NonUniqueIndex
deriving
( -- | @since 1.0.0.0
Eq
, -- | @since 1.0.0.0
Ord
, -- | @since 1.0.0.0
Show
)
-- Internal helper
uniquenessToSql :: IndexUniqueness -> RawSql.RawSql
uniquenessToSql uniqueness =
case uniqueness of
UniqueIndex -> RawSql.fromString "UNIQUE "
NonUniqueIndex -> mempty
{- |
Type to represent a SQL "DROP INDEX" statement. E.G.
> DROP INDEX foo
'DropIndexExpr' 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 DropIndexExpr
= DropIndexExpr RawSql.RawSql
deriving
( -- | @since 1.0.0.0
RawSql.SqlExpression
)
{- |
Construct a SQL DROP INDEX for a given 'IndexName'.
@since 1.0.0.0
-}
dropIndexExpr :: IndexName -> DropIndexExpr
dropIndexExpr indexName =
DropIndexExpr $
RawSql.fromString "DROP INDEX " <> RawSql.toRawSql indexName