orville-postgresql-1.0.0.0: src/Orville/PostgreSQL/PgCatalog/PgClass.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{- |
Copyright : Flipstone Technology Partners 2023
License : MIT
Stability : Stable
@since 1.0.0.0
-}
module Orville.PostgreSQL.PgCatalog.PgClass
( PgClass (..)
, RelationName
, relationNameToString
, RelationKind (..)
, pgClassTable
, relationNameField
, namespaceOidField
, relationKindField
)
where
import qualified Data.String as String
import qualified Data.Text as T
import qualified Database.PostgreSQL.LibPQ as LibPQ
import qualified Orville.PostgreSQL as Orville
import Orville.PostgreSQL.PgCatalog.OidField (oidField, oidTypeField)
{- |
The Haskell representation of data read from the @pg_catalog.pg_class@
table. Rows in this table correspond to tables, indexes, sequences, views,
materialized views, composite types and TOAST tables.
@since 1.0.0.0
-}
data PgClass = PgClass
{ pgClassOid :: LibPQ.Oid
-- ^ The PostgreSQL @oid@ for the relation.
, pgClassNamespaceOid :: LibPQ.Oid
-- ^ The PostgreSQL @oid@ of the namespace that the relation belongs to.
-- References @pg_namespace.oid@.
, pgClassRelationName :: RelationName
-- ^ The name of the relation.
, pgClassRelationKind :: RelationKind
-- ^ The kind of relation (table, view, etc).
}
{- |
A Haskell type for the name of the relation represented by a 'PgClass'.
@since 1.0.0.0
-}
newtype RelationName
= RelationName T.Text
deriving (Show, Eq, Ord, String.IsString)
{- |
Convert a 'RelationName' to a plain 'String'.
@since 1.0.0.0
-}
relationNameToString :: RelationName -> String
relationNameToString (RelationName text) =
T.unpack text
{- |
The kind of relation represented by a 'PgClass', as described at
https://www.postgresql.org/docs/13/catalog-pg-class.html.
@since 1.0.0.0
-}
data RelationKind
= OrdinaryTable
| Index
| Sequence
| ToastTable
| View
| MaterializedView
| CompositeType
| ForeignTable
| PartitionedTable
| PartitionedIndex
deriving (Show, Eq)
{- |
An Orville 'Orville.TableDefinition' for querying the
@pg_catalog.pg_class@ table.
@since 1.0.0.0
-}
pgClassTable :: Orville.TableDefinition (Orville.HasKey LibPQ.Oid) PgClass PgClass
pgClassTable =
Orville.setTableSchema "pg_catalog" $
Orville.mkTableDefinition
"pg_class"
(Orville.primaryKey oidField)
pgClassMarshaller
pgClassMarshaller :: Orville.SqlMarshaller PgClass PgClass
pgClassMarshaller =
PgClass
<$> Orville.marshallField pgClassOid oidField
<*> Orville.marshallField pgClassNamespaceOid namespaceOidField
<*> Orville.marshallField pgClassRelationName relationNameField
<*> Orville.marshallField pgClassRelationKind relationKindField
{- |
The @relnamespace@ column of the @pg_catalog.pg_class@ table.
@since 1.0.0.0
-}
namespaceOidField :: Orville.FieldDefinition Orville.NotNull LibPQ.Oid
namespaceOidField =
oidTypeField "relnamespace"
{- |
The @relname@ column of the @pg_catalog.pg_class@ table.
@since 1.0.0.0
-}
relationNameField :: Orville.FieldDefinition Orville.NotNull RelationName
relationNameField =
Orville.coerceField $
Orville.unboundedTextField "relname"
{- |
The @relkind@ column of the @pg_catalog.pg_class@ table.
@since 1.0.0.0
-}
relationKindField :: Orville.FieldDefinition Orville.NotNull RelationKind
relationKindField =
Orville.convertField
(Orville.tryConvertSqlType relationKindToPgText pgTextToRelationKind)
(Orville.unboundedTextField "relkind")
{- |
Converts a 'RelationKind' to the corresponding single character text
representation used by PostgreSQL.
See also 'pgTextToRelationKind'
@since 1.0.0.0
-}
relationKindToPgText :: RelationKind -> T.Text
relationKindToPgText kind =
T.pack $
case kind of
OrdinaryTable -> "r"
Index -> "i"
Sequence -> "S"
ToastTable -> "t"
View -> "v"
MaterializedView -> "m"
CompositeType -> "c"
ForeignTable -> "f"
PartitionedTable -> "p"
PartitionedIndex -> "I"
{- |
Attempts to parse a PostgreSQL single character textual value as a
'RelationKind'.
See also 'relationKindToPgText'
@since 1.0.0.0
-}
pgTextToRelationKind :: T.Text -> Either String RelationKind
pgTextToRelationKind text =
case T.unpack text of
"r" -> Right OrdinaryTable
"i" -> Right Index
"S" -> Right Sequence
"t" -> Right ToastTable
"v" -> Right View
"m" -> Right MaterializedView
"c" -> Right CompositeType
"f" -> Right ForeignTable
"p" -> Right PartitionedTable
"I" -> Right PartitionedIndex
kind -> Left ("Unrecognized PostgreSQL relation kind: " <> kind)