{- |
Module: Squeal.PostgreSQL.Definition.Constraint
Description: comments
Copyright: (c) Eitan Chatav, 2020
Maintainer: eitan@morphism.tech
Stability: experimental
 
comments
-}

{-# LANGUAGE
    AllowAmbiguousTypes
  , ConstraintKinds
  , DeriveAnyClass
  , DeriveGeneric
  , DerivingStrategies
  , FlexibleContexts
  , FlexibleInstances
  , GADTs
  , LambdaCase
  , MultiParamTypeClasses
  , OverloadedLabels
  , OverloadedStrings
  , RankNTypes
  , ScopedTypeVariables
  , TypeApplications
  , DataKinds
  , PolyKinds
  , TypeOperators
  , UndecidableSuperClasses
  #-}

module Squeal.PostgreSQL.Definition.Comment
  ( commentOnTable
  , commentOnType
  , commentOnView
  , commentOnFunction
  , commentOnIndex
  , commentOnColumn
  , commentOnSchema
  ) where

import Squeal.PostgreSQL.Definition
import Squeal.PostgreSQL.Type.Alias
import Squeal.PostgreSQL.Render
import Squeal.PostgreSQL.Type.Schema
import GHC.TypeLits (KnownSymbol)
import Data.Text (Text)

{-----------------------------------------
COMMENT statements
-----------------------------------------}

{- |
When a user views a table in the database (i.e. with \d+ <table>), it is useful
to be able to read a description of the table.
-}
commentOnTable
  :: ( KnownSymbol sch
     , KnownSymbol tab
     , Has sch db schema
     , Has tab schema ('Table table)
     )
  => QualifiedAlias sch tab -- ^ table
  -> Text -- ^ comment
  -> Definition db db
commentOnTable :: forall (sch :: Symbol) (tab :: Symbol)
       (db :: [(Symbol, [(Symbol, SchemumType)])])
       (schema :: [(Symbol, SchemumType)]) (table :: TableType).
(KnownSymbol sch, KnownSymbol tab, Has sch db schema,
 Has tab schema ('Table table)) =>
QualifiedAlias sch tab -> Text -> Definition db db
commentOnTable QualifiedAlias sch tab
alias Text
comm = forall (db0 :: [(Symbol, [(Symbol, SchemumType)])])
       (db1 :: [(Symbol, [(Symbol, SchemumType)])]).
ByteString -> Definition db0 db1
UnsafeDefinition forall a b. (a -> b) -> a -> b
$
  ByteString
"COMMENT ON TABLE" ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch tab
alias ByteString -> ByteString -> ByteString
<+> ByteString
"IS" ByteString -> ByteString -> ByteString
<+> Text -> ByteString
singleQuotedText Text
comm forall a. Semigroup a => a -> a -> a
<> ByteString
";"

{- |
When a user views a type in the database (i.e with \dT <type>), it is useful to
be able to read a description of the type.
-}
commentOnType
  :: ( KnownSymbol sch
     , KnownSymbol typ
     , Has sch db schema
     , Has typ schema ('Typedef type_)
     )
  => QualifiedAlias sch typ -- ^ type
  -> Text -- ^ comment
  -> Definition db db
commentOnType :: forall (sch :: Symbol) (typ :: Symbol)
       (db :: [(Symbol, [(Symbol, SchemumType)])])
       (schema :: [(Symbol, SchemumType)]) (type_ :: PGType).
(KnownSymbol sch, KnownSymbol typ, Has sch db schema,
 Has typ schema ('Typedef type_)) =>
QualifiedAlias sch typ -> Text -> Definition db db
commentOnType QualifiedAlias sch typ
alias Text
comm = forall (db0 :: [(Symbol, [(Symbol, SchemumType)])])
       (db1 :: [(Symbol, [(Symbol, SchemumType)])]).
ByteString -> Definition db0 db1
UnsafeDefinition forall a b. (a -> b) -> a -> b
$
  ByteString
"COMMENT ON TYPE" ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch typ
alias ByteString -> ByteString -> ByteString
<+> ByteString
"IS" ByteString -> ByteString -> ByteString
<+> Text -> ByteString
singleQuotedText Text
comm forall a. Semigroup a => a -> a -> a
<> ByteString
";"

{- |
When a user views a view in the database (i.e. with \dv <view>), it is useful
to be able to read a description of the view.
-}
commentOnView
  :: ( KnownSymbol sch
     , KnownSymbol vie
     , Has sch db schema
     , Has vie schema ('View view)
     )
  => QualifiedAlias sch vie -- ^ view
  -> Text -- ^ comment
  -> Definition db db
commentOnView :: forall (sch :: Symbol) (vie :: Symbol)
       (db :: [(Symbol, [(Symbol, SchemumType)])])
       (schema :: [(Symbol, SchemumType)]) (view :: RowType).
(KnownSymbol sch, KnownSymbol vie, Has sch db schema,
 Has vie schema ('View view)) =>
QualifiedAlias sch vie -> Text -> Definition db db
commentOnView QualifiedAlias sch vie
alias Text
comm = forall (db0 :: [(Symbol, [(Symbol, SchemumType)])])
       (db1 :: [(Symbol, [(Symbol, SchemumType)])]).
ByteString -> Definition db0 db1
UnsafeDefinition forall a b. (a -> b) -> a -> b
$
  ByteString
"COMMENT ON VIEW" ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch vie
alias ByteString -> ByteString -> ByteString
<+> ByteString
"IS" ByteString -> ByteString -> ByteString
<+> Text -> ByteString
singleQuotedText Text
comm forall a. Semigroup a => a -> a -> a
<> ByteString
";"

{- |
When a user views an index in the database (i.e. with \di+ <index>), it is
useful to be able to read a description of the index.
-}
commentOnIndex
  :: ( KnownSymbol sch
     , KnownSymbol ind
     , Has sch db schema
     , Has ind schema ('Index index)
     )
  => QualifiedAlias sch ind -- ^ index
  -> Text -- ^ comment
  -> Definition db db
commentOnIndex :: forall (sch :: Symbol) (ind :: Symbol)
       (db :: [(Symbol, [(Symbol, SchemumType)])])
       (schema :: [(Symbol, SchemumType)]) (index :: IndexType).
(KnownSymbol sch, KnownSymbol ind, Has sch db schema,
 Has ind schema ('Index index)) =>
QualifiedAlias sch ind -> Text -> Definition db db
commentOnIndex QualifiedAlias sch ind
alias Text
comm = forall (db0 :: [(Symbol, [(Symbol, SchemumType)])])
       (db1 :: [(Symbol, [(Symbol, SchemumType)])]).
ByteString -> Definition db0 db1
UnsafeDefinition forall a b. (a -> b) -> a -> b
$
  ByteString
"COMMENT ON INDEX" ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch ind
alias ByteString -> ByteString -> ByteString
<+> ByteString
"IS" ByteString -> ByteString -> ByteString
<+> Text -> ByteString
singleQuotedText Text
comm forall a. Semigroup a => a -> a -> a
<> ByteString
";"

{- |
When a user views a function in the database (i.e. with \df+ <function>), it is
useful to be able to read a description of the function.
-}
commentOnFunction
  :: ( KnownSymbol sch
     , KnownSymbol fun
     , Has sch db schema
     , Has fun schema ('Function function)
     )
  => QualifiedAlias sch fun -- ^ function
  -> Text -- ^ comment
  -> Definition db db
commentOnFunction :: forall (sch :: Symbol) (fun :: Symbol)
       (db :: [(Symbol, [(Symbol, SchemumType)])])
       (schema :: [(Symbol, SchemumType)]) (function :: FunctionType).
(KnownSymbol sch, KnownSymbol fun, Has sch db schema,
 Has fun schema ('Function function)) =>
QualifiedAlias sch fun -> Text -> Definition db db
commentOnFunction QualifiedAlias sch fun
alias Text
comm = forall (db0 :: [(Symbol, [(Symbol, SchemumType)])])
       (db1 :: [(Symbol, [(Symbol, SchemumType)])]).
ByteString -> Definition db0 db1
UnsafeDefinition forall a b. (a -> b) -> a -> b
$
  ByteString
"COMMENT ON FUNCTION" ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch fun
alias ByteString -> ByteString -> ByteString
<+> ByteString
"IS" ByteString -> ByteString -> ByteString
<+> Text -> ByteString
singleQuotedText Text
comm forall a. Semigroup a => a -> a -> a
<> ByteString
";"

{- |
When a user views a table in the database (i.e. with \d+ <table>), it is useful
to be able to view descriptions of the columns in that table.
-}
commentOnColumn
  :: ( KnownSymbol sch
     , KnownSymbol tab
     , KnownSymbol col
     , Has sch db schema
     , Has tab schema ('Table '(cons, cols))
     , Has col cols '(def, nulltyp)
     )
  => QualifiedAlias sch tab -- ^ table
  -> Alias col -- ^ column
  -> Text -- ^ comment
  -> Definition db db
commentOnColumn :: forall (sch :: Symbol) (tab :: Symbol) (col :: Symbol)
       (db :: [(Symbol, [(Symbol, SchemumType)])])
       (schema :: [(Symbol, SchemumType)]) (cons :: TableConstraints)
       (cols :: ColumnsType) (def :: Optionality) (nulltyp :: NullType).
(KnownSymbol sch, KnownSymbol tab, KnownSymbol col,
 Has sch db schema, Has tab schema ('Table '(cons, cols)),
 Has col cols '(def, nulltyp)) =>
QualifiedAlias sch tab -> Alias col -> Text -> Definition db db
commentOnColumn QualifiedAlias sch tab
table Alias col
col Text
comm = forall (db0 :: [(Symbol, [(Symbol, SchemumType)])])
       (db1 :: [(Symbol, [(Symbol, SchemumType)])]).
ByteString -> Definition db0 db1
UnsafeDefinition forall a b. (a -> b) -> a -> b
$
  ByteString
"COMMENT ON COLUMN" ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL QualifiedAlias sch tab
table forall a. Semigroup a => a -> a -> a
<> ByteString
"." forall a. Semigroup a => a -> a -> a
<> forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias col
col ByteString -> ByteString -> ByteString
<+> ByteString
"IS"
  ByteString -> ByteString -> ByteString
<+> Text -> ByteString
singleQuotedText Text
comm forall a. Semigroup a => a -> a -> a
<> ByteString
";"

{- |
When a user views a schema in the database (i.e. with \dn+ <schema>), it is
useful to be able to read a description.
-}
commentOnSchema
  :: ( KnownSymbol sch
     , Has sch db schema
     )
  => Alias sch -- ^ schema
  -> Text -- ^ comment
  -> Definition db db
commentOnSchema :: forall (sch :: Symbol) (db :: [(Symbol, [(Symbol, SchemumType)])])
       (schema :: [(Symbol, SchemumType)]).
(KnownSymbol sch, Has sch db schema) =>
Alias sch -> Text -> Definition db db
commentOnSchema Alias sch
schema Text
comm = forall (db0 :: [(Symbol, [(Symbol, SchemumType)])])
       (db1 :: [(Symbol, [(Symbol, SchemumType)])]).
ByteString -> Definition db0 db1
UnsafeDefinition forall a b. (a -> b) -> a -> b
$
  ByteString
"COMMENT ON SCHEMA" ByteString -> ByteString -> ByteString
<+> forall sql. RenderSQL sql => sql -> ByteString
renderSQL Alias sch
schema forall a. Semigroup a => a -> a -> a
<> ByteString
"IS" ByteString -> ByteString -> ByteString
<+> Text -> ByteString
singleQuotedText Text
comm forall a. Semigroup a => a -> a -> a
<> ByteString
";"