{-# language DerivingStrategies #-}
{-# language DuplicateRecordFields #-}
{-# language RecordWildCards #-}
{-# language StandaloneKindSignatures #-}
{-# language StrictData #-}

module Rel8.Schema.QualifiedName
  ( QualifiedName (..)
  , ppQualifiedName
  , showQualifiedName
  )
where

-- base
import Data.Kind (Type)
import Data.String (IsString, fromString)
import Prelude

-- pretty
import Text.PrettyPrint (Doc, text)

-- rel8
import Rel8.Schema.Escape (escape)


-- | A name of an object (such as a table, view, function or sequence)
-- qualified by an optional schema. In the absence of an explicit schema,
-- the connection's @search_path@ will be used implicitly.
type QualifiedName :: Type
data QualifiedName = QualifiedName
  { QualifiedName -> String
name :: String
    -- ^ The name of the object.
  , QualifiedName -> Maybe String
schema :: Maybe String
    -- ^ The schema that this object belongs to. If 'Nothing', whatever is on
    -- the connection's @search_path@ will be used.
   }
  deriving stock (QualifiedName -> QualifiedName -> Bool
(QualifiedName -> QualifiedName -> Bool)
-> (QualifiedName -> QualifiedName -> Bool) -> Eq QualifiedName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: QualifiedName -> QualifiedName -> Bool
== :: QualifiedName -> QualifiedName -> Bool
$c/= :: QualifiedName -> QualifiedName -> Bool
/= :: QualifiedName -> QualifiedName -> Bool
Eq, Eq QualifiedName
Eq QualifiedName =>
(QualifiedName -> QualifiedName -> Ordering)
-> (QualifiedName -> QualifiedName -> Bool)
-> (QualifiedName -> QualifiedName -> Bool)
-> (QualifiedName -> QualifiedName -> Bool)
-> (QualifiedName -> QualifiedName -> Bool)
-> (QualifiedName -> QualifiedName -> QualifiedName)
-> (QualifiedName -> QualifiedName -> QualifiedName)
-> Ord QualifiedName
QualifiedName -> QualifiedName -> Bool
QualifiedName -> QualifiedName -> Ordering
QualifiedName -> QualifiedName -> QualifiedName
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: QualifiedName -> QualifiedName -> Ordering
compare :: QualifiedName -> QualifiedName -> Ordering
$c< :: QualifiedName -> QualifiedName -> Bool
< :: QualifiedName -> QualifiedName -> Bool
$c<= :: QualifiedName -> QualifiedName -> Bool
<= :: QualifiedName -> QualifiedName -> Bool
$c> :: QualifiedName -> QualifiedName -> Bool
> :: QualifiedName -> QualifiedName -> Bool
$c>= :: QualifiedName -> QualifiedName -> Bool
>= :: QualifiedName -> QualifiedName -> Bool
$cmax :: QualifiedName -> QualifiedName -> QualifiedName
max :: QualifiedName -> QualifiedName -> QualifiedName
$cmin :: QualifiedName -> QualifiedName -> QualifiedName
min :: QualifiedName -> QualifiedName -> QualifiedName
Ord, Int -> QualifiedName -> ShowS
[QualifiedName] -> ShowS
QualifiedName -> String
(Int -> QualifiedName -> ShowS)
-> (QualifiedName -> String)
-> ([QualifiedName] -> ShowS)
-> Show QualifiedName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> QualifiedName -> ShowS
showsPrec :: Int -> QualifiedName -> ShowS
$cshow :: QualifiedName -> String
show :: QualifiedName -> String
$cshowList :: [QualifiedName] -> ShowS
showList :: [QualifiedName] -> ShowS
Show)


-- | Constructs 'QualifiedName's with 'schema' set to 'Nothing'.
instance IsString QualifiedName where
  fromString :: String -> QualifiedName
fromString String
name = QualifiedName {$sel:schema:QualifiedName :: Maybe String
schema = Maybe String
forall a. Maybe a
Nothing, String
$sel:name:QualifiedName :: String
name :: String
..}


ppQualifiedName :: QualifiedName -> Doc
ppQualifiedName :: QualifiedName -> Doc
ppQualifiedName QualifiedName {$sel:schema:QualifiedName :: QualifiedName -> Maybe String
schema = Maybe String
mschema, String
$sel:name:QualifiedName :: QualifiedName -> String
name :: String
..} = case Maybe String
mschema of
  Maybe String
Nothing -> Doc
name'
  Just String
schema -> String -> Doc
escape String
schema Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<> String -> Doc
text String
"." Doc -> Doc -> Doc
forall a. Semigroup a => a -> a -> a
<> Doc
name'
  where
    name' :: Doc
name' = String -> Doc
escape String
name


showQualifiedName :: QualifiedName -> String
showQualifiedName :: QualifiedName -> String
showQualifiedName = Doc -> String
forall a. Show a => a -> String
show (Doc -> String)
-> (QualifiedName -> Doc) -> QualifiedName -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. QualifiedName -> Doc
ppQualifiedName