{-# LANGUAGE
AllowAmbiguousTypes
, ConstraintKinds
, DeriveAnyClass
, DeriveGeneric
, DerivingStrategies
, FlexibleContexts
, FlexibleInstances
, GADTs
, LambdaCase
, MultiParamTypeClasses
, OverloadedLabels
, OverloadedStrings
, RankNTypes
, ScopedTypeVariables
, TypeApplications
, TypeInType
, TypeOperators
, UndecidableSuperClasses
#-}
module Squeal.PostgreSQL.Definition.Index
(
createIndex
, createIndexIfNotExists
, dropIndex
, dropIndexIfExists
, IndexMethod (..)
, btree
, hash
, gist
, spgist
, gin
, brin
) where
import Data.ByteString
import GHC.TypeLits
import qualified GHC.Generics as GHC
import Squeal.PostgreSQL.Type.Alias
import Squeal.PostgreSQL.Definition
import Squeal.PostgreSQL.Expression.Sort
import Squeal.PostgreSQL.Render
import Squeal.PostgreSQL.Type.Schema
createIndex
:: (Has sch db schema, Has tab schema ('Table table), KnownSymbol ix)
=> Alias ix
-> QualifiedAlias sch tab
-> IndexMethod method
-> [SortExpression 'Ungrouped '[] '[] db '[] '[tab ::: TableToRow table]]
-> Definition db (Alter sch (Create ix ('Index method) schema) db)
createIndex ix tab method cols = UnsafeDefinition $
"CREATE" <+> "INDEX" <+> renderSQL ix <+> "ON" <+> renderSQL tab
<+> "USING" <+> renderSQL method
<+> parenthesized (commaSeparated (renderIndex <$> cols))
<> ";"
where
renderIndex = \case
Asc expression -> parenthesized (renderSQL expression) <+> "ASC"
Desc expression -> parenthesized (renderSQL expression) <+> "DESC"
AscNullsFirst expression -> parenthesized (renderSQL expression)
<+> "ASC NULLS FIRST"
DescNullsFirst expression -> parenthesized (renderSQL expression)
<+> "DESC NULLS FIRST"
AscNullsLast expression -> parenthesized (renderSQL expression)
<+> "ASC NULLS LAST"
DescNullsLast expression -> parenthesized (renderSQL expression)
<+> "DESC NULLS LAST"
createIndexIfNotExists
:: (Has sch db schema, Has tab schema ('Table table), KnownSymbol ix)
=> Alias ix
-> QualifiedAlias sch tab
-> IndexMethod method
-> [SortExpression 'Ungrouped '[] '[] db '[] '[tab ::: TableToRow table]]
-> Definition db (Alter sch (CreateIfNotExists ix ('Index method) schema) db)
createIndexIfNotExists ix tab method cols = UnsafeDefinition $
"CREATE INDEX IF NOT EXISTS" <+> renderSQL ix <+> "ON" <+> renderSQL tab
<+> "USING" <+> renderSQL method
<+> parenthesized (commaSeparated (renderIndex <$> cols))
<> ";"
where
renderIndex = \case
Asc expression -> parenthesized (renderSQL expression) <+> "ASC"
Desc expression -> parenthesized (renderSQL expression) <+> "DESC"
AscNullsFirst expression -> parenthesized (renderSQL expression)
<+> "ASC NULLS FIRST"
DescNullsFirst expression -> parenthesized (renderSQL expression)
<+> "DESC NULLS FIRST"
AscNullsLast expression -> parenthesized (renderSQL expression)
<+> "ASC NULLS LAST"
DescNullsLast expression -> parenthesized (renderSQL expression)
<+> "DESC NULLS LAST"
newtype IndexMethod ty = UnsafeIndexMethod {renderIndexMethod :: ByteString}
deriving stock (Eq, Ord, Show, GHC.Generic)
instance RenderSQL (IndexMethod ty) where renderSQL = renderIndexMethod
btree :: IndexMethod 'Btree
btree = UnsafeIndexMethod "btree"
hash :: IndexMethod 'Hash
hash = UnsafeIndexMethod "hash"
gist :: IndexMethod 'Gist
gist = UnsafeIndexMethod "gist"
spgist :: IndexMethod 'Spgist
spgist = UnsafeIndexMethod "spgist"
gin :: IndexMethod 'Gin
gin = UnsafeIndexMethod "gin"
brin :: IndexMethod 'Brin
brin = UnsafeIndexMethod "brin"
dropIndex
:: (Has sch db schema, KnownSymbol ix)
=> QualifiedAlias sch ix
-> Definition db (Alter sch (DropSchemum ix 'Index schema) db)
dropIndex ix = UnsafeDefinition $ "DROP INDEX" <+> renderSQL ix <> ";"
dropIndexIfExists
:: (Has sch db schema, KnownSymbol ix)
=> QualifiedAlias sch ix
-> Definition db (Alter sch (DropSchemumIfExists ix 'Index schema) db)
dropIndexIfExists ix = UnsafeDefinition $
"DROP INDEX IF EXISTS" <+> renderSQL ix <> ";"